windows內核研究(軟件調試-軟件斷點)

軟件調試


軟件斷點

調試的本質是什么?

就是在被調試程序中觸發異常,然后被調試程序就會向_DEBUG_OBJECT結構體添加調試事件,這里我們調試器就接管這個異常了(調試的過程就是異常處理的過程)

軟件斷點

在x64dbg中通過快捷鍵F2能下一個軟件中斷,當程序運行到這里時,程序就會停下來,得到程序的控制權,也被稱之為中斷到調試器

本質上就是在當前指定位置的機器碼(硬編碼)改為了int 3,這里可以用其他內存搜索工具查看這個下斷點的地址,可以發現是被改為了int 3(CC)

在這里插入圖片描述

執行流程

  • 被調試進程
    1. 當CPU檢測到INT 3指令
    2. 查IDT表找到對應中斷處理函數
    3. CommonDispatchException
    4. KiDispatchException
    5. DbgkForwardException搜集并發送調試事件 -> DbgkpSendApiMessage(x,x)
  • 調試器進程
    1. 循環判斷調試事件
    2. 取出調試事件
    3. 獲取CPU寄存器上下文和內存
    4. 用戶處理

代碼測試

#include<iostream>
#include<windows.h>
#include <stdint.h>
#include <capstone/capstone.h>
#define DEBUGGR_PROCESS L"C:\\Users\\BananaLi\\Desktop\\HookMe.exe"// 保存原始字節
BYTE originalByte;
BYTE int3 = 0xCC;  // INT3 斷點指令HANDLE g_hDebugThread;
BOOL bInitCapstone = TRUE;
CONTEXT context = { 0 };
BOOL bIsSystemInt3 = TRUE; // 第一次為系統斷點 ntdll!LdrInitializeThunk
DWORD dwContinue DBG_CONTINUE;LPVOID lpAddress;
HANDLE hProcess;// 定義 Capstone 函數指針類型
typedef unsigned int (*cs_open_fn)(unsigned int arch, unsigned int mode, void** handle);
typedef unsigned int (*cs_disasm_fn)(void* handle, const uint8_t* code, size_t code_size, uint64_t address, size_t count, cs_insn** insn);
typedef void (*cs_free_fn)(cs_insn* insn, size_t count);
typedef unsigned int (*cs_close_fn)(void** handle);void DisassembleHex(HANDLE hProcess, LPVOID address, size_t size) {// 1. 加載 capstone.dllHMODULE capstone_dll = LoadLibrary(L"C:\\Users\\BananaLi\\Desktop\\capstone_x64.dll");if (!capstone_dll) {printf("Failed to load capstone.dll! Error: %d\n", GetLastError());}// 2. 獲取函數指針cs_open_fn cs_open = (cs_open_fn)GetProcAddress(capstone_dll, "cs_open");cs_disasm_fn cs_disasm = (cs_disasm_fn)GetProcAddress(capstone_dll, "cs_disasm");cs_free_fn cs_free = (cs_free_fn)GetProcAddress(capstone_dll, "cs_free");cs_close_fn cs_close = (cs_close_fn)GetProcAddress(capstone_dll, "cs_close");if (!cs_open || !cs_disasm || !cs_free || !cs_close) {printf("Failed to get Capstone functions!\n");FreeLibrary(capstone_dll);}// 3. 初始化 Capstone(x64 模式)void* handle;if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {printf("Failed to initialize Capstone!\n");FreeLibrary(capstone_dll);}// 2. 從內存讀取指令字節uint8_t code[32];SIZE_T bytesRead;if (!ReadProcessMemory(hProcess, address, code, size, &bytesRead) || bytesRead != size) {printf("Failed to read memory at 0x%p\n", address);cs_close(&handle);return;}// 3. 反匯編cs_insn* insn;size_t count = cs_disasm(handle, code, bytesRead, (uint64_t)address, 0, &insn);if (count > 0) {printf("Disassembly at 0x%p:\n", address);printf("Address    | Bytes       | Assembly\n");printf("----------------------------------\n");for (size_t i = 0; i < count; i++) {printf("0x%08llx | ", insn[i].address);for (size_t j = 0; j < insn[i].size; j++) {printf("%02x ", insn[i].bytes[j]);}printf("%*s | %s %s\n",(int)(15 - insn[i].size * 3), "",insn[i].mnemonic,insn[i].op_str);}cs_free(insn, count);}else {printf("Failed to disassemble at 0x%p\n", address);}// 4. 關閉引擎cs_close(&handle);
}BOOL WaitForUserCommand() {// 模擬調試器等待用戶輸入命令printf("請輸入命令:\n");system("pause");return TRUE;
}BOOL Int3ExcptionProc(EXCEPTION_DEBUG_INFO* pExceptionInfo) {BOOL bRet = FALSE;// 第一次為系統斷點if (bIsSystemInt3) {bIsSystemInt3 = FALSE;return TRUE;}else {// 恢復原碼BOOL nnn = WriteProcessMemory(hProcess, pExceptionInfo->ExceptionRecord.ExceptionAddress, &originalByte, 1, NULL);printf("error : %d\n", GetLastError());// 顯示斷點位置printf("Int 3斷點地址:0x%p\n",pExceptionInfo->ExceptionRecord.ExceptionAddress);// 獲取線程上下文context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;GetThreadContext(g_hDebugThread, &context);// 修正ripcontext.Rip--;printf("rip的值:0x%p\n\n", context.Rip);GetThreadContext(g_hDebugThread, &context);FlushInstructionCache(GetCurrentProcess(),(LPCVOID)context.Rip,1);printf("------------還原后的正確匯編指令------------\n");// 從斷點位置解釋反匯編代碼DisassembleHex(hProcess, lpAddress,16);// 等待用戶輸入命令while (bRet == FALSE) {bRet = WaitForUserCommand();}}return bRet;
}void setInt3BreakPoint(DEBUG_EVENT* pDebugEvent) {// 獲取進程入口點地址LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)pDebugEvent->u.CreateProcessInfo.lpStartAddress;hProcess = pDebugEvent->u.CreateProcessInfo.hProcess; lpAddress = pDebugEvent->u.CreateProcessInfo.lpStartAddress;printf("斷點位置:0x%p\n",lpAddress);DWORD64 oldAddressData;ReadProcessMemory(hProcess, lpAddress, &oldAddressData, sizeof(DWORD64), NULL);printf("保存前斷點地址對應的硬編碼:%llx\n" , oldAddressData);// 1. 保存原始字節ReadProcessMemory(hProcess, lpAddress, &originalByte, sizeof(BYTE), NULL);printf("保存的originalByte:%llx\n", originalByte);// 2. 寫入INT3指令WriteProcessMemory(hProcess, lpAddress, &int3, sizeof(BYTE), NULL);ReadProcessMemory(hProcess, lpAddress, &oldAddressData, sizeof(DWORD64), NULL);printf("保存后斷點地址對應的硬編碼:%llx\n\n", oldAddressData);printf("------------設置軟件斷點后的匯編指令------------\n");// 從斷點位置解釋反匯編代碼DisassembleHex(hProcess, lpAddress, 16);// 3. 刷新指令緩存FlushInstructionCache(hProcess, lpAddress, sizeof(BYTE));
}// 異常過濾器
BOOL ExceptionHandler(DEBUG_EVENT* pDebugEvent) {BOOL bRet = TRUE;// 得到異常信息EXCEPTION_DEBUG_INFO exceptionInfo = pDebugEvent->u.Exception;// 得到線程句柄g_hDebugThread = OpenThread(THREAD_ALL_ACCESS, FALSE, pDebugEvent->dwThreadId);// 判斷 異常類型switch (exceptionInfo.ExceptionRecord.ExceptionCode) {// int 3 異常case EXCEPTION_BREAKPOINT: {printf("斷點異常\n");bRet = Int3ExcptionProc(&exceptionInfo);break;}// 還有很多其他的異常類型可以處理。。。}return bRet;}int main() {BOOL nIsContinue = TRUE;DEBUG_EVENT debugEvent = { 0 };BOOL bRet = TRUE;// 1.創建調試進程STARTUPINFO startUpInfo = { 0 };PROCESS_INFORMATION pInfo = { 0 };GetStartupInfo(&startUpInfo);bRet = CreateProcess(DEBUGGR_PROCESS, NULL, NULL, NULL, TRUE, DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startUpInfo, &pInfo);if (bRet == FALSE) {printf("創建調試進程失敗,錯誤碼:%d\n",GetLastError());return 0;}// 調試循環(主框架)while (nIsContinue) {// 2.等待調試事件bRet = WaitForDebugEvent(&debugEvent, INFINITE);if (bRet == FALSE) {printf("等待調試事件失敗,錯誤碼:%d\n", GetLastError());return 0;}switch (debugEvent.dwDebugEventCode) {case EXCEPTION_DEBUG_EVENT: {// 處理異常bRet = ExceptionHandler(&debugEvent);if (!bRet)dwContinue = DBG_EXCEPTION_NOT_HANDLED;break;}case CREATE_PROCESS_DEBUG_EVENT: {// 在OPE入口設置斷點setInt3BreakPoint(&debugEvent);break;}case EXIT_PROCESS_DEBUG_EVENT: {nIsContinue = FALSE;break;}case CREATE_THREAD_DEBUG_EVENT: {break;}case EXIT_THREAD_DEBUG_EVENT: {break;}case LOAD_DLL_DEBUG_EVENT: {break;}case UNLOAD_DLL_DEBUG_EVENT: {break;}default:break;}// 讓被調試程序繼續運行bRet = ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, dwContinue);}return 0;
}

