ReflectiveDLLInjection
ReflectiveDLLInjection copied to clipboard
Unhook kernel32!BaseThreadInitThunk
Firefox on Windows hooks kernel32!BaseThreadInitThunk
which prevents the remote thread to start in the target, see https://dxr.mozilla.org/mozilla-central/source/mozglue/build/WindowsDllBlocklist.cpp#821:
0:032> u kernel32!BaseThreadInitThunk
KERNEL32!BaseThreadInitThunk:
00007ff8`550d81e0 49bb0064453af87f0000 mov r11,offset mozglue!patched_BaseThreadInitThunk (00007ff8`3a456400)
00007ff8`550d81ea 41ffe3 jmp r11
00007ff8`550d81ed c2ff15 ret 15FFh
This PR restores the function prologue if it is detected as indeed hooked - happy to fix / adapt anything you'd like.
Also took the extra liberty of fixing the indentation in Rva2Offset
:).
Cheers
My understanding is that kernel32 (as well as other dlls) are loaded at the same base across processes to maximize memory sharing (at least on a default install).
Cheers
Le mer. 14 oct. 2020 à 12:14, Frederico F. de Oliveira < [email protected]> a écrit :
@FreddieOliveira commented on this pull request.
How can you guarantee that the addresses returned by GetProcAddress and GetModuleHandle are the same for both the current process and the target process?
You saved the address of BaseThreadInitThunk for the current process in line 219 and wrote to this same address into the target process in line 235, but you can't assume for sure that the BaseThreadInitThunk function is located at the same address in both processes.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stephenfewer/ReflectiveDLLInjection/pull/17#pullrequestreview-508651627, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALIORLTKJFM5DGIARRVXWLSKX2BFANCNFSM4G5HYANA .
You're almost right, but there's a catch: when same DLLs are imported by different process they usually share the same physical memory address for those DLLs. But, the processes have different virtual addresses for them.
For example, let's suppose that our rootkit.exe and firefox.exe uses the kernel32.dll
. To use memory efficiently, Windows will load kernel32.dll
into physical address 0x003000 and share this addr with all processes that uses this DLL instead of loading it to RAM each time. When starting rootkit.exe process, it will map kernel32.dll
into the virtual address 0x001000 that in reality maps to physical address 0x003000. When starting Firefox.exe process, the kernel32.dll
will be mapped at 0x008000 virtual address that also maps to physical address 0x003000. (All these addresses are fictitious) But it's important to note that despite sharing the same physical address for the DLLs, the process have different virtual addresses. When using GetProcAddress
or GetModuleHandle
or any other function that deals with the process memory, they are usually returning virtual addresses which is unique for each process. So, you can't assume that a returned address from these functions is the same for other processes.
A good answer on how to get DLL functions address in a remote process is given here: https://stackoverflow.com/questions/26395243/getmodulehandle-for-a-dll-in-another-process
Cheers
I am familiar with how copy-on-write and how virtual memory works. Boot a
Windows 10 machine, open ProcessHacker2 on 5 different processes and notice
kernel32
having the same VA in all of them.
It's been a well known behavior for years and I'm sure it's documented somewhere.
Cheers
Le mer. 14 oct. 2020 à 13:20, Frederico F. de Oliveira < [email protected]> a écrit :
You're almost right, but there's a catch: when same DLLs are imported by different process they usually share the same physical memory address for those DLLs. But, the processes have different virtual addresses for these DLL.
For example, let's suppose that our rootkit.exe and firefox.exe uses the kernel32.dll. To use memory efficiently, Windows will load kernel32.dll into physical address 0x003000 and share this addr with all processes that uses this DLL instead of loading it to RAM each time. When starting rootkit.exe process, it will map kernel32.dll into the virtual address 0x001000 that in reality maps to physical address 0x003000. When starting Firefox.exe process, the kernel32.dll will be mapped at 0x008000 virtual address that also maps to physical address 0x003000. (All these addresses are fictitious) But it's important to note that despite sharing the same physical address for the DLLs, the process have different virtual addresses. When using GetProcAddress or GetModuleHandle or any other function that deals with the process memory, they are returning virtual addresses which is unique for each process.
A good answer on how to get DLL functions address in a remote process is given here: https://stackoverflow.com/questions/26395243/getmodulehandle-for-a-dll-in-another-process
Cheers
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stephenfewer/ReflectiveDLLInjection/pull/17#issuecomment-708638258, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALIORKPSSZMLEDSDEMB67TSKYBZFANCNFSM4G5HYANA .
Hmm, that's an interesting behavior, looks like the DLLs are not ASLR and GetProcAddress
returns the real physical address, which means the addresses returned for the DLL exported function is the same for every process.
I'm just not sure if this will be always the case. I'm also lacking documentation from my part.
Though not finding official documentation, after some research I found out:
- Windows will try to use the same virtual addresses for processes to map common DLLs, as long as possible. That means if both processes rootkit.exe and Firefox.exe uses
kernel32.dll
, they both would try to map thekernel32.dll
in the so called preferred address. If the preferred address is not available, then the DLL will be relocated to another virtual address. - Some DLLs are ASLR compatible. What is randomized is the preferred address and the randomization happens once per boot. So, rootkit.exe and firefox.exe would map
kernel32.dll
in their virtual address 0x50000, for example. After rebooting, that address would change to 0x20000. -
GetProcAddress
indeed returns the real physical address which is the same for every process. And even if the returned value was a virtual address, this value would also be the same for every process that mapped the DLL in the preferred address. So, it's highly probably that using the returned value across different processes will work, though it's not 100% guaranteed.
References:
- https://stackoverflow.com/questions/43613245/is-the-same-dll-guaranteed-to-be-mapped-to-the-same-virtual-address-in-every-pro
- https://stackoverflow.com/questions/22750112/dll-injection-with-createremotethread
- https://stackoverflow.com/questions/29865977/bypassing-windows-aslr-by-determining-the-library-address-using-shared-pages
- https://www.reddit.com/r/AskNetsec/comments/cwkhgr/does_windows_still_load_the_dlls_in_the_same/
- https://stackoverflow.com/questions/41315835/how-are-windows-dll-actually-shared
- https://stackoverflow.com/questions/44164344/getprocaddress-doesnt-return-the-real-address-for-loadlibrarya