我又回来了 - 感谢这里的好心人,尤其是@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位代码,因此我希望能够遵循它并理解它。这一切都旨在帮助我逆向设计恶意软件。
由于
答案 0 :(得分:1)
函数总是在返回地址上方查找其参数。如果您在推送内容后sub esp, 12
, args包含12个字节的垃圾。
另外,12是错误的空间量。 ESP在 a call
,according 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的二进制文件是安全的。