百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

Windows平台调试器原理与编写02.一般断点与反汇编引擎

liuian 2025-03-12 16:46 41 浏览

https://www.bpsend.net/thread-256-1-2.html

一般断点(软件断点)

断点的尊严

  1. 断的下来
  2. 走的过去
  3. 下次还来

所有合格的断点都应该满足这3个要求

OD下断点实际是把指令的第一个字节改成了CC,当程序执行到CC的时候其实是抛了一个异常(EXCEPTION_BREAKPOINT),这个异常就会进入调试器里面因为处于调试状态,调试器拿到这个异常之后就会知道程序要断到这里,写了CC之后,这条指令正常的功能就被破坏了,但是这条指令正常功能中他还是应该执行的,那怎么让他走过去呢,那就是把这条指令恢复,下次再来只需要走过去之后再把它写回CC,这条指令执行完可通过 TF 标志位 来实现, (TF置1就会抛出异常(EXCEPTION_SINGLE_STEP)),

断步配合: 断点和单步配合实现断点下次再来

调试的时候 如果 断点下次没来 就检查断步配合,如果崩了说明没有恢复,如果程序跑飞了,断点不再来,说明单步没处理好

调试器对被调试进程拥有所有的权限(除了写)

第二个成员就是调试器判断异常第一个次来还是第二次

第一个成员,异常信息结构体

获取寄存器环境 GetThreadContext

第一个参数: 线程句柄 ,第二个结构体指针(结构体类型要到 vs中去看, msdn没有)

代码实现

以扫雷为例

扫雷的过程函数:
地址                    机器码           助记符
01001BC9          55                  push    ebp
01001BCA         8BEC             mov     ebp, esp
01001BCC         83EC 40        sub     esp, 40
01001BCF         8B55 0C        mov     edx, dword ptr [ebp+C]        //在该行下断点
01001BD2         8B4D 14       mov     ecx, dword ptr [ebp+14]
01001BD5         53                  push    ebx
01001BD6         56                  push    esi
01001BD7         33DB             xor     ebx, ebx
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   include msvcrt.inc
   
   includelib user32.lib
   includelib kernel32.lib
   includelib msvcrt.lib
   
.data
    g_szExe db "winmine.exe", 0     ;被调试的程序
    g_hExe  dd 0                    ;被调试的程序句柄
    g_szEXCEPTION_DEBUG_EVENT         db "EXCEPTION_DEBUG_EVENT", 0dh, 0ah, 0
    g_szCREATE_THREAD_DEBUG_EVENT     db "CREATE_THREAD_DEBUG_EVENT", 0dh, 0ah, 0
    g_szCREATE_PROCESS_DEBUG_EVENT    db "CREATE_PROCESS_DEBUG_EVENT", 0dh, 0ah, 0
    g_szEXIT_THREAD_DEBUG_EVENT       db "EXIT_THREAD_DEBUG_EVENT", 0dh, 0ah, 0
    g_szEXIT_PROCESS_DEBUG_EVENT      db "EXIT_PROCESS_DEBUG_EVENT", 0dh, 0ah, 0
    g_szLOAD_DLL_DEBUG_EVENT          db "LOAD_DLL_DEBUG_EVENT", 0dh, 0ah, 0
    g_szUNLOAD_DLL_DEBUG_EVENT        db "UNLOAD_DLL_DEBUG_EVENT", 0dh, 0ah, 0
    g_szOUTPUT_DEBUG_STRING_EVENT     db "OUTPUT_DEBUG_STRING_EVENT", 0dh, 0ah, 0
  
    g_szLoadDllFmt    db "%08X %s", 0dh, 0ah, 0
    g_szwLoadDllFmt   dw '%', '0', '8', 'X', ' ', '%', 's', 0dh, 0ah, 0
  
    g_szBpFmt  db      "CC异常 %08X", 0dh, 0ah, 0
    g_szSsFmt  db      "单步异常 %08X", 0dh, 0ah, 0
  
    g_btOldCode db   0           ;记录没下断点之前的字符
    g_dwBpAddr  dd   01001BCFh   ;下断点的地址
    g_byteCC    db   0CCh        ; 短点符号 CC 
   
