C/C++知识点之SSDTinlinehook(64位)
小标 2019-03-01 来源 : 阅读 1651 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之SSDTinlinehook(64位),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之SSDTinlinehook(64位),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之SSDTinlinehook(64位)

源码:
https://github.com/haidragon/SSDTHOOK_win7x64/tree/master/SSDTHOOK_win7x64
SSDT表的查找:
https://blog.csdn.net/zfdyq0/article/details/26515019
补充知识点:
syscall是AMD CPU下的sysenter,以此进入内核层,由于64位下没有nt!KiFastCallEntry,而改用的是nt!KiSystemCall64,在64位系统下启用了四个新的MSR寄存器,有不同的作用,其中MSR_LSTAR保存的是rip的相关信息,可以通过rdmsr c0000082的方法查看到syscall跳转地址。这个地址正是nt!KiSystemCall64的入口地址。
32位与64位call地址的区别见:
加密解密4  543页
方式有push/ret
但是x64push只能为32位。但由于对其实际为64位。
因此方式为  push 高位


push  55667788h      //对应opcode  6844332211
mov dword ptr[rsp+4],11223344h    //对应opcode c744240488776655
ret   //对应opcode c3
总共占 14字节


第二种 jmp [addr]


opcode是
ff25 0x00 00 00 00 xx xx xx xx xx xx xx xx  也是总共14字节 前面0x00 00 00 00 用做偏移


第三种是 jmp eax 


mov rax,1122334455667788  //opcode 48b8 8877665544332211
jmp rax   //opcode ffe0 
共12字节


逆向工程核心原理 390页
纠正上面博客的一个错误:

刚好是fffff800`03e82772 4c8d15c7202300 后面四个字节(002320C7)
4c8d 是lea指令opcode  15表示r10 


  kd> u KiSystemServiceStart
  nt!KiSystemServiceStart:
  fffff800`03e8275e 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp
  fffff800`03e82765 8bf8            mov     edi,eax
  fffff800`03e82767 c1ef07          shr     edi,7
  fffff800`03e8276a 83e720          and     edi,20h
  fffff800`03e8276d 25ff0f0000      and     eax,0FFFh
  nt!KiSystemServiceRepeat:
  fffff800`03e82772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]
  fffff800`03e82779 4c8d1d00212300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]
  fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h


SSDT hook
源码:main.c


#include <hookssdt.h>

//驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
    UnhookSSDT();
    DbgPrint("Driver Unload\n");
}

