Решил попрактиковаться в переполнении буфера. Накатал быстренько уязвимую программу. При передаче такого аргумента `perl -e 'print "A"x100'` в отладчике gdb выдаёт: Вывод команды i r: Тогда как, на сколько я понимаю, регистр eip должен быть перезаписан на 0x41414141. Но такого не происходит и передать управление на шелл-код не удаётся. В чём проблема? Уязвимая программа: Code: #include <stdio.h> #include <string.h> int main (int argc, char *argv[]) { char buf[10]; if (argc > 1) strcpy(buf, argv[1]); return 0; } Дистрибутив Mandriva 2009.1 Компилятор gcc 4.3.2
1. 0x8048407 <- что за адрес? включается ли он в образ проги в памяти 2. В студии (я как бэ виндовс секурити изучаю) по умолчанию включена проверка на переполненные буферы и по умолчанию будет отслеженна такая ситуация и прога будет по тихому прибита. Есть ли в gcc такая шняга я не знаю ... 3. В таких ситуациях надо вручную смотреть как происходит переполнение в отладчике иначе трудно чтолибо говорить.
>>. В студии (я как бэ виндовс секурити изучаю) по умолчанию включена проверка на переполненные буферы ничего там не включено.только отвратительые ворнинги со словами юзайте _s или пишите CRT_SECURE_NO_DEPRECATE 2 ТС запусти отладчик?
2desTiny я не про depricated говорил вообщето Code: /GS [-] Обнаружение некоторых возможных переполнений буфера, при которых перезаписывается возвращаемый адрес. [URL=http://msdn.microsoft.com/ru-ru/library/8dbf701c.aspx]MSDN![/URL] Оно работает таки ) PHP: sub_401000 proc near ; CODE XREF: sub_401030+Ap .text:00401000 .text:00401000 var_10 = byte ptr -10h .text:00401000 var_4 = dword ptr -4 <- помещаем переменную между буфером и адресом возврата, etc .text:00401000 arg_0 = dword ptr 8 .text:00401000 .text:00401000 push ebp .text:00401001 mov ebp, esp .text:00401003 sub esp, 10h .text:00401006 mov eax, dword_40A000 .text:0040100B xor eax, ebp <- для каждой функции свое персональное значение .text:0040100D mov [ebp+var_4], eax <- сохраняем значение в качестве метки .text:00401010 mov eax, [ebp+arg_0] .text:00401013 push eax ; char * .text:00401014 lea ecx, [ebp+var_10] .text:00401017 push ecx ; char * .text:00401018 call _strcpy .text:0040101D add esp, 8 .text:00401020 mov ecx, [ebp+var_4] .text:00401023 xor ecx, ebp <- в случае если буфер переполнится, локальная переменная затрется .text:00401025 call sub_401148 <- что и проверяется здесь, если она не соответствует постоянному значению процесс тихо прибъется. .text:0040102A mov esp, ebp .text:0040102C pop ebp .text:0040102D retn .text:0040102D sub_401000 endp
2desTiny я ведь выложил листинг с gdb. Ведь поидее после передачи 200 символов в 10-символьный буфер адрес возврата стопроцентно должен перезаписаться. А у меня вместо 0x41414141 в eip 0x8048407. А, кстати, может ли это быть защита со стороны ОС или компилятора? Никакие патчи не ставил.
2InFlame В отладчике пошагово выполни прогу и смотри что у тебя в стеке и какие левые операции компилятор вставил в твою функцию + документацию по gcc найди
Code: int main(){ int a[100]; for (int j = 0; j < 1000; j++){ a[j] = j; } } трям. VS2008 сказало, что сие есть ошибка без малейшего вопроса.
да, видимо криво сказал. оно компилится, запускается и с самой чистой совестью затирает адрес возврата
2desTiny млин, ты бы хоть в вышеприведенный дизасм код посмотрел. Естественно затрется адрес возврата, НО защита не даст выйти из функции (и как результат, выполнить переход на шеллкод) и тихо убьёт процесс ExitProcess`ом. Так что креша приложения по исключению ты не наблюдал скорее всего (хотя опять же не помню с какой версии компилится с /GS по умолчанию, посмотри настройки проекта, чтото типа stack protection), а приложение тихо сдохло (это для релиз версии приминительно, насколько помню в дебаг версии там ещё перед убийством процесса окошко выдаёт, что буфер переполнился с минимальной инфой).
Buffer Security что-то там (/GS) включён компилирую вот такой код в Release (вывод добавлен, чтобы оптимизация не убила массив вообще): Code: #include "stdio.h" int main(){ int a[100]; for (int j = 0; j < 1000; j++){ a[j] = j; } printf("%d",a[99]); } получаю код: Code: 00401000 SUB ESP,190 00401006 XOR EAX,EAX 00401008 JMP SHORT aaaqqww.00401010 0040100A LEA EBX,DWORD PTR DS:[EBX] 00401010 /MOV DWORD PTR SS:[ESP+EAX*4],EAX 00401013 |INC EAX 00401014 |CMP EAX,3E8 00401019 \JL SHORT aaaqqww.00401010 0040101B MOV EAX,DWORD PTR SS:[ESP+18C] 00401022 PUSH EAX ; /<%d> = 0 00401023 PUSH aaaqqww.004020F4 ; |format = "%d" 00401028 CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf 0040102E XOR EAX,EAX 00401030 ADD ESP,198 00401036 RETN Наслаждайся Кстати конкретно данный код приводит к выполнению шеллкода совсем смешным образом - вначале он переписывет SEH запись, а затем уже пытается записать что-то выше верхней границы стека и вызывает exception, обрабатываемый перезаписанным обработчиком. Но можно и просто переписать, если тысячу уменьшить
В коде не видно защиты, добавляемой /GS, видимо при неиспользовании опасных функций код не добавляется. Я все особенности защиты не изучал, такчто возможно =/
тоже столкнулся с защитой буфера. при попытки произвести перезапись в ubuntu получаю ошибку *** stack smashing detected ***: stack_vuln terminated вообщем вопрос как обойти такую защиту?!?! говорят что ее нельзя обойти.