2010-09-08 83 views
4

我想直接在汇编中使用gcc内联调用MessageBoxA()。不过,我需要通过两种方式来实现:首先是使用动态寻址,使用LoadLibrary()和GetProcAddress() - 我找到了关于这个的教程,试图遵循它。但我也有兴趣直接调用MessageBoxA的地址,在我的Windows SP3英文中是0x7e4507ea。Windows中的MessageBoxA AT&T汇编

我试图执行此代码:

/* 
* eax holds return value 
* ebx will hold function addresses 
* ecx will hold string pointers 
* edx will hold NULL 
* 
*/ 


int main(int argc, char **argv) 
{ 
asm(" xor %eax, %eax   \t\n\ 
     xor %ebx, %ebx   \t\n\ 
     xor %ecx, %ecx   \t\n\ 
     xor %edx, %edx   \t\n\ 
     push $0x0    \t\n\ 
     push $0x44444444  \t\n\ 
     push $0x44444444  \t\n\ 
     pop %ecx    \t\n\ 
     mov %dl,0x3(%ecx)  \t\n\ 
     mov $0x7e4507ea, %ebx \t\n\ 
     push %edx    \t\n\ 
     push %ecx    \t\n\ 
     push %ecx    \t\n\ 
     push %edx    \t\n\ 
     mov $0x8, %ax   \t\n\ 
     call *%ebx    \t\n\ 
     "); 
} 

我不知道,如果在Windows中甚至可以做到这一点,直接调用地址,没有在此指定库(USER32.DLL案件)。我知道在Linux中很容易调用write()系统调用,但在Windows中我还不太熟悉。

我期望看到带有“DDDDDDDD”的消息框。有人可以帮我吗?欣赏任何帮助,也有教程链接!

非常感谢

+0

嘿,正如你在评论中提到的,你已经做到了。你能否描述我如何与IAT相处?在上例 – 2016-11-03 06:57:34

回答

2

写在C第一,编译和查看装配清单,看看编译器生成的。这是最简单的学习方式。 如果您看到一条您不明白的指令,请在“英特尔指令集参考手册”中查找它。

+0

我试过这样做,但那不是那么简单。我这样编译:gcc -c msgbox3.c -static -mpreferred-stack-boundary = 2。但是我得到的目标文件包含一些汇编指令,这些指令并没有太多帮助......无论如何感谢发布。 – jyz 2010-09-09 13:53:24

+0

@jyzuz:在学习之前,你学会了在阅读之前学会阅读的理由。对于计算机语言,这同样适用。如果你不能阅读大会,你就不要试图写出它。 – MSalters 2010-09-09 15:10:34

+0

@ MSalters:我正在学习与Richard Blum的书(适用于Linux)的阅读/写作。还学习Windows程序集阅读互联网上的一些文章。我认为最好的学习方法是阅读和练习。如果我在写一个单词之前首先成为阅读专家,那么我无法记录自己是小孩的时候。但我认为,如果不尝试和犯错误,你永远不会学习编程。也许我试图跑“比我的腿快”...呃...我很好奇嘿嘿;) – jyz 2010-09-09 16:49:41

1

直接调用地址

听起来像一个大禁忌。 API调用没有固定的地址。这取决于它在内存中加载的位置。尽管我确信User32.dll在OS启动时被加载,但我不会指望它占据相同的空间。

要调用API例程,必须将其导入,以便操作系统可以为您提供正确的地址。

+0

但这有点奇怪,因为我在这里做了几个星期的测试,每一次我在user32.dll中查找MessageBoxA的地址,它返回0x7e4507ea。这是否意味着这是MessageBoxA在user32.dll或内存中的地址? – jyz 2010-09-09 13:41:32

+0

'0x7e4507ea'是您的进程空间中的地址。这是合理的稳定有两个原因:首先,user32.dll本身加载很早。因此,它每次都倾向于在同一个位置加载。稍后加载的DLL将不得不采取任何地址,如果离开。其次,user32.dll通常只在微软修正了一个错误时才会改变,而这并不是每周都会发生的 - 当然不适用于只有安全错误得到修复的XP SP3。 – MSalters 2010-09-09 15:04:49

+0

还是一个坏主意,就像通过序数调用一样。 – 2010-09-09 15:09:51

1

“直接”调用MessageBoxA是不可能的。是的,你可以添加电话0x7e4507ea,但它并不重要。你必须添加一个条目到你的导入地址表,它说你从user32.dll调用MessageBoxA,并从哪里。当Windows加载可执行文件时,它会看到您正在调用MessageBoxA,为您加载user32.dll,并修正MessageBoxA结束的实际地址。

+0

好吧,我想我明白了。我知道Windows可执行文件与Linux ELF文件完全不同。这个“导入地址表”是Windows可执行文件中的一个会话,对吧?我会阅读更多关于此..感谢回答 – jyz 2010-09-09 16:55:51

+0

是的,也被称为“IAT”部分 – MSalters 2010-09-10 07:49:08

+0

事实上,这是可能的。现在我可以这样做:) – jyz 2010-10-07 13:38:38

2

我这样做:

int main() 
{ 
    asm("xorl %eax, %eax  \n" 
     "xorl %ebx, %ebx  \n" 
     "xorl %ecx, %ecx  \n" 
     "xorl %edx, %edx  \n" 
     "pushl %ecx    \n" 
     "pushl $0x20206c6c  \n" 
     "pushl $0x642e3233  \n" 
     "pushl $0x72657375  \n" 
     "movl %esp, %ecx  \n" 
     "movl $0x7c801d7b, %ebx \n" 
     "pushl %ecx    \n" 
     "call *%ebx    \n" 
     "movl $0xef30675e, %ecx \n" 
     "addl $0x11111111, %ecx \n" 
     "pushl %ecx    \n" 
     "pushl $0x42656761  \n" 
     "pushl $0x7373654d  \n" 
     "movl %esp, %ecx  \n" 
     "pushl %ecx    \n" 
     "pushl %eax    \n" 
     "movl $0x7c80ae40, %ebx \n" 
     "call *%ebx    \n" 
     "movl %esp, %ecx  \n" 
     "xorl %edx, %edx  \n" 
     "pushl %edx    \n" 
     "pushl %ecx    \n" 
     "pushl %ecx    \n" 
     "pushl %edx    \n" 
     "call *%eax    \n" 
     "xorl %eax, %eax  \n" 
     "pushl %eax    \n" 
     "movl $0x7c81cb12, %eax \n" 
     "call *%eax    \n" 
    ); 
} 

即使强悍完全可以硬编码的函数的地址,我更喜欢动态加载(虽然我硬编码地址KERNEL32),因此,它的工作原理在任何Windows XP上(SP1,2,3)

+0

[地址空间布局随机化](http://blogs.msdn.com/b/michael_howard/archive/2006/05/26/address-space-layout-randomization-in -windows-vista.aspx)几乎改变了图片。 *硬编码地址*和*失败*已成为同义词。 – IInspectable 2015-03-28 17:13:49