Вернуть ориентированное программирование с аргументами, использующими произвольный EBP - PullRequest
0 голосов
/ 21 апреля 2020

Я читал эту статью о "Программировании, ориентированном на возврат", и у меня есть вопрос о части с "Вызовом аргументов"

Что я понимаю, так это то, что нам нужно иметь стек в правильном формате. Аргументы, а затем обратный адрес, который нас не волнует. Они устанавливают стек следующим образом:

| 0x8048580 <not_used>             |
| 0x43434343 <fake return address> |
| 0x8048360 <address of system>    |
| 0x42424242 <fake old %ebp>       |
| 0x41414141 ...                   |
|   ... (0x6c bytes of 'A's)       |
|   ... 0x41414141                 |

Где адрес 0x8048360 - это адрес, к которому мы перейдем после завершения поврежденной функции, а адрес 0x8048580 - аргумент.

Что Я не понимаю, как мы можем получить поддельный адрес EBP. Насколько я понимаю, адрес EBP в стеке выталкивается перед возвратом из функции, а затем EBP используется для доступа к аргументам и локальным переменным. Если мы поместим поддельный адрес в стек, не будет ли функция system использовать этот поддельный адрес EBP для доступа к его аргументу без успеха?

1 Ответ

2 голосов
/ 21 апреля 2020

не будет ли "системная" функция использовать этот поддельный адрес EBP для доступа к его аргументу без успеха? Если мы поместим поддельный адрес в стек, разве «системная» функция не использует этот поддельный адрес EBP для доступа к его аргументу без успеха?

Нет. Это произойдет, если вы перезапишите EBP, а затем действительно вернетесь из функции к вызывающей стороне . Поскольку вы также перезаписываете обратный адрес, вы фактически никогда не возвращаетесь к вызывающей стороне, а вместо этого вводите system. Что произойдет при возврате в system будет:

0x0804847a <+22>: ...    ; Here %ebp is still valid.
0x0804847f <+27>: leave  ; Same as: mov %ebp, %esp; pop %ebp
0x08048480 <+28>: ret    ;          %ebp becomes invalid, but %esp is still valid.
                   |   
                   v
0x08048360 <+0>:  push   %ebp       ; Push the invalid value.
0x08048361 <+1>:  mov    %esp,%ebp  ; Move %esp (valid) into %ebp ==> %ebp is now valid again.

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

Вы можете проверьте это, запустив программу под GDB следующим образом:

$ gdb ./program

(gdb) break *0x08048480     # address of the 'ret' instruction
(gdb) run <<< "$(python -c 'print "A"*0x6c + "BBBB" + "\x60\x83\x04\x08" + "CCCC" + "\x80\x85\x04\x08"')"

Затем, когда вы достигнете точки останова, посмотрите, где вы находитесь, с помощью команды disassemble $eip, а затем перейдите к si (пошаговая инструкция) и используйте info registers для просмотра значений регистров после каждой инструкции.

...