概述
1.OD中ctrl+f9:运行到返回,就是运行到当前断点所在的函数末尾"retn xxx"处,若xxx=10,那么
10等于10进制的16,就是说这个函数有4个参数,一个参数默认是占4字节,所以就是retn 10。
2.调试程序时,在OD内部小窗口左上角会显示当前断点所在的函数层,是在系统领空还是某个应用程序领空。
3.call前出现lea edx,dword ptr ss:[ebp-x]的分析方法:
当在call处出现类似于下面,在call内部存在对edx的使用时:
call处:
lea edx,dword ptr ss:[ebp-8] ;将ebp-8堆栈地址赋给edx,注意是堆栈地址,不是堆栈地址上存储的数据。
call 0045255c
call内部:
mov esi,edx
...
push esi
那么在写call调用的时候,怎么办呢?
只需要查看当程序停在call处时,edx寄存器的数值,然后去找到edx数值代表的堆栈地址处存储的数据是什么。
是1,所以我们就可以通过ce查找出当前为0的值,为0可能就是无关数据,选择一个地址,修改为1,然后将该地址
赋给edx。
就是mov edx, xxxxx
call 0045255c
4.call内部出现mov ebx,dword ptr [esp+8],为什么此句不用分析呢,难道不可能是取call通过堆栈传的参数吗?
5.如果call是堆栈传参,那么在call前面就会有push,那么我们在分析call参数时,就要关注call内部从堆栈取数的操作;
反之,如果call是寄存器传参,那么在call前面就没有push,所以在call内部,我们就不必关注从堆栈取数的操作。
如果是堆栈传参,那么在call内部我们就不用再分析从堆栈取数的操作了,就会更加简单;其实不管是堆栈传参还是寄存器传参,
我们都可以不用管内部类似于mov edx,dword ptr ss:[ebp-8]这样的取堆栈操作,因为假如是堆栈传参,那么这样的操作一定是
取参数的,我们已经知道了在调用call前push了,何必还分析呢;假如是寄存器传参,那么对堆栈的操作也不用分析,因为我们
只关心call的参数,既然参数时寄存器,在call前只需mov xxx,yyy,就可以了。
6.OD中没有$函数头标识以及竖线,可以按ctrl+A进行分析,就可以显示了。
7.使用OD直接打开程序与附加已经运行的程序,会有所不同。
在查找花指令时,若使用附加进程,则找不到花指令,使用od直接
打开就可以找到花指令。
8.OD附加进程出现“调试字串:D3DX系统找不到指定的文件”?
去下载DX9.0c,再去下载个StrongOD插件;安装dx9.0,将StrongOD插件解压放到OD工具
PLUGIN目录下,重启软件就可以了。
9.CALL 的参数其实就是在调用 CALL 的时候所需要的运行环境。
10.找无参数call的方法:
比如找加血减血的call,那么先用CE找出血值地址,然后进入OD,将该地址设置硬件中断(hw 416698),在调用加血减血函数时,在其函数内部就会对血值写入新数值,那么在代码访问到416698地址时,就会发生中断。代码短直接看,代码长使用ctrl+f9执行到返回,这样便很容易找到call。
11.要生成一个Release版本的就可以了,你得先设置一下: 在“工程”中选择“设置”打开Project Settings对话框,
先在“设置”下拉列表中选择Win32 Release,然后在右侧设置为“使用MFC作为静态链接库”。点击确定。
再打开“组建”下的“批组建”,勾掉Win32 Debug,然后再点击“创建”。这时应该能够生成一个Release版本的应用程序。 这个程序就可以直接拷到别人的电脑上运行,不必安装VC
12.堆栈传参call写法。
经过4次的分析,最终找到了调用call,程序老是崩溃的原因:
在程序中查找call的c代码为:
int add(int a, int b)
{
return (a+b);
}
反汇编代码为:
004014E5 . E8 44020000 CALL <JMP.&MFC42.#6334>
004014EA . 8B46 64 MOV EAX,DWORD PTR DS:[ESI+0x64]
004014ED . 8B4E 68 MOV ECX,DWORD PTR DS:[ESI+0x68]
004014F0 . 50 PUSH EAX
004014F1 . 51 PUSH ECX
004014F2 . E8 D9FFFFFF CALL test.004014D0
004014F7 . 83C4 08 ADD ESP,0x8
004014FA . 8BCE MOV ECX,ESI
004014FC . 8946 60 MOV DWORD PTR DS:[ESI+0x60],EAX
004014FF . 6A 00 PUSH 0x0
00401501 . E8 28020000 CALL <JMP.&MFC42.#6334>
其中下面是add的call
004014F0 . 50 PUSH EAX
004014F1 . 51 PUSH ECX
004014F2 . E8 D9FFFFFF CALL test.004014D0
004014F7 . 83C4 08 ADD ESP,0x8
call内部为:
004014D0 /$ 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+0x8]
004014D4 |. 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+0x4]
004014D8 |. 03C1 ADD EAX,ECX
004014DA . C3 RETN
第一次调用call时,在注射器中输入
push 1
push 2
call 004014f2
add esp,0x8
程序老是要崩溃,然后就自己单步查看堆栈情况,因为这个call是通过堆栈传递的2个参数。
当程序单步到004014D0时,堆栈情况:
0532ffa8 004014f7 ;CALL test.004014D0返回地址
0532ffac 04720009 ;注入的线程调用函数返回地址
0532ffb0 00000002 ;push 2
0532ffb4 00000001 ;push 1
0532ffb8 7c80b729 ;为压栈前esp的值,在调用call之后,esp应该回到这个位置。
而在call内部,分别取ESP+0x8,ESP+0x4,这2个参数,此时esp=0532ffa8,那么
[ESP+0x8]=2,[ESP+0x4]=04720009,可以看到参数已经取错了。再次当call执行完毕后,将0532ffa8处的
函数返回地址弹出,函数继续执行下一条指令ADD ESP,0x8,此时esp=0532ffac+8=0532ffb4,可以看到
esp的值并没有回到调用call之前的值,所以造成堆栈不平衡,程序就崩溃了。
解决方法:
类似于这种堆栈传参的call调用,不能调用call所在的地址,因为这样会多在堆栈中压入一个返回地址,
从而造成堆栈不平衡。只能直接调用call内部的第一条指令,就可以了。
PUSH EAX
PUSH ECX
004014F2 CALL test.004014D0
ADD ESP,0x8
不能call 004014F2,只能call 004014D0。
正确的写法是:
push 1
push 2
call 4014D0
add esp,0x8
不管是有参还是无参call,最好都调用call内部的第一条指令地址,这样一定没有错。
13.OD命令:
hw 00416698,在00416698处添加硬件断点
dd 2AE6C68,显示2AE6C68处的内存地址
dd [03109164]+i*4+00000404 // 在od中数值方式显示数组[i]
dc [03109164]+i*4+00000404 // 在od中ASC字符方式显示数组[i]
ctrl+'-':查看上一个过程
ctrl+'+': 查看下一个过程
14.OD跟踪的使用:
右键->HIT跟踪和RUN跟踪,HIT可以查看代码的执行过程,HIT为“击中”的意思,被执行的代码会变色,而RUN可以设置条件,及从上面某一行代码开始执行(ctrl+f11跟踪步入,strl+f12跟踪步过),执行到下面某行代码满足条件,就会断下来,例如可以查找某寄存器的值在哪条代码被修改。
在已经使用跟踪的情况下,按"-"键可以一条一条查看执行过的代码和数据情况,同时在寄存器,堆栈窗口的数据也会随着代码的返回而更新。
15.mov eax,dword ptr ds:[esp+20]与mov eax,dword ptr ss:[esp+20]的区别:
ds表示从内存地址esp+20处取一个双字数据存入eax,ss表示从堆栈地址esp+20处取一个双字数据存入eax。
最后
以上就是无情小白菜为你收集整理的辅助汇编学习记录1的全部内容,希望文章能够帮你解决辅助汇编学习记录1所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复