首页
社区
课程
招聘
不明白为什么非要改成ret 8,ret2,哪来的?如何计算出来的?
发表于: 2015-7-6 10:32 11736

不明白为什么非要改成ret 8,ret2,哪来的?如何计算出来的?

2015-7-6 10:32
11736
http://bbs.pediy.com/showthread.php?t=185446


不明白  为什么  这句
004C3715      C2 1000       retn    10
要改成 retn 10呢,为什么不是9  ,11,不是20,不是其他的呢?

为什么 这句要改成
00420B45      C2 0800       retn    8
retn    8哪来的呢?

球扫盲,把所以然明白的说出来 就成了。唯独这两句搞不明白,其他的还算是看得懂。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (34)
雪    币: 1372
活跃值: (5338)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
2
既然你诚心诚意的问了。我就大发慈悲地告诉你。
我,武藏,我,小次郎。我们是穿梭在银河系的火箭队。
白洞,白色的明天在等着我们。

就是这样
2015-7-6 10:41
0
雪    币: 66
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
修改程序主要就是平盏,这个是程序执行的规则
因为里面保存了每个函数的参数和返回值
在进入这个函数前push了多少次 每次乘于4 ,因为32位程序每个盏占4字节
进入后ret 指令相当于 pop  jmp   取盏上第一条地址作为返回地址并弹出盏
ret 8 则是 pop 第一条盏然后返回 再弹出8/4条盏
这里的10 实际上是 0x10 十六进制

平盏有两种方式
你看到的是一种
还有一种是

push 1
push 2
call  XXXXX   <= 里面只有ret     
add esp,8  <= 这里也是平盏操作
2015-7-6 10:53
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4

还是不太明白,希望专家能结合图中的地址,说说如何把栈的值 搞得平衡了,
说的再具体些。。。
上传的附件:
2015-7-6 11:04
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=killbr;1379599]
还是不太明白,希望专家能结合图中的地址,说说如何把栈的值 搞得平衡了,
说的再具体些。。。[/QUOTE]

要平衡的是call之前的push,先搞清楚函数调用时的堆栈吧

func(int,int)
就是先压栈两个int,然后返回地址入栈

ret的时候要返回地址出栈,可是下面还有两个int,所以需要ret 8,把返回地址下面的两个int也弹出栈
2015-7-6 11:09
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6

给错图片了,好像该给这张才对。
上传的附件:
2015-7-6 11:13
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我好像有点开窍了,是不是因为 得根据修改的字节数来算?

未改前是:004A74D0      B8 04100000   mov     eax, 0x1004
--------------------------
修改后是:    004A74D0      B8 01000000   mov     eax, 0x1
所以下一句 就得改成 retn    4
----------------------------
0100算两个字节
所以,要想平衡 就是 retn 就得是:  4乘以2
上传的附件:
2015-7-6 11:24
0
雪    币: 199
活跃值: (856)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
平衡堆栈用的.
retn x
等同于
ret
add esp,x
其实也就是自平衡堆栈 和 函数自动平衡堆栈的问题也就是 cdecl 和 stdcall两种方式。
反正我是这么理解的
简单来说就是
(cdecl)
push 1
push 2
call xxxxxx
add esp,8

xxxxx函数的返回方式为 ret

(stdcall)
push 1
push 2
call xxxxxxxx

xxxxxx函数的返回方式为 retn 8

理解或许有疏忽,谅解。
2015-7-6 12:05
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
我还是不太明白,修改了第一句之后
那个retn 的返回值, 我理解的还是不大对啊,开始以为红了几个字就乘以相应的数字 X2 ,要怎么样才能轻易的搞懂,填对呢?
球个给菜鸟 解决的策略 就好了。
2015-7-6 12:14
0
雪    币: 199
活跃值: (856)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
这个是看堆栈的,你仔细看下堆栈变化,也可以这么说 retn的值取决于你压入的参数个数

你说的那个问题 为什么要 retn 10