效果展示

在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/92126.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/92126.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/92126.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HarmonyOS】鴻蒙應用開發中常用的三方庫介紹和使用示例

&#x1f31f; 鴻蒙應用開發常用三方庫指南&#xff08;2025 最新版&#xff09;適用版本&#xff1a;HarmonyOS NEXT / API 12 參考來源&#xff1a;HarmonyOS 三方庫中心 截止至 2025 年 8 月 1 日&#xff0c;本文整理了當前社區中下載量高、穩定性強、生態完善的熱門三方庫…

【通識】C Sharp

1. 使用 \p{名稱}構造匹配Unicode常規類別&#xff08;該示例為Pd或“標點、短劃線”類別&#xff09;和命名塊&#xff08;IsGreek和IsBsicLatin命名塊&#xff09; using System; using system.Text.RegularExpressions; public class Example {public static void main() {s…

國內首個開源SCA社區——OpenSCA開源社區

OpenSCA開源社區成果說明項目背景智能時代&#xff0c;軟件定義一切。隨著開發模式的敏捷化轉型&#xff0c;開源代碼在軟件制品中的占比越來越大&#xff0c;開源軟件已然成為軟件供應鏈的重要組成部分。由于其特殊性&#xff0c;開源代碼的引入增加了軟件應用的風險面&#x…

