注册 登录
编程论坛 汇编论坛

请教一段经典汇编代码的解释

redice 发布于 2008-07-16 00:02, 5417 次点击
请教一段经典汇编代码的解释

下面代码:
VC中嵌入汇编,实现了程序运行后自销毁程序的功能.我对Win32汇编不熟,麻烦高人解释一下.

#include "windows.h"
int main(int argc, char *argv[])
{
  char   buf[MAX_PATH];
  HMODULE module;
  module = GetModuleHandle(0);
  GetModuleFileName(module, buf, MAX_PATH);
  CloseHandle((HANDLE)4);
  __asm  
  {
    lea   eax, buf
    push   0
    push   0
    push   eax
    push   ExitProcess
    push   module
    push   DeleteFile
    push   UnmapViewOfFile
    ret
  }
  return 0;
}
21 回复
#2
redice2008-07-16 00:05
操作                      堆栈
Push UnmapViewOfFile    Address of UnmapViewOfFile()
Push DeleteFile             Address of DeleteFile()
Push module             module
push ExitProcess             address of ExitProcess()
push eax                      offset buf
push 0                      0
push 0                      0


我自己的理解:当执行到ret之前,堆栈的情况如上面所示.当执行ret时,程序返回到了UnmapViewOfFile(),但是这个函数的参数是怎么传递进去的呢?
#3
redice2008-07-16 00:06
相关API:
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
参数
  lpBaseAddress
  [in] Pointer to the base address of the mapped view of a file that is to be unmapped. This value must be identical to the value returned by a previous call to the MapViewOfFile or MapViewOfFileEx function.
#4
redice2008-07-16 01:44
等待中...
#5
redice2008-07-16 10:52
怎么没人说话呢??help!
#6
你们都要疼我哦2008-07-16 12:45
刚学,看不懂.

汇编里调用API是这形式
INVOKE API名,参数1,参数2,参数3

INVOKE是伪指令,对应于这个形式:

PUSH 参数3
PUSH 参数2
PUSH 参数1
CALL API



push   module
push   DeleteFile
push   UnmapViewOfFile  

这个已经传参了吧.2个
#7
redice2008-07-16 16:01
回复 6# 你们都要疼我哦 的帖子
??晕 难道Address Of DeleteFile 成了UnmapViewOfFile 的参数不成?
#8
redice2008-07-16 22:58
继续等高人指点
#9
ONEPROBLEM2008-07-17 07:40
LZ,VC中嵌入汇编我不懂啊.
但我想说一下个人不成熟的看法:
在WIN32汇编中,子程序或API函数在被调用的时候,它的参数都是通过栈来传递的!而且,假设当前栈顶是EBP,它就会从[EBP+XX],即向栈的底部方向获取参数.
所以,"难道Address Of DeleteFile 成了UnmapViewOfFile 的参数不成?"不是难道,而是如此!
当然,UnmapViewOfFile 的参数不一定是Address Of DeleteFile ,而是这样:
"当前栈顶"+08,"当前栈顶"+0C之类的.
那么原先被压入栈中的
    push   0
    push   0
    push   eax
    push   ExitProcess
    push   module
都有可能是它的参数.
其实,只要楼主反汇编一下,应该一切都如透视般清晰的!(呵呵~~如果被调用的函数都是从跳转指令来的,就不好追踪它的位置及栈的情况了.)

[[it] 本帖最后由 ONEPROBLEM 于 2008-7-17 08:42 编辑 [/it]]
#10
你们都要疼我哦2008-07-17 12:44
俺也不懂,乱讲的.   
UnmapViewOfFile这个也没用过,不知道参数是啥.

不过既然是销毁文件,参数总离不了句柄或者文件名,在汇编里这些都是地址指针的形式.

可以反汇编或者动态调试一下,看UnmapViewOfFile的参数就清楚了.
#11
ONEPROBLEM2008-07-17 14:37
回复 10#
言之有理有据即可,何来"乱讲"之说?
有一分光发一分热,好过冷冷清清没人搭理哦.

[[it] 本帖最后由 ONEPROBLEM 于 2008-7-17 14:39 编辑 [/it]]
#12
你们都要疼我哦2008-07-17 22:16
  楼主觉得俺讲的不靠谱,用了"难道"一词.  俺也确实不太了解内嵌汇编,甚至连WIN32汇编也是刚学,再一看楼主所发过的帖子,只好自认乱说了.