.code  

;处理异常信息
OnException proc uses esi pDE:ptr DEBUG_EVENT 
    LOCAL @dwOldProc:DWORD   ;修改之前的内存属性
    LOCAL @dwBytesOut:DWORD   
    LOCAL @hThread:HANDLE
    LOCAL @ctx:CONTEXT

    mov esi, pDE
    assume esi:ptr DEBUG_EVENT
  
    ;判断是否断点异常
    .if [esi].u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT
      
        ;判断是否是自己的CC  通过地址判断
        mov eax, [esi].u.Exception.pExceptionRecord.ExceptionAddress
        .if eax != g_dwBpAddr     ;该处地址是不是我们下断点地址
            ;不是自己的CC异常,不处理
            mov eax, DBG_EXCEPTION_NOT_HANDLED 
            ret
        .endif
  
    
        ;处理自己的CC异常
        invoke crt_printf, offset g_szBpFmt, [esi].u.Exception.pExceptionRecord.ExceptionAddress
      
         ;修改内存属性
        invoke VirtualProtect, g_dwBpAddr, 1, PAGE_EXECUTE_READWRITE, addr @dwOldProc

        ;恢复指令
        invoke WriteProcessMemory, g_hExe, g_dwBpAddr, offset g_btOldCode, size g_btOldCode, addr @dwBytesOut 
  
        ;还原内存属性
        invoke VirtualProtect, g_dwBpAddr, 1, @dwOldProc, addr @dwOldProc
      
        ;设置单步
      
        ;获取线程句柄
        invoke OpenThread, THREAD_ALL_ACCESS, FALSE, [esi].dwThreadId
        mov @hThread, eax
      
        ;设置结构体标志位,用来判断获取那些寄存器环境
        ; CONTEXT_FULL  表示获取控制,整数,段   CONTEXT_ALL 是所有的
        mov @ctx.ContextFlags, CONTEXT_FULL
        ;获取寄存器环境
        invoke GetThreadContext, @hThread, addr @ctx
      
        ;将TF标志位置1
        or @ctx.regFlag, 100h
          
        ;返回当前代码地址  @ctx.regEip 执行完CC的地址 
        dec @ctx.regEip     ;减1,cc是一个字节.
      
        ;设置寄存器环境
        invoke SetThreadContext, @hThread, addr @ctx
      
        ;关闭线程句柄
        invoke CloseHandle, @hThread
      
        mov eax, DBG_CONTINUE
        ret
    .endif
  
    ;单步来了  (如果是单步异常)
    .if [esi].u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP
        ;处理自己的单步
        invoke crt_printf, offset g_szSsFmt, [esi].u.Exception.pExceptionRecord.ExceptionAddress
      
         ;修改内存属性
        invoke VirtualProtect, g_dwBpAddr, 1, PAGE_EXECUTE_READWRITE, addr @dwOldProc
  
        ;重设断点, 重新写入CC
        invoke WriteProcessMemory, g_hExe,  g_dwBpAddr, offset g_byteCC, size g_byteCC, addr @dwBytesOut
  
        ;还原内存属性
        invoke VirtualProtect, g_dwBpAddr, 1, @dwOldProc, addr @dwOldProc
  
        ;异常已处理,继续执行代码
        mov eax, DBG_CONTINUE
        ret
    .endif
  
  
    assume esi:nothing
  
    mov eax, DBG_EXCEPTION_NOT_HANDLED 
    ret

OnException endp



OnCreateProcess proc 
    LOCAL @dwBytesOut:DWORD  
    LOCAL @dwOldProc:DWORD   ;修改之前的内存属性
  
    ;修改内存属性
    invoke VirtualProtect, g_dwBpAddr, 1, PAGE_EXECUTE_READWRITE, addr @dwOldProc
  
  
    ;保存原来的被下断点地址 指令到 g_btOldCode ,用于恢复
    invoke ReadProcessMemory, g_hExe, g_dwBpAddr, offset g_btOldCode, size g_btOldCode, addr @dwBytesOut
  
    ;在 01001BCF(断点地址)写入CC
    invoke WriteProcessMemory, g_hExe,  g_dwBpAddr, offset g_byteCC, size g_byteCC, addr @dwBytesOut
  
  
    ;还原内存属性
    invoke VirtualProtect, g_dwBpAddr, 1, @dwOldProc, addr @dwOldProc
  
    ret

