Разница между объявлением шеллкода как массива char [] и char *? - PullRequest
9 голосов
/ 17 декабря 2011

Привет всем,

Я пытаюсь выучить основы шелл-кодирования и наткнулся на что-то любопытное, что, надеюсь, кто-нибудь сможет мне объяснить.Я скомпилировал следующий код двумя способами: объявив шеллкод в виде массива и как символ *.Когда я объявляю шелл-код в виде массива, linux обнаруживает, что я пытаюсь выполнить данные, и у меня возникает ошибка по первой инструкции.Тем не менее, когда я объявляю шелл-код как char *, весь шеллкод выполняется, и я получаю «Hello world!».Как компилятор обрабатывает эти два объявления по-разному и почему один из них заканчивается шелл-кодом, который находится в незащищенной памяти?Заранее спасибо.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* This declaration ends in a segfault */
//char shellcode[] =

/* This declaration ends in successful execution */
char* shellcode = 

/* Shellcode prints "Hello world!" and exits */    
"\xeb\x1f\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\x48\x31\xc0\xb0\x01\x48\x31\xdb\xcd\x80\xe8\xdc\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21";

int main()
{
    void (*f)();
    f = (void (*)())shellcode;
    (void)(*f)();
}

Ответы [ 2 ]

9 голосов
/ 17 декабря 2011

Когда вы объявляете его как char[], память находится в стеке. Когда вы объявляете его как char* и присваиваете ему строковый литерал, память находится в самом исполняемом образе. Linux не любит, когда вы выполняете код в стеке, но хорошо, если вы выполняете память в этой части исполняемого образа. Это потому, что он пытается избежать определенного типа атаки переполнения стека, когда люди могут переполнить стек некоторыми произвольными инструкциями и затем выполнить их.

Вы можете использовать mprotect в Linux для установки разрешений для области памяти или VirtualProtectEx в Windows. Таким образом, вы можете явно установить разрешения для памяти, чтобы быть исполняемыми.

3 голосов
/ 17 декабря 2011

В вашем первом случае:

char shellcode[] =

Это помещает строковый литерал в стек как локальный массив. Стек и куча памяти обычно не имеют разрешений на выполнение (по очевидным причинам безопасности).

Во втором случае:

char* shellcode = 

Строка находится в статической памяти - обычно в том же регионе, что и остальная часть двоичного файла программы - который является исполняемым.

...