In this series of
posts, I’m going through the Open Security Training for beginning Assembly Language and thus am putting my
own spin on things to enhance my knowledge of x86 disassembly. However, to make
the most of these tutorials you may be better of reviewing the material from Open Security Training directly.
Let’s get started!
Let’s get started!
To understand unconditional jumps, let’s start with the code below:
/*
* This file focuses on flow control
via unconditional jumps using the "goto" statement and
* The objective is to get a better
understanding of how these are disassembled in C
* Author Nik Alleyne
* Blog: securitynik.blogspot.com
* File: flow_control.c
*
*/
#include <stdio.h>
int main()
{
goto label_SecurityNik;
printf("This is skipped\n");
label_SecurityNik:
printf("We're at label_SecurityNik! \n");
return 0x07;
}
Now that we have our code, let’s now
disassemble this.
Here is our disassembled code for
the code above:
int main()
{
00401000 push
ebp
00401001 mov
ebp,esp
goto label_SecurityNik;
00401003 jmp
00401012
printf("This is skipped\n");
00401005 push
404000h
0040100A call
00401070
0040100F add
esp,4
label_SecurityNik:
printf("We're at label_SecurityNik! \n");
00401012 push
404014h
00401017 call
00401070
0040101C add
esp,4
return 0x07;
0040101F mov
eax,7
}
00401024 pop
ebp
00401025 ret
As with the previous posts, this one
does not analyze the prologue and epilogue. To learn more about these, see my
post on prologue
and epilogue available here.
Let’s focus on the first instruction
after the “push ebp” and “mov ebp, esp”
As the first thing our code wants to
do is “goto label_SecurityNik”, from the disassembly perspective, the first
instruction we see is “00401003 jmp 00401012”. This means we are jumping to the
instruction at memory address “00401012”.
From the disassembly above, we see the instruction at “00401012” is “00401012 push 404014h”. This also means that the following instructions as been skipped with the EIP register and control being redirected to “00401012”:
00401005 push 404000h
From the disassembly above, we see the instruction at “00401012” is “00401012 push 404014h”. This also means that the following instructions as been skipped with the EIP register and control being redirected to “00401012”:
00401005 push 404000h
0040100A call
00401070
0040100F add
esp,4
since the instruction at “00401012” is to “push 404014h”, let’s see what is at the memory
address “404014h” that should be pushed unto the top of the stack.
0x00404014 72276557 We'r
0x00404018 74612065 e at
0x0040401C 62616c20 lab
0x00404020 535f6c65 el_S
0x00404024 72756365 ecur
0x00404028 4e797469 ityN
0x0040402C 20216b69 ik!
0x00404030 0000000a ....
0x00404030 0000000a ....
From the above we see our string “We're at label_SecurityNik! \n”.
Therefore the value “404014h” will be
pushed unto the stack. This value serves as a pointer to our string. Let’s
execute the instruction “push 404014h” to see
what we get.
EAX = 0FB21944 EBX = 00272000
ECX = 00000001 EDX = 004043CC ESI = 00401430
EDI = 00401430 EIP = 00401017 ESP = 0019FF00 EBP = 0019FF04
EFL = 00000202
0x0019FF00 00404014 .@@.
0x0019FF04 0019ff18 .ÿ..
0x0019FF08 0040141e ..@.
0x0019FF0C 00000001 ....
0x0019FF10 005c5a50 PZ\.
0x0019FF14 0059c940 @ÉY.
0x0019FF18 0019ff70 pÿ..
0x0019FF18 0019ff70 pÿ..
As we can
see from above, the memory address “404014h” has been pushed to the top of the stack.
The next
instruction says “call 00401070”. At this
point if we look at this call as well as the one which was skipped above, we
will see this is our call to the “printf” function. Note the address is the
same for both calls. Since I know this is “printf” and do not wish to
disassemble it, I will just “step over” this code. Once I step over, the output
“We're at label_SecurityNik!” is written to the screen.
Next step
is to a “add esp, 4” in which we add 4 bytes to the ESP register value, thus
cleaning up the stack. Currently the registers look like:
EAX = 0000001D EBX = 00272000 ECX = 35C43FCA EDX = 0FB20BA4 ESI = 00401430 EDI = 00401430 EIP = 0040101C ESP = 0019FF00 EBP = 0019FF04 EFL = 00000206
… and the stack look like:
EAX = 0000001D EBX = 00272000 ECX = 35C43FCA EDX = 0FB20BA4 ESI = 00401430 EDI = 00401430 EIP = 0040101C ESP = 0019FF00 EBP = 0019FF04 EFL = 00000206
… and the stack look like:
0x0019FF00 00404014 .@@.
0x0019FF04 0019ff18 .ÿ..
0x0019FF08 0040141e ..@.
0x0019FF0C 00000001 ....
0x0019FF10 005c5a50 PZ\.
0x0019FF14 0059c940 @ÉY.
0x0019FF18 0019ff70 pÿ..
0x0019FF18 0019ff70 pÿ..
After the instruction “add esp, 4” the registers look like ….
EAX = 0000001D EBX = 00272000 ECX = 35C43FCA EDX = 0FB20BA4 ESI = 00401430 EDI = 00401430 EIP = 0040101F ESP = 0019FF04 EBP = 0019FF04 EFL = 00000202
…. And the
stack looks like
0x0019FF04 0019ff18 .ÿ..
0x0019FF08 0040141e ..@.
0x0019FF0C 00000001 ....
0x0019FF10 005c5a50 PZ\.
0x0019FF14 0059c940 @ÉY.
0x0019FF18 0019ff70 pÿ..
0x0019FF1C 00401300 ..@.
0x0019FF1C 00401300 ..@.
We then see our next instruction “mov eax, 7”. If we remember from our code above, we set a return value of “7”.
Now the
value at the top of the stack “0x0019FF04” is “0019ff18”. The next
instruction says “pop ebp”. This means the value at the top of the stack will
now be pop’ed into the EBP register. Let’s verify this by executing the
instruction and looking at the registers:
EAX = 00000007 EBX = 00272000 ECX = 35C43FCA EDX = 0FB20BA4 ESI = 00401430 EDI = 00401430 EIP = 00401025 ESP = 0019FF08 EBP = 0019FF18 EFL = 00000202
EAX = 00000007 EBX = 00272000 ECX = 35C43FCA EDX = 0FB20BA4 ESI = 00401430 EDI = 00401430 EIP = 00401025 ESP = 0019FF08 EBP = 0019FF18 EFL = 00000202
Final instruction states to return “ret” so the
function which called main now regains control.
References:
Open Security Training
Open Security Training
Other posts in this series:
2. Beginning
x86 disassembly – Understanding function arguments and variables with Visual
Studio 2017
8. Beginning
x86 disassembly – Understanding the basics of “memcpy” with Visual Studio 2017
No comments:
Post a Comment