Informative Information for the Uninformed | ||||||||||||||
|
||||||||||||||
Next: Interpreting the Playing Grid
Up: Locating the WinMine Playing
Previous: Conditions
  Contents
Stacks and FramesThe 'u' command instructs WinDBG to (u)nassemble, or translate from opcodes to mnemonics with operands, the information found at the specified address. 01002fd8 e851f7ffff call WinMine!DisplayGrid (0100272e) 01002fdd c20400 ret 0x4From this, one can see that the DisplayGrid function is called and the ShowBombs function subsequently returns to the caller. But what is call actually doing? Can one tell where ret is really returning to and what does the 0x4 represent? The IA-32 Command Reference states that call "Saves procedure linking information on the stack and branches to the procedure (called procedure) specified with the destination (target) operand. The target operand specifies the address of the first instruction in the called procedure." The reader may notice that the command reference has variable behaviors for the call instruction depending on the type of call being made. To further identify what call is doing, the reader can examine the opcodes, as previously discussed, and find 0xe8. 0xe8, represents a near call. "When executing a near call, the processor pushes the value of the EIP register (which contains the offset of the instruction following the CALL instruction) onto the stack (for use later as a return-instruction pointer)." This is the first step in building a frame. Each time a function call is made, another frame is created so that the called function can access arguments, create local variables, and provide a mechanism to return to calling function. The composition of the frame is dependant on the function calling convention. For more information on calling conventions, the reader is encouraged to read the relevant documents in the reference section[1]. To view the current call stack, or series of linked frames, use the 'k' command. ChildEBP RetAddr 0006fd34 010034b0 winmine!ShowBombs 0006fd40 010035b0 winmine!GameOver+0x34 0006fd58 010038b6 winmine!StepSquare+0x9e 0006fd84 77d43b1f winmine!DoButton1Up+0xd5 0006fdb8 77d43a50 USER32!UserCallWinProcCheckWow+0x150 0006fde4 77d43b1f USER32!InternalCallWinProc+0x1b 0006fe4c 77d43d79 USER32!UserCallWinProcCheckWow+0x150 0006feac 77d43ddf USER32!DispatchMessageWorker+0x306 0006feb8 010023a4 USER32!DispatchMessageW+0xb 0006ff1c 01003f95 winmine!WinMain+0x1b4 0006ffc0 77e814c7 winmine!WinMainCRTStartup+0x174 0006fff0 00000000 kernel32!BaseProcessStart+0x23With this, the reader can track the application flow in reverse order. The reader may find it easier to navigate the call stack by pressing Alt-6, which will bring up the Call Stack window. Here, the call stack information is digested a bit more and displayed in a tabular manner. With the call stack information, one can answer the second question regarding where ret is really headed. For example, once ShowBombs returns, eip will be set to 0x010034b0. Finally, the significance of 0x4 can be learned by reading the ret instruction definition, which states that this value represents "...the number of stack bytes to be released after the return address is popped; the default is none. This operand can be used to release parameters from the stack that were passed to the called procedure and are no longer needed." More specifically, when the processor encounters a ret instruction it pops the address stored at the top of the stack, where esp is pointing, and places that value in the eip register. If the ret instruction has an operand, that operand represents how many additional bytes should be removed from the top of the stack. With this information, and knowing that 32-bit addresses are four bytes long, one can determine that the ShowBombs function accepts one argument5.3. Returning to the task at hand, the following represents the current picture of what the ShowBombs function is doing: if(iGridHeight < 1) { DisplayGrid(); return; } else { //do stuff }Continuing on, one can see the following in the Disassembly window, which will take the place of "//do stuff". 01002f8a 53 push ebx 01002f8b 56 push esi 01002f8c 8b3534530001 mov esi,[winmine!xBoxMac (01005334)] 01002f92 57 push edi 01002f93 bf60530001 mov edi,0x1005360Begin by stepping WinDBG twice (by pressing 'p' twice) so that eip is set to 0x1002f8a. The next two instructions are storing the ebx and esi registers on the stack. This can be demonstrated by first viewing the memory referenced by esp, identifying the value stored in ebx, pressing 'p' to execute push ebx, and revisiting the value stored at esp. The reader will find the value of ebx stored at esp. 0:000> dd esp 0006fd38 010034b0 0000000a 00000002 010035b0 0006fd48 00000000 00000000 00000200 0006fdb8 ... 0:000> r ebx ebx=00000001 0:000> p eax=00000018 ebx=00000001 ecx=0006fd14 edx=7ffe0304 esi=00000000 edi=00000000 eip=01002f8b esp=0006fd34 ebp=0006fdb8 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 winmine!ShowBombs+0xb: 01002f8b 56 push esi 0:000> dd esp 0006fd34 00000001 010034b0 0000000a 00000002 0006fd44 010035b0 00000000 00000000 00000200Notice, that esp has been decremented by four (the size of a 32-bit pointer) and the value of ebx is at that location. The behavior can be observed again by stepping to execute push esi. Again, the reader will notice the value of esp decrement by four and the value within esi is at this new location. This is the basic principal of how the stack works. The stack pointer is decremented and the value being push'd onto the stack is placed at the new address esp is pointing at. It is also important to note that the stack grows down. That is, as values are placed on the stack, the stack pointer decreases to make room. Which begs the question, what are the upper and lower limits of the stack? It can't keep on growing for ever, can it? The short answer is no, the stack has a floor and ceiling. Which can be identified by examining the Thread Environment Block or TEB. Luckily, WinDBG comes with an extension command to accomplish this, !teb. 0:000> !teb TEB at 7ffde000 ExceptionList: 0006fe3c StackBase: 00070000 StackLimit: 0006c000 SubSystemTib: 00000000 FiberData: 00001e00 ArbitraryUserPointer: 00000000 Self: 7ffde000 EnvironmentPointer: 00000000 ClientId: 00000ff4 . 00000ff8 RpcHandle: 00000000 Tls Storage: 00000000 PEB Address: 7ffdf000 LastErrorValue: 183 LastStatusValue: c0000008 Count Owned Locks: 0 HardErrorMode: 0Note the values for StackBase and StackLimit, which refer to the stack's ceiling and floor, respectively. For more information on the TEB, the reader is encouraged to read the related documents in the reference section [11]. That was an exciting tangent. Circling back, the reader is found at the following instruction: 01002f8c 8b3534530001 mov esi,[winmine!xBoxMac (01005334)]This, if convention holds true, will store the width of the playing grid in esi. By single stepping ('p'), the reader will notice the esi register is denoted in red within the Registers window and now contains the value 0x1e. 0x1e is 30 in decimal, which, if the reader recalls, is the width of the current playing grid. Hence, one can make the educated determination that xBoxMac represents the width of the playing grid. The next instruction, push edi, is saving the value in the edi register on the stack in preparation for the subsequent instruction; mov edi,0x1005360. This is were things get a bit more interesting, as this instruction begs the question; what is the significance of 0x1005360? Considering the previous instructions gathered prerequisite information about the playing grid, perhaps this address is indeed the playing grid itself! To determine this, the reader should examine some aspects of this memory address. The aforementioned !vprot extension command will provide information regarding the type of access permitted to this memory address, which is PAGE_READWRITE. This information isn't overly valuable but is favorable in the sense that this address does not reside within an executable portion of the application space and is therefore likely a variable allocation. If this area is truly the playing grid one should be able to identify a pattern while viewing the memory. To accomplish this, type 0x1005360 in to the Memory window. The following should appear: 01005360 10 42 cc 8f 8f 8f 8f 0f 8f 8f 8f 8f 0f 0f 8f 0f .B.............. 01005370 0f 8f 8f 8f 8f 8f 8f 0f 0f 0f 8f 0f 0f 8f 8f 10 ................ 01005380 10 8f 0f 0f 8f 8f 0f 0f 0f 0f 0f 8f 0f 0f 8f 8f ................ 01005390 0f 8f 0f 0f 0f 8f 8f 8f 0f 0f 8f 8f 8f 8f 8f 10 ................ 010053a0 10 0f 0f 8f 0f 0f 8f 0f 0f 0f 0f 0f 8f 0f 0f 0f ................ 010053b0 8f 0f 0f 0f 8f 8f 0f 0f 8f 0f 8f 0f 8f 8f 0f 10 ................ 010053c0 10 0f 0f 8f 0f 0f 8f 0f 0f 0f 8f 0f 0f 8f 0f 0f ................ 010053d0 8f 0f 0f 8f 0f 0f 0f 8f 0f 0f 0f 8f 0f 0f 0f 10 ................ 010053e0 10 0f 0f 8f 0f 8f 8f 0f 0f 8f 8f 0f 0f 8f 0f 0f ................ 010053f0 0f 0f 0f 0f 8f 0f 0f 0f 0f 0f 0f 0f 8f 0f 0f 10 ................ 01005400 10 8f 0f 0f 0f 0f 0f 0f 8f 8f 0f 8f 8f 0f 0f 8f ................ 01005410 0f 8f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 8f 8f 0f 10 ................ 01005420 10 8f 0f 8f 8f 0f 8f 8f 0f 0f 0f 8f 8f 0f 8f 0f ................
Next: Interpreting the Playing Grid
Up: Locating the WinMine Playing
Previous: Conditions
  Contents
|