Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Права доступа к страницам в linux x86_64

#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.

Комментариев нет:

Отправить комментарий