发新话题
打印

[原创]今天你“hello word”了吗?

[原创]今天你“hello word”了吗?

文章作者:Asm
信息来源:邪恶八进制信息安全团队(http://www.eviloctal.com/)

    最近在回顾一下经典的汇编入门程序 "hello word"的时候,由于忘记了一个传递的参数,程序提示:“你的程序遇到问题需要关闭”:


来看一下错误的代码:
复制内容到剪贴板
代码:
.386
.model flat,stdcall
option casemap:none
include  windows.inc
include  user32.inc
includelib  user32.lib
include  kernel32.inc
includelib  kernel32.lib
.data
szCaption  db  '恭喜',0
szText  db  'hello word',0
.code
start:  
invoke  MessageBox,NULL,offset szText,szCaption,MB_OK  
invoke  ExitProcess,NULL
end  start
很显然,在利用伪指令调用MessageBox的时候,忘记了一个offset,正确的应该是:
invoke  MessageBox,NULL,offset szText,offset szCaption,MB_OK.
估计是什么寄存器传递时候的错误,现在我们来分析一下。
     先看反汇编正确程序看看机器码:
复制内容到剪贴板
代码:
push 00401000 ;push MB_OK 由先进后出的顺序压栈
push 00401002 ;push offset szCaption
push 00401007 ;push offset szText
push 0040100C ;push NULL
call 0040100E ;MessageBox
push 00401013 ;NULL
call 00401012 ;ExitProcess
正确的是将内存地址为00401002H,也就是szCaption在内存中的地址压栈,这样的话才能够正确执行。那么错误的代码程序,反汇编后会是怎么样的?
复制内容到剪贴板
代码:
push 00401000 ;push MB_OK
push 00401002 ;NULL
mov al,byte ptr [00403000]
movzx ax,al
push ax
push 0040100F ;push szText
push 00401004 ;push NULL
call 00401016 ;MessageBox
push 0040100B ;NULL
call 0040101D ;ExitProcess
问题出在这里,mov al,byte ptr [00403000],这句的意思是,把内存地址为00403000的变量地址强制转换成一个8位的字节,保存在al,然后讲8位的al扩展成16位,在执行push ax压栈操作。实际上就等于了DS:[00403000],那么[00403000]的实际地址是多少?在直接寻址方式中,例如 mov ax,[2000h],和mov ax,2000h是不一样的,后者直接把2000h赋给ax,前者是讲2000h的物理地址,也就是 物理地址=(DS)*16D+有效地址存到ax,[2000h]只是一个有效地址,假设DS=3000H,执行后,AX=16D*3000H+2000H=32000H,实际上,AX的值不是1000H了。现在很容易明白,mov al,byte ptr [00403000]后,要压入堆栈的内存地址,已经不是00403000,而是另有所指,具体位置可以这样算:al=(DS)*16D+00403000H 因为我们不知道DS的值,所以也就无法知道最后al等于多少.接着扩展了一下al成为ax,例如01H是al,扩展后,ax=0001H,所以我估计,mov al,byte ptr [00403000]后al只存着一个八位数的值,最终压栈的也就是一个16位的,这样,根据堆栈先进后出的原则,还原成汇编代码是:
复制内容到剪贴板
代码:
invoke MessageBox,NULL,offset szText,offset ax,NULL,MB_OK
根据MSDN中对MessageBox的声明,很显然,错在此咯..并且,ax也不可能直接成为一个参数,至少,在没有扩展movzx eax,ax之前,这样已经是一个明显的错误咯。

   以上分析是本人愚见,如有错漏,请指出  [s:39]


PS:这个"hello word"隐藏在背后的东西真是不少呀  [s:37]
游戏吧  http://www.game8.cc/MyBlog    http://www.asm32.cn

TOP

引用:
start:
invoke  MessageBox,NULL,offset szText,szCaption,MB_OK
invoke  ExitProcess,NULL
end  start


很显然,在利用伪指令调用MessageBox的时候,忘记了一个offset,正确的应该是:
invoke  MessageBox,NULL,offset szText,szCaption,MB_OK.
两个invoke调用有什么不一样的吗??

TOP

[s:39] 不好意思,写错鸟,我改改 
游戏吧  http://www.game8.cc/MyBlog    http://www.asm32.cn

TOP

出现异常而已,为何ASM兄把主题写得这么?让我这个小菜看得很是许郁闷。
下面我说说自己的几个看法:
1、invoke  MessageBox,NULL,offset szText,szCaption,MB_OK

//szCaption
addr szCaption
相当于
p
*p
编译器在处理过程中没检测参数造成了,这个值在不同的环境是不固定的。这个你得动态调试才知道,正是因为这个情况触发了Win的SEH。
复制内容到剪贴板
代码:
push 00401000 ;push MB_OK
push 00401002 ;NULL
mov al,byte ptr [00403000]
movzx ax,al
push ax
push 0040100F ;push szText
push 00401004 ;push NULL
call 00401016 ;MessageBox
push 0040100B ;NULL
call 0040101D ;ExitProcess
这里哪条指令会造成异常?没有!
PE程序对API的调用都是
push xxx (参数1) ;保存在堆栈
push xxx (参数0)
call API ;实际上就是调用IAT中保存的函数地址(相应的在哪个dll提供的函数)
进而直接跳转过去再使用
push [esp+-立即数] ;获取保存在堆栈中的具体参数
...
call API           ;这里才是真正的操作只有往这里继续查看才会找出触发异常的具体地址和指令,可以肯定地说是不可读错误。

TOP

提示: 作者被禁止或删除 内容自动屏蔽

TOP

提示: 作者被禁止或删除 内容自动屏蔽

TOP

发新话题