超聚變:智能體時代,AI原生重構城企數智化基因

2025 世界人工智能大會&#xff08;WAIC&#xff09;世博展覽館內&#xff0c;超聚變展臺前人頭攢動&#xff0c;其展示的AI落地全棧解決方案及上百個AI應用場景吸引了眾多參觀者駐足觀看。這是今年WAIC大會火爆的一角&#xff0c;更是當下AI應用爆發的一個縮影。當人工智能發展…

Traccar:開源GPS追蹤系統的核心價值與技術全景

Traccar&#xff1a;開源GPS追蹤系統的核心價值與技術全景 —— 從設備兼容到企業級定位管理的開源實踐 一、項目定位&#xff1a;多場景定位管理的開源基石 Traccar是一個高擴展性的開源GPS追蹤平臺&#xff0c;支持全球超過200種通信協議與2000款GPS設備&#xff08;包括車…

編程與數學 03-002 計算機網絡 20_計算機網絡課程實驗與實踐

編程與數學 03-002 計算機網絡 20_計算機網絡課程實驗與實踐一、實驗環境搭建&#xff08;一&#xff09;使用模擬器&#xff08;如Cisco Packet Tracer&#xff09;搭建網絡實驗環境&#xff08;二&#xff09;實驗設備的配置與連接二、基礎網絡實驗&#xff08;一&#xff09…

15個命令上手Linux!

1、id&#xff0c;顯示當前登錄系統的用戶信息2、pwd&#xff0c;顯示當前工作目錄的絕對路徑3、ls&#xff0c;顯示當前目錄下的內容&#xff08;ls -r&#xff1a;按反向順序列出內容&#xff0c;ls -l&#xff1a;以詳細列表形式顯示&#xff09;4、cd&#xff0c;切換工作目…

MongoDB分片技術實現

MongoDB分片技術實現概述MongoDB分片&#xff08;Sharding&#xff09;是MongoDB的水平擴展解決方案&#xff0c;通過將數據分布到多個分片&#xff08;shard&#xff09;上來處理大數據量和高吞吐量的需求。MongoDB分片架構1. 分片集群組件# MongoDB分片集群架構 version: 3.8…

Python開發環境PyCharm下載與安裝

python下載 python下載地址&#xff1a; Download Python | Python.org 上面的下載速度慢的話&#xff0c;用下面的地址下載&#xff08;window&#xff09;&#xff1a; https://download.csdn.net/download/liangmengbk/91580033 PyCharm下載 PyCharm下載地址&#xff1a…

汽車供應鏈PPAP自動化審核指南:如何用AI實現規則精準匹配與文件智能校驗

