004011F3 | FF2485 60124000 | jmp dword ptr ds:eax\*4+401260 | //跳转表
| eax | eax\*4+401260 | 自定义代码处 |
|---|---|---|
| Load菜单(eax=0) | 401260 | =403B42 |
| Save菜单(eax=4) | 401270 | =403BAE |
| Exit菜单(eax=2) | 401268 | =401159 |
![]() |
|---|
Exit菜单
修复方案:将跳转指向现有的退出代码(00401159),该代码调用PostQuitMessage。
修改步骤:
当前00401268处的值为0040124B(指向SetFocus调用)。修改为00401159(退出代码地址)。
汇编修改:将00401268处的4字节值从0040124B改为00401159。
![]() |
|---|
Load菜单
内存布局:
405A70:文件路径缓冲区(260字节)
405AB0:文件内容缓冲区(1024字节)
405544:存储Edit控件句柄的指针
核心流程:
调用自定义的OpenFileDialog函数让用户选择文件
使用ReadFileContent函数读取选中的文件内容
通过SetWindowTextA API将文件内容显示到Edit控件中
; ==================================================
; 文件加载并更新Edit控件文本的汇编代码注解
; 地址范围:00403B42 - 00403BA2
; ==================================================
00403B42 | 60 | pushad | ; 保存所有通用寄存器现场
00403B43 | 33C0 | xor eax,eax | ; 清空EAX寄存器
00403B45 | C605 705A4000 00 | mov byte ptr ds:[405A70],0 | ; 初始化文件路径缓冲区首字节为0(空字符串)
; 空指令区域 - 为后续代码调整预留的空间
00403B4C | 90 | nop |
00403B4D | 90 | nop |
00403B4E | 90 | nop |
; ========== 第一阶段:打开文件对话框 ==========
00403B4F | 68 04010000 | push 104 | ; 参数3:缓冲区大小(260字节,MAX_PATH)
00403B54 | 68 705A4000 | push douby_2.405A70 | ; 参数2:文件路径缓冲区地址(405A70)
00403B59 | 6A 00 | push 0 | ; 参数1:父窗口句柄(0表示桌面)
00403B5B | B8 FF100110 | mov eax,<46.OpenFileDialog> | ; 加载OpenFileDialog函数地址到EAX
00403B60 | FFD0 | call eax | ; 调用打开文件对话框函数
00403B62 | 85C0 | test eax,eax | ; 检查返回值(用户是否选择了文件)
00403B64 | 74 3B | je douby_2.403BA1 | ; 如果取消或失败,跳转到清理退出
; 空指令区域 - 预留空间
00403B66 | 90 | nop |
00403B67 | 90 | nop |
00403B68 | 90 | nop |
00403B69 | 90 | nop |
00403B6A | 90 | nop |
00403B6B | 90 | nop |
; ========== 第二阶段:读取文件内容 ==========
00403B6C | 68 00040000 | push 400 | ; 参数3:读取的最大字节数(1024字节)
00403B71 | 68 B05A4000 | push douby_2.405AB0 | ; 参数2:文件内容缓冲区地址(405AB0)
00403B76 | 68 705A4000 | push douby_2.405A70 | ; 参数1:文件路径字符串地址
00403B7B | B8 76120110 | mov eax,<46.ReadFileContent> | ; 加载ReadFileContent函数地址到EAX
00403B80 | FFD0 | call eax | ; 调用读取文件内容函数
00403B82 | 85C0 | test eax,eax | ; 检查读取是否成功
00403B84 | 74 1B | je douby_2.403BA1 | ; 如果读取失败,跳转到清理退出
; ========== 第三阶段:更新Edit控件文本 ==========
00403B86 | 90 | nop |
00403B87 | 68 B05A4000 | push douby_2.405AB0 | ; 参数2:文件内容缓冲区地址(要显示的文本)
00403B8C | FF35 44554000 | push dword ptr ds:[405544] | ; 参数1:从内存[405544]获取Edit控件句柄
00403B92 | E8 E9376E76 | call <user32.SetWindowTextA> | ; 调用系统API设置Edit控件文本
; ========== 成功返回处理 ==========
00403B97 | B8 01000000 | mov eax,1 | ; 设置成功返回值(EAX=1)
00403B9C | EB 03 | jmp douby_2.403BA1 | ; 跳转到清理退出
; 空指令区域
00403B9E | 90 | nop |
00403B9F | 90 | nop |
00403BA0 | 90 | nop |
; ========== 清理退出部分 ==========
00403BA1 | 61 | popad | ; 恢复所有通用寄存器
00403BA2 | E9 66D6FFFF | jmp douby_2.40120D | ; 跳转回主程序流程
![]() |
|---|
Save菜单
; ==================================================
; Save功能注释
; 功能:将文本框内容通过保存对话框保存到文件
; 起始地址: 00403BAE
; ==================================================
00403BAE: 60 pushad ; 保存所有通用寄存器状态
00403BAF: 33C0 xor eax, eax ; 清空EAX寄存器,确保初始状态干净
; --------------------------------------------------
; 1. 获取文本框内容
; --------------------------------------------------
00403BB1: 90 nop
00403BB2: 90 nop
00403BB3: 90 nop
00403BB4: 68 00040000 push 400h ; 参数3: 缓冲区大小(1024字节)
00403BB9: 68 A0674000 push 4067A0h ; 参数2: 文本缓冲区地址(用于接收文本框内容)
00403BBE: FF35 44554000 push dword ptr [405544h] ; 参数1: 文本框句柄(从内存405544h读取)
00403BC4: E8 D7206E76 call GetWindowTextA ; 调用API获取文本框文本内容
00403BC9: 90 nop
; --------------------------------------------------
; 2. 调用保存文件对话框
; --------------------------------------------------
00403BCA: 68 04010000 push 104h ; 参数3: 文件路径缓冲区大小(260字节)
00403BCF: 68 50674000 push 406750h ; 参数2: 文件路径缓冲区地址
00403BD4: 6A 00 push 0 ; 参数1: 父窗口句柄(NULL)
00403BD6: B8 63110110 mov eax, 10011163h ; SaveFileDialog函数地址
00403BDB: FFD0 call eax ; 调用保存文件对话框
00403BDD: 85C0 test eax, eax ; 测试对话框返回值
00403BDF: 74 3B je 403C1Ch ; 如果用户取消(返回0),跳转到清理部分
; --------------------------------------------------
; 3. 调用文件写入功能
; --------------------------------------------------
00403BE1: 90 nop
00403BE2: 90 nop
; ... 多个nop指令用于代码对齐
00403BE9: 68 00040000 push 400h ; 参数3: 要写入的数据大小(1024字节)
00403BEE: 68 A0674000 push 4067A0h ; 参数2: 文本数据缓冲区(包含文本框内容)
00403BF3: 68 50674000 push 406750h ; 参数1: 文件路径(从对话框获取)
00403BF8: B8 49120110 mov eax, 10011249h ; WriteFileContent函数地址
00403BFD: FFD0 call eax ; 调用文件写入功能
00403BFF: 85C0 test eax, eax ; 测试写入结果
00403C01: 74 19 je 403C1Ch ; 如果写入失败,跳转到清理部分
; --------------------------------------------------
; 4. 成功处理路径
; --------------------------------------------------
00403C03: 90 nop
00403C04: 90 nop
; ... 多个nop指令
00403C0A: 33C0 xor eax, eax ; 设置EAX=0(失败状态)
00403C0C: EB 0E jmp 403C1Ch ; 跳转到清理代码
; --------------------------------------------------
; 5. 成功执行路径
; --------------------------------------------------
00403C14: B8 01000000 mov eax, 1 ; 设置EAX=1(成功状态)
00403C19: 90 nop
00403C1A: 90 nop
; --------------------------------------------------
; 6. 清理和返回
; --------------------------------------------------
00403C1C: 61 popad ; 恢复所有通用寄存器
00403C1D: E9 EBD5FFFF jmp 40120Dh ; 跳转回主程序(已验证的安全返回点)
![]() |
|---|
编写DLL文件,实现文件打开保存读写功能。 OpenFileDialog 、 SaveFileDialog 、ReadFileContent 、WriteFileContent 。
把随机基址改成否,这样在OD里调用地址就不会变了。
![]() |
|---|
把写好的dll静态注入程序,这样可以少写点汇编代码。
![]() |
|---|
把生成的dll文件放在程序同一目录下,程序运行会自动加载dll。
![]() |
|---|






