问题
My code:
.section .data
name: .string "/bin/sh"
args:
.string "-c"
.string "ls"
.section .text
.globl _start
_start:
pushq $0
pushq name
movq $59, %rax
movq %rsp, %rdi
pushq $0
pushq args
movq %rsp, %rsi
movq $0, %rdx
syscall
I know that the second argument of execve
is array of chars.
How to do this in assembly avoiding this:
execve("./payload", ["./payload"], 0x7ffc291fd160 /* 40 vars */) = 0
execve("/bin/sh", [0x736c00632d], NULL) = -1 EFAULT (Bad address)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xfffffffffffffff2} ---
+++ killed by SIGSEGV +++
Segmentation fault
回答1:
The execve
system call has signature
execve(const char *path, char *const argv[], char *const envp[]);
The argument vector is an array of strings, that is, a pointer to an array of pointers to arrays of characters. You however supplied a pointer to an array of characters, which is incorrect and will not work. To fix this, add an array of pointers referring to your arguments:
.section .data
name: .string "/bin/sh"
arg1: .string "-c"
arg2: .string "ls"
args: .quad name
.quad arg1
.quad arg2
.quad 0
.section .text
.globl _start
_start: movq $59, %rax
leaq name(%rip), %rdi
leaq args(%rip), %rsi
movq $0, %rdx
syscall
See how now args
is a NULL-terminated array of pointers to the arguments. Also note that the first argument (at index 0) is conventionally the program name itself. It won't work as expected to pass an actual option there.
I have also simplified the code by loading the addresses of the strings directly using a lea
instruction instead of the roundabout way you used.
来源:https://stackoverflow.com/questions/64411826/execve-argv-in-gas-att-assembler