Search code examples
windowsfileassemblyx86fasm

How do I find a file inside the current directory in x86 Windows Assembly


I am having a few issues with my code. I am trying to read both of the PE headers inside of an executable file. However, when I invoke ReadFile, it sets [hFile] to 5A, which is not the handle I put inside from CreateFile. From what I understand, ReadFile should not change this in any way. However, when I store the handle inside another variable and use it to set the file pointer, the next ReadFile instruction still gives me the MZ header instead of the PE header, which is located at offset 3C from the MZ header.

Summary: ReadFile changes my handle, SetFilePointer sees the change as an invalid handle, SetFilePointer does not change the pointer for the next read when given a valid handle.

format PE console 4.0
entry start

include 'win32ax.inc'

section '.data' data readable writeable

thisFile db "thisfile.exe",0
read db ?
hFile dd ?

section '.text' data readable executable

start:
;========Open File================
invoke CreateFile,thisFile,GENERIC_READ,FILE_SHARE_READ,0,\
                  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov [hFile],eax

;========MZ HEADER================
invoke ReadFile,[hFile],read,2,NULL,0 ; = MZ, , however, changes [hFile]
                                      ;to 5A? Why does it change it?
invoke printf,read

;========PE HEADER================
invoke SetFilePointer,[hFile],03Ch,0,FILE_CURRENT ; = 0, beginning of file ATM
                                                  ;Should make next read = PE
invoke ReadFile,[hFile],read,3,NULL,0 ; = PE

invoke printf,read

invoke getchar
invoke ExitProcess,0 

Solution

  • Here you're reading 2 bytes into read:

    invoke ReadFile,[hFile],read,2,NULL,0
    

    But look at how you've declared read:

    read db ?
    

    That's a single byte. So the second byte you're reading with ReadFile will get written into whatever follows read in memory, which happens to be hFile. Thus, you're overwriting the least significant byte of hFile.

    There's another place in your code where you're trying to read 3 bytes into read, but I guess that will fail since by then your hFile will be invalid.

    What you need to do is to reserve more space for read, as much as you ever plan on storing in it. Let's say that you want 4 bytes, you could get that with:

    read db 4 dup(0)
    

    or

    read: times 4 db 0
    

    or

    read rb 4
    

    or

    read dd ?
    

    Since you're passing read to printf as a string, keep in mind that strings are expected to be NUL-terminated.