能力值:
(RANK:350 )
|
-
-
2 楼
::004012E5:: 6A 00 PUSH 0 //改成jmp 004012F9
::004012E7:: 68 68274000 PUSH 402768 \->: test2.exe
::004012EC:: 68 60274000 PUSH 402760 \->: Open
::004012F1:: 6A 00 PUSH 0
::004012F3:: FF15 B0224000 CALL NEAR DWORD PTR [4022B0] >>>: SHELL32.DLL:ShellExecuteA
004012F9:: 8B4C24 0C MOV ECX, DWORD PTR [ESP+C]
|
能力值:
(RANK:260 )
|
-
-
3 楼
看雪老师亲自回答了...
对于很多像我这样的新手,
可能不太明白原理
我只是补充一下
高手莫笑
修改的原则,就是保持堆栈的平衡.
基础知识(给小菜看的)
在CALL之前,连续的压栈操作是将调用函数的参数压入堆栈,压入的数据都是临时数据,在函数返回后便没有用了,所以必须要进行清栈
如果函数的返回入的指令是 retn X 这样的形式,(比如函数需要3个参数,那么这里便是 retn 0C),在C语言中,意思就是这个函数是 _cdecl 属性的
而C语言中 _stdcall 在汇编层面表现就是函数以 retn 指令返回,而在call指令下面,有一条清栈的指令,一般为 add esp,X (如3个参数,X便为0C).(一般是紧接着的一条指令,但不一定,可能会因为改善代码密度等原因被编译器进行优化,推迟几条指令,或者几个CALL之后再批量清栈)
对于后种情况,直接将 CALL 指令 NOP 掉是最简单的修改方法
对于前种情况,可以像看雪老师给出的示例那样,在参数压栈之前便进行修改,便可以保持堆栈平衡,而如果要在CALL上做手脚的话,必须改为 add esp, X 的形式
当然只是为了说明原理,不同的方法都是正确的.
可以这样改:
::004012E5:: 6A 00 PUSH 0
::004012E7:: 68 68274000 PUSH 402768 \->: test2.exe
::004012EC:: 68 60274000 PUSH 402760 \->: Open
::004012F1:: 6A 00 PUSH 0
::004012F3:: FF15 B0224000 CALL NEAR DWORD PTR [4022B0] >>>: SHELL32.DLL:ShellExecuteA // 这里改为 add esp,0x10
::004012F9
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
为什么在push 0那里改,而不在push 5那里改?push 5是第一个参数啊.
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
谢谢!
不好意思!是我的代码没有贴完整!
|