64位转32位汇编求助:注入LoadLibraryA时程序崩溃的栈问题
32位程序DLL注入崩溃问题分析与修复
你的64位注入逻辑没问题,但32位下崩溃的核心原因是栈平衡、寄存器破坏、原指令缺失这几个点没处理好,下面逐个拆解并给出修复方案:
1. 栈平衡与调用约定问题
32位下LoadLibraryA采用__stdcall调用约定:函数会在返回时自动通过ret 4清理栈上的参数(因为只有一个4字节的字符串地址参数)。你当前的代码逻辑本身栈是平衡的,但崩溃可能来自跳转位置错误:
- 确认
entryfunc的跳转目标:你替换了入口处的指令为JMP codecave,所以最后应该跳转到原指令的下一条地址,而非原指令的位置(原位置已经被改成跳转指令了)。
2. 寄存器破坏问题
32位Windows API允许修改EAX、ECX、EDX寄存器,但原程序的入口逻辑可能依赖这些寄存器的初始值。你只保存了EAX,但如果ECX/EDX被LoadLibraryA修改,就会导致后续流程出错。最稳妥的方式是在codecave开头保存所有寄存器,结尾恢复:
; 保存所有通用寄存器 PUSHAD ; 执行你的DLL加载逻辑 PUSH dllstr CALL dword ptr [loadlibrarya] ; 恢复所有寄存器 POPAD
3. 原指令缺失问题
如果入口处你替换的不是空指令(NOP),而是一条有效业务指令,必须在codecave中补执行这条指令,否则程序会缺失关键流程直接崩溃。比如原入口指令是MOV EAX, [EBX+0x10],那codecave里要先执行这条指令,再加载DLL:
PUSHAD ; 补执行被替换的原指令 MOV EAX, [EBX+0x10] ; 加载DLL PUSH dllstr CALL dword ptr [loadlibrarya] POPAD JMP entryfunc_after_original
4. 其他验证点
- 确认
dllstr是以null结尾的ANSI字符串,且地址是有效的32位内存地址,所在内存页有读权限(codecave在.text段的话默认是可读可执行,没问题)。 - 确认
loadlibrarya的地址是从目标程序导入表中获取的正确32位地址,不是64位的地址。
修复后的完整32位Codecave示例
; codecave起始位置 PUSHAD ; 保存所有寄存器 ; 补执行被替换的原入口指令(根据实际情况修改) ; MOV EAX, [EBX+0x4] ; 加载目标DLL PUSH dllstr ; 压入ANSI字符串地址 CALL dword ptr [loadlibrarya] ; 调用LoadLibraryA(stdcall自动清理参数栈) POPAD ; 恢复所有寄存器 JMP entryfunc_next ; 跳回原入口指令的下一条位置
内容的提问来源于stack exchange,提问作者iegrm
相关产品推荐
相关产品推荐

