niedziela, 26 lutego 2012

Łatwe prlimit bez prlimit

Ostatnio pisałem w jaki sposób poradzić sobie bez wywołania systemowego prlimit. Okazuje się, że poradzić sobie można nawet jeszcze łatwiej!

Wystarczy znaleźć adress funkcji setrlimit w pamięci naszego procesu

# cat /proc/7747/maps | grep libc
b767f000-b781b000 r-xp 00000000 08:03 64163 /lib/libc-2.15.so
b781b000-b781d000 r--p 0019c000 08:03 64163 /lib/libc-2.15.so
b781d000-b781e000 rw-p 0019e000 08:03 64163 /lib/libc-2.15.so

# printf "0x%x\n" $(( 0xb767f000 + 0x000e06d0 ))
0xb775f6d0

Pamiętajcie, że liczba 0x000e06d0 to oczywiście offset funkcji setrlimit w bibliotece dzielonej libc-2.15.so, który znaleźliśmy ostatnio ;] Teraz wystarczy już tylko:



(gdb) set var $sl = 0xb775f6d0
(gdb) call malloc(16)
$1 = 142942216
(gdb) set *(long *) $1 = -1
(gdb) set *(long *) ($1 + 4) = -1
(gdb) call $sl ( 4, $1 )
$2 = 0
(gdb) q
A debugging session is active.

Inferior 1 [process 7747] will be detached.

Quit anyway? (y or n) y
Detaching from program: /root/rtcore/mkcore, process 7747
[1]+ Segmentation fault (core dumped) ./mkcore


Niesamowite ale to działa! Tylko dlaczego? Okazuje się, że linuks używa w bibliotekach dzielonych wywołań typu stdcall (lub gdb jest na tyle miły, że sprząta stos) a do tego nie realokuje kodu i zachowuje oryginalne przesunięcia z pliku - a przynajmniej tak to wygląda w przypadku libc :) Upraszcza to niezwykle sprawę i powoduje że cała zabawa jest już banalnie prosta :)