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_CREAT
和 O_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]!
我是 Aarch64 汇编的新手(但我知道 x86 汇编的一些基础知识)。我正在尝试在 Android OS.
上写类似 "shellcode" 的内容这个shellcode被注入到另一个函数中。它应该使用 execve
和 /system/bin/sh -c
创建一个文件 /data/local/tmp/AAABBBCCC
。在我的例子中,我不必关心空字节。
在 execve
调用之前,我进行了系统调用 open_at
(使用 O_CREAT
和 O_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]!