We will notice that there is some kind of loop. I have highlighted the section in Pink, which I want to avoid.
There is also some kind of a counter check to see if it reached 0x14, which is 20 in base 10. Hence, the loop will loop for a max of 20 characters.
Looking at the circled algorithm, we can see that the counter is always retrieved from
- Updated counter is always retrieved from
- Index = (counter + counter*4) * 16
- Get byte from binary pointed to by RSI[Index]
- Get byte from user input pointed to by Input[counter]
- Transfer the user input byte such that
input_byte = ((input_byte XOR 0x32)+1) XOR 0x32
- Ensure the new input byte amd the byte from the memory are equal, and proceed to check the remaining bytes.
What we know so far are that there are a total of 20 iterations. We know our user input is being check to a value from memory at a location determined by Step 2 above.
By calculating the Index for possible values if Counter in range 0 to 19 inclusive, we can compute our Index values to be 0, 80, 160, 240 and so on. So basically we are accessing the memory in increment of 80 bytes.
We can see that the values are from a .data section in memory.
I set a breakpoint.
b * 0x000055555555483b
Then I ran the application again,
The bytes collated was
[0x3a, 0x31, 0x52, 0x30, 0x34, 0x36, 0x52, 0x30, 0x33, 0x5c, 0x3a, 0x51, 0x73, 0x30, 0x35, 0x45, 0x5c, 0x31, 0x5a, 0x34].
Then I proceeded to use python to reverse the algorithm as such.
a =[0x3a, 0x31, 0x52, 0x30, 0x34, 0x36, 0x52, 0x30, 0x33, 0x5c, 0x3a, 0x51, 0x73, 0x30, 0x35, 0x45, 0x5c, 0x31, 0x5a, 0x34] def f(input): ... for i in input: ... dec = ((i^0x32)-1)^0x32 ... print(chr(dec)) ... f(a) 5 0 m 3 7 1 m 3 2 _ 5 P r 3 4 D _ 0 U 7