Переполнение буффера/Ubuntu/Gdb

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Fad.Mypl, 9 Jun 2011.

  1. Fad.Mypl

    Fad.Mypl New Member

    Joined:
    16 Sep 2009
    Messages:
    10
    Likes Received:
    0
    Reputations:
    0
    Приветствую. Интересует вот такой вот вопрос =>
    Возьмем простенькую программку.
    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. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Первые 2 случая нарывались на участки отсутствующей виртуальной памяти (т.е. нет выделенной памяти в тех адресах) о чем свидетельствует сигнал SIGSEGV или же память защищена от чтения (для исполнения должны быть права на чтение) или если включен DEP, то у тех страниц памяти вообще отсутствовали права на исполнения.

    А вот в третьем случае eip реально стал равен 0x41414141, но скорее всего по этому адресу уже находились какие-то данные (возможно образ проги или библиотек или еще что нибудь) и по этому началось исполнение данные по этому адресу. Затем там попалась какая-либо инструкция (чтение/записи памяти, или переход/вызов определенного адреса) которая обратилась к отсутствующей памяти или права доступа были не те (не было прав на запись если была инструкция записи или не было прав на чтение)

    так что просто посмотри что находится по адресу 0x41414141

    Для проверки можешь сделать бектрейс вызовов в обработчике SIGSEGV и тогда увидишь полную картину работу
     
    #2 slesh, 9 Jun 2011
    Last edited: 9 Jun 2011
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    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 ==
    
     
  4. Fad.Mypl

    Fad.Mypl New Member

    Joined:
    16 Sep 2009
    Messages:
    10
    Likes Received:
    0
    Reputations:
    0
    SIGSEGV скорей всего вылазит просто потому, что идет переполнение. С правами и со всем остальным нормально. Далее=〉
    Что выдает бт и посмотрим что есть по адресу "должному" нашему...
    По 0х41414141 находится мусор.
    Бт выдает все как надо, на функцию strcpy с еип адресом...
    ПС. А зачем писать? В гдб есть свой бт.
    ПС2. Саппорт с хакер.ру сказал-
    Походу просто стек кончился. Попробуй с меньшим размером буфера. (с) :(
     
  5. Fad.Mypl

    Fad.Mypl New Member

    Joined:
    16 Sep 2009
    Messages:
    10
    Likes Received:
    0
    Reputations:
    0
    указатель еип содержит =>
    "адрес:ret"
    Тобишь идет выгрузка уже...