PDA

View Full Version : KeStackAttachProcess


Patafix
October 13th, 2009, 09:33

Hi guys,

I'm trying to implement my own KeStackAttachProcess (obliviously to evade some hooks...). 
My first step is to understand how it works.
Atm, I don't want to reinvent the wheel but just to call KiAttachProcess from my own function.

I'm working on a XP sp2 VM to make my tests.


windbg listing:


0: kd> uf KeStackAttachProcess
nt!KeStackAttachProcess:
804f8ada 8bff            mov     edi,edi
804f8adc 55              push    ebp
804f8add 8bec            mov     ebp,esp
804f8adf 56              push    esi
804f8ae0 57              push    edi
804f8ae1 64a124010000    mov     eax,dword ptr fs:[00000124h]
804f8ae7 8bf0            mov     esi,eax
804f8ae9 64a194090000    mov     eax,dword ptr fs:[00000994h]
804f8aef 85c0            test    eax,eax
804f8af1 741c            je      nt!KeStackAttachProcess+0x35 (804f8b0f)

nt!KeStackAttachProcess+0x19:
804f8af3 64a194090000    mov     eax,dword ptr fs:[00000994h]
804f8af9 50              push    eax
804f8afa 0fb68665010000  movzx   eax,byte ptr [esi+165h]
804f8b01 50              push    eax
804f8b02 ff7644          push    dword ptr [esi+44h]
804f8b05 ff7508          push    dword ptr [ebp+8]
804f8b08 6a05            push    5
804f8b0a e8c1120000      call    nt!KeBugCheckEx (804f9dd0)

nt!KeStackAttachProcess+0x35:
804f8b0f 8b7d08          mov     edi,dword ptr [ebp+8]
804f8b12 397e44          cmp     dword ptr [esi+44h],edi
804f8b15 750c            jne     nt!KeStackAttachProcess+0x49 (804f8b23)

nt!KeStackAttachProcess+0x3d:
804f8b17 8b450c          mov     eax,dword ptr [ebp+0Ch]
804f8b1a c7401001000000  mov     dword ptr [eax+10h],1
804f8b21 eb3b            jmp     nt!KeStackAttachProcess+0x84 (804f8b5e)

nt!KeStackAttachProcess+0x49:
804f8b23 33c9            xor     ecx,ecx
804f8b25 ff1588804d80    call    dword ptr [nt!_imp_KeAcquireQueuedSpinLockRaiseToSynch (804d8088)]
804f8b2b 80be6501000000  cmp     byte ptr [esi+165h],0
804f8b32 884508          mov     byte ptr [ebp+8],al
804f8b35 740f            je      nt!KeStackAttachProcess+0x6c (804f8b46)

nt!KeStackAttachProcess+0x5d:
804f8b37 ff750c          push    dword ptr [ebp+0Ch]
804f8b3a ff7508          push    dword ptr [ebp+8]
804f8b3d 57              push    edi
804f8b3e 56              push    esi
804f8b3f e86cfdffff      call    nt!KiAttachProcess (804f88b0)
804f8b44 eb18            jmp     nt!KeStackAttachProcess+0x84 (804f8b5e)

nt!KeStackAttachProcess+0x6c:
804f8b46 8d864c010000    lea     eax,[esi+14Ch]
804f8b4c 50              push    eax
804f8b4d ff7508          push    dword ptr [ebp+8]
804f8b50 57              push    edi
804f8b51 56              push    esi
804f8b52 e859fdffff      call    nt!KiAttachProcess (804f88b0)
804f8b57 8b450c          mov     eax,dword ptr [ebp+0Ch]
804f8b5a 83601000        and     dword ptr [eax+10h],0

nt!KeStackAttachProcess+0x84:
804f8b5e 5f              pop     edi
804f8b5f 5e              pop     esi
804f8b60 5d              pop     ebp
804f8b61 c20800          ret     8




In this Windows version, we can see KiAttachProcess is preceded by a push edi and push esi. So it's pretty easy to scan KeStackAttachProcess to get the KiAttachProcess address:



VOID (*pKiAttachProcess)(PKTHREAD, PKPROCESS, KIRQL, PKAPC_STATE);

VOID ScanForKiAttachProcess(ULONG pAddress)
{
    int i;

    for(i = 0; i < 0x84; i++)
    {
        if( *((UCHAR*)pAddress + i) == 0x57 && *((UCHAR*)pAddress + i + 1) == 0x56)
        {
            pKiAttachProcess = (VOID (*)(PKTHREAD, PKPROCESS, KIRQL, PKAPC_STATE))((ULONG)( pAddress + i + 7) + (*((PULONG)(pAddress + i + 3))));
        
            break;
        }
    }    
}


