Article: x86 MASM32 Input Processing + Register Concatenation


Download source: Click here



09 December 2018

This is mainly a short article on using ReadConsole, dereferencing values from an address, and parsing data from user input.



The LOCAL directive can only be used right after a PROC and it creates a stack-based variable within the procedure's scope. Essentially we can define "fields" within a local scope instead of the global scope of .data. During the ReadConsole INVOKE, the ADDR (similar to OFFSET) provides the LPVOID back to the buffer. What happens next gets a little tricky.


Line 67: Unlike "buffer" which is local, charsWritten is global (.data) and I'm verifying that the user only submitted one character.
Line 70: lea edx, buffer
- This loads the effective address into edx.
Line 71: Zeroing out eax, im preparing to transfer the dereferenced value from edx into it.
Line 72: mov al, [edx] - edx is moved into the lower 8 bits of eax, which means that only the first byte moves and the rest is truncated. The brackets around edx means we want the value at edx.


For a better visualization of using the 32-bit registers, here's a screenshot from Skull Security:



What happens at Line 72 (and by the time we reach it) is that edx contains the address to buffer, and when we go to the address of the buffer in memory there are 3 bytes stored. These bytes are 35 OD 0A. Recalling Line 67 where "one character" was submitted, however I was comparing it against "3" - this is because "/r/n" is also submitted into the buffer when the user presses the Enter Key. Converting Hex<35 0D 0A> to ASCII: "5CRLF" or "5 (carriage return) (new line)>". Below shows both the edx register and the address in memory.



To solve this I decided to only move 8 bits of the dereference of edx (buffer). If you move a 32-bit value into an 8-bit register, the first 8-bits of the value are preserved and the remaining are trunacated. Similarly if you move a 32-bit value into a 16-bit register, the first 2 bytes are preserved and the other two are truncated. Below shows a picture of moving the dereferenced edx into various register derivatives of eax.



Finally, my solution of moving edx into the lower 8-bit register al to only preserve 35h (the user input of "5"):



If you would like, download the assembly file above which contains all the code you need to run this example. It's a small number guessing game that runs until you correctly guess the random number. A few of the includelibs weren't included because they are automatically linked on VS2017 (such as kernel32, user32, etc).