首页
社区
课程
招聘
[原创] 无限硬件中断的代码实现
发表于: 2023-5-6 15:27 22691

[原创] 无限硬件中断的代码实现

2023-5-6 15:27
22691

在学习vt时了解到无限硬件断点技术,即不依赖于dr寄存器实现硬件断点。
由于硬件断点依赖于调试寄存器 dr0-dr3,这就意味着只能设置4个硬件断点。

无限硬件断点的原理

关键函数的源码如下:

效果图:

图片描述

需要注意的是,我的测试环境为Windows10,单核。

参考:https://bbs.kanxue.com/thread-111149.htm

自己踩过的坑:

 
void HandleOfInterruption()
{
    Rflags rflags = { 0 };
    VmExitInterruptInformation exit_interrupt_info = { 0 };
    ExitQualification exit_qualification = { 0 };
    IA32_DEBUGCTL_STRUCRION ia32_debugctl = { 0 };
 
    rflags.all = g_pGuestRegs->rflags;
    asm_vmread32(&g_vmm_handle_config.exit_instruction_length, VM_EXIT_INSTRUCTION_LEN);
    asm_vmread(&exit_qualification, EXIT_QUALIFICATION);
    asm_vmread32(&exit_interrupt_info, VM_EXIT_INTR_INFO);
    asm_vmread32(&ia32_debugctl, IA32_DEBUGCTL);
 
    if (exit_interrupt_info.Bits.valid)
    {
        /*
        *   中断类型: 0.外部中断, 2.nmi, 3.硬件中断, 6.软中断
        */
        switch (exit_interrupt_info.Bits.vector)
        {
 
        case 1// debug 硬件中断
        {
            // signel-step      exit_qualification.Bits.bs=true
            if (rflags.Bits.tf && !ia32_debugctl.Bits.btf)
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #DB signel-step ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
 
                /*
                *   是否开启无线硬件中断? 若开启则重新设置页属性nx
                */
                if (g_vmx_config.enable_unlimit_hardware_breakpoint)
                {
                    unsigned __int64 guest_cr3;
                    asm_vmread(&guest_cr3, GUEST_CR3);
 
                    if (directory_table_base.user_cr3 == guest_cr3 ||
                        directory_table_base.kernel_cr3 == guest_cr3)
                    {
                        SetupPteNx(g_pGuestRegs->rip, TRUE);
 
                        rflags.Bits.tf = FALSE;
                        asm_vmwrite(GUEST_RFLAGS, rflags.all);
                        break;
                    }
                }
 
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
                break;
            }
 
            // haredWare breakpointer
            if (!rflags.Bits.tf && (exit_qualification.all & 0xf))
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #DB hard-ware ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
                break;
            }
 
            break;
        }
 
        case 3// int3 软中断
        {
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #BP ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
            g_vmm_handle_config.Config.Bits.event_inject = TRUE;
            break;
        }
 
        case 0xe:   // page_fault   软中断
        {
            unsigned __int64 guest_cr3;
            asm_vmread(&guest_cr3, GUEST_CR3);
 
            if (g_vmx_config .enable_unlimit_hardware_breakpoint && (
                directory_table_base.user_cr3 == guest_cr3 ||
                directory_table_base.kernel_cr3 == guest_cr3))
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #PF ==> GuestRIP: 0x%p, GuestRSP: 0x%p, fault_address: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp, exit_qualification.all);
 
                /*
                *   目标地址: 1.取消nx; 2.将异常注入给#DB;
                */
                if (exit_qualification.all == targetAddress)
                {
                    exit_interrupt_info.Bits.type = 3;
                    exit_interrupt_info.Bits.vector = 1;
                    exit_interrupt_info.Bits.error_code_valid = FALSE;
                    g_vmm_handle_config.Config.Bits.event_inject = TRUE;
 
                    SetupPteNx(exit_qualification.all, FALSE);
                }
                else
                {   /* 程序正常返回执行 signel-step */
                    SetupPteNx(exit_qualification.all, FALSE);
                    g_vmm_handle_config.Config.Bits.event_inject = FALSE;
 
                    rflags.Bits.tf = TRUE;
                    asm_vmwrite(GUEST_RFLAGS, rflags.all);
                }               
            }
            else
            {
                asm_WriteCr2(exit_qualification.all);
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
            }
 
            break;
        }
 
        default:
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] 未处理中断 ==> type: %d, index: %d\n", exit_interrupt_info.Bits.type, exit_interrupt_info.Bits.vector);
        }
 
        /*
        *   事件注入
        */
        if (g_vmm_handle_config.Config.Bits.event_inject)
        {
            VmEntryInterruptionInformationField interruption_information_field = { 0 };
            interruption_information_field.Bits.valid = TRUE;
            interruption_information_field.Bits.type = exit_interrupt_info.Bits.type;
            interruption_information_field.Bits.vector = exit_interrupt_info.Bits.vector;
 
            if (exit_interrupt_info.Bits.error_code_valid)
            {
                UINT64 ExitInterruptErrorCode = 0;
                interruption_information_field.Bits.deliver_error_code = TRUE;
                asm_vmread(&ExitInterruptErrorCode, VM_EXIT_INTR_ERROR_CODE);
                asm_vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, ExitInterruptErrorCode);
            }
 
            asm_vmwrite(VM_ENTRY_INSTRUCTION_LEN, g_vmm_handle_config.exit_instruction_length);
            asm_vmwrite(VM_ENTRY_INTR_INFO_FIELD, interruption_information_field.all);
 
            /*VmxProcessorBasedControls process_base;
            asm_vmread(&process_base.all, CPU_BASED_VM_EXEC_CONTROL);
            process_base.Bits.monitor_trap_flag = TRUE;
            asm_vmwrite(CPU_BASED_VM_EXEC_CONTROL, process_base.all);*/
        }
 
    }
    else
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] 无效ExitInterruptInfo.\n");
 
tag_ret:
    return;
}
 
__int64 pte_base;    // 用于线性地址与pte的转换
DirectoryTableBase directory_table_base = { 0 };
__int64* targetAddress = 0x0000000140001130;
_PsLookupProcessByProcessId WkPsLookUpProcessByProcessId;
 
void SetupPteNx(__int64* address, BOOLEAN setup)
{
    PHYSICAL_ADDRESS pa;
    pa.QuadPart = 0xffffffffffffffff;
    PAttachProcessStruct attach_procee = (PAttachProcessStruct)MmAllocateContiguousMemory(sizeof(AttachProcessStruct), pa);
 
    attach_procee->target_cr3 = directory_table_base.kernel_cr3;
    attach_procee->pte = (((__int64)address >> 9) & 0x7ffffffff8) + pte_base;
    attach_procee->setup = setup;
 
    /*
    *    切换Cr3并修改pte
    */
    AttachProcess(attach_procee->target_cr3, &attach_procee->currect_cr3);
    memcpy(&attach_procee->pte_t, (void*)attach_procee->pte, 8);
    attach_procee->pte_t.Bits.xd = attach_procee->setup;
    memcpy((void*)attach_procee->pte, &attach_procee->pte_t, 8);
    AttachProcess(attach_procee->currect_cr3, &attach_procee->currect_cr3);
 
    MmFreeContiguousMemory(attach_procee);
}
 
void InitDirectoryTableBaseByPid(__int64 pid)
{
    PEPROCESS pEProcess;
 
    WkPsLookUpProcessByProcessId(pid, &pEProcess);
    directory_table_base.kernel_cr3 = *(__int64*)((__int64)pEProcess + 0x28);
    directory_table_base.user_cr3 = *(__int64*)((__int64)pEProcess + 0x280);
    ObDereferenceObject(pEProcess);
}
 
void UnlimitHareWareBreakpoint(int index)
{
    UNICODE_STRING unicode_PsLookUpProcessByProcessId;
    UNICODE_STRING unicode_MiSystemFault;
 
    idt_hook_config.Bits.set_pte_nx = TRUE;
 
    // 初始化PsLookupProcessByProcessId
    RtlInitUnicodeString(&unicode_PsLookUpProcessByProcessId, L"PsLookupProcessByProcessId");
    WkPsLookUpProcessByProcessId = (_PsLookupProcessByProcessId)MmGetSystemRoutineAddress(&unicode_PsLookUpProcessByProcessId);
 
    pte_base = *(__int64*)((__int64)MmProtectMdlSystemAddress + 0xc9);
 
    InitDirectoryTableBaseByPid(3724);
    SetupPteNx(targetAddress, TRUE);
}
 
asm_AttachProcess    proc
    mov        rax, cr3
    mov        [rdx], rax
    mov        cr3, rcx
    ret
asm_AttachProcess    endp
void HandleOfInterruption()
{
    Rflags rflags = { 0 };
    VmExitInterruptInformation exit_interrupt_info = { 0 };
    ExitQualification exit_qualification = { 0 };
    IA32_DEBUGCTL_STRUCRION ia32_debugctl = { 0 };
 
    rflags.all = g_pGuestRegs->rflags;
    asm_vmread32(&g_vmm_handle_config.exit_instruction_length, VM_EXIT_INSTRUCTION_LEN);
    asm_vmread(&exit_qualification, EXIT_QUALIFICATION);
    asm_vmread32(&exit_interrupt_info, VM_EXIT_INTR_INFO);
    asm_vmread32(&ia32_debugctl, IA32_DEBUGCTL);
 
    if (exit_interrupt_info.Bits.valid)
    {
        /*
        *   中断类型: 0.外部中断, 2.nmi, 3.硬件中断, 6.软中断
        */
        switch (exit_interrupt_info.Bits.vector)
        {
 
        case 1// debug 硬件中断
        {
            // signel-step      exit_qualification.Bits.bs=true
            if (rflags.Bits.tf && !ia32_debugctl.Bits.btf)
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #DB signel-step ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
 
                /*
                *   是否开启无线硬件中断? 若开启则重新设置页属性nx
                */
                if (g_vmx_config.enable_unlimit_hardware_breakpoint)
                {
                    unsigned __int64 guest_cr3;
                    asm_vmread(&guest_cr3, GUEST_CR3);
 
                    if (directory_table_base.user_cr3 == guest_cr3 ||
                        directory_table_base.kernel_cr3 == guest_cr3)
                    {
                        SetupPteNx(g_pGuestRegs->rip, TRUE);
 
                        rflags.Bits.tf = FALSE;
                        asm_vmwrite(GUEST_RFLAGS, rflags.all);
                        break;
                    }
                }
 
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
                break;
            }
 
            // haredWare breakpointer
            if (!rflags.Bits.tf && (exit_qualification.all & 0xf))
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #DB hard-ware ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
                break;
            }
 
            break;
        }
 
        case 3// int3 软中断
        {
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #BP ==> GuestRIP: 0x%p, GuestRSP: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp);
            g_vmm_handle_config.Config.Bits.event_inject = TRUE;
            break;
        }
 
        case 0xe:   // page_fault   软中断
        {
            unsigned __int64 guest_cr3;
            asm_vmread(&guest_cr3, GUEST_CR3);
 
            if (g_vmx_config .enable_unlimit_hardware_breakpoint && (
                directory_table_base.user_cr3 == guest_cr3 ||
                directory_table_base.kernel_cr3 == guest_cr3))
            {
                DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] #PF ==> GuestRIP: 0x%p, GuestRSP: 0x%p, fault_address: 0x%p\n", g_pGuestRegs->rip, g_pGuestRegs->rsp, exit_qualification.all);
 
                /*
                *   目标地址: 1.取消nx; 2.将异常注入给#DB;
                */
                if (exit_qualification.all == targetAddress)
                {
                    exit_interrupt_info.Bits.type = 3;
                    exit_interrupt_info.Bits.vector = 1;
                    exit_interrupt_info.Bits.error_code_valid = FALSE;
                    g_vmm_handle_config.Config.Bits.event_inject = TRUE;
 
                    SetupPteNx(exit_qualification.all, FALSE);
                }
                else
                {   /* 程序正常返回执行 signel-step */
                    SetupPteNx(exit_qualification.all, FALSE);
                    g_vmm_handle_config.Config.Bits.event_inject = FALSE;
 
                    rflags.Bits.tf = TRUE;
                    asm_vmwrite(GUEST_RFLAGS, rflags.all);
                }               
            }
            else
            {
                asm_WriteCr2(exit_qualification.all);
                g_vmm_handle_config.Config.Bits.event_inject = TRUE;
            }
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-5-6 15:28 被ALwalker编辑 ,原因:
收藏
免费 9
支持
分享
最新回复 (13)
雪    币: 2517
活跃值: (1735)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
前排瓜子麻花
2023-5-6 16:41
0
雪    币: 15028
活跃值: (6233)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
ring3 VirtualProtect即可。
2023-5-6 17:18
0
雪    币: 12857
活跃值: (9172)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
4
燕国地图出来了是吧
2023-5-6 18:50
0
雪    币: 4651
活跃值: (4617)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
有没有调用的例子
2023-5-7 10:33
0
雪    币: 3785
活跃值: (3947)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
感谢分享!
2023-5-7 10:46
0
雪    币: 1935
活跃值: (4180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2023-5-7 11:26
0
雪    币: 16568
活跃值: (1855)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
@ALwalker
刚刚学会用Delphi写x64dbg插件,
那请问下能不能让x64dbg也享受到此待遇?
2023-5-8 09:45
0
雪    币: 1045
活跃值: (5165)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
killbr @ALwalker 刚刚学会用Delphi写x64dbg插件, 那请问下能不能让x64dbg也享受到此待遇?
你可以自己尝试以下
2023-5-8 10:31
0
雪    币: 3573
活跃值: (31026)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享
2023-5-9 09:05
1
雪    币: 3479
活跃值: (3163)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好诡异的操作,学到了,哈哈
2023-5-9 16:53
0
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
厉害厉害 下一步就是过VT检测了吧
2023-5-10 21:24
0
雪    币: 61
活跃值: (996)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
无限硬断应该是用ept直接把物理地址设为不可执行吧
2023-5-23 09:58
0
雪    币: 516
活跃值: (1908)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
MTF的GUEST RIP不是断下指令的下一行,这是什么鬼???是一个内核地址KiDebugTrapOrFault
2024-6-8 23:41
0
游客
登录 | 注册 方可回帖
返回
//