Вопрос или проблема
Я пытаюсь создать главный файл вот так:
char main[] = "\xeb\x0d\x6a\x01\x58\x48\x89\xc7\x5e\x6a\x0c\x5a\x0f\x05\xff\xe8\xee\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x57\x6f\x72\x6c\x64\x21"; // опкод для Hello world в asm
Я скомпилировал свой код с помощью:
$ gcc -g3 -o shellcode shellcode.c
Но я всегда получаю Segmentation fault (core dumped)
Используя GDB, я вижу, что первая инструкция выполняется правильно, но следующие шаги – нет.
pwndbg> b * main
Точка останова 1 на 0x4020
pwndbg> r
────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────────
► 0x555555558020 <main> jmp main+15 <main+15>
↓
0x55555555802f <main+15> call main+2 <main+2>
0x555555558034 <main+20> insb byte ptr [rdi], dx
0x555555558037 <main+23> insb byte ptr [rdi], dx
0x555555558038 <main+24> outsd dx, dword ptr [rsi]
0x555555558039 <main+25> sub al, 0x57
0x55555555803b <main+27> outsd dx, dword ptr [rsi]
0x55555555803c <main+28> jb 0x5555555580aa <0x5555555580aa>
0x55555555803e <main+30> and dword ptr fs:[rax], eax
0x555555558041 <completed> add byte ptr [rax], al
0x555555558043 add byte ptr [rax], al
pwndbg> disass
Сброс кода ассемблера для функции main:
=> 0x0000555555558020 <+0>: jmp 0x55555555802f <main+15>
0x0000555555558022 <+2>: push 0x1
0x0000555555558024 <+4>: pop rax
0x0000555555558025 <+5>: mov rdi,rax
0x0000555555558028 <+8>: pop rsi
0x0000555555558029 <+9>: push 0xc
0x000055555555802b <+11>: pop rdx
0x000055555555802c <+12>: syscall
0x000055555555802e <+14>: (bad)
0x000055555555802f <+15>: call 0x555555558022 <main+2>
0x0000555555558034 <+20>: rex.W
0x0000555555558035 <+21>: gs ins BYTE PTR es:[rdi],dx
0x0000555555558037 <+23>: ins BYTE PTR es:[rdi],dx
0x0000555555558038 <+24>: outs dx,DWORD PTR ds:[rsi]
0x0000555555558039 <+25>: sub al,0x57
0x000055555555803b <+27>: outs dx,DWORD PTR ds:[rsi]
0x000055555555803c <+28>: jb 0x5555555580aa
0x000055555555803e <+30>: and DWORD PTR fs:[rax],eax
pwndbg> ni
0x555555558020 <main> jmp main+15 <main+15>
↓
► 0x55555555802f <main+15> call main+2 <main+2>
rdi: 1
rsi: 0x7fffffffdff8 —▸ 0x7fffffffe26d ◂— '/shellcode'
rdx: 0x7fffffffe008 —▸ 0x7fffffffe2ba ◂— 'SHELL=/bin/bash'
rcx: 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
0x555555558034 <main+20> insb byte ptr [rdi], dx
0x555555558037 <main+23> insb byte ptr [rdi], dx
0x555555558038 <main+24> outsd dx, dword ptr [rsi]
0x555555558039 <main+25> sub al, 0x57
0x55555555803b <main+27> outsd dx, dword ptr [rsi]
0x55555555803c <main+28> jb 0x5555555580aa <0x5555555580aa>
0x55555555803e <main+30> and dword ptr fs:[rax], eax
0x555555558041 <completed> add byte ptr [rax], al
0x555555558043 add byte ptr [rax], al
pwndbg> ni
Программа получила сигнал SIGSEGV, ошибка сегментации.
0x555555558020 <main> jmp main+15 <main+15>
► 0x55555555802f <main+15> call main+2 <main+2>
rdi: 1
rsi: 0x7fffffffdff8 —▸ 0x7fffffffe26d ◂— '/shellcode'
rdx: 0x7fffffffe008 —▸ 0x7fffffffe2ba ◂— 'SHELL=/bin/bash'
rcx: 0x555555557df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5555555550e0 (__do_global_dtors_aux) ◂— endbr64
0x555555558034 <main+20> insb byte ptr [rdi], dx
0x555555558037 <main+23> insb byte ptr [rdi], dx
0x555555558038 <main+24> outsd dx, dword ptr [rsi]
0x555555558039 <main+25> sub al, 0x57
0x55555555803b <main+27> outsd dx, dword ptr [rsi]
0x55555555803c <main+28> jb 0x5555555580aa <0x5555555580aa>
0x55555555803e <main+30> and dword ptr fs:[rax], eax
0x555555558041 <completed> add byte ptr [rax], al
0x555555558043 add byte ptr [rax], al
Как видно, первая инструкция выполняется, потому что мы переходим на 0x55555555802f
.
Я пробовал использовать только инструкции nop
, но та же проблема продолжает повторяться.
Так что кто-то может помочь мне? Спасибо
Ответ или решение
Для решения вашей проблемы с кодом shellcode в языке C и ошибкой сегментации (segmentation fault), необходимо проанализировать несколько ключевых аспектов, связанных с компиляцией и выполнением кода.
1. Понимание Shellcode
Shellcode – это небольшой фрагмент кода, предназначенный для выполнения как часть уязвимости в системе, обычно в контексте поставленного задания или теста на проникновение. В данном случае ваш shellcode должен выводить фразу "Hello, World!" в Unix-подобной системе.
Ваш текущий код:
char main[] = "\xeb\x0d\x6a\x01\x58\x48\x89\xc7\x5e\x6a\x0c\x5a\x0f\x05\xff\xe8\xee\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x57\x6f\x72\x6c\x64\x21";
2. Ошибка Сегментации
Ошибки сегментации возникают, когда программа пытается получить доступ к памяти, к которой она не имеет разрешения. В вашем случае проблема может заключаться в том, что вы пытаетесь выполнить массив main[]
как исполняемый код, тогда как он фактически находится в сегменте данных, который обычно не является исполняемым.
3. Исполняемый код в C
Для того чтобы код был исполнимым, он должен находиться в области памяти, которую ОС помечает как исполняемую. Это может быть сделано с помощью системных вызовов или выделения памяти с правами на выполнение. В C это можно сделать следующим образом:
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
unsigned char code[] =
"\xeb\x0d\x6a\x01\x58\x48\x89\xc7\x5e\x6a\x0c\x5a\x0f\x05\xff\xe8\xee\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x57\x6f\x72\x6c\x64\x21";
int main() {
// Выделяем память и устанавливаем ее как исполняемую
void *exec = mmap(0, sizeof(code), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (exec == MAP_FAILED) {
perror("mmap");
return 1;
}
// Копируем ваш shellcode в выделенную память
memcpy(exec, code, sizeof(code));
// Выполняем исполняемый код
((void (*)())exec)();
return 0;
}
4. Объяснение кода
mmap
: Этот системный вызов выделяет страницу памяти с правами на чтение, запись и выполнение.memcpy
: Копирует ваш shellcode в выделенную область памяти.- *`((void ()())exec)()`**: Приводит адрес выделенной памяти к типу функции и вызывает её.
5. Компиляция и запуск
Скомпилируйте код с помощью следующей команды:
gcc -o shellcode shellcode.c
При запуске, вы должны увидеть "Hello, World!" без возникновения ошибок сегментации.
Заключение
Использование правильных прав доступа к памяти и понимание ее структуры является ключевым моментом при работе с shellcode в C. Следуя вышеприведенным шагам, вы сможете успешно запустить ваш код без ошибок сегментации. Вам необходимо быть внимательным к тому, чтобы не пытаться запускать код, который хранится в сегментах данных, так как это может привести к ошибкам.