One possibility: Insert a "code cave" into your hosting process, and let it load the DLL. For how to do it in a "generic" way in x64, look here. An important step of this is how to get the address of the kernel32.dll
:
get_OS_DllAddresses:
mov rax, gs:[60h] ; PEB
mov rax, [rax + 18h] ; PEB::Ldr
mov rax, [rax + 20h] ; PEB::Ldr.InMemoryOrderModuleList
mov rax, [rax] ; 1st entry
mov r15, [rax + 20h] ; ntdll.dll base address!
mov rax, [rax] ; 3nd entry
mov rax, [rax + 20h] ; kernel32.dll base address!
ret
PEB → PEB::Ldr → walk the InMemoryOrderModuleList
linked list (LDR_DATA_TABLE_ENTRY).
After running this snippet, you have in rax
the address of kernel32.dll
(correctly also in the case of ASLR), and in r15
the address of ntdll.dll
.
If you study the example given in the above link, you learn how to extract the necessary LoadLibrary
calls (for your DLL to be checked), and the GetProcAddress
calls, in case your DLL exports API calls.
A simple way to get the "shellcode" bytes is to make a little Assembler project e.g. in VisualStudio and let it create the binary code for you.