【问题标题】:Error when calling function in user32.dll directly直接调用user32.dll中的函数时出错
【发布时间】:2019-04-26 22:30:08
【问题描述】:

前段时间,我从一个人那里读到一篇文章,他演示了如何通过内存地址直接调用程序集 (NASM) 中的 user32.dll 中的函数。我没有这篇文章了,但我正在尝试重现这个实验。

我要执行的函数是user32.dll中的MessageBoxA,在我的电脑上,该函数应该位于地址0x76cd75c0。

函数如下:

int MessageBoxA(
     HWND hWnd,              # NULL
     LPCSTR IpText,          # text
     LPCSTR IpCaption,       # title
     UINT uType              # style
);

这是程序:

global _main                        

section .data                       
msgText:    db 'Hello World', 0
msgCaption: db 'Title', 0       

section .text                   
_main:                          
    push 0
    push msgCaption
    push msgText
    push 0
    call 0x76cd75c0

    add esp, 4
    ret 0x10

为了编译我使用的程序:

nasm –f win32 message_box.asm

但是,我收到以下错误消息:

error: Win32 COFF does not correctly support relative references to absolute 
addresses

无论我使用普通地址还是相对地址,我都会收到相同的错误消息。

谁知道问题出在哪里?

【问题讨论】:

  • 这看起来像是一种使用 Win32 API 的过于复杂的方式。为什么不使用 Hutch 的 MASM32 包?它的包含和库文件,以及使用invoke,使得访问 Win32 API 非常舒适。如果您喜欢坚持使用开放软件,请尝试兼容 MASM 的JWASM
  • 是的,这就是重点:) 否则我会使用 _MessageBoxA@16。这纯粹是实验性的,如果可行的话会很酷。

标签: winapi assembly x86 nasm


【解决方案1】:

问题在于它不存在直接(地址直接作为操作数给出)、近(无段)和绝对的call
here

call XXX是近而直接的,所以不可能是绝对的。
其实是相对的。
NASM tries to create a relocation 用于相对调用(注意 OUT_REL4ADR 类型),但 0x76cd75c0 在源代码中定义的任何部分之外,显然不支持。

使用绝对地址调用函数的唯一方法是使用FAR 调用,但这需要立即段值。
这在保护模式下很少能很好地结束,并且在 cmets 中注意到了一个,这也会推动cs。 (否则,您可以使用0x23 selector that Windows sets for 32-bit applications,如call 0x23:0x76cd75c0)。

您可以使用间接调用:

mov ebx, 0x76cd75c0
call ebx

注意add esp, 4 在这里看起来非常错误,Win API 遵循stdcall 调用对流(它们自己清除堆栈)。

【讨论】:

  • call 0x23:0x76cd75c0 会慢很多,并且会推送 CS:EIP。如果函数在堆栈上查找任何参数,它将获取 CS 作为第一个参数。 mov eax, 0x76cd75c0 / call eax 应该会好很多。或者使用通过内存中的指针调用的普通DLL机制。
  • 值得一提的是Linux/ELF位置相关代码可以使用相对调用来达到绝对地址;我不知道为什么 Windows 会忽略它并强制 asm 效率低下。但至少这解释了为什么How to write an absolute target for a near direct relative call/jmp in MASM没有答案
  • @PeterCordes 关于远程呼叫的好点,最好删除它。
  • 我已经尝试将地址移动到ECX,然后调用ECX解决了编译器的问题。但是......程序崩溃......任何想法为什么?我链接了“ld -e _main hello.obj -lkernel32”
  • @Lavonen 您是否尝试过使用调试器单步执行?像 OllyDbg/x96dbg 之类的?可能有很多原因,包括MessageBoxA 不存在或user32.dll 本身。调试器将排除这些基本问题。
猜你喜欢
  • 2012-10-14
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 2018-10-30
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
相关资源
最近更新 更多