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

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

问题描述

我又回来了 - 感谢这里的好心人,尤其是@Jester 和@PeterCordes,我的四个目标平台中有三个正在运行.我有 Win 32 和 Win 64 工作,我有 OS X 64 工作,但我似乎无法使用 libc 库使 OS X 程序集在 32 位工作.

我可以使用系统调用(64 位)和 int 0x80(32 位)来做一个hello world"和其他事情,我可以让 _printf 在 64 位下工作,但我无法做到以 32 位工作.

理论上,我需要将参数压入堆栈,然后16字节对齐堆栈,但是我运行代码时出现了segmentation fault: 11 error.

 8 节 .data910 hello db "Hello, world", 0x0a, 0x001112节.text1314 全局_main15 extern _printf, _exit1617 _主要:18推你好19 子 esp, 12 ;16 字节对齐堆栈20 调用_printf2122 添加 esp, 16 ;撤消堆栈对齐23 推 024 子 esp, 12 ;16 字节对齐堆栈25 调用_exit

我在没有堆栈对齐代码的情况下尝试过,但遇到了同样的错误.我在网上找到了各种示例,但我无法使它们工作,我什至使用 GCC 来输出 Intel 语法汇编程序,但我无法将其转换为 nasm.

我使用 nasm 是因为它适用于 Windows、OS X 和 Linux,所以我只需要学习一种汇编语法.

我意识到所有英特尔 Mac 都是 64 位的,但它们可以运行 32 位代码,所以我希望能够遵循并理解它.这一切都是为了帮助我对恶意软件进行逆向工程.

谢谢

解决方案

函数总是在返回地址上方寻找它们的参数.如果您在推送某些内容后 sub esp, 12参数包含 12 字节的垃圾.

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

sub esp,12main 的顶部会将堆栈对齐 16.但是你也做了另一个 push ,这也在 call

之前移动 ESP

您的 2 个选项是 sub esp, 8/push hello
sub esp,12/mov dword [esp], hello.

_main: ;ESP 是 16 字节对齐的 *before* 调用推送返回地址子 esp, 8 ;将 ESP 提高到对齐边界上方 4 个字节推你好;ESP 现在是 16 字节对齐的.调用_printfmov dword [esp], 0 ;推迟弹出堆栈呼叫 _exit;添加 esp, 4+8 ;弹出参数+填充.但退出不返回;返回.rodata 节;你不需要写这个字符串,所以把它放在rodata你好数据库你好,世界",0x0a,0x00

<小时><块引用>

所有的 Intel Mac 都是 64 位的

不完全正确:第一代 Intel macs 使用 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天全站免登陆