首页
社区
课程
招聘
通用的inline hook,
发表于: 2014-3-3 11:34 718

通用的inline hook,

2014-3-3 11:34
718
#include "ntddk.h"
#include "ade32.h"

#define KERNEL_SEG        0x0008

UNICODE_STRING ObjPtrName = { 0 };
typedef void (*DBGPRINT)();
DBGPRINT MyDbgPrint = NULL;

typedef struct patch_info
{
    int patch_len;
    BYTE org_bytes[32];
    PVOID org_func_addr;
    PVOID new_func_addr;
}PATCH_INFO, *PPATCH_INFO;

ULONG g_uCr0 = 0;

void WPOFF()
{
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr;
   
}

VOID WPON()
{
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0;
        mov cr0, eax;
        pop eax;
    };
}

NTSTATUS PatchCommonDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

PVOID GetKernelFuncAddr(PCHAR func_name)
{
    ANSI_STRING ansi_name;
    UNICODE_STRING uni_name;
    PVOID func_addr;
   
    RtlInitString(&ansi_name, func_name);
    RtlAnsiStringToUnicodeString(&uni_name, &ansi_name, TRUE);
   
    func_addr = MmGetSystemRoutineAddress(&uni_name);
   
    RtlFreeUnicodeString(&uni_name);
   
    return func_addr;
}

BOOLEAN IfDirty(PVOID func_addr, CHAR* startbytes, int len)
{
    PCHAR addr = (PCHAR)func_addr;
    int i = 0;
   
    while(i < len)
    {
        if(addr[i] != startbytes[i])
            return TRUE;
        i++;
    }
   
    return FALSE;
}

__declspec(naked) NewStubForIoGetDeviceObjectPointer()
{
    PUNICODE_STRING ObjectName;
   
    _asm
    {
        nop
        nop
        nop
        nop
        nop
        push ebp
        mov ebp, esp
        sub esp, __LOCAL_SIZE
        mov edi, [ebp+8]
        mov ObjectName, edi
    }
        
    _asm mov edi, DWORD PTR DbgPrint
    _asm mov MyDbgPrint, edi
   
    //MyDbgPrint("object name %ws/n", ObjectName->Buffer);
    //_asm add esp, 8
   
    if(RtlCompareUnicodeString((PUNICODE_STRING)ObjectName, &ObjPtrName, TRUE) == 0)
    {
        _asm
        {
            mov esp, ebp
            pop ebp
            mov eax, 0xC000000D
            ret 10h
        }
    }
   
    __asm
    {
        mov esp, ebp
        pop ebp

        //must declare this tag for insert orginal function's starting bytes here
        _emit 0xaa
        _emit 0xaa
        _emit 0xaa
        _emit 0xaa
    }
}

int GetPatchLength(PCHAR func_start, int max_need_len)
{
    int one_oplen = 0;
    int actual_oplen = 0;
    struct disasm_struct dis;
   
    while(actual_oplen < max_need_len)
    {
        one_oplen = ade32_disasm(func_start, &dis);
        func_start += one_oplen;
        actual_oplen += one_oplen;
    }
   
    return actual_oplen;
}

BOOLEAN UnpatchX(PPATCH_INFO pach)
{
    if(pach->patch_len &&
        pach->org_func_addr)
    {
        RtlCopyMemory(pach->org_func_addr, pach->org_bytes, pach->patch_len);
        return TRUE;
    }
   
    return FALSE;
}

