Стек и окружение программы

Последнее обновление: 05.10.2023

При загрузке программы стек начинается со следующих значений (от старших адресов к младшим):

------------------------------------------------------------
Нулевой указатель
------------------------------------------------------------
Указатель на n-ю переменную среды (при наличии)
------------------------------------------------------------
Указатель на вторую переменную среды (при наличии)
------------------------------------------------------------
Указатель на первую переменную среды (при наличии)
------------------------------------------------------------
Нулевой указатель
------------------------------------------------------------
Указатель на n-й аргумент программы (при наличии)
------------------------------------------------------------
Указатель на второй аргумент программы (при наличии)
------------------------------------------------------------
Указатель на первый аргумент программы (при наличии)
------------------------------------------------------------
Указатель на имя файла программы
--------------------------------------------------------------
Количество аргументов командной строки                  
---------------------------------------------------------------

Таким образом, даже если мы находимся в точке входа _start, мы можем получить эту информацию в нашей программе.

Переменные среды хранятся в виде отдельных строк видаMYVAR=MYVAL, где MYVAR - имя переменной, а MYVAL - ее значение.

Например, загрузим количество аргументов в регистр %rax, а указатель на имя файла - в регистр %rbx:

_start:
    movq 0(%rsp), %rax      # количество аргументов
    movq 8(%rsp), %rbx      # указатель на файл

Проблема при использовании подобных данных заключается в том, что нам может быть сложно вычислить длину строки (например, длину файла или длину переменных) для взаимодействии с ними, особенно на различных эмуляторов типа WSL.

При использовании библиотеки C (когда точкой входа в программу является функция main, а не метка _start) получение подобных данных можно упростить. Так, первый параметр main — это количество аргументов командной строки (и, следовательно, он будет доступен в %rdi). Второй параметр main — это указатель на массив указателей на строки аргументов командной строки, и этот указатель будет находиться в %rsi. Наконец, мы можем получить переменные среды по отдельности, вызвав функцию getenv, которая есть в в библиотеке языка Си, или получить разом все переменные с помощью функции environ.

Стоит учитывать, что хотя начало стека (растущего вниз в памяти) находится рядом с 0x00007ffffffffffff, Linux реализует некоторую рандомизацию для этого, чтобы хакеры не могли угадать, где на самом деле находится стек в памяти.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850