【问题标题】:os x 32-bit printf from assembler来自汇编程序的 os x 32 位 printf
【发布时间】:2016-06-28 01:21:36
【问题描述】:

我又回来了 - 感谢这里的好心人,尤其是 @Jester 和 @PeterCordes,我的四个目标平台中有三个正在运行。我有 Win 32 和 Win 64 工作,我有 OS X 64 工作,但我似乎无法使用 libc 库使 OS X 程序集在 32 位中工作。

我可以使用系统调用(64 位)和 int 0x80(32 位)做一个“hello world”和其他事情,我可以让 _printf 在 64 位下工作,但我无法做到工作在 32 位。

理论上,我需要将参数压入堆栈,然后 16 字节对齐堆栈,但是运行代码时出现分段错误:11 错误。

 8 section .data
 9 
10 hello   db  "Hello, world", 0x0a, 0x00
11 
12 section .text
13 
14 global _main
15 extern _printf, _exit
16 
17 _main:
18     push hello
19     sub esp, 12     ; 16-byte align stack
20     call _printf
21 
22     add esp, 16     ; undo stack alignment
23     push 0
24     sub esp, 12     ; 16-byte align stack
25     call _exit

我在没有堆栈对齐代码的情况下尝试过它,但我得到了同样的错误。我在网上找到了各种示例,但我无法让它们工作,我什至使用 GCC 来输出 Intel 语法汇编器,但我无法将其转换为 nasm。

我使用 nasm 是因为它可以在 Windows、OS X 和 Linux 上运行,所以我只需要学习一种汇编语法。

我知道所有的 Intel Mac 都是 64 位的,但它们可以运行 32 位代码,所以我希望能够遵循并理解它。这一切都是为了帮助我对恶意软件进行逆向工程。

谢谢

【问题讨论】:

  • 您在将 gcc -masm=intel 输出转换为 NASM 时遇到问题?这很奇怪;它很像 MASM,所以除了写DWORD PTR 而不是DWORD 之外基本相同。您总是可以只使用输出正确 nasm 语法的反汇编程序,例如Agner Fog 的优秀 objconv 反汇编程序。

标签: macos assembly x86 32-bit libc


【解决方案1】:

函数总是在返回地址上方寻找它们的参数。如果你在 push 之后sub esp, 12args 包含 12 字节的垃圾

另外,12 是错误的空间量。 ESP 在callaccording to the ABI之前是 16 字节对齐的,因此堆栈 args 的开头是 16 字节对齐的。但是call 推送了一个返回地址,所以在进入函数时ESP+4ESP-12 是最近的对齐边界。

main 顶部的sub esp,12 会将堆栈对齐 16。但是您还要执行另一个 push,这也会将 ESP 移动到 call 之前

您的 2 个选项是 sub esp, 8 / push hello
sub esp,12 / mov dword [esp], hello

_main:                ; ESP was 16-byte aligned *before* call pushed a return address
    sub   esp, 8      ; get ESP to 4 bytes above an alignment boundary
    push  hello       ; ESP is now 16-byte aligned.
    call  _printf

    mov   dword [esp], 0    ; defer popping the stack
    call  _exit
    ;add   esp, 4+8        ; pop args+padding.  But exit doesn't return
    ;ret

    section .rodata      ; You don't need to write this string, so put it in rodata

     hello   db  "Hello, world", 0x0a, 0x00

所有的 Intel Mac 都是 64 位的

并非完全正确:第一代 Intel mac 使用 Intel Core CPU(基本上是 Pentium-M),而不是 Core2。如果他们等了一代人,他们就不需要太关心 32 位了。

尽管在这一点上,我认为分发无法在 32 位 OS X 上运行的二进制文件是安全的。

【讨论】:

  • 嗨,彼得。这对堆栈是有道理的——我认为它看起来很奇怪,最糟糕的是,这正是我在一些网站上看到的,据说是解释如何做到这一点的。我想我现在搞砸了链接,因为它会组装但会生成 Segmentation Fault: 11 错误。
  • @querist:使用file 命令确保它是 32 位二进制文​​件。或使用gcc -m32 hello.o 链接。查看objdump -d -Mintel 的输出,或者你喜欢的任何反汇编程序,看看你的二进制文件发生了什么。或者更好的是,在 gdb 下运行它。使用调试器对于学习 asm 是必不可少的。 (gdb 有一个 intel 语法模式。把 set disassembly-flavor intel 放在你的 ~/.gdbinit 中)
  • 这是一个 32 位的可执行文件。我在 _main: ld: warning: PIE disabled 中收到关于绝对寻址的警告。代码签名的 PIE 中不允许使用绝对寻址(可能是 -mdynamic-no-pic),但在 hello32x.o 的 _main 中使用。要修复此警告,请勿使用 -mdynamic-no-pic 进行编译或使用 -Wl 链接,-no_pie 仍然会出现分段错误。没想到用 libc 让它在 32 位下工作这么难。
  • 最新版本的 OS X 带有 lldb。我会更加熟悉它。谢谢!
  • 如果您仍然无法获得 32 位链接,请提出一个新问题。这个问答被困在传递参数的错误上,这也适用于 32 位 Windows 和 Linux,因为它们使用相同的调用约定。 OS X 有很多关于位置无关代码的规则,但我很惊讶它们适用于 RIP 相对寻址不可用的 32 位。我想这使得 OS X 上的 32 位代码比其他操作系统上的 32 位代码更糟糕。
猜你喜欢
  • 2013-12-03
  • 2016-06-28
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 2015-06-14
  • 2011-07-23
  • 1970-01-01
相关资源
最近更新 更多