Uninformed: Informative Information for the Uninformed

Vol 1» 2005.May


Understanding Assemblies

The goal for this chapter is to simply locate where the playing grid resides. With that in mind, revisit the previously identified ShowBombs function. Logically, it wouldn't be that long of a jump to assume this function will lead to the playing grid. Set a breakpoint on this function by issuing the following command:

bp WinMine!ShowBombs
WinDBG provides no positive feedback that the breakpoint was successfully set. However, WinDBG will alert the user if it is unable to resolve the name or address being requested. To obtain a list of set breakpoints, issue the following command:
bl
The Command window should reflect:
0 e 01002f80     0001 (0001)  0:*** WinMine!ShowBombs
The leading digit represents the breakpoint number, which can be used as a reference for other breakpoint aware commands. The next field depicts the status of the breakpoint, as either (e)nabled or (d)isabled. This is followed by the virtual address of the breakpoint. The next four digits speak to the number of passes remaining until this breakpoint will activate. Adjacent, in parentheses, is the initial pass count. Next, is the process number, not to be confused with process ID, a colon acting as a separator between what would be a thread ID, if this was a thread specific breakpoint. It's not, hence three asterisks. Lastly, at least in the above example, is the module name and symbol/function where WinDBG will break at.

Set WinMine in motion by hitting F5 (Go) or type 'g' in the Command window. The reader should notice that WinDBG informs the user the "Debugee is running". Switch to the WinMine window and click on the upper left box, which should reveal the number two. Next, click the box to the right and it will be very apparent that a bomb has been selected, as the reader will no longer be able to interact with WinMine. This is due to the fact that WinDBG recognized that a breakpoint condition has been met and is waiting for instruction. When back in the WinDBG, the Command window has highlighted the following instruction:

01002f80 a138530001       mov     eax,[WinMine!yBoxMac (01005338)]
This is the first instruction within the ShowBombs function, which corresponds to the address previously identified when current breakpoints were listed. Before attempting to understand this instruction, let's first cover a few functional and syntactical aspects of IA-32 assembly. It is recommended that the reader make available the aforementioned supplemental material mentioned in Chapter 2.

Each line in the disassembly describes an instruction. Use the above instruction to identify the major components of an instruction without getting distracted by how this instruction relates to the ShowBombs function. If distilled, the previous instruction can be abstracted and represented as:

<address> <opcodes> <mnemonic> <operand1>, <operand2>
The <address> represents the virtual location of the <opcodes>. Opcodes are literal instructions that the processor interprets to perform work. Everything to the right of <opcodes> represents a translation of these opcodes into assembly language. The <mnemonic> can be thought of as a verb or function that treats each operand as an argument. It's of importance to note that in Intel5.2 style assembly, these operations move from right to left. That is, when performing arithmetic or moving data around, the result typically finds its destination at <operand1>.

Looking back at the original instruction one can determine that the 32-bit value, or word, located at 0x01005338 is being copied into the eax register. Brackets ([]) are used to deference the address contained in an operand, much like an asterisk (*) does in C. Let's focus on the opcodes for a moment. If the reader looks up the opcode for a mov instruction into the eax register, the value 0xa1 will be found.

Opcode Instruction      Description
...
A0     MOV AL,moffs8*   Move byte at (seg:offset) to AL.
A1     MOV AX,moffs16*  Move word at (seg:offset) to AX.
A1     MOV EAX,moffs32* Move doubleword at (seg:offset) to EAX.
...
It is not by coincidence that the first byte of <opcodes> is also 0xa1. This leaves <operand2> for the remainder, which brings us to the short discussion in endianness.