Reputation: 425
I am new to Aarch64 assembly (but I know some basics of x86 assembly). I am trying to write something like a "shellcode" on Android OS.
This shellcode is injected into another function. It is supposed to create a file /data/local/tmp/AAABBBCCC
using execve
and /system/bin/sh -c
. I don't have to care about null bytes in my case.
Prior to execve
call I make a syscall open_at
(with O_CREAT
and O_EXCL
) and create another file in /data/local/tmp/
(I load the address of the filename using 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"
I know that for x86 you need to get the address of the first string using a trick with CALL
instruction in order to make the argument array on the stack, because if you use labels like I did here, the addresses of the labels are contained within the instruction opcodes and after the injection they're not valid. But this should be a different case, right? The instruction ADR
should be pc-relative and in its opcode I don't see any addresses, just relative distances.
When I inject the code to the funtion, the call to open_at
always succeeds and the file is created. However the file that should be created by execve
is never created.
What is the right way to make the argument array on the stack for execve
on Aarch64? The stack must be 16-aligned, so I tried to always push two arguments at a time (using STP
), but that did not work either.
The code for injecting is made using aarch64-linux-android
toolchain like this:
as -o code.o code.asm
objcopy -O binary code.bin code.o
xxd -i code.bin
Thank you for your answers!
Upvotes: 2
Views: 1344
Reputation: 425
After a few minutes after I posted this question I realized where the mistake was.
The correct way to create the array of arguments on the stack is using the STP instruction. It stores two registers at a time (I was using it wrong before -- I provided the registers in a wrong order). It should be done like this:
mov x1, 0
adr x2, arg2
stp x2, x1, [sp, #-16]!
adr x1, arg1
adr x2, arg0
stp x2, x1, [sp, #-16]!
Upvotes: 2