OnCreateProcess endp


main proc
    LOCAL @si:STARTUPINFO
    LOCAL @pi:PROCESS_INFORMATION
    LOCAL @de:DEBUG_EVENT 
    LOCAL @dwStatus:DWORD   ;事件处理结果
  
    invoke RtlZeroMemory, addr @si, size @si
    invoke RtlZeroMemory, addr @pi, size @pi
    invoke RtlZeroMemory, addr @de, size @de
  
    mov @dwStatus, DBG_CONTINUE
    ;建立调试会话
    invoke CreateProcess, NULL, offset g_szExe, NULL, NULL, FALSE, \
        DEBUG_ONLY_THIS_PROCESS,\
        NULL, NULL,\
        addr @si,\
        addr @pi
    .if !eax
        ret
    .endif 
    mov eax, @pi.hProcess
    mov g_hExe, eax
  
    ;循环接受调试事件
    .while TRUE
        invoke WaitForDebugEvent, addr @de, INFINITE
      
        ;处理调试事件
        .if @de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
            ;invoke crt_printf, offset g_szEXCEPTION_DEBUG_EVENT
            invoke OnException, addr @de
            mov @dwStatus, eax
        .elseif @de.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT
            invoke crt_printf, offset g_szCREATE_THREAD_DEBUG_EVENT
        .elseif @de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT
            ;invoke crt_printf, offset g_szCREATE_PROCESS_DEBUG_EVENT
            invoke OnCreateProcess
        .elseif @de.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT
            invoke crt_printf, offset g_szEXIT_THREAD_DEBUG_EVENT
        .elseif @de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT
            invoke crt_printf, offset g_szEXIT_PROCESS_DEBUG_EVENT
        .elseif @de.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT
            ;invoke OnLoadDll, addr @de
        .elseif @de.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT
            invoke crt_printf, offset g_szUNLOAD_DLL_DEBUG_EVENT
        .elseif @de.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT
            invoke crt_printf, offset g_szOUTPUT_DEBUG_STRING_EVENT
        .endif
      
        ;提交事件处理结果
        invoke ContinueDebugEvent, @de.dwProcessId, @de.dwThreadId, @dwStatus
        invoke RtlZeroMemory, addr @de, size @de
    .endw
  
    ret

main endp


start:
    invoke main 

end start

反汇编引擎

https://bbs.pediy.com/thread-205590.htm

udis86官网
http://udis86.sourceforge.net/

udis86.zip

