Проблема с перезаписью адреса возврата при переполнении буфера

Тема в разделе "WASM.BEGINNERS", создана пользователем InFlame, 24 сен 2009.

  1. InFlame

    InFlame New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2009
    Сообщения:
    12
    Решил попрактиковаться в переполнении буфера. Накатал быстренько уязвимую программу. При передаче такого аргумента `perl -e 'print "A"x100'` в отладчике gdb выдаёт:
    Вывод команды i r:
    Тогда как, на сколько я понимаю, регистр eip должен быть перезаписан на 0x41414141. А у меня вместо 0x41414141 в eip 0x8048407.
    И может ли это быть защита со стороны ОС или компилятора? Никакие патчи не ставил.
    В чём проблема?

    Уязвимая программа:
    Код (Text):
    1. #include <stdio.h>
    2. #include <string.h>
    3.  
    4. int main (int argc, char *argv[])
    5. {
    6.   char buf[10];
    7.  
    8.   if (argc > 1)
    9.     strcpy(buf, argv[1]);
    10.  
    11.   return 0;
    12. }
    Дистрибутив Mandriva 2009.1
    Компилятор gcc 4.3.2
     
  2. Quatre_R_Winner

    Quatre_R_Winner Member

    Публикаций:
    0
    Регистрация:
    10 ноя 2008
    Сообщения:
    66
    Надо посмотреть во что ваш main компилируется и тогда станет ясно почему это не пашет. Судя по всему, а конкретно по esp=0x4141413d eip=0x8048407<main+99> у вас произошёл обвал потому что указатель стека восстановился из затёртого же стека и юзался до возврата из функции.
     
  3. InFlame

    InFlame New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2009
    Сообщения:
    12
    Код (Text):
    1. (gdb) disas main                                                          
    2. Dump of assembler code for function main:                                
    3. 0x08048374 <main+0>:    lea    0x4(%esp),%ecx                            
    4. 0x08048378 <main+4>:    and    $0xfffffff0,%esp                          
    5. 0x0804837b <main+7>:    pushl  -0x4(%ecx)                                
    6. 0x0804837e <main+10>:   push   %ebp                                      
    7. 0x0804837f <main+11>:   mov    %esp,%ebp                                  
    8. 0x08048381 <main+13>:   push   %ecx
    9. 0x08048382 <main+14>:   sub    $0x24,%esp
    10. 0x08048385 <main+17>:   mov    %ecx,-0x18(%ebp)
    11. 0x08048388 <main+20>:   mov    -0x18(%ebp),%eax
    12. 0x0804838b <main+23>:   cmpl   $0x1,(%eax)
    13. 0x0804838e <main+26>:   jle    0x80483aa <main+54>
    14. 0x08048390 <main+28>:   mov    -0x18(%ebp),%edx
    15. 0x08048393 <main+31>:   mov    0x4(%edx),%eax
    16. 0x08048396 <main+34>:   add    $0x4,%eax
    17. 0x08048399 <main+37>:   mov    (%eax),%eax
    18. 0x0804839b <main+39>:   mov    %eax,0x4(%esp)
    19. 0x0804839f <main+43>:   lea    -0xe(%ebp),%eax
    20. 0x080483a2 <main+46>:   mov    %eax,(%esp)
    21. 0x080483a5 <main+49>:   call   0x80482b0 <strcpy@plt>
    22. 0x080483aa <main+54>:   mov    $0x0,%eax
    23. 0x080483af <main+59>:   add    $0x24,%esp
    24. 0x080483b2 <main+62>:   pop    %ecx
    25. 0x080483b3 <main+63>:   pop    %ebp
    26. 0x080483b4 <main+64>:   lea    -0x4(%ecx),%esp
    27. 0x080483b7 <main+67>:   ret
    28. End of assembler dump.
     
  4. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    ну вы хотя бы посмотрите, что у вас в стеке
    Код (Text):
    1. main.return
    2. l -0x4(%ecx)
    3. %ebp
    4. %ecx
    5. 0x20 some bytes
    6. %eax
    7. strcpy.return
    8. ...
     
  5. InFlame

    InFlame New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2009
    Сообщения:
    12
    Можно поподробней? Что делать-то?
     
  6. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    чтобы перезаписать адрес возврата, надо проанализировать стек атакуемой функции. если вы хотите тренироваться переполнять буфер программы, то для начала прочитайте как это делается (правильно), а потом уже приступайте к реализации на практике, а не тупо лепите что попало.
     
  7. InFlame

    InFlame New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2009
    Сообщения:
    12
    Делаю в точности как в статье по переполнению буфера. В статье происходит одно - у меня совсем другое. Вот и пытаюсь выяснить в чём проблема...
     
  8. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    ну а проанализировать стек, убедиться, что все попадает туда куда надо, посмотреть, что там по тому адресу, куда вы отправляете выполнение. в статье разве этого не написано?
     
  9. Quatre_R_Winner

    Quatre_R_Winner Member

    Публикаций:
    0
    Регистрация:
    10 ноя 2008
    Сообщения:
    66
    Проблема хотя бы в том что разные компилы компилят разный код и как следствие переполнять разные результаты нужно по разному. Вот и всё. Как именно переполнение устраивать смотрится из кода на асме а не на сишнике.
     
  10. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    InFlame
    кстати, а что за статья? и что там происходит (страшного)?
     
  11. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Ох, обожаем этот синтаксис. Агррхъ.
    )
    Код (Text):
    1. lea ecx, [esp+4]    ; pArg1
    2. and esp, -$10
    3. push [ecx-4]        ; ret addr
    4. push ebp
    5. mov ebp, esp
    6. push ecx        ; pArg1
    7. sub esp, $24
    8. ...
    9. add esp, $24
    10. pop ecx
    11. pop ebp
    12. lea esp, [ecx-4]
    13. ret
    InFlame
    В общем, это можно рассматривать как некий сорт защиты от переполнения, реализуемой компилятором. Не знаем, как называется – вообще говоря, первый раз видим такое. Вероятно, существуют какие-нибудь ключи для gcc, контролирующие создание подобного кода.
    Вот vc9 под винду для защиты от переполнения может класть в стек кукис (GSCookie == (ebp + delta) xor [__security_cookie], delta обычно нуль), а перед выполнением возврата вызывать микрофункцию, которая проверяет, не изменился ли этот самый кукис – и бьёт тревогу, ежели что.

    InFlame
    Так. В явном виде никто не сказал ещё? Вероятно, на этом этапе уже стало ясно, но ежели что: исключение происходит при выполнении инструкции ret – процессор пытается прочитать адрес возврата из невалидной области памяти по адресу 4141413d (== 41414141 - 4). Если стек рандомизируется (различен при каждом запуске программы), то вероятность овладевания чрезвычайно низка.
     
  12. InFlame

    InFlame New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2009
    Сообщения:
    12
    Делал по этой статье http://www.securitylab.ru/contest/212095.php, да и не только по этой (тут, на wasm'е ещё читал) - результат один.
    А кто-нибудь пытался проделывать нечто похожее, используя компилятор gcc версий >4.3? Может быть действительно проблема в компиляторе?
     
  13. Quatre_R_Winner

    Quatre_R_Winner Member

    Публикаций:
    0
    Регистрация:
    10 ноя 2008
    Сообщения:
    66
    В данном случае если положения стека известно заранее (стек всегда в одном и том же месте) и смещение в нём постоянно и нужные значения можно передать через заполняющую буфер функцию, то это можно обойти. Просто в буфер передаётся сначала 10 байт мусора или кода, потом 4 байта для ecx из которых получится esp, потом какой нить мусор или полезное значение для ebp ну и адрес возврата на нужный код по 4 байта соответственно. Собственно в значении для ecx и проблема, но если стек известен всё прокатит.