#assembly #x86-64 #system-calls #shellcode #execve
#сборка #x86-64 #системные вызовы #шелл-код #execve
Вопрос:
Мой код:
.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
Я знаю, что вторым аргументом execve
является массив символов.
Как это сделать в сборке, чтобы избежать этого:
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. Второй аргумент to
execve
— это указатель на массив указателей на символы, то есть массив строк, а не массив символов. Вот почему ваш код не работает.2. Если я изменю .asciz на .string тот же результат
3. Это в конечном итоге для использования буфера?
4. Это для моего первого шелл-кода, я студент CTF.
5. @EntyAV Это ничего не меняет;
.asciz
является псевдонимом.string
. Вам нужен массив строк, а не массив символов. То есть массив указателей на массивы символов. Последний указатель должен бытьNULL
, а последний символ в каждом массиве символов должен быть нулевым символом (.asciz
гарантирует это для вас).
Ответ №1:
execve
Системный вызов имеет подпись
execve(const char *path, char *const argv[], char *const envp[]);
Вектор аргументов представляет собой массив строк, то есть указатель на массив указателей на массивы символов. Однако вы указали указатель на массив символов, который неверен и не будет работать. Чтобы исправить это, добавьте массив указателей, ссылающихся на ваши аргументы:
.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
Посмотрите, как теперь args
массив указателей на аргументы завершается нулем. Также обратите внимание, что первым аргументом (с индексом 0) обычно является само имя программы. Передача фактического параметра там не будет работать должным образом.
Я также упростил код, загрузив адреса строк непосредственно с помощью lea
инструкции, а не обходным путем, который вы использовали.
Комментарии:
1. В конечном итоге это будет шелл-код, поэтому была причина, по которой они пытались собрать аргументы в стеке. Я считаю, что более предпочтительным здесь был бы ответ, который строит аргументы в стеке и передает адреса данных стека в
syscall
.2. @MichaelPetch Мой ответ направлен на объяснение требуемой структуры данных. Заставить это работать как код оболочки по-прежнему является проблемой.
3. @fuz как заставить его работать как шелл-код, я новичок и не могу понять, почему сгенерированный шелл-код вызывает ошибку неправильной инструкции. Возможно, мне следует писать полезные нагрузки в NASM, а не в GAS.
4. @EntyAV Выбор ассемблера на самом деле не имеет значения. Существует несколько способов заставить это работать в коде оболочки. Для новичка это немного сложно, и я не рекомендую выполнять эту задачу. Общая идея состоит в том, чтобы создавать массивы в стеке вместо того, чтобы иметь их в разделе данных.