os x 32-bit printf from assembler

落爺英雄遲暮 提交于 2020-01-06 20:14:34

问题


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 or
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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!