2

I'm trying to understand the behaviour of the code below so I can determine what input will trigger the "YOU DID IT !~!" string (at the end of the program instructions):

 .text:00C21034 Buf= byte ptr -6Ch .text:00C21034 var_68= byte ptr -68h .text:00C21034 var_4= dword ptr -4 .text:00C21034 .text:00C21034 push ebp .text:00C21035 mov ebp, esp .text:00C21037 sub esp, 6Ch .text:00C2103A mov eax, ___security_cookie .text:00C2103F xor eax, ebp .text:00C21041 mov [ebp+var_4], eax .text:00C21044 push ebx .text:00C21045 push offset aPleaseEnterThe ; "Please enter the password: " .text:00C2104A call sub_C21006 .text:00C2104F xor ebx, ebx .text:00C21051 push ebx .text:00C21052 call ds:__acrt_iob_func .text:00C21058 push eax ; File .text:00C21059 lea eax, [ebp+Buf] .text:00C2105C push 64h ; MaxCount .text:00C2105E push eax ; Buf .text:00C2105F call ds:fgets .text:00C21065 lea ecx, [ebp+Buf] .text:00C21068 add esp, 14h .text:00C2106B lea edx, [ecx+1] .text:00C2106E .text:00C2106E loc_C2106E: ; CODE XREF: sub_C21034+3F↓j .text:00C2106E mov al, [ecx] .text:00C21070 inc ecx .text:00C21071 test al, al .text:00C21073 jnz short loc_C2106E .text:00C21075 sub ecx, edx .text:00C21077 cmp ecx, 5 .text:00C2107A jnz short loc_C210C3 .text:00C2107C mov [ebp+var_68], bl .text:00C2107F .text:00C2107F loc_C2107F: ; CODE XREF: sub_C21034+5E↓j .text:00C2107F mov eax, ebx .text:00C21081 and eax, 3 .text:00C21084 mov al, [ebp+eax+Buf] .text:00C21088 xor byte_C23018[ebx], al .text:00C2108E inc ebx .text:00C2108F cmp ebx, 0Ah .text:00C21092 jb short loc_C2107F .text:00C21094 mov ecx, offset byte_C23018 .text:00C21099 mov edx, offset loc_C23024 .text:00C2109E mov eax, [ecx] .text:00C210A0 cmp eax, [edx] .text:00C210A2 jnz short loc_C210C3 .text:00C210A4 mov eax, [ecx+4] .text:00C210A7 cmp eax, [edx+4] .text:00C210AA jnz short loc_C210C3 .text:00C210AC movzx eax, byte ptr [ecx+8] .text:00C210B0 cmp al, [edx+8] .text:00C210B3 jnz short loc_C210C3 .text:00C210B5 push offset aYouDidIt ; "YOU DID IT !~!\r\n" .text:00C210BA call sub_C21006 .text:00C210BF xor eax, eax .text:00C210C1 jmp short loc_C210D0 .text:00C210C3 ; --------------------------------------------------------------------------- .text:00C210C3 .text:00C210C3 loc_C210C3: ; CODE XREF: sub_C21034+46↑j .text:00C210C3 ; sub_C21034+6E↑j ... .text:00C210C3 push offset aOhhhhNooTryAga ; "Ohhhh noo... try again.\r\n" .text:00C210C8 call sub_C21006 .text:00C210CD xor eax, eax .text:00C210CF inc eax 


NOTE:
The goal here is to find the correct input. I know that I can just put the IP where I want and make the program print it.


What I understood so far:

The program asks for input in this instruction:

 .text:00C2105F call ds:fgets 

After that, it runs a loop that counts how many chars are in the input, including the "new line" char at the end (when the user gives input and presses "enter"):

 .text:00C2106E loc_C2106E: ; CODE XREF: sub_C21034+3F↓j .text:00C2106E mov al, [ecx] .text:00C21070 inc ecx .text:00C21071 test al, al .text:00C21073 jnz short loc_C2106E 

Then, it subtracts the address of the last input char and the address of the first input char to determine the input's length:

 .text:00C21075 sub ecx, edx .text:00C21077 cmp ecx, 5 .text:00C2107A jnz short loc_C210C3 

If the input length is different than 5 (including the "new line" char), then it jumps to this label that prints out "Ohhhh noo... try again." and terminates the program:

 .text:00C210C3 push offset aOhhhhNooTryAga ; "Ohhhh noo... try again.\r\n" .text:00C210C8 call sub_C21006 