//驱动入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath)
{
    DbgPrint("Hello World\n");
    //获取KeServiceDescriptorTable
    KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
    //开启Hook
    HookSSDT();
    pDriver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


hookssdt.h


#include <ntddk.h>

typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID       ServiceTableBase;
    PVOID       ServiceCounterTableBase;
    ULONGLONG   NumberOfServices;
    PVOID       ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DESCRIPTOR_TABLE {
    SYSTEM_SERVICE_TABLE ntoskrnl;  // ntoskrnl.exe (native api)
    SYSTEM_SERVICE_TABLE win32k;    // win32k.sys   (gdi/user)
    SYSTEM_SERVICE_TABLE Table3;    // not used
    SYSTEM_SERVICE_TABLE Table4;    // not used
}SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

//NtTerminateProcess
typedef NTSTATUS(__fastcall *NTTERMINATEPROCESS)(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus);

NTKERNELAPI UCHAR * PsGetProcessImageFileName(PEPROCESS Process);

//SSDT表基址
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
NTTERMINATEPROCESS NtTerminateProcess = NULL;
ULONG OldTpVal;

//自己的NtTerminateProcess
NTSTATUS __fastcall Fuck_NtTerminateProcess(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus)
{
    PEPROCESS Process;
    NTSTATUS st = ObReferenceObjectByHandle(ProcessHandle, 0, *PsProcessType, KernelMode, &Process, NULL);
    DbgPrint("Fake_NtTerminateProcess called!");
    if (NT_SUCCESS(st))
    {
        if (!_stricmp(PsGetProcessImageFileName(Process), "calc.exe"))
            return STATUS_ACCESS_DENIED;
        else
            return NtTerminateProcess(ProcessHandle, ExitStatus);
    }
    else
        return STATUS_ACCESS_DENIED;
}
//关闭写保护
KIRQL WPOFFx64()
{
    KIRQL irql = KeRaiseIrqlToDpcLevel();
    UINT64 cr0 = __readcr0();
    cr0 &= 0xfffffffffffeffff;
    __writecr0(cr0);
    _disable();
    return irql;
}
//开启写保护
void WPONx64(KIRQL irql)
{
    UINT64 cr0 = __readcr0();
    cr0 |= 0x10000;
    _enable();
    __writecr0(cr0);
    KeLowerIrql(irql);
}

ULONGLONG GetKeServiceDescriptorTable64() //我的方法
{
    PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
    PUCHAR i = NULL;
    UCHAR b1 = 0, b2 = 0, b3 = 0;
    ULONG templong = 0;
    ULONGLONG addr = 0;
    for (i = StartSearchAddress;i < EndSearchAddress;i++)
    {
        if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
        {
            b1 = *i;
            b2 = *(i + 1);
            b3 = *(i + 2);
            if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
            {
                memcpy(&templong, i + 3, 4);
                addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
                return addr;
            }
        }
    }
    return 0;
}

//获取SSDT中的函数地址
ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
    LONG dwtmp = 0;
    PULONG ServiceTableBase = NULL;
    ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
    dwtmp = ServiceTableBase[id];
    dwtmp = dwtmp >> 4;
    return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}

ULONG GetOffsetAddress(ULONGLONG FuncAddr)
{
    ULONG dwtmp = 0;
    PULONG ServiceTableBase = NULL;
    ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
    dwtmp = (ULONG)(FuncAddr - (ULONGLONG)ServiceTableBase);
    return dwtmp << 4;
}

//InlineHook_KeBugCheckEx
VOID FuckKeBugCheckEx()
{
    KIRQL irql;
    ULONGLONG myfun;
    UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";
    myfun = (ULONGLONG)Fuck_NtTerminateProcess;//替换成自己的函数地址
    memcpy(jmp_code + 2, &myfun, 8);
    irql = WPOFFx64();
    memset(KeBugCheckEx, 0x90, 15);
    memcpy(KeBugCheckEx, jmp_code, 12);
    WPONx64(irql);
}

VOID HookSSDT()
{
    KIRQL irql;
    ULONGLONG dwtmp = 0;
    PULONG ServiceTableBase = NULL;
    //get old address
    NtTerminateProcess = (NTTERMINATEPROCESS)GetSSDTFuncCurAddr(41);
    DbgPrint("Old_NtTerminateProcess: %llx", (ULONGLONG)NtTerminateProcess);
    //set kebugcheckex
    FuckKeBugCheckEx();
    //show new address
    ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
    OldTpVal = ServiceTableBase[41];    //record old offset value
    irql = WPOFFx64();
    ServiceTableBase[41] = GetOffsetAddress((ULONGLONG)KeBugCheckEx);
    WPONx64(irql);
    DbgPrint("KeBugCheckEx: %llx", (ULONGLONG)KeBugCheckEx);
    DbgPrint("New_NtTerminateProcess: %llx", GetSSDTFuncCurAddr(41));
}

VOID UnhookSSDT()
{
    KIRQL irql;
    PULONG ServiceTableBase = NULL;
    ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
    //set value
    irql = WPOFFx64();
    ServiceTableBase[41] = GetOffsetAddress((ULONGLONG)NtTerminateProcess); //OldTpVal; //直接填写这个旧值也行
    WPONx64(irql);
    //没必要恢复KeBugCheckEx的内容了,反正执行到KeBugCheckEx时已经完蛋了。
    DbgPrint("NtTerminateProcess: %llx", GetSSDTFuncCurAddr(41));
}

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程