In this part, we will look at how to create load-time and run-time dlls using MinGW assembler. Writing code for dll is almost same writing any assembly code except for the following
- Define the exported functions with the suffix ‘_’
- List the exported functions section ‘.drectve’ without ‘_’
# file - dll.asm
# This file becomes a dll after assembling and linking and can be
# loaded during load-time or run-time
.intel_syntax noprefix
.include "macroA.inc"
.include "user32.inc"
.include "kernel32.inc"
.section .data
msg_box_title:
.ascii "Message Box Title\0"
msg:
.ascii "Hello DLL\0"
.section .text
.global dllMain
dllMain:
# function prologue
push ebp
mov ebp, esp
mov ebx, dword ptr [ebp+12]
cmp ebx, DLL_PROCESS_DETACH
jz process_detach
cmp ebx, DLL_PROCESS_ATTACH
jz process_attach
cmp ebx, DLL_THREAD_ATTACH
jz thread_attach
cmp ebx, DLL_THREAD_DETACH
jz thread_detach
process_attach:
jmp exit_dll
thread_attach:
jmp exit_dll
thread_detach:
jmp exit_dll
process_detach:
jmp exit_dll
# return boolean value
mov eax, TRUE
# function epilogue
exit_dll:
mov esp, ebp
pop ebp
ret
.global _hello
_hello:
# function prologue
push ebp
mov ebp, esp
invoke MessageBox, 0, "offset msg", "offset msg_box_title", 0
# function epilogue
mov esp, ebp
pop ebp
ret
.section .drectve
.ascii " -export:hello"
Load-time DLL:
dll will be loaded the moment you load an executable into the memory. As you can see, when calling a function using load-time dll, you have to use the function name as defined in the dll, NOT as exported
# file - hello.asm
# calls a function in dll by loading the dll during load-time
.intel_syntax noprefix
.include "macroA.inc"
.include "kernel32.inc"
.section .data
dll_lib:
.ascii "message.dll\0"
dll_func:
.ascii "hello\0"
.section .text
.globl _start
_start:
# calls hello function in the dll
call _hello
invoke ExitProcess, 0
.end
An example should clarify this.
Save the above two files in D:\examples and run the following commands. Make sure you also download include files from this website and place in D:\example\includes
as -o dll.o dll.asm -ID:\examples\includes ld --out-implib libmessage.a -shared -s -o message.dll dll.o -LD:\MinGW\lib -luser32 -lkernel32 as -o hello.o hello.asm -ID:\examples\includes ld --subsystem windows -o hello.exe hello.o -s -LD:\MinGW\lib -luser32 -lkernel32 -LD:\examples -lmessage
Run-time DLL:
dll is being loaded into memory programmatically, not when an executable is loaded into memory. To find the address of the function, pass the name of the function as exported in dll, NOT as defined.
# file - hello.asm
# calls a function in dll by loading the dll at run-time
.intel_syntax
.include "macroA.inc"
.include "kernel32.inc"
.section .data
dll_lib:
.ascii "message.dll\0"
dll_func:
.ascii "hello\0"
.section .text
.globl _start
_start:
# load message.dll library
invoke LoadLibraryA, "offset dll_lib"
# get the address of the hello exported function in message.dll
invoke GetProcAddress, eax, "offset dll_func"
# call hello function
invoke eax
invoke ExitProcess, 0
.end
Run the following commands to see run-time loading in action.
as -o dll.o dll.asm -ID:\examples\includes ld -s -shared -o message.dll dll.o -LD:\MinGW\lib -luser32 -lkernel32 as -o hello.o hello.asm -ID:\examples\includes ld -s --subsystem windows -o hello.exe hello.o -LD:\MinGW\lib -luser32 -lkernel32
In the next part, we will see an example of shared memory in a dll.