A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #6573  by Alex
 Sun May 29, 2011 11:28 am
Lets say we have an upper filter driver, this driver filtrates IRP_MJ_READ/WRITE/DEVICE_CONTROL requests. All these requests (data) have to be passed back to user-mode process (not the same process which generates these IO requests...) which dispatches received data (it isn't important what the process is doing with received data...) and at the same time filter driver passes filtrated requests down to the lower driver. Size of intercepted data is rather small < 512bytes. Now I'm looking for fastest and universal (Windows 2000 - Windows 7) method of transferring data from kernel mode (PASSIVE_LEVEL) to user mode (other process address space) without losing data and inserting useless delays. I wouldn't like to say anything about methods I'm testing now, because I don't need to suggest anything to you. I don't care if proposed method is or isn't documented, crucial for me information is if this method allows to transfer mentioned data immediately.

Thank you in advance for your suggestions,
Alex
 #6575  by Vrtule
 Sun May 29, 2011 2:47 pm
Hello,

I would suggest to transfer the data through pyhsical pages mapped to kernel space and to the address space of the destination proces (MDL probably)s. And to build some syhcnronization mechanism above it. However, I think that you wouldn't ask this question if this kind of solution is acceptable for you.
 #6578  by Twister
 Mon May 30, 2011 5:24 am
Fastest way - KeUserModeCallback (article, src). But it will not work if you need to send data to address space of another process (BSOD on KeUserModeCallback after KeStackAttachProcess).
 #6581  by Alex
 Mon May 30, 2011 3:28 pm
Yes, the first idea was using KeUserModeCallback - I know your articles Twister, but I didn't check it and as you are writing I can't use it to send data to address space of another process. Could you tell me why it is impossible and is there any theoretical hack which could solve this problem?
The second idea was using user APCa, but I don't know could they be faster than method suggested by Vrtule. What about other methods like FLT mechanism, communication ports, ... do you have any experiences with these methods?
 #6582  by t4L
 Mon May 30, 2011 5:11 pm
It all depends how the process will go, whether kmode has to wait for reply from usermode or not. In a filter driver I coded for our AV product which supports from 2000 to 7, both x86 and amd64, I use a pool of shared sections. Each time data arrives, the current thread picks a shared section from that pool, writes data down to it, waits for reply on pool's member Synchronization event and goes back to IRP processing chain.

If your program doesnt have to work on win7 amd64, LPC is the best way to go. It is robust and system oriented. BTW, altho LPC is just a wrapper of shared sections, but I still cant find an approach for wow64 win7 amd64 processes to communicate correctly with x64 driver via LPC while this method works really sweet on xp/2k3/Vista 64bit. I tried many ways to fix that but it seems to be impossible. This is the main reason I chose the former above-mentioned method aka manual LPC.
 #6585  by Twister
 Tue May 31, 2011 4:08 am
Could you tell me why it is impossible and is there any theoretical hack which could solve this problem?
KeUserModeCallback calls KiCallUserMode. It has some checks:
1. Current IRQL must be equal to PASSIVE_LEVEL or you will have BSOD with IRQL_GT_ZERO_AT_SYSTEM_SERVICE
2. You can't return to user mode if kernel APCs are disabled or a process is attached:
Code: Select all
mov     ebx,PCR[PcPrcbData + PbCurrentThread] ; get current thread address
; <...>
Kcb00:  movzx   eax,byte ptr[ebx]+ThApcStateIndex ; get APC state index
        mov     edx,[ebx]+ThCombinedApcDisable ; get kernel APC disable
        or      eax,eax                ; check if process attached
        jne     short Kcb05            ; if ne, process is attached
        or      edx,edx                ; check if kernel APCs disabled
        jz      short Kcb07            ; if z, kernel APCs enabled
Kcb05:  stdCall _KeBugCheck2,<APC_INDEX_MISMATCH,0,eax,edx,0,0>
_KiServiceExit on x86 has the same checks. Also current thread must be non-system (filled KTHREAD->TrapFrame).

I think what any hacks can lead system to instability. And I don't recommend to you to do this hacks.
KeUserModeCallback is the excellent mechanism which provides fastest communications between r0 and r3 in context of one process, no more.
 #6623  by Alex
 Thu Jun 02, 2011 6:56 am
t4L LPC's work "sweet" - it's true, and because I don't need to run this code on win7 amd64 I will use them for a while until I will not write own implementation of shared sections. I'm curious why this doesn't work under win7 amd64 - could you tell us on which level there is the problem?

Twister thank you for the explenation it's good to know these details.
 #6628  by t4L
 Thu Jun 02, 2011 8:13 am
@Alex:
If the usermode process is an native process, it works perfectly like it should. It doesnt work only if your process is an wow64 one.

I did manage to establish a connection between the wow64 process to 64bit driver via LPC on win7 by forcely re-aligning PORT_MESSAGE, PORT_VIEW and REMOTE_PORT_VIEW, but the thread which sends data to usermode would block, even the corresponding internal event object of the port is notified and it wont return from the wait. I guess there's smt wrong with re-aligning the LPC structures and wow64 ntdll doesnt support that. But w/o re-aligning the structures, there's no way to create a working LPC connection from wow64 processes to native 64bit threads. I havent digged deeper cos I think MS wont take care for it so I implemented my own manual LPC.
 #6630  by Fabian Wosar
 Thu Jun 02, 2011 9:49 am
We are using LPC on Windows 7 x64 just fine. Though we don't use it for inter mode communication but only for inter process communication. The only limitation is that the WOW64 translation layer doesn't realign the LPC structures correctly. So you have to realign them to be be identical to their x64 counter parts yourself if you find yourself being a WOW64 process. Another method would be to abuse the File Mini Filter API (FltSendMessage) that is essentially just a wrapper around LPC or ALPC.
 #6631  by t4L
 Thu Jun 02, 2011 10:04 am
@Fabian Wosar:
Yep, I did re-align wow64 process LPC structures to approriate 64bit structures and got a working LPC connection, but as i said before, sending data over that connection results deadblocking threadsm and stuck there.

Anyway, sticking with APC is ok Alex :mrgreen: