<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    無限硬件中斷的代碼實現

    VSole2023-06-01 09:06:35

    一、簡介

    在學習vt時了解到無限硬件斷點技術,即不依賴于dr寄存器實現硬件斷點。

    由于硬件斷點依賴于調試寄存器 dr0-dr3,這就意味著只能設置4個硬件斷點。

    無限硬件斷點的原理

    1.根據目標地址計算出其PTE地址,設置PTE的 nx/xd 屬性,即不可執行屬性。

    (由于PTE控制著4KB物理頁的屬性,因此目標代碼所屬的整個物理頁都被設置為不可執行。)

    2.當執行流執行至目標物理頁時,由于代碼的不可執行屬性而觸發 #PF 缺頁中斷。

    3.此時根據觸發缺頁中斷的線性地址判斷是否為目標地址?若是,則修改PTE的執行屬性并進行事件注入至 #DB,內核異常處理函數將會將該異常派發給調試器。若不是,則仍需要修復PTE的可執行屬性,置位rflags.TF以便于下條指令觸發 #DB 異常被vmm接管,修復cr2并進行事件注入 #PF。

    4.當vmm接管 #DB 異常時,判斷是否為目標進程的目標線性地址,并根據情況進行分類處理。

    二、源碼實現

    關鍵函數的源碼如下:

    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", 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", 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", 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", 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", 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.");
    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
    

    效果圖:


    需要注意的是,我的測試環境為Windows10,單核。
    中斷處理asm
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    (由于PTE控制著4KB物理頁的屬性,因此目標代碼所屬的整個物理頁都被設置為不可執行。若是,則修改PTE的執行屬性并進行事件注入至 #DB,內核異常處理函數將會將該異常派發給調試器。若不是,則仍需要修復PTE的可執行屬性,置位rflags.TF以便于下條指令觸發 #DB 異常被vmm接管,修復cr2并進行事件注入 #PF。
    假如想在x86平臺運行arm程序,稱arm為source ISA, 而x86為target ISA, 在虛擬化的角度來說arm就是Guest, x86為Host。這種問題被稱為Code-Discovery Problem。每個體系結構對應的helper函數在target/xxx/helper.h頭文件中定義。
    內核學習-異常處理
    2021-12-31 16:22:12
    異常產生后,首先是要記錄異常信息,然后要尋找異常的處理函數,稱為異常的分發,最后找到異常處理函數并調用,稱為異常處理。異常處理,異常分發,異常處理 展開。
    API(Application Programming Interface),我們調用時只需提供正確的參數以及接收返回值就可以判斷API執行是否成功或者通過GetLastError獲得錯誤原因.
    能運行的環境包括I/O,權限控制,系統調用,進程管理,內存管理等多項功能都可以歸結到上邊兩點中。需要注意的是,kernel 的crash 通常會引起重啟。注意大多數的現代操作系統只使用了 Ring 0 和 Ring 3。
    MSF+生成流量免殺木馬
    2022-01-14 11:34:16
    在實戰中,即便你繞過了殺毒軟件的檢測,也很有可能會結束在某些流量監控的設備上。MSF可以說其是每一個內網玩家的必用工具。理所當然,這款工具也自然而然地被各大安全廠商分析,捕捉其在命令執行時產生的數據和流量。當我們使用一個沒有做過加密處理的原版工具時,內網中的安全設備會根據我們的流量特征進行判斷,認定我們為惡意進程,從而導致控制中斷。Meterpreter技巧生成后門msfvenom?
    看雪論壇作者ID:xxxlion
    nmap -PN -sS -sV --script=vulscan –script-args vulscancorrelation=1 -p80 target. nmap -PN -sS -sV --script=all –script-args vulscancorrelation=1 target. NetCat,它的實際可運行的名字叫nc,應該早很就被提供,就象另一個沒有公開但是標準的Unix工具。
    vmp 相關的問題
    2021-11-19 16:58:50
    為新版本的符合一個叫做寄存器輪轉的問題所以他可能jmp ebp,jmp edi等等的。
    虛擬機檢測技術整理
    2023-05-11 09:15:35
    第一次嘗試惡意代碼分析就遇到了虛擬機檢測,于是就想著先學習一下檢測的技術然后再嘗試繞過。學習后最終發現,似乎最好的方法不應該是去patch所有檢測方法,而是直接調試并定位檢測函數再繞過。但既然已經研究了兩天,索性將收集到的資料整理一下,方便后人查找。惡意軟件可以搜索這些文件、目錄或進程的存在。VMware 虛擬機中可能會有如下的文件列表:C:\Program Files\VMware\
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类