2

I took an example code that creates a simple DLL from FASM examples directory and am adjusting it to my needs. However, when I do some (innocent from my POV) changes, the generated binary file gets corrupted - running an exe that uses this library produces error code 0xC000007B aka INVALID_IMAGE_FORMAT.

DLL code:

; DLL creation example

format PE GUI 4.0 DLL
entry DllEntryPoint

include 'win32a.inc'

section '.text' code readable executable

proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
        mov     eax,TRUE
        ret
endp

proc ShowErrorMessage hWnd,dwError
  local lpBuffer:DWORD
        lea     eax,[lpBuffer]
        invoke  FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER+FORMAT_MESSAGE_FROM_SYSTEM,0,[dwError],LANG_NEUTRAL,eax,0,0
        invoke  MessageBox,[hWnd],[lpBuffer],NULL,MB_ICONERROR+MB_OK
        ret
endp

proc ShowLastError hWnd
        ret
endp

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GetLastError,'GetLastError',\
         SetLastError,'SetLastError',\
         FormatMessage,'FormatMessageA',\
         LocalFree,'LocalFree'

  import user,\
         MessageBox,'MessageBoxA'

section '.edata' export data readable

  export 'DLL.DLL',ShowErrorMessage,'ShowErrorMessage',ShowLastError,'ShowLastError'

section '.reloc' fixups data readable discardable

Executable code:

format PE GUI 4.0
entry start

include 'win32a.inc'

section '.text' code readable executable

  start:
jmp ShowLastError

section '.idata' import data readable writeable

  library mydll,'DLL.DLL'

  import mydll,\
         ShowLastError,'ShowLastError'

When I change, say,

export 'DLL.DLL',ShowErrorMessage,'ShowErrorMessage',ShowLastError,'ShowLastError'

line to

export 'DLL.DLL',ShowLastError,'ShowLastError'

the code breaks. The same happens if I change ShowErrorMessage body to just ret.

I'm completely confused by this. Is this a FASM bug, or I'm doing something wrong?

arrowd
  • 33,231
  • 8
  • 79
  • 110
  • 1
    This code doesn't deal with calling convention at all (particularly `stdcall`, which `DllEntryPoint` requires). And it is not safe to `JMP` into a DLL function (`ShowLastError`), you need to `INVOKE` it instead, like you do the other imported DLL functions you use (`FormatMessage` and `MessageBox`). And especially because `ShowLastError` takes an input parameter that you are not passing to it – Remy Lebeau Oct 18 '17 at 15:10
  • @RemyLebeau the DLL doesn't even get loaded, so this is orthogonal to my problem. – arrowd Oct 18 '17 at 15:30
  • 1
    it is still worth fixing. In any case, the usual culprit for `INVALID_IMAGE_FORMAT` is a 32bit process loading a 64bit DLL or vice versa. Is that the case here? – Remy Lebeau Oct 18 '17 at 15:31

1 Answers1

3

I wasn't able to find an explanation for this, but at least I found a workaround. Changing following line

section '.reloc' fixups data readable discardable

to just

data fixups
end data

fixes the issue.

arrowd
  • 33,231
  • 8
  • 79
  • 110