辅助汇编学习记录1

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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值