if the input length is exactly 5 (including the "new line" char), then it proceeds to this instruction that removes the "new line" char from the end of the input string, such that instead of 'A' hexa, there will be '0' hexa (bl initially have a value of 0):

 .text:00C2107C mov [ebp+var_68], bl 

So, if the input's length is 5 (including the new line char), it should proceeds to the code below. It's a loop that runs 10 times. ebx is initially 0, and it keeps running until ebx = 0A hexa = 10 decimal:

 .text:00C2107F loc_C2107F: ; CODE XREF: sub_C21034+5E↓j .text:00C2107F mov eax, ebx .text:00C21081 and eax, 3 .text:00C21084 mov al, [ebp+eax+Buf] .text:00C21088 xor byte_C23018[ebx], al .text:00C2108E inc ebx .text:00C2108F cmp ebx, 0Ah .text:00C21092 jb short loc_C2107F 

Now, the thing about this loop is that the following instruction guarentees that eax will always have values in the range 0-3:

 .text:00C21081 and eax, 3 

So, supposed I entered the input "G00D", that loop will XOR each char of the input string with every char of the string "G00D job!" (byte_C23018 that appears in the XOR instruction stores this string, see "P.S" at the end of the post), here is a demo of this loop ('20h' is the ascii value of the "space" char):

 eax = 0 | eax = 1 | eax = 2 | eax = 3 | eax = 0 | eax = 1 |etc G XOR G = 0|0 XOR 0 = 0| 0 XOR 0 = 0|D XOR D = 0|G XOR '20h' = g|0 XOR j = z|etc 

After that loop I'm starting to struggle.
The 2 labels in the code below are 6 addresses away from each other:

 .text:00C21094 mov ecx, offset byte_C23018 .text:00C21099 mov edx, offset loc_C23024 

But they have to point to exactly the same address so this "cmp" instruction that comes after it will succeed:

 .text:00C210A0 cmp eax, [edx] 

Otherwise - the condition for the "jnz" instruction below is met, and it jumps to that label that prints the "oh no try again" string:

 .text:00C210A2 jnz short loc_C210C3 
 .text:00C210C3 push offset aOhhhhNooTryAga ; "Ohhhh noo... try again.\r\n" .text:00C210C8 call sub_C21006 

Any suggestions or ideas? did I understand something wrong?

Thanks in advance!


P.S:
This is where the "G00D job!" is stored. Notice that the "G" is '47h'

 .data:00C23018 byte_C23018 db 47h ; DATA XREF: sub_C21034+54↑w .data:00C23018 ; sub_C21034+60↑o .data:00C23019 a00dJob db '00D job!',0 .data:00C23022 align 4 .data:00C23024 .data:00C23024 loc_C23024: ; DATA XREF: sub_C21034+65↑o .data:00C23024 add eax, 62657D71h .data:00C23029 sub esp, [edx] .data:00C2302B inc ebx .data:00C2302C arpl [eax], ax 

And if I input "G00D", it stores it here:

 debug007:00BBF8A0 db 47h ; G debug007:00BBF8A1 db 30h ; 0 debug007:00BBF8A2 db 30h ; 0 debug007:00BBF8A3 db 44h ; D 

1 Answer 1

1

You were almost there.

But they have to point to exactly the same address so this "cmp" instruction that comes after it will succeed

This statement is incorrect. Not addresses are being compared, but the data at each. The code, starting from .text:00C21094 compares 13 subsequent bytes at byte_C23018 with their counterparts at loc_C23024.

So, to get the correct password, we have to investigate them. It's easy to see, that at the start of the program, they are not the same, so they have to be modified at some point. The only place where it happens is the loop at loc_C2107F. It xors subsequent letters of your password with the letters of "G00D job!" string. As you have pointed out, password has to have length 5, including \n character, so it makes sense that the loop only uses first four bytes of the password.

But xor is invertible operation; in other words, if A xor B = C, then A = C xor B, since B xor B = 0 and A xor 0 = A.

In your case, A is the password you are providing, B is the "G00d job!" string, and C is the string at loc_C23024. So, to find relevant A you just need to xor B with C.

1
  • AMAZING! That did the job. Thank you so much!!! This is the accepted answer. Commented Dec 29, 2019 at 0:16

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.