SSDT的例子2-NtOpenProcess

前言

看人家的工程中,都不是直接返回STATUS_ACCESS_DENIED.
在MyNtOpenProcess直接返回STATUS_ACCESS_DENIED并不会影响打开进程.

试验记录

#include <Ntddk.h>
#include <stdlib.h>
#include <stdio.h>

typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int size_t;
typedef unsigned long DWORD;

#define MAXBYTE 0xff
#define MAKEDWORD(L, H) (((WORD)((DWORD_PTR)(L) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(H) & 0xffff))) << 16)

#pragma pack(push)
#pragma pack(1)

typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID   ServiceTableBase;        //这个指向系统服务函数地址表
    PULONG  ServiceCounterTableBase;
    ULONG   NumberOfService;         //服务函数的个数,NumberOfService*4 就是整个地址表的大小
    ULONG   ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DESCRIPTOR_TABLE {
    SYSTEM_SERVICE_TABLE   ntoskrnel;  //ntoskrnl.exe的服务函数
    SYSTEM_SERVICE_TABLE   win32k;     //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)
    SYSTEM_SERVICE_TABLE   NotUsed1;
    SYSTEM_SERVICE_TABLE   NotUsed2;
} SYSTEM_DESCRIPTOR_TABLE, *PSYSTEM_DESCRIPTOR_TABLE;

#pragma pack(pop)

extern PSYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable;
SYSTEM_SERVICE_TABLE* g_pSST = NULL;

// typedef NTSTATUS (__stdcall *PFN_ZwOpenProcess)(
//               __out PHANDLE  ProcessHandle,
//               __in ACCESS_MASK  DesiredAccess,
//               __in POBJECT_ATTRIBUTES  ObjectAttributes,
//               __in_opt PCLIENT_ID  ClientId
//               );

// PFN_ZwOpenProcess g_pfn = NULL;

DWORD g_dwSsdtFunIndexAddr_NtOpenProcess = 0;
DWORD g_dwPfnNtOpenProcessOrg = 0;

// naked 函数内不能初始化变量
// 在裸函数内使用的变量必须在函数外定义
DWORD g_dwAddrJmp_MyNtOpenProcess = 0x805c22a0;
const DWORD g_dw_STATUS_ERR = STATUS_ACCESS_DENIED;
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
                                                     ACCESS_MASK DesiredAccess,
                                                     POBJECT_ATTRIBUTES ObjectAttributes,
                                                     PCLIENT_ID ClientId)
{
    /**
    kd> u 805C2296
    nt!NtOpenProcess:
    805c2296 68c4000000      push    0C4h
    805c229b 68a8aa4d80      push    offset nt!ObWatchHandles+0x25c (804daaa8)
    // 用 __asm + _emit, 在InlineHook函数后,可以跳到任意地址
    // 但是call指令有重定位问题, 如果不修正, 只能在call之前打住

    // 跳到这
    805c22a0 e86b6cf7ff      call    nt!_SEH_prolog (80538f10)

    805c22a5 33f6            xor     esi,esi
    805c22a7 8975d4          mov     dword ptr [ebp-2Ch],esi
    805c22aa 33c0            xor     eax,eax
    805c22ac 8d7dd8          lea     edi,[ebp-28h]
    805c22af ab              stos    dword ptr es:[edi]
    */
    __asm {
        // 这里可以用int 3来调试
        // int 3 

        // 68c4000000
        // 805c2296 68c4000000      push    0C4h

        _emit 0x68
        _emit 0xc4
        _emit 0x00
        _emit 0x00
        _emit 0x00

        // 68a8aa4d80
        // 805c229b 68a8aa4d80      push    offset nt!ObWatchHandles+0x25c (804daaa8)
        _emit 0x68
        _emit 0xa8
        _emit 0xaa
        _emit 0x4d
        _emit 0x80

        // e86b6cf7ff
        // 805c22a0 e86b6cf7ff      call    nt!_SEH_prolog (80538f10)
        // f8dc841a e86b6cf7ff      call    f8d3f08a
        // call 指令涉及到重定位了, opcode一模一样也不是相同的反汇编指令
        // 怪不得人家只跳过前10个字节
//         _emit 0xe8
//         _emit 0x6b
//         _emit 0x6c
//         _emit 0xf7
//         _emit 0xff

        pushf
        pusha
    }
    // do my hook task
    // 调用 KdPrint 可以正常打印
    KdPrint(("MyNtOpenProcess : don't allow open process ^_^\r\n"));
    __asm {
        popa
        popf

        // 对函数入口10字节的2个push进行平栈
        pop eax
        pop eax

        // 返回
        // 返回其他值(不是STATUS_SUCCESS), 进程还是会打开
        // 不管返回什么值, 进程还是会被打开
        // 可能不能Hook这个API.
        // 先丢这里, 以后再玩. SSDT Hook已经成功了
        mov eax, g_dw_STATUS_ERR
        ret

        // jmp g_dwAddrJmp_MyNtOpenProcess
    }
    // return STATUS_SUCCESS;
    // return 0;
}

