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!
Whereas the previous post on bit
shifting focused on multiplying and dividing leveraging bit shifting, this post
leverages the “imul” and “div” instruction. Also the previous post focused on
multiplying and dividing numbers which were multiples of two, thus the bit
shifting was easy. In this post, we will look at some different numbers to make
things interesting and expand our knowledge.
To understand “imul” and “div”, let’s start with the code below:
/*
* This file focuses on imul and div
* The objective is to get a better
understanding of how these are disassembled in C
* Author Nik Alleyne
* Blog: securitynik.blogspot.com
* File: imul_div.c
*
*/
#include <stdio.h>
int main()
{
unsigned int a = 1;
a = a * 6;
a = a / 3;
return "imul_div_example";
}
And the disassembled code
int main()
{
00401000 push
ebp
00401001 mov
ebp,esp
00401003 push
ecx
unsigned int a = 1;
00401004 mov
dword ptr [ebp-4],1
a = a * 6;
0040100B imul
eax,dword ptr [ebp-4],6
0040100F mov
dword ptr [ebp-4],eax
a = a / 3;
00401012 mov
eax,dword ptr [ebp-4]
00401015 xor
edx,edx
00401017 mov
ecx,3
0040101C div
eax,ecx
0040101E mov
dword ptr [ebp-4],eax
return "imul_div_example";
00401021 mov
eax,404000h
}
00401026 mov
esp,ebp
00401028 pop
ebp
00401029 ret
Let’s start off with the
disassembled code and the first two instructions “push ebp“ and “mov ebp,esp”
which as always is the prologue. See
this post for more on prologue and epilogue.
The next instruction “push ecx”
allocates space on the stack for our “unsigned int a”. Now that we have space
allocated for “a”. Our next instruction “mov dword ptr [ebp-4],1” says to put
the value “1” in the position occupied by “[ebp-4]”. Once we execute this
instruction and look at the registers, we see …
EAX = 66CD1944 EBX = 00248000
ECX = 00000001 EDX = 004043A0 ESI = 004013B0
EDI = 004013B0 EIP = 0040100B ESP = 0019FF00 EBP = 0019FF04
EFL = 00000202
… and the stack we see …
0x0019FF00 00000001 .... – [ebp-4] – Now has a value of 1
0x0019FF04 0019ff18 .ÿ.. - EBP
0x0019FF08 0040139e ž.@.
0x0019FF0C 00000001 ....
0x0019FF10 006bbd18 ..k.
0x0019FF14 006b8338 8ƒk.
0x0019FF18 0019ff70 pÿ..
0x0019FF18 0019ff70 pÿ..
Our next instruction “imul eax,dword
ptr [ebp-4],6” says to take the value at “[ebp-4]” which we know is “1” and
multiply it by “6”, then store the value “6” which is from “1*6” in the “eax”
register. Looking at our registers with a focus on “eax” after execution we see
…
EAX = 00000006 EBX = 00248000 ECX = 00000001
EDX = 004043A0 ESI = 004013B0 EDI = 004013B0
EIP = 0040100F ESP = 0019FF00 EBP = 0019FF04
EFL = 00000206
Our next instruction “mov dword ptr
[ebp-4],eax” says to now take our “6” which is in the “eax” register and place
it in position “[ebp-4]” which is the space reserved for “a”. Once we execute
this instruction, we see the following on our stack …
0x0019FF00 00000006 .... – [ebp-4] – 6 matches the value in eax
0x0019FF04
0019ff18 .ÿ.. - EBP
0x0019FF08 0040139e ž.@.
0x0019FF0C 00000001 ....
0x0019FF10 006bbd18 ..k.
0x0019FF14 006b8338 8ƒk.
0x0019FF18 0019ff70 pÿ..
0x0019FF18 0019ff70 pÿ..
Our next instruction “mov eax,dword
ptr [ebp-4]” basically takes our “6” which is at “[ebp-4]” and put it in the
“eax” register. However, as we now, the “eax” register already has a value of
6, so no need to dwell further on this.
Moving along to our next instruction
“xor edx,edx”, we are now zeroing out the “edx” register. To demonstrate this,
let’s look at the registers before execution …
EAX = 00000006 EBX = 00248000
ECX = 00000001 EDX = 004043A0
ESI = 004013B0 EDI = 004013B0 EIP = 00401015
ESP = 0019FF00 EBP = 0019FF04 EFL = 00000206
… and after execution …
EAX = 00000006 EBX = 00248000
ECX = 00000001 EDX = 00000000
ESI = 004013B0 EDI = 004013B0 EIP = 00401017
ESP = 0019FF00 EBP = 0019FF04 EFL = 00000246
As we can see the “edx” register is
now “0”
The next instruction “mov ecx,3” takes
the value of “3” and puts it in “ecx” as we can see from the previous printout
of the registers, “ECX = 00000001”. After execution the registers
show “ECX = 00000003”.
EAX = 00000006 EBX = 00248000 ECX = 00000003
EDX = 00000000 ESI = 004013B0 EDI = 004013B0
EIP = 0040101C ESP = 0019FF00 EBP = 0019FF04
EFL = 00000246
The next instruction “div eax,ecx”,
divides the value in “eax” (“6”) by the value in “ecx” (“3”) and store the
result “2” in “eax”. After execution, our registers look like
EAX = 00000002 EBX = 00248000 ECX = 00000003
EDX = 00000000 ESI = 004013B0 EDI = 004013B0
EIP = 0040101E ESP = 0019FF00 EBP = 0019FF04
EFL = 00000246
Our next instruction “mov dword ptr
[ebp-4],eax”, says to now take our “2” which is in “eax” and place it at
position “[ebp-4]” which as we should know by now is the location reserved for
our variable “a”.
From our previous printout of the
stack above, we see “[ebp-4]” has a value of 6. After execution of our
instruction we see “[ebp-4]” now has the “2” which is also in our “eax”
register.
0x0019FF00 00000002 ....
0x0019FF04 0019ff18 .ÿ..
0x0019FF08 0040139e ž.@.
0x0019FF0C 00000001 ....
0x0019FF10 006bbd18 ..k.
0x0019FF14 006b8338 8ƒk.
0x0019FF18 0019ff70 pÿ..
0x0019FF18 0019ff70 pÿ..
The final instruction we will look
at states “mov eax,404000h”. The address “404000h” is a pointer to our string “imul_div_example”.
Let’s verify this by going to this memory address and looking at the stack
0x00404000 6c756d69 imul
0x00404004 7669645f _div
0x00404008 6178655f _exa
0x0040400C 656c706d mple
0x00404010 00000000 ....
0x00404014 ffffffff ÿÿÿÿ
0x00404018 00000001 ....
0x00404018 00000001 ....
As we can see the address “404000h”
is a pointer to our string. For what we have seen so far, the “eax” register
stores the return value and as we know our code is returning the string above.
Let’s execute the instruction “mov eax,404000h” and now look at our register …
EAX = 00404000 EBX = 00248000 ECX = 00000003
EDX = 00000000 ESI = 004013B0 EDI = 004013B0
EIP = 00401026 ESP = 0019FF00 EBP = 0019FF04
EFL = 00000246
Awesome! The “eax” register once
again contains our return value.
The rest of the code we will not
review as this is part of the epilogue. To learn more about prologues and
epilogues, see this
post.
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