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+4
和 ESP-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.
我又回来了——感谢这里的好心人,尤其是@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+4
和 ESP-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.