#linux #memory #x64 #x86_64 #виртуальная_память
Изучаю как устроена атака на переполнение буфера. Написал вот такую программу
typedef void(*Function)();
int main() {
const char* shell = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
Function f = (Function)shell;
f();
return 0;
}
shell - пара десятков nop-ов.(0x90 - опкод nop-a).
Пошагово прошелся по ней в gdb и она падает от segfault при вызове f, а точнее при
выполнении инструкции
callq *%rdx
При этом в rdx записан адрес 0x4005d8( Именно по этому адресу располагаются nop-ы).
И все это можно было бы объяснить тем, что адрес 0x4005d8 относится к странице у которой
не выставлено право на исполнение, но:
1) Вот вывод утилиты pmap для этого процесса
26040: ./main
0000000000400000 4K r-x-- main
0000000000600000 4K r---- main
0000000000601000 4K rw--- main
0000000001c65000 132K rw--- [ anon ]
00007f40de3ce000 1792K r-x-- libc-2.23.so
00007f40de58e000 2048K ----- libc-2.23.so
00007f40de78e000 16K r---- libc-2.23.so
00007f40de792000 8K rw--- libc-2.23.so
00007f40de794000 16K rw--- [ anon ]
00007f40de798000 152K r-x-- ld-2.23.so
00007f40de995000 12K rw--- [ anon ]
00007f40de9bd000 4K r---- ld-2.23.so
00007f40de9be000 4K rw--- ld-2.23.so
00007f40de9bf000 4K rw--- [ anon ]
00007ffd8e874000 132K rw--- [ stack ]
00007ffd8e924000 12K r---- [ anon ]
00007ffd8e927000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 4356K
И если я правильно понимаю что тут написано, то у диапазона адресов 0х400000-0х60000
есть право на исполнение.
2) Что подтверждает предыдущий пункт: адрес функции main был 0х400507 что довольно
близко к последовательности nop-ов.
Однако если в rdx положить адрес main то никакого segfault-а не происходит. Проясните,
пожалуйста, что не так.
Ответы
Ответ 1
Учитывая, что сегмент константных данных (а именно туда попадает const char* shell) отображается без права на исполнение, скорее всего, вы столкнулись с ASLR. ASLR (Address Space Layout Randomisation, разбиение адресного пространства случайным образом) — это механизм, который как раз и направлен против шелл-атак, полагающихся на фиксированный адрес тех или иных участков памяти. Он разбрасывает программу, библиотеки и стек случайным образом по всей виртуальной памяти, доступной программе, причём из запуска в запуск результат подобного распределения отличается. При первом запуске (под gdb) адрес 0x4005d8 попадал в сегмент неизменяемых данных программы (на это указывают права доступа сегмента, да и const-переменные находятся только там). При втором же запуске (для pmap) по тому адресу стал располагаться сегмент кода. Если вы хотите получить согласованный результат, запускайте pmap параллельно с gdb, в другом окне или вкладке консоли. (Немного о праве на исполнение блока памяти) Начиная с версии 2.3.23, Linux имеет встроенную поддержку DEP. DEP (Data Execution Prevention, предотвращение выполнения данных) — это механизм, направленный на запрет исполнения кода там, где должны лежать данные (к примеру, в стеке или сегменте данных). Он работает за счёт того, что к уже существующим флагам прав доступа к странице (чтение, запись, доступ только из режима ядра и т. д.) был добавлен ещё один (запрет на исполнение), который операционная система устанавливает для всех страниц, не соответствующих сегментам кода исполняемых файлов (а main() как раз и лежит в подобном сегменте). Единственное, где может сработать ваш шелл — это в областях памяти, созданных при помощи mmap() с одновременно выставленными флагами PROT_EXEC и PROT_WRITE.
Комментариев нет:
Отправить комментарий