У меня есть круговой двоичный файл (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 влияет только на базовый адрес областей памяти (например, стек, куча, ...) и смещение между переменной внутри одной области памяти должно быть фиксированным.
Смещение от буфера до начала кадра стека действительно фиксировано. Смещение от буфера до начала стека не согласовано.
Почему смещение от буфера до начала стека не соответствует? Не могли бы вы объяснить это подробно?