Find the pass |
Program takes a string from user, hashes value and compares to the expected hash at 00405064 - "pcx|xpzlhgu}"
Two things stood out to me in this challenge.
#1 - The compiler optimization for division.
004014b1 ba67666666 mov edx, 0x66666667
004014b6 89c8 mov eax, ecx
004014b8 f7ea imul edx
004014ba c1fa02 sar edx, 0x2
The above code is equivalent to simply dividing edx by 10, or (edx / 10).
The reason for this has to do with a compilers affinity for working in powers of 2's and the cost of the division instruction.
A good read on this can be found at: http://blog.dkbza.org/2007/09/reverse-engineering-compiler-produced.html
A good reference on these operations can be found at: https://flaviojslab.blogspot.com/2008/02/integer-division.html
#2 - Using an unnecessarily large buffer
00401472 8b4508 mov eax, dword [ebp+0x8 {pass}]
00401475 890424 mov dword [esp {var_6c_1}], eax
00401478 e88b270000 call strlen
0040147d 8945ec mov dword [ebp-0x14 {var_18}], eax
00401480 8b45ec mov eax, dword [ebp-0x14 {var_18}]
00401483 c1e002 shl eax, 0x2
00401486 890424 mov dword [esp {var_6c_2}], eax
00401489 e8da270000 call malloc // make the hashed password buffer 4x bigger
The above code shows that the program gets the length of the password. We then allocate memory to that length shifted left 2 times.
At first I wasn't sure of the purpose of why the developer did this until the end of the hashing function.
0040149a mov eax, dword [ebp-0xc {i}]
0040149d lea edx, [eax*4] // store i * 4, aka i shifted left by 0x2
004014a4 mov eax, dword [ebp-0x18 {offsets}]
004014a7 lea ebx, [edx+eax] // ebx now holds offsets[i*4]
004014aa call rand
004014af mov ecx, eax
004014b1 mov edx, 0x66666667
004014b6 mov eax, ecx
004014b8 imul edx
004014ba sar edx, 0x2
004014bd mov eax, ecx
004014bf sar eax, 0x1f
004014c2 sub edx, eax
004014c4 mov eax, edx
004014c6 shl eax, 0x2
004014c9 add eax, edx
004014cb add eax, eax
004014cd sub ecx, eax
004014cf mov edx, ecx
004014d1 mov dword [ebx], edx // store the current offset at offsets[i*4]
004014d3 add dword [ebp-0xc {i}], 0x1
I believe the reason for this is just throw a bit of confusion to the reverser.
This way there will be 4 junk bytes between each hash offset in memory and will no longer be contiguous in memory.
Conclusion: Other than those two things it just has a bit of math for the hashing function to get the offsets. I hope this read helps you :)
|