曾经发现win7下程序基地址不停地变动,又发现下移代码会导致程序crash,一度怀疑win7系统或者vs编译器是不是做了什么校验机制,专门针对数据逆向者,限制反汇编修改代码,打断了我学习外挂编写的信心和脚步,后来在一骗博客中解决了基地址不停地变动的问题,现在一块儿看看这个下移代码导致程序crash的问题,首先写个测试工程,VS2008,Debug版,就有一对话框,点击按钮相应代码如下:
void CttDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
__asm mov eax,eax
if (mint==1)
{
AfxMessageBox(_T("1111"));
}
else
{
AfxMessageBox(_T("2222"));
}
}
内嵌汇编是方便反汇编定位时用的,比较方便
看看这个成员按钮响应函数的反汇编:
00412D0C CC int3
00412D0D CC int3
00412D0E CC int3
00412D0F CC int3
00412D10 > 55 push ebp
00412D11 8BEC mov ebp,esp
00412D13 81EC CC000000 sub esp,0xCC
00412D19 53 push ebx
00412D1A 56 push esi
00412D1B 57 push edi
00412D1C 51 push ecx
00412D1D 8DBD 34FFFFFF lea edi,dword ptr ss:[ebp-0xCC]
00412D23 B9 33000000 mov ecx,0x33
00412D28 B8 CCCCCCCC mov eax,0xCCCCCCCC
00412D2D F3:AB rep stos dword ptr es:[edi]
00412D2F 59 pop ecx
00412D30 894D F8 mov dword ptr ss:[ebp-0x8],ecx
00412D33 8BC0 mov eax,eax
00412D35 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
00412D38 8378 78 01 cmp dword ptr ds:[eax+0x78],0x1
00412D3C 75 10 jnz short tt.00412D4E
00412D3E 6A 00 push 0x0
00412D40 6A 00 push 0x0
00412D42 68 F0CE4100 push tt.0041CEF0 ; UNICODE "1111"
00412D47 E8 5FE7FFFF call tt.004114AB
00412D4C EB 0E jmp short tt.00412D5C
00412D4E 6A 00 push 0x0
00412D50 6A 00 push 0x0
00412D52 68 E4CE4100 push tt.0041CEE4 ; UNICODE "2222"
00412D57 E8 4FE7FFFF call tt.004114AB
00412D5C 5F pop edi
00412D5D 5E pop esi
00412D5E 5B pop ebx
00412D5F 81C4 CC000000 add esp,0xCC
00412D65 3BEC cmp ebp,esp
00412D67 E8 16E8FFFF call tt.00411582
00412D6C 8BE5 mov esp,ebp
00412D6E 5D pop ebp
00412D6F C3 retn
00412D70 CC int3
00412D71 CC int3
00412D72 CC int3
00412D73 CC int3
测试1:把最后retn指令后面的几个int3改为NOP指令,保存文件,双击执行看看程序是否运行正常
结果:正常运行
猜想:VS应该没有做反汇编方面的限制,否则程序应该crash
测试2:把下面几个指令下移(空出来的位置用NOP填充)
00412D6C 8BE5 mov esp,ebp
00412D6E 5D pop ebp
00412D6F C3 retn
结果:正常运行
猜想:vs和win7应该没有做限制吧,最少限制没有那么绝,但是自己反汇编修改代码的时候经常会导致程序crash又是什么原因呢,难道是堆栈平衡,应该不是吧,只是下移代码,又没有缺少什么指令,继续看测试3
测试3:把00412d3c地址后的指令下移(具体操作:选中下移代码->二进制复制->选中下移目标区域->二进制填充->二进制粘贴)得到的代码:
00412D0E CC int3
00412D0F CC int3
00412D10 > 55 push ebp
00412D11 8BEC mov ebp,esp
00412D13 81EC CC000000 sub esp,0xCC
00412D19 53 push ebx
00412D1A 56 push esi
00412D1B 57 push edi
00412D1C 51 push ecx
00412D1D 8DBD 34FFFFFF lea edi,dword ptr ss:[ebp-0xCC]
00412D23 B9 33000000 mov ecx,0x33
00412D28 B8 CCCCCCCC mov eax,0xCCCCCCCC
00412D2D F3:AB rep stos dword ptr es:[edi]
00412D2F 59 pop ecx
00412D30 894D F8 mov dword ptr ss:[ebp-0x8],ecx
00412D33 8BC0 mov eax,eax
00412D35 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
00412D38 8378 78 01 cmp dword ptr ds:[eax+0x78],0x1
00412D3C 90 nop
00412D3D 75 10 jnz short tt2.00412D4F
00412D3F 6A 00 push 0x0
00412D41 6A 00 push 0x0
00412D43 68 F0CE4100 push tt2.0041CEF0 ; UNICODE "1111"
00412D48 E8 5FE7FFFF call tt2.004114AC
00412D4D EB 0E jmp short tt2.00412D5D
00412D4F 6A 00 push 0x0
00412D51 6A 00 push 0x0
00412D53 68 E4CE4100 push tt2.0041CEE4 ; UNICODE "2222"
00412D58 E8 4FE7FFFF call tt2.004114AC
00412D5D 5F pop edi
00412D5E 5E pop esi
00412D5F 5B pop ebx
00412D60 81C4 CC000000 add esp,0xCC
00412D66 3BEC cmp ebp,esp
00412D68 E8 16E8FFFF call tt2.00411583
00412D6D 8BE5 mov esp,ebp
00412D6F 5D pop ebp
00412D70 C3 retn
00412D71 90 nop
00412D72 90 nop
00412D73 90 nop
00412D74 90 nop
00412D75 90 nop
00412D76 90 nop
00412D77 90 nop
00412D78 90 nop
00412D79 CC int3
结果:程序crash
猜想:妹的,小弟瞬间崩溃,为什么这个就会崩溃呢?
解决:一步一步调试发现程序崩溃在一个call函数上边,仔细观察发现call函数的地址变了,代码下移之后call函数地址也随之加一,这不胡扯吗?Call函数实际调用的是afxmessagebox函数,这是API,地址应该是不会变的,下移部分代码,里面的call的地址会发生变化,这个还真没注意到,以前知道跳转指令的地址可能会发生变化,因为有的跳转的是绝对地址,有的跳转的是相对偏移,所以移动跳转指令的时候一定要注意移动之后的代码跳转的位置是否和移动之前的一致,这个call应该是call的绝对地址啊,怎么会有改变呢?暂时不知道,不过先改过来再说,把两个call地址都改回原来的之后程序正常运行。