Вы также можете использовать #define для определения своего шелл-кода. Таким образом, препроцессор вставит код непосредственно в основной
#define SHELLCODE "\x31\xc0\xb0\x1d\xcd\x80"
int main()
{
(*(void(*)())SHELLCODE)();
}
Более старый стиль написания шеллкода не работает на более новых системах из-за мер безопасности.
Вам также, вероятно, придется скомпилировать с отключенной защитой стека:
gcc -z execstack -fno-stack-protector shellcode.c -o shellcode
Вот полностью рабочий пример, использующий системный вызов exit, который я тестировал на ядре 3.2.0.3 x86_64:
#include<stdio.h>
#define SHELLCODE "\x48\xc7\xc0\x3c\x00\x00\x00\x48\xc7\xc7\xe7\x03\x00\x00\x0f\05"
main()
{
int (*function)();
// cast shellcode as a function
function = (int(*)())SHELLCODE;
// execute shellcode function
(int)(*function)();
return 0;
}
В шелл-коде используются 64-битные регистры, поэтому он не будет работать на 32-битной машине.
Чтобы убедиться, что код работает, вы можете проверить его с помощью strace:
strace shellcode
execve("./shellcode", ["shellcode"], [/* 38 vars */]) = 0
....
munmap(0x7ffff7fd5000, 144436) = 0
_exit(999) <---- we passed 999 to exit, our shellcode works!