来自汇编程序

时间:2016-03-12 20:58:21

标签: macos assembly x86 32-bit libc

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

我可以做一个"你好世界"使用syscall(64位)和int 0x80(32位)的其他东西,我可以使_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位代码,因此我希望能够遵循它并理解它。这一切都旨在帮助我逆向设计恶意软件。

由于

1 个答案:

答案 0 :(得分:1)

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

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

位于sub esp,12顶部的

main会将堆栈与16对齐。但您还要执行另一个push,这也会在call之前移动ESP

您的两个选项是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位

并非严格意义:第一代英特尔Mac使用英特尔酷睿CPU(基本上是奔腾M),而非Core2。如果他们等了一代人,他们就不需要太在意32bit了。

虽然此时我认为分发不适用于32位OS X的二进制文件是安全的。