Monday, July 24, 2017

Beginning x86 disassembly – Understanding "imul" and "div" with Visual Studio 2017

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!

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ÿ..

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ÿ..

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ÿ..

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  ....

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:
8. Beginning x86 disassembly – Understanding the basics of “memcpy” with Visual Studio 2017

No comments:

Post a Comment