汇编程序的os x 32位printf [英] os x 32-bit printf from assembler

查看:130
本文介绍了汇编程序的os x 32位printf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我又回来了-多亏了这里的好心人,尤其是@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您好, 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字节对齐堆栈
20调用_printf
21
22 add esp,16;撤消堆栈对齐
23 push 0
24 sub esp,12; 16字节对齐堆栈
25调用_exit

我尝试了不对齐堆栈代码,我得到相同的错误。我在网上找到了各种示例,但我无法使它们正常工作,我什至通过使用GCC来输出Intel语法汇编程序来完成技巧,而无法将其转换为nasm。



我之所以使用nasm,是因为它可在Windows,OS X和Linux上运行,因此我只需要学习一种汇编语法。



<我意识到所有的Intel Macs都是64位的,但是它们可以运行32位的代码,因此我希望能够遵循并理解它。都是为了帮助我对恶意软件进行逆向工程。



谢谢

解决方案

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



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



sub esp,12 在顶部 main 的值将使堆栈对齐16。但是您还要执行另一个 push ,这也会将ESP移到<$之前c $ c> call



您的2个选项是 sub esp,8 / push hello

sub esp,12 / mov dword [esp ],你好

  _main:; ESP在调用之前将返回地址
sub esp,8对齐为16字节。使ESP达到对齐边界
以上4个字节push hello; ESP现在是16字节对齐的。
call _printf

mov dword [esp],0;推迟弹出
调用_exit
;添加esp,4 + 8;弹出args + padding。但是退出并不会返回
;退出

section .rodata;您无需编写此字符串,因此将其放入rodata

hello db Hello,world,0x0a,0x00







所有Intel Mac均为64位




并非完全正确:第一代Intel Mac使用的是Intel Core CPU(基本上是Pentium-M),而不是Core2。如果他们等了一代人,他们根本就不需要关心32位。



尽管在这一点上,我认为分发不包含二进制文件的二进制文件被认为是安全的。不能在仅32位的OS X上运行。


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

解决方案

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.

这篇关于汇编程序的os x 32位printf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