void fnHook_SSDT()
{
    DWORD dwAddr = 0;

    do {
        if (NULL == KeServiceDescriptorTable) {
            break;
        }

        g_pSST = &KeServiceDescriptorTable->ntoskrnel;

        if (NULL == g_pSST) {
            break;
        }

        KdPrint(("g_pSST = %p\r\n", g_pSST));

        if (NULL == g_pSST->ServiceTableBase) {
            break;
        }

        KdPrint(("g_pSST->ServiceTableBase = %p\r\n", g_pSST->ServiceTableBase));
        // 0x7a is OpenProcess Index On SSDT
        dwAddr = (DWORD)g_pSST->ServiceTableBase + 0x7a * sizeof(DWORD);

        if (0 == dwAddr) {
            break;
        }

        // 要换的就是g_dwSsdtFunIndexAddr_NtOpenProcess地址中的内容
        g_dwSsdtFunIndexAddr_NtOpenProcess = dwAddr;
        KdPrint(("g_dwSsdtFunIndexAddr_NtOpenProcess = %p\r\n", g_dwSsdtFunIndexAddr_NtOpenProcess));
        g_dwPfnNtOpenProcessOrg = *((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess));
        KdPrint(("g_dwPfnNtOpenProcessOrg = %p\r\n", g_dwPfnNtOpenProcessOrg));
        /**
        >> DriverEntry
        g_pSST = 80553FA0
        g_pSST->ServiceTableBase = 80502B8C
        g_dwSsdtFunIndexAddr_NtOpenProcess = 80502D74
        g_dwPfnNtOpenProcessOrg = 805C2296

        kd> u 805C2296
        nt!NtOpenProcess:
        805c2296 68c4000000      push    0C4h
        805c229b 68a8aa4d80      push    offset nt!ObWatchHandles+0x25c (804daaa8)
        805c22a0 e86b6cf7ff      call    nt!_SEH_prolog (80538f10)
        805c22a5 33f6            xor     esi,esi
        805c22a7 8975d4          mov     dword ptr [ebp-2Ch],esi
        805c22aa 33c0            xor     eax,eax
        805c22ac 8d7dd8          lea     edi,[ebp-28h]
        805c22af ab              stos    dword ptr es:[edi]
        */
        __asm { //去掉内存保护
            cli
            mov  eax, cr0
            and  eax, not 10000h
            mov  cr0, eax
        }
        *((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess)) = (DWORD)MyNtOpenProcess;
        __asm { //恢复内存保护
            mov  eax, cr0
            or   eax, 10000h
            mov  cr0, eax
            sti
        }
        KdPrint(("Hook By MyNtOpenProcess = %p\r\n", MyNtOpenProcess));
    } while (0);
}

void fnUnHook_SSDT()
{
    __asm { //去掉内存保护
        cli
        mov  eax, cr0
        and  eax, not 10000h
        mov  cr0, eax
    }
    *((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess)) = (DWORD)g_dwPfnNtOpenProcessOrg;
    __asm { //恢复内存保护
        mov  eax, cr0
        or   eax, 10000h
        mov  cr0, eax
        sti
    }
    KdPrint(("UnHook By g_dwPfnNtOpenProcessOrg = %p\r\n", g_dwPfnNtOpenProcessOrg));
}

VOID fnDrvUnLoad(__in struct _DRIVER_OBJECT* DriverObject)
{
    KdPrint((">> fnDrvUnLoad"));
    fnUnHook_SSDT();
}

NTSTATUS fnDrvDisPatch(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
    KdPrint((">> fnDrvDisPatch"));
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT*  DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    KdPrint((">> DriverEntry"));
    DriverObject->DriverUnload = fnDrvUnLoad;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_READ] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SET_EA] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_POWER] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CHANGE] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_PNP] = fnDrvDisPatch;
    DriverObject->MajorFunction[IRP_MJ_MAXIMUM_FUNCTION] = fnDrvDisPatch;
    fnHook_SSDT();
    return STATUS_SUCCESS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值