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

Discussion in 'Реверсинг' started by InFlame, 22 Sep 2009.

  1. InFlame

    InFlame Banned

    Joined:
    27 Oct 2008
    Messages:
    207
    Likes Received:
    32
    Reputations:
    0
    Решил попрактиковаться в переполнении буфера. Накатал быстренько уязвимую программу. При передаче такого аргумента `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 InFlame, 22 Sep 2009
    Last edited: 23 Sep 2009
  2. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    1. 0x8048407 <- что за адрес? включается ли он в образ проги в памяти
    2. В студии (я как бэ виндовс секурити изучаю) по умолчанию включена проверка на переполненные буферы и по умолчанию будет отслеженна такая ситуация и прога будет по тихому прибита. Есть ли в gcc такая шняга я не знаю ...
    3. В таких ситуациях надо вручную смотреть как происходит переполнение в отладчике иначе трудно чтолибо говорить.
     
  3. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    >>. В студии (я как бэ виндовс секурити изучаю) по умолчанию включена проверка на переполненные буферы

    ничего там не включено.только отвратительые ворнинги со словами юзайте _s или пишите CRT_SECURE_NO_DEPRECATE

    2 ТС
    запусти отладчик?
     
  4. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    2desTiny

    я не про depricated говорил вообщето

    Code:
    /GS [-]
    Обнаружение некоторых возможных переполнений буфера, при которых перезаписывается возвращаемый адрес.
    
    [URL=http://msdn.microsoft.com/ru-ru/library/8dbf701c.aspx]MSDN![/URL] 
    
    Оно работает таки )

    PHP:

     sub_401000      proc near               
    CODE XREFsub_401030+Ap
    .text:00401000
    .text:00401000 var_10          byte ptr -10h
    .text:00401000 var_4           dword ptr -<- помещаем переменную между буфером и адресом возвратаetc
    .text:00401000 arg_0           dword ptr  8
    .text:00401000
    .text:00401000                 push    ebp
    .text:00401001                 mov     ebpesp
    .text:00401003                 sub     esp10h
    .text:00401006                 mov     eaxdword_40A000
    .text:0040100B                 xor     eaxebp <- для каждой функции свое персональное значение
    .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     esp8
    .text:00401020                 mov     ecx, [ebp+var_4]
    .
    text:00401023                 xor     ecxebp <- в случае если буфер переполнитсялокальная переменная затрется
    .text:00401025                 call    sub_401148 <- что и проверяется здесьесли она не соответствует постоянному значению процесс тихо прибъется.
    .
    text:0040102A                 mov     espebp
    .text:0040102C                 pop     ebp
    .text:0040102D                 retn
    .text:0040102D sub_401000      endp


     
    #4 Hiro Protagonist, 24 Sep 2009
    Last edited: 24 Sep 2009
  5. InFlame

    InFlame Banned

    Joined:
    27 Oct 2008
    Messages:
    207
    Likes Received:
    32
    Reputations:
    0
    2desTiny
    я ведь выложил листинг с gdb. Ведь поидее после передачи 200 символов в 10-символьный буфер адрес возврата стопроцентно должен перезаписаться. А у меня вместо 0x41414141 в eip 0x8048407.
    А, кстати, может ли это быть защита со стороны ОС или компилятора? Никакие патчи не ставил.
     
  6. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    2InFlame
    В отладчике пошагово выполни прогу и смотри что у тебя в стеке и какие левые операции компилятор вставил в твою функцию + документацию по gcc найди
     
  7. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    Code:
    int main(){
        int a[100];
    	for (int j = 0; j < 1000; j++){
    		a[j] = j;
    	}
    }
    
    трям. VS2008 сказало, что сие есть ошибка без малейшего вопроса.
     
  8. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    ага, в дебаг версии оно тебе скажет конечно про переполнение. Только, что ты этим хотем показать?
     
  9. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    да, видимо криво сказал. оно компилится, запускается и с самой чистой совестью затирает адрес возврата
     
  10. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    2desTiny
    млин, ты бы хоть в вышеприведенный дизасм код посмотрел. Естественно затрется адрес возврата, НО защита не даст выйти из функции (и как результат, выполнить переход на шеллкод) и тихо убьёт процесс ExitProcess`ом. Так что креша приложения по исключению ты не наблюдал скорее всего (хотя опять же не помню с какой версии компилится с /GS по умолчанию, посмотри настройки проекта, чтото типа stack protection), а приложение тихо сдохло (это для релиз версии приминительно, насколько помню в дебаг версии там ещё перед убийством процесса окошко выдаёт, что буфер переполнился с минимальной инфой).
     
    #10 Hiro Protagonist, 27 Sep 2009
    Last edited: 27 Sep 2009
  11. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    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, обрабатываемый перезаписанным обработчиком. Но можно и просто переписать, если тысячу уменьшить
     
  12. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    В коде не видно защиты, добавляемой /GS, видимо при неиспользовании опасных функций код не добавляется. Я все особенности защиты не изучал, такчто возможно =/
     
  13. KwKeeper

    KwKeeper New Member

    Joined:
    21 Oct 2009
    Messages:
    31
    Likes Received:
    1
    Reputations:
    0
    тоже столкнулся с защитой буфера.
    при попытки произвести перезапись в ubuntu
    получаю ошибку
    *** stack smashing detected ***: stack_vuln terminated

    вообщем вопрос как обойти такую защиту?!?!
    говорят что ее нельзя обойти.