View previous topic :: View next topic |
Author |
Message |
Burningmace Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 520 Location: Inside the Intel CET shadow stack
|
Posted: Thu Jul 26, 2018 9:22 am Post subject: How does CE identify the name/path of WOW DLLs? |
|
|
I'm working on a DLL injection scanner. I'm trying a bunch of different techniques to identify DLLs that have been loaded into the process:
- CreateToolhelp32Snapshot and Module32First/Module32Next
- EnumProcessModulesEx
- Parsing the LDR entries manually
- Walking the memory space and calling GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
- Walking the process space with VirtualQuery to identify executable allocations that return a fail status when GetModuleHandleEx is called, then check to see if the allocation starts with 'MZ'.
The first four methods show most of the DLLs loaded but fail to identify wow64win.dll, wow64cpu.dll, or wow64.dll in the process. The final method identifies the spaces where these DLLs are loaded, but trying any of the usual avenues to retrieve the DLL name just results in failures. If I inspect the process with CE and directly go to the memory addresses, CE displays the proper DLL name along with the page info. How does it find that name?
The only thing I can think of is that the WOW64 DLLs are not identifiable from within the process itself because it's a 32-bit process, whereas CE can because it's a 64-bit process. I know there's meant to be a "shadow" LDR for WOW64 but when I tried to get it (NtQueryInformationThread to get the thread information, TEB pointer from that, PEB pointer from that plus a 0x2000 offset, LDR pointer from that) I find that the LDR pointer is null. This is regardless of whether I offset the TEB pointer by 0x2000, which is weird.
_________________
It's not fun unless every exploit mitigation is enabled. |
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 468
Joined: 09 May 2003 Posts: 25718 Location: The netherlands
|
Posted: Thu Jul 26, 2018 3:02 pm Post subject: |
|
|
call EnumProcessModulesEx twice. once for 64 bit and once for 32 bit
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
Burningmace Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 520 Location: Inside the Intel CET shadow stack
|
Posted: Thu Jul 26, 2018 3:39 pm Post subject: |
|
|
Interesting. I've been calling it with LIST_MODULES_ALL and not seeing the WOW64 modules, but will give it a go with LIST_MODULES_32BIT and LIST_MODULES_64BIT separately.
As an aside, any idea why I'm not getting LDR data for the PEB32 here? In fact the whole PEB32 struct looks broken.
Code: |
0:005> !peb
Wow64 PEB32 at 8f9000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 0000000000a50000
Ldr 0000000077af7ba0
*** _PEB_LDR_DATA type was not found...
*** unable to read Ldr table at 0000000077af7ba0
SubSystemData: 0000000000000000
ProcessHeap: 0000000000080000
ProcessParameters: 0000000000081f98
*** _CURDIR type was not found...
WindowTitle: '< Name not readable >'
ImageFile: '< Name not readable >'
CommandLine: '< Name not readable >'
DllPath: '< Name not readable >'
Environment: 0000000000000000
Unable to read Environment string.
Wow64 PEB at 00000000008f8000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 0000000000a50000
Ldr 00007ffbdd3dc360
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 0000000000c92ca0 . 0000000000c934f0
Ldr.InLoadOrderModuleList: 0000000000c92e10 . 0000000000c934d0
Ldr.InMemoryOrderModuleList: 0000000000c92e20 . 0000000000c934e0
|
This is just in a regular MSVC 32-bit executable on an x64 box, nothing fancy going on.
EDIT: Just tried EnumProcessModulesEx and passing either LIST_MODULES_32BIT or LIST_MODULES_64BIT gives the exact same list of modules, neither showing the WOW64 DLLs. Really confused now.
EDIT2: The plot thickens. Running the lm command on the process does show the WOW modules... and the Wow64PEB LDR data does show the WOW modules too. So now I'm wondering if I've really screwed up my LDR walking code somehow.
_________________
It's not fun unless every exploit mitigation is enabled. |
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Thu Jul 26, 2018 4:10 pm Post subject: |
|
|
That's documented behaviour:
Quote: | EnumProcessModulesEx function
...
This function is intended primarily for 64-bit applications. If the function is called by a 32-bit application running under WOW64, the dwFilterFlag option is ignored and the function provides the same results as the EnumProcessModules function. | source
The purpose of wow64 is to emulate a 32-bit environment. Accordingly, this should be as transparent to the application as possible. There's no official way of doing what you want to do AFAIK.
Try looking into undocumented functions (e.g. NtWow64QueryInformationProcess64; github).
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Burningmace Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 520 Location: Inside the Intel CET shadow stack
|
Posted: Thu Jul 26, 2018 5:34 pm Post subject: |
|
|
I literally just this second got it working. I realised that I was getting bogus results because the data from WinDbg didn't match what I was seeing in my process, and swapping between 32-bit and 64-bit WinDbg produced different results too.
The mistake I made was reading the PEB64 as a PEB structure in the x86 process, which of course is compiled as a 32-bit struct rather than 64-bit.
The first step was duplicating the PEB, PEB_LDR_DATA, LDR_DATA_TABLE_ENTRY, etc. structures and replacing pointers with PVOID64. Then I wrote a wrapper around NtWow64ReadVirtualMemory64 to allow me to read the 64-bit memory space. Then I wrote a variant of my LDR enumeration function that reads the structs from 64-bit memory as it goes rather than using direct pointers.
It's now working and I can dump all the module names! w00t!
_________________
It's not fun unless every exploit mitigation is enabled. |
|
Back to top |
|
 |
atom0s Moderator
Reputation: 204
Joined: 25 Jan 2006 Posts: 8581 Location: 127.0.0.1
|
Posted: Sun Jul 29, 2018 1:05 am Post subject: |
|
|
Manual mapped modules will bypass these API's and the PEB list entirely. You will have to resort to manual scans of the memory regions and such. Don't rely on PE headers either as they are commonly stripped from memory once the DLL is injected. Keep an eye out for hooks and such as well on the given API you listed above too for hiding methods.
Lower level will need to be taken into effect as well since ring0 hiding can be used making all the user level API useless for finding anything.
_________________
- Retired. |
|
Back to top |
|
 |
|