• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

            內(nèi)核級(jí)利用通用Hook函數(shù)方法檢測(cè)進(jìn)程

            介紹通用Hook的一點(diǎn)思想:
                在系統(tǒng)內(nèi)核級(jí)中,MS的很多信息都沒公開,包括函數(shù)的參數(shù)數(shù) 目,每個(gè)參數(shù)的類型等。在系統(tǒng)內(nèi)核中,訪問了大量的寄存器,而很多寄存器的值,是上層調(diào)用者提供的。如果值改變系統(tǒng)就會(huì)變得不穩(wěn)定。很可能出現(xiàn)不可想象的 后果。另外有時(shí)候?qū)π枰狧ook的函數(shù)的參數(shù)不了解,所以不能隨便就去改變它的堆棧,如果不小心也有可能導(dǎo)致藍(lán)屏。所以Hook的最佳原則是在自己的 Hook函數(shù)中呼叫原函數(shù)的時(shí)候,所有的寄存器值,堆棧里面的值和Hook前的信息一樣。這樣就能保證在原函數(shù)中不會(huì)出錯(cuò)。一般我們自己的Hook的函數(shù) 都是寫在C文件里面的。例如Hook的目標(biāo)函數(shù)KiReadyThread。
            那么一般就自己實(shí)現(xiàn)一個(gè):
            MyKiReadyThread(...)
            {
                ......
                call KiReadyThread
                ......
            }
            但是用C編譯器編譯出來的代碼會(huì)出現(xiàn)一個(gè)堆棧幀:
            Push ebp
            mov  ebp,esp
            這就和我們的初衷不改變寄存器的數(shù)違背了。所以我們可以自己用匯編來實(shí)現(xiàn)MyKiReadyThread。

            _func@0 proc
                pushad        ;保存通用寄存器
                call _cfunc@0  ;這里是在進(jìn)入原來函數(shù)前進(jìn)行的一些處理。
                popad         ;恢復(fù)通用寄存器
                push eax  
                mov eax,[esp+4] ;得到系統(tǒng)在call 目標(biāo)函數(shù)時(shí)入棧的返回地址。
                mov ds:_OrgRet,eax ;保存在一個(gè)臨時(shí)變量中
                pop eax
                mov [esp],retaddr  ;把目標(biāo)函數(shù)的返回地址改成自己的代碼空間的返回地址,使其返回                后能接手繼續(xù)的處理
                jmp _OrgDestFunction ;跳到原目標(biāo)函數(shù)中
            retaddr:
                pushad         ;原函數(shù)處理完后保存寄存器
                call _HookDestFunction@0 ;再處理
                popad      ;回復(fù)寄存器
                jmp ds:_OrgRet ;跳到系統(tǒng)調(diào)用目標(biāo)函數(shù)的下一條指令。
            _func@0 endp

            當(dāng)我們要攔截目標(biāo)API的時(shí)候,只要修改原函數(shù)頭5個(gè)字節(jié)的機(jī)器為一個(gè)JMP _func就行了。
            然后把原來的5字節(jié)保存。在跳入原函數(shù)時(shí),恢復(fù)那5個(gè)字節(jié)即可。

            Hook KiReadyThread檢測(cè)系統(tǒng)中的進(jìn)程:
            在線程調(diào)度搶占的的時(shí)候會(huì)調(diào)用KiReadyThread,它的原型為
            VOID FASTCALL KiReadyThread (IN PRKTHREAD Thread)
            在進(jìn)入KiReadyThread時(shí),ecx指向Thread。
            所以完全可以Hook KiReadyThread 然后用ecx的值得到但前線程的進(jìn)程信息。
            KiReadyThread沒被ntosknrl.exe導(dǎo)出,所以通過硬編碼來。在2000Sp4中地址為0x8043141f

            具體實(shí)現(xiàn):
            ////////////////////////////////
            // 1.cpp
            ////////////////////////////////
            #ifdef __cplusplus
            extern "C" {
            #endif

            #include "ntddk.h"
            #include "string.h"
            #include "ntifs.h"
            #include "stdio.h"

            #define FILE_DEVICE_EVENT  0x8000

            #define IOCTL_PASSBUF \
                CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

            void DriverUnload (IN PDRIVER_OBJECT pDriverObject);

            NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);

            void cfunc ();

            void HookDestFunction();
            NTSTATUS DeviceIoControlDispatch(IN  PDEVICE_OBJECT  DeviceObject,
                                             IN  PIRP            pIrp);
            extern void func();

            void ResumeDestFunction();

            const WCHAR devLink[]  = L"\\??\\MyEvent";
            const WCHAR devName[]  = L"\\Device\\MyEvent";
            UNICODE_STRING          devNameUnicd;
            UNICODE_STRING          devLinkUnicd;    

            ULONG OrgDestFunction = (ULONG)0x8043141f; //KiReadyThread

            char JmpMyCode [] = {0xE9,0x00,0x00,0x00,0x00};
            char OrgCode [5];

            char OutBuf[128][16];

            int Count = 0;

            ULONG orgcr0;
            #ifdef __cplusplus
            }
            #endif

            VOID DisableWriteProtect( PULONG pOldAttr)
            {

                 ULONG uAttr;

                 _asm
                {
                      push eax;
                      mov  eax, cr0;
                      mov  uAttr, eax;
                      and  eax, 0FFFEFFFFh; // CR0 16 BIT = 0
                      mov  cr0, eax;
                      pop  eax;
                };

                 *pOldAttr = uAttr; //保存原有的 CRO 屬性

            }

            VOID EnableWriteProtect( ULONG uOldAttr )
            {

              _asm
              {
                   push eax;
                   mov  eax, uOldAttr; //恢復(fù)原有 CR0 屬性
                   mov  cr0, eax;
                   pop  eax;
              };

            }

            NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
            {
                NTSTATUS                Status;
                PDEVICE_OBJECT            pDevice;

                DbgPrint("DriverEntry called!\n");
                RtlInitUnicodeString (&devNameUnicd, devName );
                RtlInitUnicodeString (&devLinkUnicd, devLink );
                Status = IoCreateDevice ( pDriverObject,
                0,
                     &devNameUnicd,
                FILE_DEVICE_UNKNOWN,
                   0,
                   TRUE,
                   &pDevice );
                    if( !NT_SUCCESS(Status))
                    {
                    DbgPrint(("Can not create device.\n"));
                    return Status;
                }
                   Status = IoCreateSymbolicLink (&devLinkUnicd, &devNameUnicd);
                   if( !NT_SUCCESS(Status))
                   {
                       DbgPrint(("Cannot create link.\n"));
                       return Status;
                   }
                   pDriverObject->DriverUnload  = DriverUnload;
                   pDriverObject->MajorFunction[IRP_MJ_CREATE] =
                pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
                pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =    DeviceIoControlDispatch;
                  
                pDriverObject->DriverUnload = DriverUnload;
                * ( (ULONG*) (JmpMyCode+1) ) = (ULONG)func - (ULONG)OrgDestFunction - 5;
                memcpy(OrgCode,(char*)OrgDestFunction,5);
                HookDestFunction();
                
                return STATUS_SUCCESS;
            }

            void DriverUnload (IN PDRIVER_OBJECT pDriverObject)
            {
                NTSTATUS            status;
                ResumeDestFunction();
                if(pDriverObject->DeviceObject != NULL)

                    {
                       status=IoDeleteSymbolicLink( &devLinkUnicd );
                    if ( !NT_SUCCESS( status ) )
                        {
                                DbgPrint((  "IoDeleteSymbolicLink() failed\n" ));
                        }
                        IoDeleteDevice( pDriverObject->DeviceObject );
                    }
            }

            void DisplayName(PKTHREAD Thread)
            {
                PKPROCESS Process = Thread->ApcState.Process;
                PEPROCESS pEprocess = (PEPROCESS)Process;
                DbgPrint("ImageFileName = %s \n",pEprocess->ImageFileName);
                sprintf(OutBuf[Count++],"%s",pEprocess->ImageFileName);
            }

            void cfunc (void)
            {
                ULONG PKHeader=0;
                __asm
                {
                    mov PKHeader,ecx  //ecx寄存器是KiReadyThread中的PRKTHREAD參數(shù)
                }
                ResumeDestFunction();
                
                if ( PKHeader != 0 && Count < 128 )
                {
                    DisplayName((PKTHREAD)PKHeader);    
                }    
            }

            void HookDestFunction()
            {
                DisableWriteProtect(&orgcr0);
                memcpy((char*)OrgDestFunction,JmpMyCode,5);
                EnableWriteProtect(orgcr0);    
            }

            void ResumeDestFunction()
            {
                DisableWriteProtect(&orgcr0);
                memcpy((char*)OrgDestFunction,OrgCode,5);
                EnableWriteProtect(orgcr0);
            }

            NTSTATUS DeviceIoControlDispatch(
                                             IN  PDEVICE_OBJECT  DeviceObject,
                                             IN  PIRP            pIrp
                                           )
            {
                PIO_STACK_LOCATION              irpStack;
                NTSTATUS                        status;
                PVOID                           inputBuffer;
                ULONG                           inputLength;
                PVOID                           outputBuffer;
                ULONG                           outputLength;
                OBJECT_HANDLE_INFORMATION       objHandleInfo;

                status = STATUS_SUCCESS;
                // 取出IOCTL請(qǐng)求代碼
                irpStack = IoGetCurrentIrpStackLocation(pIrp);

                switch (irpStack->MajorFunction)
                {
                case IRP_MJ_CREATE :
                    DbgPrint("Call IRP_MJ_CREATE\n");
                    break;
                case IRP_MJ_CLOSE:
                    DbgPrint("Call IRP_MJ_CLOSE\n");
                    break;
                case IRP_MJ_DEVICE_CONTROL:
                    DbgPrint("IRP_MJ_DEVICE_CONTROL\n");
                    inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;
                    outputLength=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
                    switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
                    {
                      case    IOCTL_PASSBUF:
                        {
                            RtlCopyMemory(pIrp->UserBuffer, OutBuf, 20*16);
                            
                            memset(OutBuf,0,128*16);
                            Count = 0;
                            break;
                        }
                        default:
                            break;
                    }

                default:
                    DbgPrint("Call IRP_MJ_UNKNOWN\n");
                    break;
                }
                pIrp->IoStatus.Status = status;
                pIrp->IoStatus.Information = 0;
                IoCompleteRequest (pIrp, IO_NO_INCREMENT);
                return status;
            }

            ////////////////////////////////
            // 1.asm
            ////////////////////////////////
            .386
            .model small

            .data
            _OrgRet dd 0

            .code
            public _func@0
            extrn _cfunc@0:near
            extrn _HookDestFunction@0:near
            extrn _OrgDestFunction:DWORD

            _func@0 proc
                pushad
                call _cfunc@0
                popad
                push eax
                mov eax,[esp+4]
                mov ds:_OrgRet,eax
                pop eax
                mov [esp],retaddr
                jmp _OrgDestFunction
            retaddr:
                pushad
                call _HookDestFunction@0
                popad
                jmp ds:_OrgRet
            _func@0 endp
            END

            //////////////////////////////////////////
            // app.cpp
            //////////////////////////////////////////

            #include <windows.h>
            #include <stdio.h>

            #define FILE_DEVICE_EVENT  0x8000
            #define CTL_CODE( DeviceType, Function, Method, Access ) (                 \

                ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
            )

            #define FILE_ANY_ACCESS                 0
            #define METHOD_BUFFERED                 0
            #define FILE_DEVICE_UNKNOWN             0x00000022

            #define IOCTL_PASSBUF \
                CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

            int main()
            {
                   HANDLE      hDevice;    
                    bool        status;
                   ULONG       dwReturn;
                    char        outbuf[129][16];
                    hDevice = NULL;
                    m_hCommEvent = NULL;
                    hDevice = CreateFile( "\\\\.\\MyEvent",
                                GENERIC_READ|GENERIC_WRITE,
                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);
                    if(hDevice == INVALID_HANDLE_VALUE)
                    {
                       printf("createfile wrong\n");
                       getchar();
                       return 0;
                    }
                while(1)
             {
                    memset(outbuf,0,129*16);
                    status =DeviceIoControl(hDevice,
                                IOCTL_PASSBUF,
                                NULL,
                                0,
                                &outbuf,
                                128*16,
                                &dwReturn,NULL);
                    if( !status)
                    {
                        printf("IO wrong+%d\n", GetLastError());
                        getchar();
                        return 0;
                    }
                    int c=0;
                    while( *((char*)(&outbuf)+c*16) )
                    {
                        //把csrss.exe和自身進(jìn)程信息跳過,因?yàn)闀?huì)產(chǎn)生有大量的信息。
                        if ( strcmp((char*)(&outbuf)+c*16,"app.exe") && \
                             strcmp((char*)(&outbuf)+c*16,"csrss.exe")  )
                            printf("%s\n",(char*)(&outbuf)+c*16);
                        c++;
                    }
                    Sleep(1);
                }
            }

            試驗(yàn)結(jié)果:
            ......
            TTPlayer.exe
            System
            TTPlayer.exe
            vrvmon.exe
            TTPlayer.exe
            System
            System
            Explorer.EXE
            Explorer.EXE
            Explorer.EXE
            ......
            測(cè)試,編譯環(huán)境 2000 Sp4 2000 DDK
            沒寫出線程的隱藏進(jìn)程代碼。不過基本上實(shí)現(xiàn)得差不多了,只需要把返回的信息,和Ring3級(jí)查詢得到的信息進(jìn)行適時(shí)對(duì)比就能查出異常進(jìn)程了。

            posted on 2007-07-29 13:59 旅途 閱讀(602) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 深入windows

            99久久无色码中文字幕人妻| 久久精品国产亚洲AV无码麻豆| 久久久久久久波多野结衣高潮| 国产精品熟女福利久久AV| 久久久av波多野一区二区| 亚洲AV成人无码久久精品老人| 久久精品综合网| 亚洲а∨天堂久久精品| 久久久久久久亚洲精品| 久久精品无码免费不卡| 久久综合给合综合久久| 国产高潮国产高潮久久久91 | 国产A三级久久精品| 久久久久青草线蕉综合超碰| 人人妻久久人人澡人人爽人人精品| 亚洲国产精品嫩草影院久久| 青草久久久国产线免观| 99久久香蕉国产线看观香| 久久国产色av免费看| 狠狠色狠狠色综合久久| 久久精品人人做人人妻人人玩 | 久久精品99久久香蕉国产色戒 | 亚洲国产精品无码久久一区二区| 久久天天躁狠狠躁夜夜2020一| 亚洲AV无码久久精品狠狠爱浪潮 | 99久久无色码中文字幕人妻| 久久精品人人做人人妻人人玩| 999久久久无码国产精品| segui久久国产精品| 日产精品久久久久久久| 国产亚洲精品美女久久久| 2020最新久久久视精品爱| 狠狠色丁香婷婷久久综合| 国产精品久久一区二区三区| 久久综合伊人77777| 久久99精品久久久久久hb无码| 久久精品国产亚洲Aⅴ香蕉| 人妻少妇久久中文字幕一区二区 | 国产精品美女久久久久久2018| 精品久久久久久国产牛牛app| 99久久精品免费看国产一区二区三区 |