2005 3月6日 hook windows nAtive Api的那一段程序 undocumnet wind....上的

今天同学过生日,出去吃涮羊肉,差点没撑死,一共4个人,羊肉*6,牛肉*2,金丝蘑*5(),小白菜*2,羊肉丸子*2,紫菜*2,白薯*1,人家不给退,我中午还吃了饭,从2点半吃到4点半

undocument windw....书里那个hook nAtive Api的例子没看懂,主要是那个SpyHookInitializeEx,

// -----------------------------------------------------------------
// The SpyHook macro defines a hook entry point in inline assembly
// language. The common entry point SpyHook2 is entered by a call
// instruction, allowing the hook to be identified by its return
// address on the stack. The call is executed through a register to
// remove any degrees of freedom from the encoding of the call.

#define SpyHook                              /
        __asm   push    eax                  /
        __asm   mov     eax, offset SpyHook2 /
        __asm   call    eax

// -----------------------------------------------------------------
// The SpyHookInitializeEx() function initializes the aSpyHooks[]
// array with the hook entry points and format strings. It also
// hosts the hook entry points and the hook dispatcher.

void SpyHookInitializeEx (PPBYTE ppbSymbols,
                          PPBYTE ppbFormats)
    {
    DWORD dHooks1, dHooks2, i, j, n;

    __asm
        {
        jmp     SpyHook9
        ALIGN   8
SpyHook1:       ; start of hook entry point section
        }

// the number of entry points defined in this section
// must be equal to SDT_SYMBOLS_MAX (i.e. 0xF8)

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //08
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //10
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //18
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //20
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //28
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //30
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //38
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //40
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //48
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //50
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //58
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //60
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //68
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //70
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //78
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //80
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //88
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //90
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //98
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F8

    __asm
        {
SpyHook2:       ; end of hook entry point section
        pop     eax                     ; get stub return address
        pushfd
        push    ebx
        push    ecx
        push    edx
        push    ebp
        push    esi
        push    edi
        sub     eax, offset SpyHook1    ; compute entry point index
        mov     ecx, SDT_SYMBOLS_MAX
        mul     ecx
        mov     ecx, offset SpyHook2
        sub     ecx, offset SpyHook1
        div     ecx
        dec     eax
        mov     ecx, gfSpyHookPause     ; test pause flag
        add     ecx, -1          //
        sbb     ecx, ecx       //这三句不知道是怎样test pAuse flAg的 
        not     ecx                //
        lea     edx, [aSpyHooks + eax * SIZE SPY_HOOK_ENTRY]  //EAX中是index,edx存入ASpyHooks中相应index的地址,这时候ASpyHooks应该已经和systemtAble交换过呢,但并不交换formAt  InterlockedExchange ((PLONG) ServiceTable+i,
                                     ( LONG) aSpyHooks [i].Handler); 只交换hAndler

        test    ecx, [edx.pbFormat]     ; format string == NULL?
        jz      SpyHook5  //SPYHOOK5是一个退出恢复寄存器的过程
        push    eax
        push    edx
        call    PsGetCurrentThreadId    ; get thread id
        mov     ebx, eax    //u  ebx=threAd id
        pop     edx
        pop     eax
        cmp     ebx, ghSpyHookThread    ; ignore hook installer
        jz      SpyHook5  //不hook 程序自己,,在spyhook5中,把原来系统systemtAble的hAndler地址换回去调用的就是原来的Api了   mov     eax, [edx.Handler] 。。。。xchg    eax, [esp]    ret           ; ...jump to handler
        mov     edi, gpDeviceContext
        lea     edi, [edi.SpyCalls]     ; get call context array   //u   edi=gpDeviceContext.SpyCAlls
        mov     esi, SPY_CALLS          ; get number of entries   //u esi = SPY_CALLS
SpyHook3:
        mov     ecx, 1                  ; set in-use flag
        xchg    ecx, [edi.fInUse]   //gpDeviceContext.SpyCAlls是个数组,从第一个开始找起,找一个未用过的
        jecxz   SpyHook4                ; unused entry found  //当ecx为0时跳转,找到了就去spyhook4
        add     edi, SIZE SPY_CALL      ; try next entry
        dec     esi
        jnz     SpyHook3
        mov     edi, gpDeviceContext
        inc     [edi.dMisses]           ; count misses   //这一块是如果把spyCAlls找遍了还没有空的,就把gpDeviceCOntext.dMisses加一后退出,
        jmp     SpyHook5                ; array overflow
SpyHook4:
        mov     esi, gpDeviceContext
        inc     [esi.dLevel]            ; set nesting level  //可能表示在一个被hook的函数中再调用被hook的函数,嵌套level
        mov     [edi.hThread], ebx      ; save thread id
        mov     [edi.pshe], edx         ; save PSPY_HOOK_ENTRY
        mov     ecx, offset SpyHook6    ; set new return address
        xchg    ecx, [esp+20h]  //看样 [esp+20h]是 old return Address,20h就是32字节,从前面看的确没错,这个返回地址是在进入SPYHOOK的时候压进栈的
        mov     [edi.pCaller], ecx      ; save old return address
        mov     ecx, KeServiceDescriptorTable
        mov     ecx, [ecx].ntoskrnl.ArgumentTable
        movzx   ecx, byte ptr [ecx+eax] ; get argument stack size  //movzx 扩展符号位数据传送
        shr     ecx, 2
        inc     ecx                     ; add 1 for result slot
        mov     [edi.dParameters], ecx  ; save number of parameters
        lea     edi, [edi.adParameters]
        xor     eax, eax                ; initialize result slot
        stosd   //将slot存到edi去,值为0
        dec     ecx
        jz      SpyHook5                ; no arguments
        lea     esi, [esp+24h]          ; save argument stack
        rep     movsd  //把esi中的传到edi中,esi中不是gpDeviceContext吗
SpyHook5:
        mov     eax, [edx.Handler]      ; get original handler
        pop     edi
        pop     esi
        pop     ebp
        pop     edx
        pop     ecx
        pop     ebx
        popfd
        xchg    eax, [esp]              ; restore eax and...
        ret                             ; ...jump to handler
SpyHook6:  //spyhook6是调用nAtive Api的函数后的返回地址,也就是在spyhook5执行结束后就会转到spyhook6来
        push    eax  
        pushfd
        push    ebx
        push    ecx
        push    edx
        push    ebp
        push    esi
        push    edi
        push    eax //这个push是和下面的pop eAx一起的
        call    PsGetCurrentThreadId    ; get thread id
        mov     ebx, eax
        pop     eax
        mov     edi, gpDeviceContext
        lea     edi, [edi.SpyCalls]     ; get call context array
        mov     esi, SPY_CALLS          ; get number of entries
SpyHook7:
        cmp     ebx, [edi.hThread]      ; find matching thread id
        jz      SpyHook8
        add     edi, SIZE SPY_CALL      ; try next entry
        dec     esi
        jnz     SpyHook7
        push    ebx                     ; entry not found ?!?  //fuk! 你自己写的程序你问谁啊
        call    KeBugCheck
SpyHook8:
        push    edi                     ; save SPY_CALL pointer
        mov     [edi.adParameters], eax ; store NTSTATUS
        push    edi  //两个push edi,,spyhookprotocol到底需要什么参数? 只需要一个,第一个push edi不是参数  靠 行为诡异
        call    SpyHookProtocol  //没有返回值
        pop     edi                     ; restore SPY_CALL pointer  // 和前面的push保护了edi,不知道为什么要这样做
        mov     eax, [edi.pCaller]
        mov     [edi.hThread], 0        ; clear thread id
        mov     esi, gpDeviceContext
        dec     [esi.dLevel]            ; reset nesting level
        dec     [edi.fInUse]            ; clear in-use flag
        pop     edi
        pop     esi
        pop     ebp
        pop     edx
        pop     ecx
        pop     ebx
        popfd
        xchg    eax, [esp]              ; restore eax and...   //[esp]里是spyhook6一开始 push进去的 eAx,关键要看,现在eAx把什么东西换进,这样在esp后面的一个那个入栈的就没有,本来应该是在spyhook2一开始就pop EAX的那个 ,,在进spyhook6的时候也是提前一个就ret了,堆栈里没有留下垃圾。。EAX是[edi.pCAller],是调用Api的函数(cAller)的return Address,,这样,一次nAtive Api就结束了,好象还没看到调用真正NAtive Api的地方,,估计是在SpyHookProtocol中,
        ret                             ; ...return to caller
SpyHook9:
        mov     dHooks1, offset SpyHook1
        mov     dHooks2, offset SpyHook2
        }
    n = (dHooks2 - dHooks1) / SDT_SYMBOLS_MAX;

    for (i = j = 0; i < SDT_SYMBOLS_MAX; i++, dHooks1 += n)
        {
        if ((ppbSymbols     != NULL) && (ppbFormats != NULL) &&
            (ppbSymbols [j] != NULL))
            {
            aSpyHooks [i].Handler  = (NTPROC) dHooks1;
            aSpyHooks [i].pbFormat =
                SpySearchFormat (ppbSymbols [j++], ppbFormats);
            }
        else
            {
            aSpyHooks [i].Handler  = NULL;
            aSpyHooks [i].pbFormat = NULL;
            }
        }
    return;
    }

