如何在Windows系统中编写自修改代码?解决调试异常问题
运行时修改自身代码:Windows vs DOS的差异及解决方案
核心原因
你猜的没错,问题根源就是Windows的内存保护机制:DOS是实模式系统,没有内存分页和权限隔离,代码段与数据段可直接读写执行;但Windows采用保护模式,可执行文件的代码节(通常是.text)默认被标记为PAGE_EXECUTE_READ(可执行、只读),直接向代码页写入会触发EXCEPTION_ACCESS_VIOLATION异常,这就是OllyDbg报错的原因。
可行解决方案
1. 修改目标内存页的属性(最直接方法)
使用Windows API VirtualProtect 修改代码所在内存页的权限,临时赋予可写权限,修改完成后可按需恢复原权限。
汇编示例(x86):
; 假设要修改的代码起始地址为target_code,大小为4字节 push ebp mov ebp, esp sub esp, 4 ; 预留保存旧属性的栈空间 push 0 ; lpflOldProtect:旧属性指针 push PAGE_EXECUTE_READWRITE ; flNewProtect:新属性(可执行、可读、可写) push 4 ; dwSize:修改的内存大小 push target_code ; lpAddress:目标代码地址 call VirtualProtect ; 调用API修改权限 ; 执行代码修改操作,例如替换为NOP指令 mov byte ptr [target_code], 0x90 ; 恢复原属性(可选操作) push dword ptr [ebp-4] ; 传入之前保存的旧属性 push 0 push 4 push target_code call VirtualProtect mov esp, ebp pop ebp
2. 文件映射技术的应用
文件映射更适合持久化修改可执行文件或跨进程共享代码修改,而非运行时动态修改当前进程的内存代码:
- 通过
CreateFile打开自身可执行文件 - 用
CreateFileMapping创建映射对象 - 用
MapViewOfFile获取映射到内存的地址 - 修改映射区域后,调用
UnmapViewOfFile同步到磁盘
这种方式修改的是磁盘上的文件,而非当前运行进程的内存代码;若要修改运行时内存,VirtualProtect的效率和直接性更高。
3. 其他替代思路
- 将代码放在数据段:把需要修改的代码放在数据节(默认
PAGE_READWRITE),再用VirtualProtect给该段添加PAGE_EXECUTE权限,即可实现读写执行。 - 动态分配可执行内存:用
VirtualAlloc分配一块PAGE_EXECUTE_READWRITE属性的内存,将需要修改的代码拷贝到该区域,修改后直接执行这块内存中的代码。
内容的提问来源于stack exchange,提问作者Jekgley
相关产品推荐
相关产品推荐

