Skip to main content

Deep Dive to Windows, Part 2


In this section, I’d like to disassemble our main function which we’ve written in series 1 and would like to see how it looks like. Also would like to see if we can see the string “Hello World”.
I’ve launched my sample executable using WinDbg.
Then Issued following command:

x sample_hello!*main*
*** WARNING: Unable to verify checksum for Sample_Hello.exe
00419048          Sample_Hello!__native_dllmain_reason = 0xffffffff
0041917c          Sample_Hello!mainret = 0n0
004114b0          Sample_Hello!wmain (int, wchar_t **)
004122b0          Sample_Hello!__tmainCRTStartup (void)
00412290          Sample_Hello!wmainCRTStartup (void)
00413592          Sample_Hello!__wgetmainargs ()
0041a3d8          Sample_Hello!_imp____wgetmainargs =
Since we know my intended function is ‘main’ so I searched for it. The highlighted one is our main function.

Then unassembled the function using following command:

0:000> uf Sample_Hello!wmain
Sample_Hello!wmain [f:\fordebugging\sample_hello\sample_hello\sample_hello.cpp @ 10]:
   10 004114b0 55              push    ebp
   10 004114b1 8bec            mov     ebp,esp
   10 004114b3 81eccc000000    sub     esp,0CCh
   10 004114b9 53              push    ebx
   10 004114ba 56              push    esi
   10 004114bb 57              push    edi
   10 004114bc 8dbd34ffffff    lea     edi,[ebp-0CCh]
   10 004114c2 b933000000      mov     ecx,33h
   10 004114c7 b8cccccccc      mov     eax,0CCCCCCCCh
   10 004114cc f3ab            rep stos dword ptr es:[edi]
   12 004114ce 8bf4            mov     esi,esp
   12 004114d0 a110a34100      mov     eax,dword ptr [Sample_Hello!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0041a310)]
   12 004114d5 50              push    eax
   12 004114d6 68fc774100      push    offset Sample_Hello!`string' (004177fc)
   12 004114db 8b0d0ca34100    mov     ecx,dword ptr [Sample_Hello!_imp_?coutstd (0041a30c)]
   12 004114e1 51              push    ecx
   12 004114e2 e877fcffff      call    Sample_Hello!ILT+345(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0041115e)
   12 004114e7 83c408          add     esp,8
   12 004114ea 8bc8            mov     ecx,eax
   12 004114ec ff1508a34100    call    dword ptr [Sample_Hello!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (0041a308)]
   12 004114f2 3bf4            cmp     esi,esp
   12 004114f4 e8b5fcffff      call    Sample_Hello!ILT+425(__RTC_CheckEsp) (004111ae)
   13 004114f9 8bf4            mov     esi,esp
   13 004114fb 8d45fb          lea     eax,[ebp-5]
   13 004114fe 50              push    eax
   13 004114ff 8b0d04a34100    mov     ecx,dword ptr [Sample_Hello!_imp_?cinstd (0041a304)]
   13 00411505 51              push    ecx
   13 00411506 ff1500a34100    call    dword ptr [Sample_Hello!_imp_??$?5DU?$char_traitsDstdstdYAAAV?$basic_istreamDU?$char_traitsDstd (0041a300)]
   13 0041150c 83c408          add     esp,8
   13 0041150f 3bf4            cmp     esi,esp
   13 00411511 e898fcffff      call    Sample_Hello!ILT+425(__RTC_CheckEsp) (004111ae)
   14 00411516 33c0            xor     eax,eax
   15 00411518 52              push    edx
   15 00411519 8bcd            mov     ecx,ebp
   15 0041151b 50              push    eax
   15 0041151c 8d1540154100    lea     edx,[Sample_Hello!wmain+0x90 (00411540)]
   15 00411522 e88dfbffff      call    Sample_Hello!ILT+175(_RTC_CheckStackVars (004110b4)
   15 00411527 58              pop     eax
   15 00411528 5a              pop     edx
   15 00411529 5f              pop     edi
   15 0041152a 5e              pop     esi
   15 0041152b 5b              pop     ebx
   15 0041152c 81c4cc000000    add     esp,0CCh
   15 00411532 3bec            cmp     ebp,esp
   15 00411534 e875fcffff      call    Sample_Hello!ILT+425(__RTC_CheckEsp) (004111ae)
   15 00411539 8be5            mov     esp,ebp
   15 0041153b 5d              pop     ebp
   15 0041153c c3              ret

The highlighted line shows, stack pointer has changed and this indicates function allocated some space in stack. So, would like to know how much space has been allocated?

Issued command:

0:000> ? 0CCh
Evaluate expression: 204 = 000000cc
So, function wmain allocated 204(0x0CC) bytes on stack.
Now I’m interested to know where ‘Hello World’ String is. If we look at call stack, there is an entry like below:

12 004114d6 68fc774100      push    offset Sample_Hello!`string' (004177fc)

Executed following command and it displays it content:

0:000> da 004177fc
004177fc  "Hello World"

More to come....
 
Happy Debugging.

Comments

Popular posts from this blog

Reversing char array without splitting the array to tokens

 I was reading about strdup, a C++ function and suddenly an idea came to my mind if this can be leveraged to aid in reversing a character array without splitting the array into words and reconstructing it again by placing spaces and removing trailing spaces. Again, I wanted an array to be passed as a function argument and an array size to be passed implicitly with the array to the function. Assumed, a well-formed char array has been passed into the function. No malformed array checking is done inside the function. So, the function signature and definition are like below: Below is the call from the client code to reverse the array without splitting tokens and reconstructing it. Finally, copy the reversed array to the destination.  For GNU C++, we should use strdup instead _strdup . On run, we get the following output: Demo code

XOR (Exclusive OR) for branchless coding

The following example shows the array reversing using the  XOR operator . No need to take any additional variable to reverse the array.   int main(int argc, _TCHAR* argv[]) { char str[] = "I AM STUDENT"; int length = strlen(str); for(int i = 0; i < ((length/2)); i++) { str[i] ^= str[length - (1+i)]; str[length - (1+i)] ^= str[i]; str[i] ^= str[length - (1+i)]; } cout << str << endl; return 0; } The above example is one of the uses of XOR but XOR comes in handy when we can do branchless coding  methods like butterfly switch etc. Sometimes this is very effective in speeding up the execution.  Let's see one of the uses of XOR in branchless coding. I am taking a simple example of Y = | X |.  Yes, I am generating abs of a supplied number. So, my function signature/definition in C++ looks like below: int absoluteBranch( int x) {     if (x < 0 ) {         return -x;     }     else {         retur

Power of Two

  I n this post will be discussing how to calculate if a number is a power of two or not. As an example, 8 is a power of two but the number 10 is not. There are many ways we can solve this. First , we will take an approach which is simple and iterative. In this case, we will calculate the power of two one by one and check with the supplied number. The below code illustrates it. bool isPowerofTwo(unsigned num) { auto y = 1; while (0 != y) { if (num == y) return true; if (num < y) return false; y <<= 1; } return false; } Second , assuming, the number is a 32-bit number, this is also an iterative solution. In this scenario, iterating all bits and counting the set bits. Any number which is a power of 2 will have only one bit set and the rest will be zeros. As an example, 8 in binary representation is 1000. Using this observation, we can implement an iterative solution. bool isPowerofTwo(unsigned num) { auto one_count = 0; for (auto index = 0; index < 32;