Upload
claire-marsh
View
213
Download
0
Embed Size (px)
Citation preview
Win32 ProgrammingLesson 22: DLL Magic Part DeuxAll your base are belong to us…
Where are we? We’ve looked at injection techniques in
general But now it’s time to get specific
Remind Me… What’s the trick we’re trying to pull off?
Injecting DLLs using a Remote Thread Remember, we’re trying to get a DLL into
another process’ address space One way to do this is to create a thread in a
remote process And Windows provides an easy way to do
this…
So… HANDLE CreateRemoteThread(
HANDLE hProcess, PSECURITY_ATTRIBUTES psa, DWORD dwStackSize, PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam, DWORD fdwCreate, PDWORD pdwThreadId);
Look familiar…?
Problems? Troy, does this solve all our problems? Casey? Chris? Invisible Dan? …
Bingo! This only works if we have code in the
remote thread that we want to execute to load our Trojan DLL…
Hmmm… can we fix it? How do you load a DLL during program
execution?
Right: LoadLibrary But LoadLibrary doesn’t exist (someone tell me why?) So basically, we want to execute a line of code which looks
like this: HANDLE hThread = CreateRemoteThread(
hProcessRemote, NULL, 0, LoadLibraryA, "C:\\MyLib.dll", 0,
NULL);
BUT this is still wrong… why?
Right: Real address The address of LoadLibraryA as a function
won’t be the same because of relocation But the *real* address of LoadLibraryA in
KERNEL32.DLL will be the same (provided it loads in the same location)
So, how do we get that?
Right: GetProcAddress… GetProcAddress(GetModuleHandle(TEXT("
Kernel32")), "LoadLibraryA"); Easy eh? Predicated on the identical loading of
Kernel32… but that’s quite common But it still doesn’t work right… there’s still
one string attached to this idea…
Right: The STRING “c:\\mylib.dll” The String exists in Process A’s address space,
but we need it to exist in Process B’s Hmmm How can we fix that?
Right: VirtualAllocEx Bingo! PVOID VirtualAllocEx(
HANDLE hProcess, PVOID pvAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
But we’re still not done Processes boundaries stop one process writing
to another… So we need a function which can read and
write Process memory And Windows gives us such a function…
Memory… BOOL ReadProcessMemory(
HANDLE hProcess, PVOID pvAddressRemote, PVOID pvBufferLocal, DWORD dwSize, PDWORD pdwNumBytesRead); BOOL WriteProcessMemory( HANDLE hProcess, PVOID pvAddressRemote, PVOID pvBufferLocal, DWORD dwSize, PDWORD pdwNumBytesWritten);
7 Step Process Use the VirtualAllocEx function to allocate memory
in the remote process’s address space. Use the WriteProcessMemory function to copy the
DLL's pathname to the memory allocated in step 1. Use the GetProcAddress function to get the real
address (inside Kernel32.dll) of the LoadLibraryA or LoadLibraryW function.
Use the CreateRemoteThread function to create a thread in the remote process that calls the proper LoadLibrary function, passing it the address of the memory allocated in step 1.
Continued… Use the VirtualFreeEx function to free the
memory allocated in step 1. Use the GetProcAddress function to get the
real address (inside Kernel32.dll) of the FreeLibrary function.
Use the CreateRemoteThread function to create a thread in the remote process that calls LoadLibrary function, passing the remote DLL's HINSTANCE.
Lastly… hProcess = OpenProcess(
PROCESS_CREATE_THREAD | // For CreateRemoteThread PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx PROCESS_VM_WRITE, // For WriteProcessMemory FALSE, dwProcessId);
Next: The Trojan DLL Replace some DLL you want… But you have to export all the same functions
Injecting a DLL via a Debugger Tricky and processor-specific But can work well, as Debuggers have special
privileges
Injecting Via CreateProcess Have your process spawn the child process suspended. Retrieve the primary thread's starting memory address from
the .exe module's file header. Save the machine instructions at this memory address. Force some hand-coded machine instructions at this address.
The instructions should call LoadLibrary to load a DLL. Resume the child process’s primary thread so that this code
executes. Restore the original instructions back into the starting
address. Let the process continue execution from the starting address
as if nothing had happened