os 来自汇编程序的 x 32 位 printf

os x 32-bit printf from assembler

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

我可以使用 syscall(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 输出英特尔语法汇编器来完成技巧,但我无法将其翻译成 nasm.

我正在使用 nasm,因为它适用于 Windows、OS X 和 Linux,因此我只需要学习一种汇编语法。

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

谢谢

函数总是在 return 地址上方寻找它们的参数。如果您 sub esp, 12 在推送内容后,args 包含 12 个字节的垃圾

此外,12 是 space 的错误数量。 ESP 是 16 字节对齐的 before a call, according to the ABI,所以堆栈参数的开始是 16 字节对齐的。但是 call 压入一个 return 地址,所以在函数入口处 ESP+4ESP-12 是最近的对齐边界。

main 顶部的

sub esp,12 会将堆栈对齐 16。但是您还执行另一个 push,这也会在 call[= 之前​​移动 ESP 26=]

您的 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

all the Intel Macs are 64-bit

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

虽然在这一点上,我认为分发不适用于 32 位的二进制文件被认为是安全的 OS X.