On my system, I have KiAttachProcess address = 0x804f88b0
So ok... I'm trying to call it like that in my MyStackAttachProcess function:



VOID MyKeStackAttachProcess(PKPROCESS pkProcess, PKAPC_STATE pKapc_State)
{
    KIRQL OldIRQL;
    PRKTHREAD Thread;

    if(KeGetCurrentIrql() > DISPATCH_LEVEL) return;

    Thread = KeGetCurrentThread();

    KeRaiseIrql(DISPATCH_LEVEL, &OldIRQL);

    if(KeIsExecutingDpc() != FALSE) 
    {
        KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
                     (ULONG_PTR)pkProcess,
                     (ULONG_PTR)Thread->ApcState.Process,
                     (ULONG)Thread->ApcStateIndex,
                     (ULONG)KeIsExecutingDpc());
    }


    if(Thread->ApcState.Process == pkProcess)
    {
        KeLowerIrql(OldIRQL);
        pKapc_State->Process = (PKPROCESS)1;
        return;
    }


    if (Thread->ApcStateIndex != 0)
    {
        pKiAttachProcess(Thread, pkProcess, OldIRQL, pKapc_State);
    }
    else

    {
        pKiAttachProcess(Thread, pkProcess, OldIRQL, &Thread->SavedApcState);
        pKapc_State->Process = NULL;
    }
    
    KeLowerIrql(OldIRQL);
}



Actually i'm not yet using KeAcquireQueuedSpinLockRaiseToSynch in my function... Do you think it's why my system freeze?
No bugcheck... it's just than when pKiAttachProcess is called, it never return.

Do you have any suggestions?

Regards,

Orkblutt


Kayaker
October 13th, 2009, 21:58
In an earlier version of SP2 I have, KeAcquireQueuedSpinLockRaiseToSynch is replaced by the simpler KeRaiseIrqlToDpcLevel. Raising the IRQL to disable a certain level of interrupts is part of the requirement of KeStackAttachProcess. So why not just include that call in your code as well?

The IRQL is lowered again within _KiAttachProcess, so that part is taken care of. If you want to emulate KeAcquireQueuedSpinLockRaiseToSynch / KeRaiseIrqlToDpcLevel rather than calling it, you could create your own function.

A couple of refs which might be of some use:

http://ext2fsd.sourceforge.net/documents/irql.htm

http://www.woodmann.net/forum/showthread.php?t=11280


PS, what are you going to do when they start hooking KiAttachProcess as well?

Patafix
October 14th, 2009, 02:38
Hi Kayaker,

In fact I have already tested using KeRaiseIrqlToDpcLevel (like in win2k) but the result is the same. Now I'm not sure about how I'm calling KiAttachProcess...

Quote:
PS, what are you going to do when they start hooking KiAttachProcess as well?

You're right... It's the eternal race to who is going the deeper. One day we will need to load/duplicate/map the entire OS from binaries to evade... I could restore the original hooked functions too but atm I just want to participate to that race.

GamingMasteR
October 14th, 2009, 18:58
If you want to bypass Context switching hook you can directly execute APC Routine in any thread of the victim process

Kayaker
October 14th, 2009, 21:38
I'm a big fan of APC injections as well, very versatile

Out of curiousity, what are KeStackAttachProcess/KeAttachProcess hooks used for? Besides strictly for AV/ARK purposes. I've read that a couple of "known" protections use that.

Is it to protect against driver based attach attempts and/or certain usermode attacks? KeStackAttachProcess xrefs with many other API's such as MmMapViewOfSection, NtAllocateVirtualMemory, NtProtectVirtualMemory, NtSetInformationThread. So the protection could presumably detect use by the ring3 counterparts of those API's.


Also,

Code:

KiAttachProcess (
__inout PRKTHREAD Thread,
__in PRKPROCESS Process,
__in PKLOCK_QUEUE_HANDLE LockHandle,
__out PRKAPC_STATE SavedApcState
);

Patafix
October 15th, 2009, 02:54
Hey guys,

yup i'm aware about APC injection since Kayaker popularize it around :-)

In fact, I'm not fighting against real products... I'm just experimenting for my own knowledge without real target here. I'm thinking maybe use that work one day against anti-cheat products more than against AV/ARK.


Quote:
PKLOCK_QUEUE_HANDLE LockHandle

crap... So I well have to use KeAcquireQueuedSpinLockRaiseToSynch or at least to implement my own.

It's working! Thank you!

ps: here a keattachprocess hook found by googleling: https://forum.eviloctal.com/thread-38697-1-1.html

Orkblutt

aionescu
December 13th, 2009, 20:09
You can also check out the ReactOS sources for the functions and just use them -- they should work out of the box.