00513D41    8945 FC         mov     dword ptr [ebp-4], eax
00513D44    817D FC 4EE640B>cmp     dword ptr [ebp-4], BB40E64E
00513D4B    75 09           jnz     short 00513D56
00513D4D    C745 FC 4FE640B>mov     dword ptr [ebp-4], BB40E64F
00513D54    EB 1C           jmp     short 00513D72
00513D56    8B55 FC         mov     edx, dword ptr [ebp-4]
00513D59    81E2 0000FFFF   and     edx, FFFF0000
00513D5F    75 11           jnz     short 00513D72
00513D61    8B45 FC         mov     eax, dword ptr [ebp-4]
00513D64    0D 11470000     or      eax, 4711
00513D69    C1E0 10         shl     eax, 10
00513D6C    0B45 FC         or      eax, dword ptr [ebp-4]
00513D6F    8945 FC         mov     dword ptr [ebp-4], eax
00513D72    8B4D FC         mov     ecx, dword ptr [ebp-4]
00513D75    890D 04A05100   mov     dword ptr [__security_cookie], e>
00513D7B    8B55 FC         mov     edx, dword ptr [ebp-4]
00513D7E    F7D2            not     edx
00513D80    8915 00A05100   mov     dword ptr [__security_cookie_com>
00513D86    8BE5            mov     esp, ebp
00513D88    5D              pop     ebp
00513D89    C3              ret

#include "udis86.h"
#pragma comment(lib, "libudis86.lib")

#include 
using namespace std;

int  main()
{
	unsigned char data[73] = {
	0x89, 0x45, 0xFC, 0x81, 0x7D, 0xFC, 0x4E, 0xE6, 0x40, 0xBB, 0x75, 0x09, 0xC7, 0x45, 0xFC, 0x4F,
	0xE6, 0x40, 0xBB, 0xEB, 0x1C, 0x8B, 0x55, 0xFC, 0x81, 0xE2, 0x00, 0x00, 0xFF, 0xFF, 0x75, 0x11,
	0x8B, 0x45, 0xFC, 0x0D, 0x11, 0x47, 0x00, 0x00, 0xC1, 0xE0, 0x10, 0x0B, 0x45, 0xFC, 0x89, 0x45,
	0xFC, 0x8B, 0x4D, 0xFC, 0x89, 0x0D, 0x04, 0xA0, 0x51, 0x00, 0x8B, 0x55, 0xFC, 0xF7, 0xD2, 0x89,
	0x15, 0x00, 0xA0, 0x51, 0x00, 0x8B, 0xE5, 0x5D, 0xC3
	};
  
	ud_t ud_obj;                                        //定义
	ud_init(&ud_obj);                                   //初始化
	ud_set_input_buffer(&ud_obj, data, sizeof(data));   //缓冲区来源
	ud_set_mode(&ud_obj, 32);                           //32还是64位反汇编
	ud_set_syntax(&ud_obj, UD_SYN_INTEL);               //默认语法     
	ud_set_pc(&ud_obj, 0x00513D41);                     //指令开始地址
	while (ud_disassemble(&ud_obj))                     //开始反汇编
	{
		auto nLen = ud_insn_len(&ud_obj);   //当前指令长度
		auto nOff = ud_insn_off(&ud_obj);   //EIP  当前指令地址
		auto pHex = ud_insn_hex(&ud_obj);   //机器码
		auto ptr = ud_insn_ptr(&ud_obj);    //在本程序内存中的地址
		auto opr = ud_insn_opr(&ud_obj, 0);  
		auto mn = ud_insn_mnemonic(&ud_obj);
		auto mn0 = ud_lookup_mnemonic(mn);
		cout << hex << nOff << " "
			<< pHex << "\t\t"
			<< ud_insn_asm(&ud_obj) << endl;              //反汇编结果
	}

	return 0;
}

相关推荐

驱动网卡(怎么从新驱动网卡)
驱动网卡(怎么从新驱动网卡)

网卡一般是指为电脑主机提供有线无线网络功能的适配器。而网卡驱动指的就是电脑连接识别这些网卡型号的桥梁。网卡只有打上了网卡驱动才能正常使用。并不是说所有的网卡一插到电脑上面就能进行数据传输了,他都需要里面芯片组的驱动文件才能支持他进行数据传输...

2026-01-30 00:37 liuian

win10更新助手装系统(微软win10更新助手)

1、点击首页“系统升级”的按钮,给出弹框,告诉用户需要上传IMEI码才能使用升级服务。同时给出同意和取消按钮。华为手机助手2、点击同意,则进入到“系统升级”功能华为手机助手华为手机助手3、在检测界面,...

windows11专业版密钥最新(windows11专业版激活码永久)

 Windows11专业版的正版密钥,我们是对windows的激活所必备的工具。该密钥我们可以通过微软商城或者通过计算机的硬件供应商去购买获得。获得了windows11专业版的正版密钥后,我...

手机删过的软件恢复(手机删除过的软件怎么恢复)
手机删过的软件恢复(手机删除过的软件怎么恢复)

操作步骤:1、首先,我们需要先打开手机。然后在许多图标中找到带有[文件管理]文本的图标,然后单击“文件管理”进入页面。2、进入页面后,我们将在顶部看到一行文本:手机,最新信息,文档,视频,图片,音乐,收藏,最后是我们正在寻找的[更多],单击...

2026-01-29 23:55 liuian

一键ghost手动备份系统步骤(一键ghost 备份)

  步骤1、首先把装有一键GHOST装系统的U盘插在电脑上,然后打开电脑马上按F2或DEL键入BIOS界面,然后就选择BOOT打USDHDD模式选择好,然后按F10键保存,电脑就会马上重启。  步骤...

怎么创建局域网(怎么创建局域网打游戏)

  1、购买路由器一台。进入路由器把dhcp功能打开  2、购买一台交换机。从路由器lan端口拉出一条网线查到交换机的任意一个端口上。  3、两台以上电脑。从交换机任意端口拉出网线插到电脑上(电脑设置...

精灵驱动器官方下载(精灵驱动手机版下载)

是的。驱动精灵是一款集驱动管理和硬件检测于一体的、专业级的驱动管理和维护工具。驱动精灵为用户提供驱动备份、恢复、安装、删除、在线更新等实用功能。1、全新驱动精灵2012引擎,大幅提升硬件和驱动辨识能力...

一键还原系统步骤(一键还原系统有哪些)

1、首先需要下载安装一下Windows一键还原程序,在安装程序窗口中,点击“下一步”,弹出“用户许可协议”窗口,选择“我同意该许可协议的条款”,并点击“下一步”。  2、在弹出的“准备安装”窗口中,可...

电脑加速器哪个好(电脑加速器哪款好)

我认为pp加速器最好用,飞速土豆太懒,急速酷六根本不工作。pp加速器什么网页都加速,太任劳任怨了!以上是个人观点,具体性能请自己试。ps:我家电脑性能很好。迅游加速盒子是可以加速电脑的。因为有过之...

任何u盘都可以做启动盘吗(u盘必须做成启动盘才能装系统吗)

是的,需要注意,U盘的大小要在4G以上,最好是8G以上,因为启动盘里面需要装系统,内存小的话,不能用来安装系统。内存卡或者U盘或者移动硬盘都可以用来做启动盘安装系统。普通的U盘就可以,不过最好U盘...

u盘怎么恢复文件(u盘文件恢复的方法)

开360安全卫士,点击上面的“功能大全”。点击文件恢复然后点击“数据”下的“文件恢复”功能。选择驱动接着选择需要恢复的驱动,选择接入的U盘。点击开始扫描选好就点击中间的“开始扫描”,开始扫描U盘数据。...

系统虚拟内存太低怎么办(系统虚拟内存占用过高什么原因)

1.检查系统虚拟内存使用情况,如果发现有大量的空闲内存,可以尝试释放一些不必要的进程,以释放内存空间。2.如果系统虚拟内存使用率较高,可以尝试增加系统虚拟内存的大小,以便更多的应用程序可以使用更多...

剪贴板权限设置方法(剪贴板访问权限)
剪贴板权限设置方法(剪贴板访问权限)

1、首先打开iphone手机,触碰并按住单词或图像直到显示选择选项。2、其次,然后选取“拷贝”或“剪贴板”。3、勾选需要的“权限”,最后选择开启,即可完成苹果剪贴板权限设置。仅参考1.打开苹果手机设置按钮,点击【通用】。2.点击【键盘】,再...

2026-01-29 21:37 liuian

平板系统重装大师(平板重装win系统)

如果你的平板开不了机,但可以连接上电脑,那就能好办,楼主下载安装个平板刷机王到你的个人电脑上,然后连接你的平板,平板刷机王会自动识别你的平板,平板刷机王上有你平板的我刷机包,楼主点击下载一个,下载完成...

联想官网售后服务网点(联想官网售后服务热线)

联想3c服务中心是联想旗下的官方售后,是基于互联网O2O模式开发的全新服务平台。可以为终端用户提供多品牌手机、电脑以及其他3C类产品的维修、保养和保险服务。根据客户需求层次,联想服务针对个人及家庭客户...