4

我正在尝试使用 gcc 内联直接在程序集中调用 MessageBoxA()。但是我需要以两种方式做到这一点:首先是使用动态寻址,使用 LoadLibrary() 和 GetProcAddress() - 我找到了一个关于这个的教程,试图遵循它。但我也有兴趣直接调用 MessageBoxA 的地址,在我的 Windows SP3 英语中是 0x7e4507ea。

我正在尝试执行此代码:

/*
 *    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”的消息框。有人可以帮我吗?感谢任何帮助,还有教程链接!

非常感谢

4

4 回答 4

2

先用C写,编译查看汇编列表,看看编译器生成了什么。这是最简单的学习方法。如果您看到不理解的指令,请在英特尔指令集参考 PDF 中查找。

于 2010-09-08T19:13:13.207 回答
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)上运行

于 2010-10-18T11:55:14.237 回答
1

直接调用地址

听起来像是一个很大的禁忌。API 调用没有固定地址。这取决于它在内存中的加载位置。虽然我确定在操作系统启动时加载了 User32.dll,但我不会指望它占用相同的空间。

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

于 2010-09-09T13:14:31.890 回答
1

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

于 2010-09-09T15:09:16.693 回答