2015-08-08 3 views
5

Я пытаюсь научиться выполнять shellcode изнутри программы, но я не могу получить даже самый базовый код для запуска. Следующий код просто должен выйти из терминала, когда он запущен:Кастинг символьной строки как функции

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
#include <sys/mman.h> 

char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80"; 

int main() { 
    int (*func)(); 
    func = (int (*)())exitcode; 
    (int)(*func)(); 
    return 0; 
} 

Но все это я получаю выдаёт ошибку сегментации. GDB говорит, что это происходит, когда программа обращается к ячейке памяти exitcode [at (int) (* func)(); ], но я не уверен, почему это вызывает проблему. Я запускаю 64-битную ОС Linux Mint. Любая помощь приветствуется.

+0

Если память для шеллкода находится в неисполняемом регионе, тогда это не сработает. Большинство современных операционных систем, вероятно, этого не допустят. Вы также должны убедиться, что шелл-код правильный для вашей архитектуры. –

+1

Это для C или C++? Семантика и возможные ответы могут различаться. – Olaf

+0

Приведение указателя объекта к указателю на функцию _undefined behaviour_. Все может случиться – Olaf

ответ

6

Современные операционные системы используют защиту памяти. Страницы памяти имеют права доступа, как файлы: читаемые, записываемые, исполняемые. Ваш сегмент данных вашей программы, как правило, находится на невыполнимаемой странице, и попытка выполнить его приводит к segfault.

Если вы хотите выполнить динамически записанный двоичный код из вашей программы в Linux, сначала вам нужно сопоставить страницу с помощью mmap(), которую вы можете записать, затем поместите там свой код, а затем измените его на только для чтения, исполняемый файл используя mprotect(). ТОГДА вы можете прыгать туда.

Для получения более подробной информации, вы можете, например, read this article.

EDIT: Если речь идет о нарушениях безопасности, обратите внимание, что в настоящее время стек также не исполняется ... так что все эти старые «хакерские учебники» больше не будут работать. Если вас интересуют новые методы, читайте о обратном ориентированном программировании.

0

Ваш Шеллкод:

mov $0x1,%al 
xor %ebx,%ebx 
int $0x80 

Есть две проблемы:

  1. Системный вызов 0x1 является sys_write на 64-битной (но на 32-битной это sys_exit)
  2. Вы должны назначить до% rax, а не% al. % rax будет содержать остатки в высоких разрядах.
4

Код должен быть помечен как исполняемый код. Один из способов сделать это - скопировать этот двоичный машинный код в исполняемый буфер.

#include <unistd.h> 
#include <sys/mman.h> 
#include <string.h> 

char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80"; 

int main(int argc, char **argv) 
{ 
    void *buf; 

    /* copy code to executable buffer */  
    buf = mmap (0,sizeof(exitcode),PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANON,-1,0); 
    memcpy (buf, exitcode, sizeof(code)); 

    /* run code */ 
    int i = ((int (*) (void))buf)(); 
    printf("OK. returned: %d", i); 
return 0; 
} 
0

У меня была эта проблема, попробовав много, чтобы ее решить.

Вы должны использовать этот код, чтобы скомпилировать код C (Чтобы отключить защиту стека и сделать его исполняемым):

gcc -fno-stack-protector -z execstack -o hello hello.c 

Испытано в Кали 32/64 бит. Больше нет segfault.

Удача