DLL Injection
DLL Injection
Outline
• DLL basics
• DLL injection
• Example DLL
DLL basics
• Conserve memory
• The pages are shared by all of the applications
• DLL owns nothing
• Local variables
• Use the thread’s stack
• Global and static data variables
• Create instances of them when process maps a DLL image file
into its address space
DLL injection methods
• Registry
• Windows Hooks
• Remote Threads
• Trojan DLL
• Else…
DLL injection (1/8)
• Goal
• Break through process boundary walls to access another
process’ address space
• Problem
• Separate address spaces
• Solution
• Get the code into another process’ address space
DLL injection (2/8)
• Idea
• Create a remote thread in another process
• CreateRemoteThread
• Load DLL in that thread
• LoadLibraryW
HANDLE CreateRemoteThread(
HANDLE hProcess,
PSECURITY_ATTRIBUTES psa,
DWORD dwStackSize,
PTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam,
DWORD fdwCreate,
PDWORD pdwThreadId);
DLL injection (3/8)
• Use LoadLibraryW instead of thread function
• CreateRemoteThread needs a thread function
• DWORD WINAPI ThreadFunc(PVOID pvParam);
• LoadLibraryW function
• HMODULE WINAPI LoadLibraryW(LPCWSTR lpLibFileName);
• Single parameter
• Return a value
• WINAPI calling convention
• HANDLE hThread =
CreateRemoteThread(hProcessRemote, NULL, 0,
LoadLibraryW, L"C:\\MyLib.dll", 0, NULL);
DLL injection (4/8)
• HANDLE hThread =
CreateRemoteThread(hProcessRemote, NULL, 0,
LoadLibraryW, L"C:\\MyLib.dll", 0, NULL);
• The L before the string means this is an Unicode string,
which LoadLibraryW needs
• 2 problems
• LoadLibraryW actually calls to module’s import section
and then jumps to the actual function
• The string L”C:\\MyLib.dll” is in the calling process’
address space
DLL injection (5/8)
• LoadLibraryW actually calls to module’s import
section and then jumps to the actual function
• The import section may be different in different
processes
• GetProcAddress(GetModuleHandle(TEXT("Kernel32")),
"LoadLibraryW");
DLL injection (6/8)
• Assumptions
• The address of LoadLibraryW may change between two
reboots if Address Space Layout Randomization (ASLR) is
enabled
• A normal executable image file may mapped into different
addresses at each “restart”. However, LoadLibraryW is in
Kernel32.dll and it will be loaded at each “reboot”.
• LoadLibraryW is mapped to the same memory location
in every process
DLL injection (7/8)
• The string L”C:\\MyLib.dll” is in the calling process’
address space
• VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT,
PAGE_READWRITE);
• WriteProcessMemory(hProcess, pszLibFileRemote,
(PVOID) pszLibFile, cb, NULL);
• hProcess: handle of remote process
• cb: the number of bytes needed for the DLL's pathname
• pszLibFileRemote: the address of the destination
• pszLibFile: the address of the source
DLL injection (8/8)
• Walkthrough
• OpenProcess
• VirtualAllocEx
• WriteProcessMemory
• GetProcAddress
• CreateRemoteThreadEx
Example DLL (1/4)
• Target executable image file: Ragnarok Online
• Print the message when DLL had been loaded
• DllMain function called with DLL_PROCESS_ATTACH
when DLL loaded
• DisplayMessage("Loading test plugin.", 0x64FFFF);
• Print the current experience after killing a monster
• Need to patch the game
Example DLL (2/4)
• At address 0x0073BAD8
• A3 2C 51 9C 00 mov dword, ptr DS:[9C512C], eax
• The code that save the experience after killing a
monster
• Total bytes need to >= 5 because of the call opcode
• Idea
• Change 0x0073BAD8 to a call to shellcode in DLL
• Shellcode simply do the same thing at 0x0073BAD8 and
call our desired function
Example DLL (3/4)
• Summary
• The process reaches the patch
• The patch calls the wrapper
• The over-written instruction(s) run in the wrapper
• The wrapper saves the registers
• The wrapper calls the hack function
• The wrapper restores the variables
• The wrapper returns back to the ordinary code
• Program continues executing normally
Example DLL (4/4)
• Assumptions
• The patch will fail when the target executable image file
enables ASLR.