Last active
October 15, 2025 16:36
-
-
Save madzohan/96c515312d8ce037f6c93c5e6599a476 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| // https://crackmes.one/crackme/68c96889224c0ec5dcedc063 | |
| import ( | |
| "encoding/binary" | |
| "fmt" | |
| ) | |
| /* | |
| After you launched `Detect It Easy` and found nothing in strings ... | |
| but few things are still helpful :) | |
| Endianess LE, Mode 32-bit | |
| How to (for Ghidra newbies): | |
| 1. Run the program from cmd.exe and observe what it does. | |
| You’ll see: | |
| - putchar("Input the password:") | |
| - scanf() reads your input | |
| - putchar() prints either '?' or 'Incorrect' | |
| 2. Open the binary in Ghidra, analyze with default parameters. | |
| Then go through these functions in order: | |
| 1) entry | |
| 2) FUN_004011b0 | |
| 3) FUN_00401460 | |
| 4) DAT_00404020 | |
| 3. Press Alt+W -> Bytes to open the byte view. | |
| 4. Return to Decompile -> FUN_00401460 and double-click on DAT_00404020. | |
| 5. In the Bytes view, look at selected address 00404020. | |
| You’ll see a pattern: one non-zero byte followed by three zeros. | |
| → That means each character is encoded in 4 bytes (uint32 ?). | |
| 6. In FUN_00401460, there are 4 for-loops: | |
| 1. Prints "Input the password:" (0x14 = 20 chars) | |
| 2. After scanf, compares user input with DAT_00404020; if equal, adds 1 to local_18 | |
| 3. Prints "Correct password" | |
| 4. Prints "Incorrect password" | |
| 7. The correct password is 6 characters long. | |
| The program reads 0x2A (42) bytes from DAT_00404020. | |
| Assuming 1 char = 4 bytes → 42 * 4 = 168 bytes total. | |
| 8. In the Bytes view, select 168 bytes starting from address 00404020 (49 00 00 00 ...). | |
| You can check the selection size in the blue tab title bar. | |
| 9. Right-click -> Copy Special -> C Array. | |
| Now you have the equivalent of the "data" variable from the source code. | |
| 10. In code, you must reproduce the logic `local_c8[local_14] / (local_14 + 1)` inside a for-loop from 0 to 42. | |
| But before doing any math operations, remember that each character takes 4 bytes. | |
| Convert every 4-byte group into a `uint32` using `binary.LittleEndian.Uint32` | |
| (Little Endian was confirmed in the DIE section). | |
| Each loop iteration should extract 4 bytes: | |
| data[i*4 : (i+1)*4] | |
| This converts: | |
| [168]byte → [42]uint32 | |
| 0x49, 0x00, 0x00, 0x00 → 73 | |
| Now you can try to decode characters inside a for-loop from 0 to 42 ... for example i==0: | |
| dwords[0] / (0+1) | |
| 73 / 1 | |
| ASCII code 73 is represented by the character "I" ... first one from "Input the password:", Profit! | |
| */ | |
| var data = [168]byte{ | |
| 0x49, 0x00, 0x00, 0x00, | |
| 0xdc, 0x00, 0x00, 0x00, | |
| 0x50, 0x01, 0x00, 0x00, | |
| 0xd4, 0x01, 0x00, 0x00, | |
| 0x44, 0x02, 0x00, 0x00, | |
| 0xc0, 0x00, 0x00, 0x00, | |
| 0x2c, 0x03, 0x00, 0x00, | |
| 0x40, 0x03, 0x00, 0x00, | |
| 0x8d, 0x03, 0x00, 0x00, | |
| 0x40, 0x01, 0x00, 0x00, | |
| 0xd0, 0x04, 0x00, 0x00, | |
| 0x8c, 0x04, 0x00, 0x00, | |
| 0xd7, 0x05, 0x00, 0x00, | |
| 0x4a, 0x06, 0x00, 0x00, | |
| 0xf9, 0x06, 0x00, 0x00, | |
| 0xf0, 0x06, 0x00, 0x00, | |
| 0x92, 0x07, 0x00, 0x00, | |
| 0x08, 0x07, 0x00, 0x00, | |
| 0x4e, 0x04, 0x00, 0x00, | |
| 0x80, 0x02, 0x00, 0x00, | |
| 0x0a, 0x08, 0x00, 0x00, | |
| 0x56, 0x08, 0x00, 0x00, | |
| 0xe2, 0x09, 0x00, 0x00, | |
| 0x18, 0x09, 0x00, 0x00, | |
| 0xbe, 0x0a, 0x00, 0x00, | |
| 0xda, 0x09, 0x00, 0x00, | |
| 0x11, 0x07, 0x00, 0x00, | |
| 0x24, 0x0c, 0x00, 0x00, | |
| 0xea, 0x0c, 0x00, 0x00, | |
| 0x5c, 0x0d, 0x00, 0x00, | |
| 0x3b, 0x0c, 0x00, 0x00, | |
| 0x60, 0x0c, 0x00, 0x00, | |
| 0xf4, 0x0e, 0x00, 0x00, | |
| 0xb2, 0x09, 0x00, 0x00, | |
| 0x0a, 0x0f, 0x00, 0x00, | |
| 0xec, 0x0d, 0x00, 0x00, | |
| 0x0b, 0x10, 0x00, 0x00, | |
| 0xec, 0x10, 0x00, 0x00, | |
| 0x5e, 0x11, 0x00, 0x00, | |
| 0xc8, 0x0f, 0x00, 0x00, | |
| 0xdb, 0x0f, 0x00, 0x00, | |
| 0x08, 0x13, 0x00, 0x00} | |
| func main() { | |
| var dwords [42]uint32 | |
| setupDwords(&data, &dwords) | |
| var decodedData string | |
| for i := range 42 { | |
| decodedData += string(decodeChar(i, &dwords)) | |
| } | |
| fmt.Printf("\tDecoded data:\n%s\n\n", decodedData) | |
| fmt.Printf("\tLittle endian uint32 data representation: \n%v\n\n", dwords) | |
| fmt.Printf("\tCorrect password is: \n%s\n", decodedData[20:26]) | |
| } | |
| func setupDwords(data *[168]byte, dwords *[42]uint32) { | |
| for i := range 42 { | |
| dwords[i] = binary.LittleEndian.Uint32(data[i*4 : (i+1)*4]) | |
| } | |
| } | |
| func decodeChar(i int, dwords *[42]uint32) rune { | |
| return rune(dwords[i] / uint32(i+1)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment