ARM64 程序集 - 在堆栈上执行参数

ARM64 assembly - execve arguments on stack

我是 Aarch64 汇编的新手(但我知道 x86 汇编的一些基础知识)。我正在尝试在 Android OS.

上写类似 "shellcode" 的内容

这个shellcode被注入到另一个函数中。它应该使用 execve/system/bin/sh -c 创建一个文件 /data/local/tmp/AAABBBCCC。在我的例子中,我不必关心空字节。

execve 调用之前,我进行了系统调用 open_at(使用 O_CREATO_EXCL)并在 /data/local/tmp/ 中创建了另一个文件(我加载使用 adr x1, path).

的文件名地址
...

call to open_at

... 

// push terminating 0
mov     x1, 0
str     x1, [sp, #-16]!
// push arg2
adr     x1, arg2
str     x1, [sp, #-16]!
// push arg1
adr     x1, arg1
str     x1, [sp, #-16]!
// push arg0
adr     x1, arg0
str     x1, [sp, #-16]!
// call execve
adr     x0, command
ldr     x1, [sp]
mov     x2, 0
mov     x8, SYS_EXECVE
svc     0

...
.balign 4
command:
    .string "/system/bin/sh"
arg0:
    .string "/system/bin/sh"
arg1:
    .string "-c"
arg2:
    .string "/system/bin/touch /data/local/tmp/AAABBCCC"

我知道对于 x86,您需要使用带有 CALL 指令的技巧来获取第一个字符串的地址,以便在堆栈上创建参数数组,因为如果您像我在这里那样使用标签,标签的地址包含在指令操作码中,并且在注入后它们无效。但这应该是不同的情况吧?指令 ADR 应该是 pc-relative 并且在它的操作码中我没有看到任何地址,只有相对距离。

当我将代码注入函数时,对 open_at 的调用总是成功并创建了文件。然而,应该由 execve 创建的文件从未创建。

在 Aarch64 上为 execve 在堆栈上创建参数数组的正确方法是什么?堆栈必须是 16 对齐的,所以我尝试总是一次压入两个参数(使用 STP),但这也不起作用。

注入代码是使用 aarch64-linux-android 工具链编写的,如下所示:

as -o code.o code.asm
objcopy -O binary code.bin code.o
xxd -i code.bin

感谢您的回答!

在我发布这个问题几分钟后,我意识到错误在哪里。

在堆栈上创建参数数组的正确方法是使用 STP 指令。它一次存储两个寄存器(我之前用错了——我以错误的顺序提供了寄存器)。应该这样做:

mov     x1, 0
adr     x2, arg2
stp     x2, x1, [sp, #-16]!

adr     x1, arg1
adr     x2, arg0
stp     x2, x1, [sp, #-16]!