BOOLEAN PatchX(PCHAR func_name, PVOID new_func, int new_func_len, PPATCH_INFO pach)
{
    int i = 0;
    BOOLEAN bFoundTag = FALSE;
   
    WPOFF();
   
    //get original function's address
    pach->org_func_addr = GetKernelFuncAddr(func_name);
    if(pach->org_func_addr)
    {
        pach->patch_len = GetPatchLength(pach->org_func_addr, 7);
        
        pach->new_func_addr = (PVOID)ExAllocatePoolWithTag(NonPagedPool, new_func_len, ' kdD');
        if(pach->new_func_addr)
        {
            RtlCopyMemory(pach->new_func_addr, new_func, new_func_len);
            
            for(i = 0; i < new_func_len-(pach->patch_len + 7); i++)
            {
                //find tag for insert orginal function's starting bytes
                if(((BYTE*)new_func)[i] == 0xaa &&
                    ((BYTE*)new_func)[i+1] == 0xaa &&
                    ((BYTE*)new_func)[i+2] == 0xaa &&
                    ((BYTE*)new_func)[i+3] == 0xaa )
                {
                    bFoundTag = TRUE;
                    break;
                }
            }
            
            if(bFoundTag)
            {
                //save original function's starting bytes for later Unpatch
                RtlCopyMemory(pach->org_bytes, pach->org_func_addr, pach->patch_len);
               
                //modify new_func to jmp to original function
                RtlCopyMemory((BYTE*)pach->new_func_addr + i, pach->org_func_addr, pach->patch_len);
                ((BYTE*)pach->new_func_addr + i + pach->patch_len)[0] = 0xea;
                *(ULONG*)((BYTE*)pach->new_func_addr + i + pach->patch_len + 1) = (ULONG)pach->org_func_addr + pach->patch_len;
                *(USHORT*)((BYTE*)pach->new_func_addr + i + pach->patch_len + 5) = KERNEL_SEG;
               
                //modify original function to jmp to new_func first
                ((BYTE*)pach->org_func_addr)[0] = 0xea;
                *(ULONG*)((BYTE*)pach->org_func_addr+1) = (ULONG)pach->new_func_addr;
                *(USHORT*)((BYTE*)pach->org_func_addr+5) = KERNEL_SEG;
               
                return TRUE;
            }
            else
            {
                ExFreePool(pach->new_func_addr);
                pach->new_func_addr = NULL;
            }
        }
    }
   
    WPON();
   
    return FALSE;
}

NTSTATUS PatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    WCHAR* DeviceName = L"//Device//Harddisk0//DR0";
    UNICODE_STRING uni_name;
    PDEVICE_OBJECT TempDeviceObject;
    PFILE_OBJECT TempFileObject;
    NTSTATUS status;
    PATCH_INFO pach;
   
    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case 1:
        RtlZeroMemory(&pach, sizeof(PATCH_INFO));
        PatchX("IoGetDeviceObjectPointer", NewStubForIoGetDeviceObjectPointer, 256, &pach);
        
        RtlInitUnicodeString(&uni_name, DeviceName);
        status = IoGetDeviceObjectPointer(&uni_name, FILE_READ_DATA, &TempFileObject, &TempDeviceObject);
        
        //UnpatchX(&pach);
        //status = IoGetDeviceObjectPointer(&uni_name, FILE_READ_DATA, &TempFileObject, &TempDeviceObject);
        break;
    }
   
    return PatchCommonDispatch(DeviceObject, Irp);
}

void PatchUnload(    PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING uni_symbolic;
    IoDeleteDevice(DriverObject->DeviceObject);

    RtlInitUnicodeString(&uni_symbolic, L"//DosDevices//doptr");
    IoDeleteSymbolicLink(&uni_symbolic);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    PDEVICE_OBJECT DeviceObject;
    WCHAR* DeviceName = L"//Device//doptr";
    WCHAR* SymbolicName = L"//DosDevices//doptr";
    UNICODE_STRING uni_name, uni_symbolic;
    NTSTATUS status;
    int i;
   
    RtlInitUnicodeString(&ObjPtrName, L"//Device//Harddisk0//DR0");
   
    for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
        DriverObject->MajorFunction[i] = PatchCommonDispatch;
   
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PatchDeviceControl;
    DriverObject->DriverUnload = PatchUnload;
   
    RtlInitUnicodeString(&uni_name, DeviceName);
    status = IoCreateDevice(DriverObject,
                                0,
                                &uni_name,
                                0,
                                0,
                                FALSE,
                                &DeviceObject);
    if(NT_SUCCESS(status))
    {
        DbgPrint("%ws/n", SymbolicName);
        RtlInitUnicodeString(&uni_symbolic, SymbolicName);
        status = IoCreateSymbolicLink(&uni_symbolic, &uni_name);
    }
   
    return status;
}

本文来自 xiaoqiangvs007的专栏
http://blog.csdn.net/xiaoqiangvs007/article/details/5543319

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//