在汽車行業質量管理的核心環節&#xff0c;PPAP&#xff08;生產件批準程序&#xff09;審核長期困擾著供應商與主機廠。 隨著IATF 16949等標準持續升級、新能源零件復雜度激增&#xff0c;傳統人工審核模式正面臨系統性挑戰。 行業數據顯示&#xff0c;超過70%的SQE&#xf…

正則表達式在js中的應用

正則表達式在 JavaScript 中的應用非常廣泛&#xff0c;尤其是在字符串處理和驗證方面。以下是一些常見的正則表達式方法及其應用示例&#xff0c;包括 .test() 方法。 1. .test() 方法 .test() 方法用于測試一個字符串是否匹配正則表達式。如果匹配&#xff0c;返回 true&…

Rust視頻處理開源項目精選

Rust視頻處理開源項目精選 基于Rust實現的視頻處理示例 以下是一些基于Rust實現的視頻處理或多媒體相關的開源項目或示例,涵蓋編解碼、流媒體、分析工具等方向,可作為實際開發參考: 視頻編解碼與處理 rav1e:Rust編寫的AV1視頻編碼器,高性能且內存安全,適合研究視頻壓縮…

Python爬蟲實戰:研究pycrumbs庫,構建豆瓣讀書數據采集系統

1. 引言 1.1 研究背景 在大數據與人工智能技術快速發展的背景下,互聯網作為全球最大的信息載體,蘊含著海量結構化與非結構化數據。高效、合規地獲取這些數據成為數據分析、業務決策的前提。網絡爬蟲作為自動化數據采集工具,通過模擬人類瀏覽行為遍歷網頁并提取信息,已成為…

linux的用戶操作(詳細介紹)

在 Linux 系統中&#xff0c;用戶管理是系統管理員的核心工作之一&#xff0c;涉及用戶賬號的創建、修改、刪除、權限分配等操作。Linux 采用多用戶多任務機制&#xff0c;通過嚴格的用戶和組管理確保系統安全性和資源分配合理性。以下是 Linux 用戶操作的詳細介紹&#xff1a;…

k8s常見問題

以下是 Kubernetes 常見問題&#xff08;FAQ&#xff09;的整理&#xff0c;涵蓋了初學者和運維人員常遇到的痛點&#xff1a; ?一、部署與安裝問題? ?安裝太復雜&#xff1f;?? 解決方案&#xff1a;使用 ?kubeadm?&#xff08;官方工具&#xff09;、Minikube?&#…

RK Android14 新建分區恢復出廠設置分區數據不擦除及開機動畫自定義(一)

文章目錄 前言 一、分區創建與參數配置 二、分區掛載配置 三、SELinux 安全策略 四、系統初始化配置 五、開機動畫路徑重定向 總結 前言 本方案通過在 RK3568 Android 14 系統中創建一個獨立的 rk_partition 分區(128MB),實現以下核心功能: 出廠設置保護:該分區在恢復出廠…

如何快速給PDF加書簽--保姆級教程

買的電子書沒有目錄書簽看著不舒服&#xff0c;手動加書簽加到想吐。想有沒有辦法快速加書簽。這要分為PDF目錄部分可以被復制和不可被復制兩種情況。不可復制時&#xff0c;要用到工具把目錄提取出來&#xff0c;變成文字。 工具&#xff1a;Foxit Phantom福昕閱讀器&#xff…

Redis面試精講 Day 9:Redis模塊開發與擴展

【Redis面試精講 Day 9】Redis模塊開發與擴展 文章標簽 Redis,模塊開發,擴展機制,面試技巧,Redis模塊,Redis插件 文章簡述 本文是"Redis面試精講"系列第9天&#xff0c;聚焦Redis模塊開發與擴展機制。文章詳細解析Redis模塊系統的架構設計&#xff0c;包括模塊加…

八股訓練--Spring

目錄 一、引言 二、Spring 1.Spring框架的特性 2.介紹一下IOC和AOP 3.IOC和AOP都是如何實現的 4.怎么實現依賴注入 5.為什么AOP不用靜態代理 6.介紹一下反射 7.Spring如何解決循環依賴問題 8.Spring常用注解 9.Spring事務什么情況會失效 10.Bean的生命周期 11.Bean…

無公網環境下在centos7.9上使用kk工具部署k8s平臺(amd64架構)

文章目錄前言一、環境列表二、思路三、環境準備四、有網環境下準備文件1.下載所需的rpm包2.準備harbor需要用到的鏡像3. k8s的鏡像文件4、 生成離線安裝包5、harbor創建項目腳本五、無公網環境部署單點集群1、基礎環境安裝2、安裝harbor3 、 準備k8s鏡像4、安裝k8s六、無公網環…