2012-03-30 6 views
2

Я просматривал разные стили переполнения буфера и сталкивался с проблемой, о которой я не помню, почему это происходит. Код следующим образом является программой я попытка выполнить переполнение буфера:Переменные среды переполнения буфера Linux

#include <stdio.h> 

void func(char *buff){ 
    char buffer[5]; 
    strcpy(buffer, buff); 
    printf("%s\n", buffer); 
} 

int main(int argc, char *argv[]){ 
    func(argv[1]); 
    printf("I'm done!\n"); 
    return 0; 
} 

Основная концепция программы очень прост, я просто переполнить буфер для перезаписи адреса возврата func(). Это отлично работает, когда я даю ему адрес, такой как 0x0804850c, который является <_fini> программы. Конечным результатом, когда я реализую переполнение с этим адресом, является завершение программы «изящно» без печати I'm done!. Проблема, с которой я столкнулся сейчас, - это когда я пытаюсь перенаправить обратный адрес на что-то, скажем, переменную среды, расположенную в 0xbfffd89.

Код оболочки, расположенный в этой конкретной переменной окружения, должен просто выйти из программы после объявления hello. Однако этого не происходит, программа просто отключается, и все. Код оболочки уже подтвержден для работы в предыдущей программе, которую я написал, для проверки кода оболочки. У кого-нибудь есть идеи, почему это не работает. Thx

+1

Запустите его под gdb, чтобы узнать, что вызывает срабатывание segfault. Мое предположение: переменная среды живет в области памяти, которая читаема, но не является исполняемой[email protected] EugeneMayevski'EldoSCorp: Я предполагаю, что «shell-код» здесь - это жаргон для машинного кода, который запускает оболочку и некоторые внешние команды, которые, как правило, хотят делать. Хотя в этом случае это звучит, как будто никакая реальная оболочка не запускается. – Celada

+0

@Celada Любые предложения о том, как я могу использовать GDB, чтобы проверить, являются ли переменные среды READ-ONLY. Также вы правильно знаете код оболочки. – Blackninja543

+0

@ EugeneMayevski'EldoSCorp Обычно код оболочки - это байтовый код двоичного кода. В этом случае я сгенерировал код оболочки, написав то, что я хотел получить в ASM x86. Когда я перенаправляю обратный адрес функции, я направляю ее в область памяти, содержащую новый набор инструкций. – Blackninja543

ответ

2

Переменные окружения расположены в области памяти, которая считывает & разрешение на запись, но не выполняет разрешение. Я воспроизвел легко следующим образом:

#include <stdio.h> 
#include <stdlib.h> 

int 
main(int argc, char **argv) 
{ 
void (*function)(void); 

     function = (void (*)(void))getenv("PATH"); 
     function(); 
     return 0; 
} 

Запуска под gdb, я получил это:

Program received signal SIGSEGV, Segmentation fault. 
0x00007fffffffeb51 in ??() 
(gdb) 

Затем я посмотрел адрес 0x00007fffffffeb51 если /proc/PID/maps и нашел такую ​​строку:

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0       [stack] 

Существует -, где обычно будет найден бит x (выполнить).

+0

Итак, давайте предположим, что я не могу изменить разрешения переменных среды, какие другие возможности существуют для выполнения моего кода оболочки вне переменных окружения. – Blackninja543

+1

Правдоподобный сценарий для уязвимой программы: переменная окружения копируется в кучу. Возможно, переменная среды называет каталог и объединяется с именем файла, чтобы сформировать полное имя пути в 'malloc()' ed memory. Теперь переполнение буфера может перейти к этому адресу в куче. Он будет исполняемым. Но вы должны угадать, что это за куча адрес ... удачи с этим :-) – Celada

0

Можете ли вы подтвердить адрес переменной между прогонами? Если ваша система использует что-то вроде ASLR, она может отличаться при каждом запуске. Однако адрес argv [1] может быть предоставлен через некоторый регистр, поэтому, если вы укажете обратный адрес с адресом инструкции, выполняющим косвенный вызов через этот регистр (вы, вероятно, найдете такую ​​инструкцию, используя objdump -d в своей программе), он будет запускать ваш код по любому адресу, который будет - если этот адрес находится на исполняемой странице. И регистры используются в вашем ABI для передачи параметров. Однако могут возникнуть другие проблемы ...

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

+0

Я добавлю дизассемблированный код, когда у меня появится шанс. Что касается рандомизации адресного пространства, у меня это отключено в тестовой среде. Как показала Челада, и я проверил свою собственную среду, мои переменные среды не являются неисполнимыми. У вас есть мысли о том, как я могу вставить код оболочки кода, чтобы сделать его исполняемым. Единственный способ, которым я могу думать на этом этапе, - использовать переменные среды. – Blackninja543

2

Современные дистрибутивы linux затвердевают от такого рода нападений. Например, бит NX устанавливается для страниц стека на x86-64. А адреса карт рандомизированы, чтобы предотвратить возможность угадывать извне процесса. Смотрите следующее:

http://en.wikipedia.org/wiki/Executable_space_protection http://en.wikipedia.org/wiki/Address_space_layout_randomization

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

+1

Исправить. Что не очевидно в этом конкретном случае, так это то, что переменные окружения на самом деле находятся в той же области памяти, что и стек. Я этого не знал до сих пор! – Celada

+0

@Celada: фактически все 'argc',' argv', 'envp' и' auxv' и соответствующие указатели на них передаются каждому процессу в стеке. – ninjalj

+0

@ninjalj Я знал, что 'argv',' envp' и 'auxv' были все вместе в области памяти, известной как« пользовательская область », но я не знал, что она была той же областью, что и стек. Но я был на Solaris, когда узнал об этом несколько тревожных лет назад, и все могло измениться. Спасибо за разъяснения! – Celada