004B1599  |.  56            push    esi
004B159A  |.  6A 18         push    18
004B159C  |.  52            push    edx
004B159D  |.  50            push    eax
004B159E  |.  E8 6D210100   call    004C3710
004B15A3  |.  A3 F84B5300   mov     dword ptr [534BF8], eax
004B15A8  |.  85C0          test    eax, eax
004B15AA  |.  7D 0A         jge     short 004B15B6
004B15AC  |.  C705 F84B5300>mov     dword ptr [534BF8], 168
004B15B6  |>  8B8C24 281000>mov     ecx, dword ptr [esp+1028]

这里它压入了四个数 即  4*4 = 16 也就是  0x10
所以retn 10

同理
004AE212  |.  6A 01         push    1
004AE214  |.  8D9424 141000>lea     edx, dword ptr [esp+1014]
004AE21B  |.  52            push    edx
004AE21C  |.  E8 1F29F7FF   call    00420B40
004AE221  |.  A2 C03C4F00   mov     byte ptr [4F3CC0], al

4*2 = 8
故 retn 8

这样就言简意赅了吧。。。咳咳.. 一个栈占四个字节 就这么算 你压入一个参数 就占一个栈.很通俗了吧
2015-7-6 12:26
0
雪    币: 66
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
首先告诉我你会不会编程吧,最好是C++的容易理解一点

一个函数可以有很多个参数,参数的个数决定了平盏的大小
int test(int a,int b,int c); 如果是这个函数则需要平盏 0xC   3*4 = 12 = 0xC

如果你实在搞不懂,你就自己写几个函数,然后拖到OD 或者IDA 查看汇编代码
2015-7-6 12:38
0
雪    币: 16
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
压入栈的是2个32位寄存器中的值,也就是每个值4字节,retn idata废除的是idata/4个无用参数。
在16位段中,如果使用retn idata,则废除的是idata/2个无用参数,不过现在除基础汇编教学基本上不用16位端 。
2015-7-6 12:41
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
感谢,要的就是这种表达,这次彻底明白了。

今天 上午算是没有白来,再次感谢下。
2015-7-6 13:28
0
雪    币: 199
活跃值: (856)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
那就赶紧结贴吧= =我要转正式会员
2015-7-6 16:02
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
回来评你为最佳答案,让我再弄几个同学来学习下,万一我又遇到新问题呢。
2015-7-6 18:36
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我看到有的破解
还有出现
push XXXX  具体一个数值的情况(程序就变成了注册版的了。)
请问那个数值是如何算出来的呢?
2015-7-6 18:41
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
这是stdcall调用约定方式的堆栈平衡的实现.
simple example:
      int add(int a, int b, int c)它的汇编如下格式:

      push c;
      push b;
      push b;
      call add();     //这是调用add函数,下面要进入add.

      a=a+b;
      a=a+c;
      mov eax,a
      retn 0b         //4(int)*3=12=0xB,因为压了三个形参入栈,相当于栈ESP-0x0B。退出函数的时候,要     平衡栈,所以要ESP+0xB.
2015-7-6 22:29
0
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
不是压入 形参 吧,abc已经是实参了。形参只是占位符。

做加法的汇编应该是:
mov eax, a
add eax, b
add eax, c

---------
2015-7-6 22:45
0
雪    币: 153
活跃值: (181)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
19
和调用约定有关,用完栈空间要回收的嘛
2015-7-7 00:42
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
一个参数是四个字节,那ret8就代表返回两个参数(一个为4字节)
2015-7-7 06:24
0
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21

返回值用寄存器,一般只有一个。
retn 8 中的 8 是在平栈,就是设置栈顶指针 +8
2015-7-7 07:13
0
雪    币: 96
活跃值: (216)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
retn 8是释放局部参数的,然后才能返回调用这个函数的下一条指令
2015-7-7 11:18
0
雪    币: 11
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
哟西,  见过ret 20的, 还没见过ret 11的
2015-7-9 20:05
0
雪    币: 16554
活跃值: (1845)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
亲,那什么时候需要平盏呢?如何分辨和看得出来呢?

我看到过很多的破解,通常都是这样的,
F7进到那个call 里
通常第一句就是push XXX

然后他们一般就改为了 mov eax,1
.............................ret
2015-7-12 09:39
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
来学习学习
2015-7-15 19:53
0
游客
登录 | 注册 方可回帖
返回
//