问题
I'm back again - thanks to the kind folks here, especially @Jester and @PeterCordes, I have three out of my four target platforms working. I have Win 32 and Win 64 working, and I have OS X 64 working, but I can't seem to make OS X assembly work in 32-bit using the libc library.
I can do a "hello world" and other things using syscall (64-bit) and int 0x80 (32-bit), and I can make _printf work in 64-bit, but I can't manage to make it work in 32-bit.
In theory, I need to push the parameters onto the stack and then 16-byte align the stack, but I get a segmentation fault: 11 error when I run the code.
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
I've tried it without the stack aligning code and I get the same error. I've found various samples online and I could not make them work, and I've even done the trick with using GCC to output Intel-syntax assembler and I could not manage to translate it to nasm.
I'm using nasm because it works on Windows, OS X, and Linux, so that way I only need to learn one assembler syntax.
I realize that all the Intel Macs are 64-bit, but they can run 32-bit code so I want to be able to follow it and understand it. This is all aimed at helping me reverse-engineer malware.
Thanks
回答1:
Functions always look for their arguments just above the return address. If you sub esp, 12
after pushing something, the args include 12 bytes of garbage.
Also, 12 is the wrong amount of space. ESP is 16-byte aligned before a call
, according to the ABI, so the start of the stack args is 16-byte aligned. But call
pushes a return address, so on entry to a function ESP+4
and ESP-12
are the nearest alignment boundaries.
sub esp,12
at the top of main
would align the stack by 16. But you doing another push
as well, which also moves ESP before call
Your 2 options are sub esp, 8
/ push hello
orsub 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
Not strictly true: the very first gen Intel macs used Intel Core CPUs (basically Pentium-M), not Core2. If they'd waited one generation, they never would have needed to care much about 32bit.
Although at this point, I assume it's considered safe to distribute binaries that don't work on 32bit-only OS X.
来源:https://stackoverflow.com/questions/35963233/os-x-32-bit-printf-from-assembler