Почему расположение переменных среды так сильно различается?

9

Читая книгу «Взлом: искусство эксплуатации» Джона Эриксона, я пытаюсь приблизить адрес переменной среды, SHELLCODEчтобы использовать программу.

Каждый раз, когда я бегу, getenv("SHELLCODE");чтобы узнать местоположение, результат совершенно другой.

Выписка из моей раковины:

> for i in $(seq 10); do ./a.out SHELLCODE; done
SHELLCODE is at 0xff9ab3a3
SHELLCODE is at 0xffcdb3a3
SHELLCODE is at 0xffb9a3a3
SHELLCODE is at 0xffa743a3
SHELLCODE is at 0xffdb43a3
SHELLCODE is at 0xfff683a3
SHELLCODE is at 0xffef03a3
SHELLCODE is at 0xffc1c3a3
SHELLCODE is at 0xff85a3a3
SHELLCODE is at 0xff8e03a3

Я понимаю, что если имя программы изменяется или добавляются новые переменные среды, позиция будет немного отличаться, но почему местоположение так сильно меняется?

Janman
источник
getenvРуководство говорит она возвращает указатель на строку , содержащую значение переменной. Все остальное не определено, поэтому ваше ядро ​​и / или компилятор могут сохранять значение в любом месте, пока это обещание указателя остается верным. Я предполагаю, что точный ответ на это может быть тяжелым волшебством и зависеть от различных деталей реализации отображения памяти и фазы луны. (Я не достаточно волшебник, чтобы дать вам точный ответ.)
Anko
«Я понимаю, что если имя программы изменилось или были добавлены новые переменные среды, положение было бы немного другим, но почему расположение так сильно меняется?» Это верно в простейшей из всех возможных реализаций, но это, безусловно, не требуется.
dmckee --- котенок экс-модератора

Ответы:

13

То, что вы описываете, - это функция защиты от эксплуатации, называемая рандомизацией расположения адресного пространства (ASLR). По сути, ядро ​​помещает самый верхний адрес стека вызовов функций программы в несколько иной («случайный») адрес каждый раз, когда ядро ​​загружает файл ELF программы с диска. Адреса argvи переменные среды, одним из которых является ваш шелл-код, заканчиваются по-разному с каждым вызовом программы.

Предполагается, что ASLR усложнит использование переполнения буфера и других уязвимостей, связанных со стеком. Эксплуататор должен написать код или сделать что-то, чтобы учесть различные адреса переменных и значений в стеке вызовов функций.

Похоже, вы можете отключить ASLR, выполнив что-то вроде:

echo 0 > /proc/sys/kernel/randomize_va_space

как пользователь root. Поскольку вы явно цитируете Ubuntu, приведенная выше команда отличается:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Брюс Эдигер
источник
Да, это помогло. Я заметил, что автор книги использует Ubuntu 10.04, в которой еще не было ASLR.
Янман