After cracking the Magic Numbers crackme, I've chosen to crack (from the crackmes collection mentioned in Magic Numbers) one more. This time it's crackme "Bin" by Basse.
Goal: Find the correct key.
We have a GetDlgItemInt command call at 0040105E.
0040105E | E8 31010000 | CALL
This function translates the text of a specified control into an integer value. So the key is integer value. And the key after this function call is stored at EAX.
After calling GetDlgItemInt the offset of ASCII data (located at offset 00403000) is copying to ESI register.
Then after checks 4 bytes of ESI data for 0 (null terminator - end of data):00401068 | 833E 00 | CMP DWORD PTR DS:[ESI],0
we're jumping to 00401071 if not end of ASCII data:
0040106B | 75 04 | JNE SHORT Bin.00401071otherwise we're jumping to 0040107D if the end of ASCII data:
0040106D | EB 0E | JMP SHORT Bin.0040107D
The important comparison is performed here:
0040107D | 3D BF96287A | CMP EAX,7A2896BF
the result of function is compared to the hex value 0x7A2896BF (2049480383),
and if the result is equal to this value - the "Congratulation, you found the right key" message is shown:
00401084 | 6A 40 | PUSH 4000401086 | 68 30354000 | PUSH OFFSET Bin.00403530 ; ASCII "In the Bin"
0040108B | 68 3B354000 | PUSH OFFSET Bin.0040353B ; ASCII "Congratulation, you found the right key"
00401090 | FF75 08 | PUSH DWORD PTR SS:[EBP+8]
00401093 | E8 02010000 | CALL
After jumping to 00401071 we moving current 4 bytes of ASCII data to EBX register.
00401071 | 8B1E | MOV EBX,DWORD PTR DS:[ESI]
Then an important function at 0040110F is called:
00401073 | E8 97000000 | CALL Bin.0040110F
After that the ASCII data pointer at ESI by 4 (dword) increased:
00401078 | 83C6 04 | ADD ESI,4
And we jump back to 00401068:
0040107B | EB EB | JMP SHORT Bin.00401068
Now lets look into the this important function:
We have 4 bytes of ASCII data at EBX register, and the key value at EAX.
Here is the code of this function with comments.
Address | Hex dump | Command ; Comments
0040110F | 51 | PUSH ECX ; push ECX onto stack
00401110 | 52 | PUSH EDX ; push EDX onto stack
00401111 | 8BD3 | MOV EDX,EBX ; copy 4 bytes of data
00401113 | 8BC8 | MOV ECX,EAX ; copy key
00401115 | 40 | INC EAX ; key = key + 1
00401116 | F7D0 | NOT EAX ; key = ~(key)
00401118 | 43 | INC EBX ; data = data + 1
00401119 | F7D3 | NOT EBX ; data = ~(data)
0040111B | 40 | INC EAX ; key = key + 1
0040111C | 43 | INC EBX ; data = data + 1
0040111D | 23C2 | AND EAX,EDX ; key = key & copy of data
0040111F | 23D9 | AND EBX,ECX ; data = data & copy of key
00401121 | 03C3 | ADD EAX,EBX ; result = key + data
00401123 | 5A | POP EDX ; restore EDX
00401124 | 59 | POP ECX ; restore ECX
00401125 | C3 | RETN ; return result
So this function is could be written this way:
result = (value & (~(key + 1) + 1)) + (key & (~(value + 1) + 1))
If simplify this function it will be:
result = key ^ value, — just exclusive or (xor) operation.
so knowing the final result 0x7A2896BF (2049480383) it's easy to find the key.
Here is my python code, to find the key:
import struct data = 'Oqiqb4EhM/4jISMjlzQf6kpGQwLrG+GEIY4bPc0JL/jWBfNLejmbme3garIrG4ngbXtWQY3Y2VdbvRxleHU9aGxFRLXkh5BDGVbm5gAAhGeBMBl65XKmZ9sbNn4xxi3cbD7M02MpwZ3BpN4lG3xyFPsofbhXbMu8Z/1rlqfdul/KLaGmkllOYRj9Mhnumqw1f464dK948rgz5JxpeSQHN45GlMNjb717x6IeCCMa6gN+YX73M/LrkH1xZEhpjZ4YLugpHGquVl9m5Kq7AvcapkVEUsZt29JWB/dzq//bFG15ykd53wpP/8gddTTwV6i2vmLXLjDrfwO4NCLolYyD78vmdPsZRvlI4B0bslHerN7buJ938iWcaKg6NjrHMfZhO6BrvbLRbhSUQSKfgyXsAhaT/O1p1fM6KoFlWbHri9HfIwKocjXQkUDsT2u7U2+82oYHVvhthhCOlxlQyiUKr11Cj9Pzbqz11sulpr0D0rfChHOO81Ht3ax1ynL/nTQmNWCj4U4C0T9cjmUNU47gdGMEa0+tyv2s75/Xvo+qTrywdVqLDEviE+3Gxy3U+vX5MRrJipxK2OnUu/g/uanoLok7CA4LKQe7+ho6Vrb91/K/scyEdIvUlZ5A3LfP3DRWsE4LbKkYcwUy6ea7aEqdaEqd6ea7cwUybKkYsE4L3DRW3LfPlZ5AdIvUscyE1/K/Vrb9+ho6KQe7CA4LLok7uanou/g/2OnUipxKMRrJ+vX5xy3UE+3GDEvidVqLTrywvo+q75/Xyv2sa0+tdGMEU47gjmUN0T9c4U4CNWCjnTQmynL/3ax181HthHOO0rfCpr0D1sulbqz1j9Pzr11CyiUKlxlQhhCOVvht2oYHU2+8T2u7kUDscjXQIwKoi9HfWbHrKoFl1fM6/O1pAhaTgyXsQSKfbhSUvbLRO6BrMfZhNjrHaKg68iWcuJ93rN7bslHe4B0bRvlIdPsZ78vmlYyDNCLofwO4LjDrvmLXV6i2dTTw/8gd3wpPykd5FG15q//bB/dz29JWUsZtpkVEAvca5Kq7Vl9mHGquLugpjZ4YZEhpkH1xM/LrYX736gN+CCMax6Ieb717lMNjN45GeSQH5Jxp8rgzdK94f464mqw1MhnuYRj9kllOLaGmul/KlqfdZ/1rbMu8fbhXFPsoG3xypN4lwZ3B02MpbD7Mxi3cNn4xZ9sb5XKmMBl6hGeB5gAAGVbmh5BDRLXkaGxFeHU9vRxl2VdbQY3YbXtWG4ngarIrme3gejmbBfNLL/jWPc0JIY4bG+GEQwLr6kpGlzQfISMjM/4jb4EhOqiq' def invert(x): return ~x & 0xffffffff def decode_func(key, value): return (value & (invert(key + 1) + 1)) + (key & (invert(value + 1) + 1)) def checker(key): result = key for i in xrange(0, len(data), 4): value = struct.unpack('I', data[i:i+4])[0] result = decode_func(result, value) return result key = checker(0x7a2896bf) print 'The key is: %s' % key