能力值:
( LV13,RANK:240 )
|
-
-
2 楼
既然你诚心诚意的问了。我就大发慈悲地告诉你。
我,武藏,我,小次郎。我们是穿梭在银河系的火箭队。
白洞,白色的明天在等着我们。
喵
就是这样
|
能力值:
( 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 <= 这里也是平盏操作
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
还是不太明白,希望专家能结合图中的地址,说说如何把栈的值 搞得平衡了,
说的再具体些。。。
|
能力值:
( LV12,RANK:270 )
|
-
-
5 楼
[QUOTE=killbr;1379599]
还是不太明白,希望专家能结合图中的地址,说说如何把栈的值 搞得平衡了,
说的再具体些。。。 [/QUOTE]
要平衡的是call之前的push,先搞清楚函数调用时的堆栈吧
func(int,int)
就是先压栈两个int,然后返回地址入栈
ret的时候要返回地址出栈,可是下面还有两个int,所以需要ret 8,把返回地址下面的两个int也弹出栈
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
给错图片了,好像该给这张才对。
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
我好像有点开窍了,是不是因为 得根据修改的字节数来算?
未改前是:004A74D0 B8 04100000 mov eax, 0x1004
--------------------------
修改后是: 004A74D0 B8 01000000 mov eax, 0x1
所以下一句 就得改成 retn 4
----------------------------
0100算两个字节
所以,要想平衡 就是 retn 就得是: 4乘以2
|
能力值:
( 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
理解或许有疏忽,谅解。
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
我还是不太明白,修改了第一句之后
那个retn 的返回值, 我理解的还是不大对啊,开始以为红了几个字就乘以相应的数字 X2 ,要怎么样才能轻易的搞懂,填对呢?
球个给菜鸟 解决的策略 就好了。
|
能力值:
( 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
这样就言简意赅了吧。。。咳咳.. 一个栈占四个字节 就这么算 你压入一个参数 就占一个栈.很通俗了吧
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
首先告诉我你会不会编程吧,最好是C++的容易理解一点
一个函数可以有很多个参数,参数的个数决定了平盏的大小
int test(int a,int b,int c); 如果是这个函数则需要平盏 0xC 3*4 = 12 = 0xC
如果你实在搞不懂,你就自己写几个函数,然后拖到OD 或者IDA 查看汇编代码
|
能力值:
( LV3,RANK:30 )
|
-
-
12 楼
压入栈的是2个32位寄存器中的值,也就是每个值4字节,retn idata废除的是idata/4个无用参数。
在16位段中,如果使用retn idata,则废除的是idata/2个无用参数,不过现在除基础汇编教学基本上不用16位端 。
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
感谢,要的就是这种表达,这次彻底明白了。
今天 上午算是没有白来,再次感谢下。
|
能力值:
( LV3,RANK:20 )
|
-
-
14 楼
那就赶紧结贴吧= =我要转正式会员
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
回来评你为最佳答案,让我再弄几个同学来学习下,万一我又遇到新问题呢。
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
我看到有的破解
还有出现
push XXXX 具体一个数值的情况(程序就变成了注册版的了。)
请问那个数值是如何算出来的呢?
|
能力值:
( 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.
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
不是压入 形参 吧,abc已经是实参了。形参只是占位符。
做加法的汇编应该是:
mov eax, a
add eax, b
add eax, c
---------
|
能力值:
( LV5,RANK:60 )
|
-
-
19 楼
和调用约定有关,用完栈空间要回收的嘛
|
能力值:
( LV2,RANK:10 )
|
-
-
20 楼
一个参数是四个字节,那ret8就代表返回两个参数(一个为4字节)
|
能力值:
( LV2,RANK:10 )
|
-
-
21 楼
返回值用寄存器,一般只有一个。
retn 8 中的 8 是在平栈,就是设置栈顶指针 +8
|
能力值:
( LV2,RANK:10 )
|
-
-
22 楼
retn 8是释放局部参数的,然后才能返回调用这个函数的下一条指令
|
能力值:
( LV2,RANK:10 )
|
-
-
23 楼
哟西, 见过ret 20的, 还没见过ret 11的
|
能力值:
( LV2,RANK:10 )
|
-
-
24 楼
亲,那什么时候需要平盏呢?如何分辨和看得出来呢?
我看到过很多的破解,通常都是这样的,
F7进到那个call 里
通常第一句就是push XXX
然后他们一般就改为了 mov eax,1
.............................ret
|
能力值:
( LV2,RANK:10 )
|
-
-
25 楼
来学习学习
|
|
|