在现代系统中编写运行自修改代码(SMC)遇权限异常求助
解决Windows下汇编SMC中栈不可执行导致的异常问题
问题根源
Windows默认启用**数据执行保护(DEP)**机制,栈内存区域默认仅被赋予可读可写权限,不允许执行代码。直接将控制权转移到栈上的指令时,会触发EXCEPTION_ACCESS_VIOLATION异常。
解决方法
通过VirtualProtect函数修改目标栈页的内存权限,将其设置为PAGE_EXECUTE_READWRITE(可读、可写、可执行),即可让栈上的代码正常执行。
修正后的示例代码
.386 .model flat, stdcall option casemap:none include smc.Inc ; 包含Win32API定义,以及MsgCaption、MsgBoxText等常量 .code magic: mov eax, esp sub esp, 28h ; 预留栈空间存放待执行的代码 ; 修改当前栈页的权限为可执行 push eax ; 保存旧权限的输出参数地址 push PAGE_EXECUTE_READWRITE ; 目标权限 push 4096 ; 内存页大小(x86平台默认4KB) push eax ; 要修改权限的栈起始地址 call VirtualProtect add esp, 10h ; 清理VirtualProtect的参数栈 ; 向栈中写入待执行的代码序列 mov dword ptr[eax], 1778421864h ; push MB_OK; nop; push mov dword ptr[eax+4], offset MsgCaption mov dword ptr[eax+8], 2425393256h ; nop nop nop push mov dword ptr[eax+12], offset MsgBoxText mov dword ptr[eax+16], 1778421992h ; push NULL; nop; call mov dword ptr[eax+20], MessageBox mov dword ptr[eax+24], 3281031312h ; ret nop nop nop ; 安全跳转到栈上执行代码 call dword ptr[eax] ret start: call magic invoke ExitProcess, NULL end start
关键说明
- 调用
VirtualProtect时,需传入栈起始地址、内存页大小、目标权限,以及一个接收旧权限的临时地址(这里直接用栈上的空间)。 - 修正了原代码中
[espx]的笔误,替换为正确的寄存器寻址[eax]。
内容的提问来源于stack exchange,提问作者AsfhtgkDavid
相关产品推荐
相关产品推荐