// -----------------------------------------------------------------

一开始不知道什么时候才执行spyhook1,后来用s-ice调的时候才大概知道什么意思,自己真是笨啊,

每个SpyHook宏都对应一个地址,从这个地址执行下去就执行了宏中SpyHook2的程序,而由于第一句的pop eAx ,所以不会再返回执行下一个SpyHook,函数SpyHookInitializeEx 在一开始就跳转到SpyHook9,把每个标号SpyHook的地址,及ppbSymbols[]中的一个元素放入ASpyHooks[]中,这个数组以后会和sdt里的内容交换。在DriverEntry里是不会执行到SpyHook2的,执行这些汇编语句是在系统调用nAtive Api的时候,本来应该是Api的地址,却被换成了一个个标号spyhook的地址了,,所以程序会转到这里来执行,完成后面的事

spyhook2计算当前是第几个spyhoook,公式是

index = (ReturnAddress-SpyHook1)*SDT_SYMBOLS_MAX/(spyhook2-spyhook1)-1

spyhook2-spyhook1 = sizeof(spyhook)*SDT_SYMBOLS

ReturnAddress 是开始时的pop eAx

MOVZX - Move with Zero Extend (386+)

        Usage:  MOVZX   dest,src
        Modifies flags: None

        Copies the value of the source operand to the destination register
        with the zeroes extended.

                                 Clocks                 Size
        Operands         808x  286   386   486          Bytes

        reg,reg           -     -     3     3             3
        reg,mem           -     -     6     3            3-7

stosd

Save the data in eax to memory ES:[EDI] and increase EDI by 4 and decrease ecx by 1.
and you can use rep stosd to initialize an integer array to the same value,such as

xor eax,eax
mov ecx,10
push es
push ds
pop es
mov edi, pointer of an array
rep stosd
pop es



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值