A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #13201  by Vrtule
 Mon May 14, 2012 12:25 am
Hello,

I used PsSetLoadImageCallback routine to register a callback that is called whenewer a PE image is mapped. I have several questions about things I can do inside the callback:

1) Is it safe to read the mapped image (its base address and virtual size are stored in ImageBase and ImageSize members of the IMAGE_INFO structure)?

2) When my driver runs on 64-bit system, the callback is called multiple times for one PE image in case the target process runs under WOW64. It seems that the operating system attempts to map 64-bit image into the process' address space first, then it realizes that this is not the right executable, hence it attempts to find better one inside SysWOW64 directory. I noticed this behavior for kernel32.dll for example. Am I right or is there another explanation?
3) Is it possible to determine the type of the image (32-bit or 64-bit) without reading this information from its OptionalHeader?
4) Before I attempt to read contents of the image, I map it to kernel space via MDL. The problem is that MmProbeAndLockPages fails sometimes with STATUS_ACCESS_VIOLATION exception. It seems that the problem appears only in WOW64 processes again.
5) Additionally, the whole system usually hangs few seconds after my driver is loaded. And my driver uses MmProbeAndLockPages inside Image Notify Callback... However, I have an intention that the system hangs also in case I do not use MDL and touch the image contents directly. Does anybody know why this might be happening?

I test my driver on latest version of Windows 7 SP1 x64. I hope my post is not too confusing.

Thanks in advance

EDIT
When I connect WinDbg to the already freezed system, I get this:
Code: Select all
Assertion: *** DPC watchdog timeout
This is NOT a break in update time
This is most likely a BUG in an ISR
Perform a stack trace to find the culprit
The period will be doubled on continuation
Use gh to continue!!
 #13212  by iSecure
 Mon May 14, 2012 2:21 pm
1) i'm 99% sure that: yes.
2) no idea.
3) look number 2 =)
4) not sure, but i guess locking pages is not needed, because while you inside image notify callback these pages not going to be paged anyway.

+ from MSDN: Calls to MmProbeAndLockPages must be enclosed in a try/except block. If the pages do not support the specified operation, the routine raises the STATUS_ACCESS_VIOLATION or other exceptions.

5) hard to say without sources.

P.S. Better wait for someone-else-more-experienced answers =)
 #13215  by Vrtule
 Mon May 14, 2012 4:46 pm
+ from MSDN: Calls to MmProbeAndLockPages must be enclosed in a try/except block. If the pages do not support the specified operation, the routine raises the STATUS_ACCESS_VIOLATION or other exceptions.
Yes, I know about this. This is not the cause of my problem (DPC watchdog timeout) AFAIK. I just noticed in in Debug Print log generated by my driver.

Thanks anyway.
 #13217  by r2nwcnydc
 Mon May 14, 2012 7:24 pm
To determine if a process is running in WOW64 you can call ZwQueryInformationProcess with ProcessWow64Information. This takes a pointer to a 64 bit integer on 64 bit OSes, and a 32 bit integer on 32 bit OSes. If the value is zero the process is not running in wow64.

The only problem with using this method, is the process needs to already be created so you can open a handle to it. I usually call this from a PsSetCreateProcessNotifyRoutine callback so I don't know if it will work when you get the PsSetLoadImageCallback callback for the process' image.

I have not had the hang or access violation issues with MDLs and Probe and Lock, so if I had to guess this sounds like a bug in your code.
 #13220  by Brock
 Tue May 15, 2012 1:01 am
The only problem with using this method, is the process needs to already be created so you can open a handle to it. I usually call this from a PsSetCreateProcessNotifyRoutine callback so I don't know if it will work when you get the PsSetLoadImageCallback callback for the process' image.
Process always exists during the phase of it's image loading, you're already in the process context whenever the loadimage callback executes. Common callbacks execute in this order for a newly created process PsSetCreateProcessNotifyRoutine -> PsSetCreateThreadNotifyRoutine -> PsSetLoadImageNotifyRoutine. Anyhow, this works fine within a loadimage callback
Code: Select all
 ULONG_PTR Process32Bit = 0;

 if (!ZwQueryInformationProcess((HANDLE)-1, 
                                         ProcessWow64Information, // 0x1A 
                                         &Process32Bit, 
                                         sizeof(Process32Bit), 
                                         NULL))
   {
     DbgPrint("32-bit process %u: %s\n", (ULONG)PsGetCurrentProcessId(), Process32Bit ? "True" : "False");
   }
Regards,
Brock
 #13228  by Brock
 Tue May 15, 2012 8:14 pm
@vrtule,

[1] Are you talking about a system driver mapped to the kernel or a usermode process which has just mapped an image to itself?

[2] 32-bit processes running under WOW64 load both 64-bit and 32-bit versions of certain system DLLs such as ntdll. wow64.dll, wow64win.dll, wow64cpu.dll are also loaded and are strictly 64-bit images. Since WOW64 processes do load images of different bitdepths (mixing them) hence there is a need for the process to have 2 PEBs (PEB64 and PEB32). PEB32 virtual address is always one PAGE_SIZE behind the PEB64 virtual address for the record. For example, you will always see 2 copies of ntdll loaded into a 32-bit process, one 64-bit and the other 32-bit, this is by design and not a "mistake" by the Windows PE loader. All of this is easily verifiable via tools like Process Explorer or view the documented behavior here which is official from Microsoft http://msdn.microsoft.com/en-us/library ... 85%29.aspx

[3] I am only aware of the OptionalHeader check as you mentioned, that's why IMAGE_NT_OPTIONAL_HDR32_MAGIC and IMAGE_NT_OPTIONAL_HDR64_MAGIC exist
 #13242  by Vrtule
 Wed May 16, 2012 10:49 am
[1] Are you talking about a system driver mapped to the kernel or a usermode process which has just mapped an image to itself?
I was talking about DLLs and EXE images loaded into process' addresss space (I mena the area accessible from usermode).
[2] 32-bit processes running under WOW64 load both 64-bit and 32-bit versions of certain system DLLs such as ntdll. wow64.dll, wow64win.dll, wow64cpu.dll are also loaded and are strictly 64-bit images. Since WOW64 processes do load images of different bitdepths (mixing them) hence there is a need for the process to have 2 PEBs (PEB64 and PEB32). PEB32 virtual address is always one PAGE_SIZE behind the PEB64 virtual address for the record. For example, you will always see 2 copies of ntdll loaded into a 32-bit process, one 64-bit and the other 32-bit, this is by design and not a "mistake" by the Windows PE loader. All of this is easily verifiable via tools like Process Explorer or view the documented behavior here which is official from Microsoft http://msdn.microsoft.com/en-us/library ... 85%29.aspx
I know about two PEBs in WOW64 processes. And also their one page distance, which I think miht differentiate in some cases (Windows Research Kernel). Thanks for information anyway.
[3] I am only aware of the OptionalHeader check as you mentioned, that's why IMAGE_NT_OPTIONAL_HDR32_MAGIC and IMAGE_NT_OPTIONAL_HDR64_MAGIC exist
Someboy suggested to use ZwQueryInformationProcess, however, your approcach seems to work fine. When I removed MmProbeAndLockPages and other MDL-related routines, the system freeze seems to gone away. I think I will return to this topic later (I have not much free time now to play with it), because I would like to know its real cause.