Как рассчитать начальный адрес стека бинарного круга в системе с включенным полным ASLR?

У меня есть круговой двоичный файл (ELF) с включенными nx и круговым битом в системе с включенным полным ASLR. У меня проблема с определением базового адреса стека. Я хочу ret2mprotect, а затем ret2shellcode в стеке, но мой эксплойт не работает, потому что смещение, которое мы используем для вычисления изменения базового адреса стека при каждом запуске двоичного файла. Не могли бы вы помочь мне решить проблему?

Вот мой уязвимый код:

#include <stdio.h>
int main(int argc,char* argv[]) {
        char buffer[256];
        printf(argv[1]);
        printf("\n");
        gets(buffer);
        return 0;
}

моя команда компиляции:

gcc -Wall -g -O0 -Wl,-rpath,./ -fcf-protection=none -fno-stack-protector -fpic vuln.c -o vuln

Я получил требуемую утечку из этой строки формата (ниже значения, переданного в программу): %1$p:%41$p 1-й адрес утечки находится в диапазоне стека. 41-й адрес утечки находится в диапазоне библиотеки libc.

Я получил эти образцы значений, чтобы определить смещение на его основе: (например, пример)

exStackStart        =   0x7ffee8986000
exStackEnd          =   0x7ffee89a8000
exLibcStart         =   0x7fea59ec5000
exLibcEnd           =   0x7fea5a03d000
exGetsBuffer        =   0x7ffee89a5d50
exStackLeaked       =   0x7ffee89a5f48
exLibcLeaked        =   0x7fea59ec7083

offsetStackLeaked2StackEnd = exStackEnd - exStackLeaked
offsetStackLeaked2GetsBuffer = exStackLeaked - exGetsBuffer
offsetLibcLeaked2LibcStart = exLibcLeaked - exLibcStart
stackSize = exStackEnd - exStackStart

io = start()

output = str(io.recvuntil(b'\n')).split(':')
runStackLeaked = int(output[0][2:], 16)
runLibcLeaked = int(output[1][:-3], 16)
runStackEnd = runStackLeaked + offsetStackLeaked2StackEnd
runStackStartRaw = runStackEnd - stackSize
runStackStart = runStackStartRaw & (~4095)                       <====== here is the problem!  sometimes this is correct and sometimes this is 0x1000 or 0x2000 far from correct address
runGetsBuffer = runStackLeaked - offsetStackLeaked2GetsBuffer
runLibcStart = runLibcLeaked - offsetLibcLeaked2LibcStart

io.send(b'A' * 300 + b'\n')
io.interactive()

Обновлять:

Vuln дает мне адрес, который находится в диапазоне стека (я проверил с помощью команды vmmap в gdb), используя уязвимость строки формата.

Полный ASLR в моей ОС включен, поэтому адрес стека для моего двоичного файла меняется при каждом запуске двоичного файла, поэтому я хотел бы добиться смещения, которое я могу добавить/вычесть к/из утекшего адреса и перейти к началу стека ( какой vmmap покажет мне).

Я проверил расстояние между просочившимся адресом и началом стека и где-то записал его, поэтому я хочу автоматически вычислить начальный адрес стека, просто добавляя/вычитая смещение к/от просочившегося адреса без ручной проверки в gdb .

но, к сожалению, смещение отличается при каждом запуске двоичного файла, поэтому достигнутое нами смещение недействительно.

смещение от просочившегося адреса до начального адреса стека (получено из gdb vmmap​):

(следующие числа в десятичном формате)

запуск1: 127480

пробег2: 128584

run3: 130632

run4: 126008

пробег5: 127656

Как видите, расстояние между смещением и началом стека различается при каждом запуске.

В чем причина проблемы и как ее победить (достичь/вычислить)?

следующие две картинки для двух запусков программы, но результат не такой, как мы ожидали. результат run1результат run2

Я ожидал, что смещение от начала стека до любого места в стеке фиксировано, но оно каждый раз меняется для моего двоичного файла, и, насколько мне известно, ASLR влияет только на базовый адрес областей памяти (например, стек, куча, ...) и смещение между переменной внутри одной области памяти должно быть фиксированным.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Смещение от буфера до начала кадра стека действительно фиксировано. Смещение от буфера до начала стека не согласовано.

Почему смещение от буфера до начала стека не соответствует? Не могли бы вы объяснить это подробно?

fest chest 16.11.2022 04:47

Другие вопросы по теме