64-bit Linux stack smashing tutorial: Part 1 использует Get environment variable address gist для получения адреса переменной окружения. Предварительным условием является сначала отключить ASLR через echo 0 > proc/sys/kernel/randomize_va_space
.Почему этот кусок кода может получить адрес переменной окружения?
Содержание сути является:
/*
* I'm not the author of this code, and I'm not sure who is.
* There are several variants floating around on the Internet,
* but this is the one I use.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *ptr;
if(argc < 3) {
printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]); /* get env var location */
ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
printf("%s will be at %p\n", argv[1], ptr);
}
Почему *2
используется для настройки для имени программы?
Я предполагаю, что имя программы сохраняется дважды над стеком.
Следующая диаграмма из https://lwn.net/Articles/631631/ дает более подробную информацию:
------------------------------------------------------------- 0x7fff6c845000
0x7fff6c844ff8: 0x0000000000000000
_ 4fec: './stackdump\0' <------+
env/ 4fe2: 'ENVVAR2=2\0' | <----+
\_ 4fd8: 'ENVVAR1=1\0' | <---+ |
/ 4fd4: 'two\0' | | | <----+
args | 4fd0: 'one\0' | | | <---+ |
\_ 4fcb: 'zero\0' | | | <--+ | |
3020: random gap padded to 16B boundary | | | | | |
На этой диаграмме ./stackdump
используется для выполнения программы. Поэтому я вижу, что имя программы ./stackdump
сохраняется один раз над строками среды. И если ./stackdump
запускается из оболочки Bash, Bashell сохранит его в строках среды с ключом _
:
_
(подчеркивания.) При запуске оболочки установлен абсолютный путь, используемый для вызова оболочки или сценарий оболочки, который передается в списке окружения или аргументов . Впоследствии он расширяется до последнего аргумента предыдущей команды после расширения. Также установлено полное имя пути, которое используется для вызова каждой команды, выполняемой и помещенной в окружение , экспортированное в эту команду. При проверке почты этот параметр содержит имя почтового файла.
Окружающая среда находится над стеком. Таким образом, имя программы сохраняется в другой раз выше стека.
Что именно вы спрашиваете? Код работает, потому что getenv получает адрес переменной среды, а вызов вашей программы также занимает место в стеке, поэтому вы соответствующим образом корректируете указатель. Это в комментариях к коду. –
Насколько мне известно, в названии программы, выделенной в стеке, обычно содержится около 2 байтов на символ. Первое место, которое я видел в этом фрагменте кода, было в * Hacking: Art of Exploitation * от Jon Erickson. Я предлагаю читать больше там или изучать ядро Linux, чтобы понять, как выглядит стек в памяти. –
@JacobH да, код берет начало с Страница 147 и 148 из * Взлом: Искусство эксплуатации, второе издание * Джона Эриксона. Но книга не объясняет, почему она работает. –