In this challenge I will be taking a look at the ASM instructions from a program (while/loop) using both Intel and AT&T syntax. After figuring out what each instruction does to the best of my ability, I will write a C program to reflect what I think is happening in the ASM instructions. These challenges are purely for practice, and will help you understand the basics of reverse engineering, as well as C and ASM.
Below you will see the ASM instructions for the C program (while/loop), and the challenge is to write the C program after looking at the ASM instructions below. The left side is Intel Syntax, where as the right side is AT&T syntax.
Note: I recommend learning both Intel and AT&T syntax as seen below
Note: Make note of the difference between the Intel and AT&T syntax above. With this smaller program you can start to see the difference between the two (i.e. mov vs movl, etc…)
These are some of the notes I took while checking the code above, starting with line 9 (value label).
In the above instructions, I can see that lines 9-11 seems to be a global variable of name value and has decimal 10 set in a 4-byte datatype as seen below.
The next set of instructions that drew my attention, were the instructions at lines 26-27, in which a value of 0 is passed into a pointer location for storage, then the next instruction jumps to label L2 without any conditions. This usually means the value at DWORD PTR -4[rbp] will be some kind of counter, or a placeholder for keeping track of iterations which we can prove or disprove in later steps, but its good to keep these ideas in mind as you go.
The unconditional jump to label L2 has the following instructions.
Lines 36-42 seems to be moving the value of the global variable (10 in decimal) to the EAX register, then the very next instruction is comparing our DWORD PTR -4[rbp] iteration placeholder to the value stored in EAX. The next instruction is to jump if the value stored in EAX is less than the value stored in our global variable (10 in decimal.) If the value is not less than the global variable, then the main function cleans up the EAX register, then leaves and returns back to previous stack frame. So this means if the value is less than the global variable, than it should jump to label L3 for more logic to happen, else end the program successfully. So let’s take a look at the logic for label L3 to see how this fits into the rest of the program.
So following the logic from before L3, it seems we have a global static value located at DWORD PTR value[rip] with the value of 10 in decimal. We also have another value located at DWORD PTR -4[rbp] that seems to be holding a temporary number that eventually gets compared to the global static value listed above.
We can see on line 29 above, that the value of 1 is being added to the value of DWORD PTR -4[rbp], then right after the same value is moved to the EAX register. The following 4 lines from lines 31-34 are setting up the printf function by adding the format string from label LC0[rip], and then the argument that was part of the format string (DWORD PTR -4[rbp]) gets moved into the ESI register. Next, 0 is moved into the EAX register as per the x64 ABI for printf function.
So all that being said and talked over, what does the program actually do?
After parsing each instruction from the above code, I wrote the following C program to re-construct the ASM instructions.
Next is to compile the code to see if it works, and then run objdump on the binary to see how close our disassembly is to the instructions we started with.
Awesome! It worked out without error, so lets double check our accuracy with objdump as seen below.
This turned out pretty good, as I can see that the instructions are very similar to the original ASM instructions above, but without the labels. You can see there is a cmp instruction followed by a jmp instruction, that jumps backwards in code to add 1 just like it did within the ASM instructions at the top of this post. When you see patterns like this in the wild, or when reverse engineering, you should start noting down it may be a loop, and in this specific example, it was a while loop being used.
I hope you learned something new, that you didn’t know before.