Приветствую. Интересует вот такой вот вопрос => Возьмем простенькую программку. Code: #include <stdio.h> #include <string.h> int main(int argc, char** argv){ char buffer[500]; strcpy(buffer, argv[1]); return 0;} Отключаем Linux ASLR и компилируем с -fno-stack-protector. Начинаем работу с gdb => Пытаемся вызвать переполнение буфера => Code: run $(python -c 'print "\x41" * n') Где 'n' число превышающее наш буфер, и полностью затирающее eip, что собсна выходит => Code: (gdb) run $(python -c 'print "\x41" * 506') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/mumeg/training/a.out $(python -c 'print "\x41" * 506') Program received signal SIGSEGV, Segmentation fault. 0x00004141 in ?? () (gdb) run $(python -c 'print "\x41" * 507') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/mumeg/training/a.out $(python -c 'print "\x41" * 507') Program received signal SIGSEGV, Segmentation fault. 0x00414141 in ?? () (gdb) run $(python -c 'print "\x41" * 508') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/mumeg/training/a.out $(python -c 'print "\x41" * 508') Program received signal SIGSEGV, Segmentation fault. 0x080483ed in main (argc=0, argv=0xbffff234) at buf_stack_over.c:8 8 return 0;} (gdb) Почему в последнем моменте eip вообще изменяется в корне? Ubuntu 11.*(i386), e5200, 2gb. Заранее благодарен ответам!
Первые 2 случая нарывались на участки отсутствующей виртуальной памяти (т.е. нет выделенной памяти в тех адресах) о чем свидетельствует сигнал SIGSEGV или же память защищена от чтения (для исполнения должны быть права на чтение) или если включен DEP, то у тех страниц памяти вообще отсутствовали права на исполнения. А вот в третьем случае eip реально стал равен 0x41414141, но скорее всего по этому адресу уже находились какие-то данные (возможно образ проги или библиотек или еще что нибудь) и по этому началось исполнение данные по этому адресу. Затем там попалась какая-либо инструкция (чтение/записи памяти, или переход/вызов определенного адреса) которая обратилась к отсутствующей памяти или права доступа были не те (не было прав на запись если была инструкция записи или не было прав на чтение) так что просто посмотри что находится по адресу 0x41414141 Для проверки можешь сделать бектрейс вызовов в обработчике SIGSEGV и тогда увидишь полную картину работу
backtrace Кому интересно как сделать backtrace то вот код (заточен под linux (под фряху там небольшие изменения)) + поддержка x64 платформ. Компилить надо с параметром -rdynamic. ну и если нет lib execinfo то надо установить её (но по дефолту она вроде есть) Code: #include <ucontext.h> #include <errno.h> #include <execinfo.h> static void signal_error(int sig, siginfo_t *si, void *ptr) { void* ErrorAddr; void* Trace[16]; int x; int TraceSize; char** Messages; printf("Signal: %s, Addr: 0x%0.16X\n", strsignal(sig), si->si_addr); #if __WORDSIZE == 64 ErrorAddr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_RIP]; #else ErrorAddr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_EIP]; #endif TraceSize = backtrace(Trace, 16); Trace[1] = ErrorAddr; Messages = backtrace_symbols(Trace, TraceSize); if (Messages) { printf("== Backtrace ==\n"); for (x = 1; x < TraceSize; x++) { printf("%s\n", Messages[x]); } printf("== End Backtrace ==\n"); free(Messages); } exit(ERROR_CODE); } в main добавить код Code: struct sigaction sigact; sigact.sa_flags = SA_SIGINFO; // ставим флаг что получаем полную информацию sigact.sa_sigaction = signal_error; // ставим адрес нашего обработчика sigemptyset(&sigact.sa_mask); // очистим маску // поставим обработчики на нужные нам сигналы которые дают ошибки sigaction(SIGFPE, &sigact, 0); sigaction(SIGILL, &sigact, 0); sigaction(SIGSEGV, &sigact, 0); sigaction(SIGBUS, &sigact, 0); sigaction(SIGABRT, &sigact, 0); На выходе можно получить лог типа Code: [-] Signal: Segmentation fault, Addr: 0x0000000000000000 == Backtrace == /home/test/proc/bin/Release/my_proc(GetParamStr+0x34) [0x8049e44] /home/test/proc/bin/Release/my_proc(GetParamInt+0x3a) [0x8049efa] /home/test/proc/bin/Release/my_proc(main+0x140) [0x804b170] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0x126bd6] /home/test/proc/bin/Release/my_proc() [0x8049ba1] == End Backtrace ==
SIGSEGV скорей всего вылазит просто потому, что идет переполнение. С правами и со всем остальным нормально. Далее=〉 Что выдает бт и посмотрим что есть по адресу "должному" нашему... По 0х41414141 находится мусор. Бт выдает все как надо, на функцию strcpy с еип адресом... ПС. А зачем писать? В гдб есть свой бт. ПС2. Саппорт с хакер.ру сказал- Походу просто стек кончился. Попробуй с меньшим размером буфера. (с)