能力值:
(RANK:410 )
2 楼
能力值:
( LV9,RANK:490 )
3 楼
自定位代码的最终目的是为了我们的代码在任何地方执行的时候都能够访问到我们自定义的变量。为了便于理解,我们
先看下面的例子:
.386
.model flat, stdcall
option casemap :none
.code
start:
call nStart
nStart:
pop ebp
sub ebp,offset nStart
ret
end start
编译成可执行代码的样子:
00401000 >/$ E8 00000000 call 00401005
00401005 |$ 5D pop ebp <- 执行到这时的 esp=00401005
00401006 |. 81ED 05104000 sub ebp, 00401005 <- 执行完这句时 ebp=0
0040100C \. C3 retn
根据机器码可见,call nStart在编译后,nStart被替换成了偏移,而sub ebp,offset nStart中的offset start 被换成
了固定地址00401005。
我们把产生的机器码再放到其他位置上看看:
00402000 >/$ E8 00000000 call 00402005
00402005 |$ 5D pop ebp <- 执行到这时的 esp=00402005
00402006 |. 81ED 05104000 sub ebp, 00401005 <- 执行完这句时 ebp=1000
0040200C \. C3 retn
这时得出的ebp有什么意义呢?很容易看出ebp其实就是这段代码目前所在位置和预先编译时所在位置的偏移。这个偏移
有什么用呢?再看下面的例子:
.386
.model flat, stdcall
option casemap :none
.code
start:
jmp @F
Var db "user32.dll",0
@@:
lea edx,Var
ret
end start
编译成可执行代码的样子:
00401000 >/$ /EB 0B jmp short 0040100D
00401002 |. |75 73 65 72 33> ascii "user32.dll",0
0040100D |> \8D15 02104000 lea edx, dword ptr [401002] <- 执行完这句 edx = 00401002
00401013 \. C3 retn
执行完之后,edx为我们预先定义的字符串的地址,可是,如果我们把这段机器码放到其他位置上,如:
00402000 >/$ /EB 0B jmp short 0040200D
00402002 |. |75 73 65 72 33> ascii "user32.dll",0
0040200D |> \8D15 02104000 lea edx, dword ptr [401002] <- 执行完这句 edx = 00401002
00402013 \. C3 retn
执行完之后,edx依然是00401002,而我们自定义的字符串现在却在00402002的位置上,显然这段代码不能在其他位置上
正确执行。好了,如果我们利用上面提到的技术,把代码写成这个样子:
.386
.model flat, stdcall
option casemap :none
.code
start:
jmp @F
Var db "user32.dll",0
@@:
call nStart
nStart:
pop ebp
sub ebp,offset nStart
lea edx,[ebp+offset Var]
ret
end start
编译之后的样子:
00401000 >/$ /EB 0B jmp short 0040100D
00401002 |. |75 73 65 72 3> ascii "user32.dll",0
0040100D |> \E8 00000000 call 00401012
00401012 |$ 5D pop ebp
00401013 |. 81ED 12104000 sub ebp, 00401012 <- 执行完这句 ebp = 0
00401019 |. 8D95 02104000 lea edx, dword ptr [ebp+401002] <- 执行完这句 edx = 00401002
0040101F \. C3 retn
执行完之后,edx为我们预先定义的字符串的地址,如果我们也把这段机器码放到其他位置上呢?如:
00402000 >/$ /EB 0B jmp short 0040200D
00402002 |. |75 73 65 72 3> ascii "user32.dll",0
0040200D |> \E8 00000000 call 00402012
00402012 |$ 5D pop ebp
00402013 |. 81ED 12104000 sub ebp, 00401012 <- 执行完这句 ebp = 1000
00402019 |. 8D95 02104000 lea edx, dword ptr [ebp+401002] <- 执行完这句 edx = 00402002
0040201F \. C3 retn
虽然改变了位置,执行完之后,edx依然是我们预先定义的字符串的地址。
所以无论你把这段机器码写到随机的申请申请的内存空间,还是写到其他进程空间,这段代码都能按我们思路正确执行
。这就是call/pop/sub这种自定位技术的魅力。
能力值:
( LV2,RANK:10 )
4 楼
看不懂啊,能写的在通俗一点吧,像我这种小小菜鸟不懂啊?
能力值:
( LV2,RANK:10 )
5 楼
太感谢petnt 啦!
说得仔细且明白!
不过还有一点小问题,这种简单的问题我都不懂,是因为我经验少呢?还是我看的书少了?
能力值:
( LV9,RANK:490 )
6 楼
应该是自己动手少了,多试几次就明白了
能力值:
( LV2,RANK:10 )
7 楼
好像明白了....得自己动手测试下.效果.谢谢大大...