昨天调试器写到内存断点功能了, 为了方便测试,打算随便找个程序进行内存断点测试,
这时,正好一位朋友发来一个ctf让帮忙瞅一眼. 程序是一个控制台下的.还好程序没有想象中的难.
测试时,发现问题非常多. 为了方便测试内存断点,我写了段如下代码:
[Asm] 纯文本查看 复制代码
007D1DB0 > B9 00100000 MOV ECX,0x1000
007D1DB5 B8 00000000 MOV EAX,0x0
007D1DBA BA BBBBBBBB MOV EDX,0xBBBBBBBB
007D1DBF 50 PUSH EAX
007D1DC0 51 PUSH ECX
007D1DC1 52 PUSH EDX
007D1DC2 83C4 0C ADD ESP,0xC
007D1DC5 33D2 XOR EDX,EDX
007D1DC7 33D9 XOR EBX,ECX
007D1DC9 51 PUSH ECX
007D1DCA 5A POP EDX
007D1DCB 90 NOP
007D1DCC 8BD1 MOV EDX,ECX
007D1DCE 81E3 DDCCBBAA AND EBX,0xAABBCCDD
007D1DD4 C1EA 10 SHR EDX,0x10
007D1DD7 40 INC EAX
007D1DD8 89D3 MOV EBX,EDX
007D1DDA ^ E2 DE LOOPD SHORT MiaoCTF_.007D1DBA
这里寄存器ECX应该是递减的过程, 但在实际测试中,发现刚开始寄存器是正常递减, 但运行几个循环后就开始变的不正常了.
经排查是多线程的问题, 多线程我还没有处理.
于是就换成控制台单线程程序测试, 正好朋友发来的ctf题是控制台的,就拿他的程序来测试了.
测试后发现寄存器EAX和ECX都是有序递增和递减,没有出错.
因为上面的代码是修改内存写入的,每次ctrl+f2(重载程序)之后都要shift+v(粘贴二进制)进去,很麻烦.
于是我就想着直接修改文件好了.
我拿od1.x修改代码,保存. 成功. 可是重新打开之后,发现代码是错误的. 修改好的代码如下.
[Asm] 纯文本查看 复制代码
00551DB0 > B9 00100000 MOV ECX,0x1000
00551DB5 B8 00000000 MOV EAX,0x0
00551DBA BA BBBBBBBB MOV EDX,0xBBBBBBBB
00551DBF 50 PUSH EAX
00551DC0 51 PUSH ECX
00551DC1 52 PUSH EDX
00551DC2 839C0C 33D233D9>SBB DWORD PTR SS:[ESP+ECX+0xD933D233],0x51
00551DCA 5A POP EDX
00551DCB 90 NOP
00551DCC 63D1 ARPL CX,DX
00551DCE 81E3 DDCCBBAA AND EBX,0xAABBCCDD
00551DD4 C1EA 10 SHR EDX,0x10
00551DD7 1889 D3E2DE90 SBB BYTE PTR DS:[ECX+0x90DEE2D3],CL
00551DDD 90 NOP
00551DDE 3100 XOR DWORD PTR DS:[EAX],EAX
可以发现保存后重新载入反汇编代码和预期不一样. 于是又试了几次, 反汇编的结果始终不对. 偶而0d1.x会提示如下:
[Asm] 纯文本查看 复制代码
---------------------------
Unable to update fixups
---------------------------
Some modified fixups are only partialy selected. OllyDbg is unable to update such fixups.
---------------------------
确定
---------------------------
看到此提示,第一反应是超出了节? 好像不对, 超出节应该是提示如下:
[Asm] 纯文本查看 复制代码
---------------------------
Error
---------------------------
Unable to locate data in executable file
---------------------------
确定
---------------------------
不信邪, 又拿winhex尝试, 搜索到oep处修改,保存,成功.再打开,还是一样错误显示.
又猜想可能是电脑hips或者其他什么进程影响? 关掉相关可疑进程,测试,还是一样出错.
冷静想想,有可能是tls之类的做了手脚. 用od1.x查看PE的tls处是为空的,如下:
[Asm] 纯文本查看 复制代码
005501C8 00000000 DD 00000000 ; TLS Table address = 0x0
005501CC 00000000 DD 00000000 ; TLS Table size = 0x0
所有可能都排除了, 那剩下的只能是 DataDirectory 处哪里做了"手脚"了.
数据目录表里面有10多项,排除空项和非可疑项,一个个去查也太过麻烦.
准备尝试使用其他调试器先做修改保存试试. 首先使用的是 yzdbg 修改保存成功. 不用看结果,肯定是错误的.
再用x64dbg修改保存.弹了个提示如下:
[Asm] 纯文本查看 复制代码
---------------------------
Error!
---------------------------
Failed to save patched file (Failed to make a copy of the original file (patch target is in use?))
---------------------------
OK
---------------------------
和OD1.x类似. 但是在点 patch 前,x64dbg还有弹出一个提示. 如下:
[Asm] 纯文本查看 复制代码
---------------------------
Patches overlap with relocation regions
---------------------------
Your patches overlap with relocation regions. This can cause your code to become corrupted when you load the patched executable. Do you want to continue?
---------------------------
&Yes &No
---------------------------
嚯!一看到提示就明白,问题果然是出在 datadirectory 中的 relocation表中. 为了验证.
用od1.x打开 ctf 的pe处 定位到 option 中的 DLLCharacteristics 此处能控制 aslr开关. ASLR(Address Space Layout Randomization).
DLLCharacteristics 默认是 0x410
[Asm] 纯文本查看 复制代码
0:000> .formats 0x8140
Evaluate expression:
Hex: 00000000`00008140
Decimal: 33088
Octal: 0000000000000000100500
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 10000001 01000000
Chars: .......@
Time: Thu Jan 01 17:11:28 1970
Float: low 4.63662e-041 high 0
Double: 1.63476e-319
其中 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 正好是 0x40, 只需将 0x8140 修改成 0x8100 即可.
修改保存, 重新载入 发现 oep 是 0x00401DB0 和 pe中的 image 0x00400000 一致. 再修改OEP处的代码,保存, 发现也正常了.
最终结论就是, 保存时 如果有一个明显的提示,能让人少走不少弯路. OllyDbg x64在写文件保存功能时,也一定要写此类明显的提示 :)
|