虽说有理有据,但是毕竟心里没底,乱说就乱说了.等以后成大牛了,再来给自己平反
#13
ONEPROBLEM2008-07-18 08:28
回复 12# 你们都要疼我哦 的帖子
"等以后成大牛了,再来给自己平反"!
呵呵~~~~指日可待了
#14
woami662008-07-18 16:20
高人给你指点,(*^__^*) 嘻嘻……,开个玩笑,别骂我啊!

这个东西其实很简单,自己画一下内存图就知道了,首先,ret指令会使EIP转向UnmapViewOfFile,这时UnmapViewOfFile需要一个参数,就是module,至于为什么不是DeleteFile,那是因为栈顶元素是返回地址,而栈顶+4才是第一个参数,这样,UnmapViewOfFile执行完后,直接“返回”到DeleteFile处执行删除自身的操作,而DeleteFile的参数就是buf,以此类推!
#15
你们都要疼我哦2008-07-18 17:32
又搜索了一下,发现这段代码很有来头的.

利用了堆栈执行的方法.
ret以后,要从堆栈里弹出返回地址,于是UnmapViewOfFile就弹出来了,这个API需要参数,于是就从堆栈里去取,它根据汇编语法,认为栈顶元素是返回地址,参数要+4,所以取到了push module.  执行完以后,又返回到它认为的返回地址,即DeleteFile,这个也需要参数,刚才module已弹出,所以它又认为push ExitProcess 是返回地址,参数要+4,所以取到了push eax,执行完以后,又返回到他认为的返回地址,即ExitProcess,...  所以为什么要PUSH进两个0的原因也清楚了,是为了堆栈平衡.

这段代码很神奇的用堆栈执行了3个操作,很有技巧和水平. 现在才明白.

感谢楼上高手指点.
#16
redice2008-07-18 18:16
回复 9# ONEPROBLEM 的帖子
"当然,UnmapViewOfFile 的参数不一定是Address Of DeleteFile ,而是这样:
"当前栈顶"+08,"当前栈顶"+0C之类的."


UnmapViewOfFile原型如下:
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);

那Address of DeleteFile() 就应该是UnmapViewOfFile的参数呀?? 你为什么说"当前栈顶"+08,"当前栈顶"+0C之类的.
#17
redice2008-07-18 18:17
LPCVOID Pointer to a constant of any type.
#18
redice2008-07-18 18:19
回复 12# 你们都要疼我哦 的帖子
不好意思 用词不当之处还望海涵

咱们共同提高!!
#19
redice2008-07-18 18:21
回复 15# 你们都要疼我哦 的帖子
谢谢了 刚才看到你们的回复

谢谢大家的参与!!
#20
ONEPROBLEM2008-07-18 18:39
回复 16# redice 的帖子
“UnmapViewOfFile原型如下:
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress); ”
====================================================
对这个函数我真的一点也不懂的。包括英文,对我而言是天书啊。 全丢给老师啦。
我之所以说,"当前栈顶"+08,"当前栈顶"+0C之类的.你可以参照14#、15#的说法。
其实我是经常反汇编才知道有这回事的。[“当前栈顶”+04],往往是CALL本函数时压入的返回地址,本函数就从[“当前栈顶”+08]开始获取参数了。
当然,我所说的“当前栈顶”是不准确的!在汇编里,调用函数或子程序时:
push  ebp
mov   ebp,esp
... ...
执行这两条指令后,EBP中的值,我把它当作“当前栈顶”(可能不正确
在运行过程中,程序会保持EBP不变,从而通过[EBP+XX],或[EBP-XX]之类来得到栈中的数据。
返回的时候:
leave    ;相当于mov esp,ebp   pop ebp
ret
就一切OK了。
#21
redice2008-07-19 17:29
汇编代码基本上我已经理解了 编译也没问题 但是达不到预期的效果-“自销毁”

郁闷

[[it] 本帖最后由 redice 于 2008-7-19 17:31 编辑 [/it]]
#22
你们都要疼我哦2008-07-19 20:52
应该是没效果了.可能2000以上都不行的.
因为前面的代码已经硬关闭了句柄, 这段ASM是在堆栈中执行,现在的系统出于安全考虑,已经有了限制, 如果不限制,可以想象,利用这个技巧可以构造很多不健康的应用
1