Почему я получаю нарушение прав доступа при записи в сегмент кода в сборке?

Я делаю эксперименты по шифрованию сегмента кода PE с помощью XOR для каждого байта с некоторым значением ключа. До сих пор мне удалось XOR этого сегмента и вставить в конце сегмента кода двоичный код, который снова декодируется с помощью XORing с тем же значением. Конечно, я также обновил AddressOfEntryPoint, чтобы он был равен адресу декодера.

Но когда я вычисляю адрес первого байта для XORed (он равен первому байту перед декодером - потому что я буду идти вверх), и я пытаюсь сделать это, я получаю нарушение доступа.

Теперь подробности:

1) в качестве тестового PE я использую супер простое консольное приложение "hello world" на простом C++

2) введенный код декодера записывается на ассемблере NASM, затем собирается в двоичный файл и затем вводится в конце секции.text тестового PE. Его код ниже:

    call    get_proc            ; push return address

get_proc:
    pop     esi                 ; pop current address
    sub     esi, 0x5            ; esi = address of injected code, 0x5 = size of call instruction

    xor     ebx, ebx            ; clear registers
    xor     ecx, ecx            ;

    mov     bl,  <DECODER_KEY>  ; decoder key
    mov     ecx, <CODE_SIZE>    ; encoded code size

    sub     esi, ecx            ; esi = address of encoded code

decoder_loop:
    mov     edx, esi            ; construct encoded byte address
    add     edx, ecx            ;
    dec     edx                 ;
    xor     byte [cs:edx], bl   ; decode
    loop    decoder_loop        ; loop back

    jmp     esi                 ; jump back to decoded code

3) <DECODER_KEY> а также <CODE_SIZE> заменены (перед сборкой) правильными значениями моим другим приложением, которое делает инъекцию

4) когда проходит первая итерация цикла, окончательное значение EDX равно адресу байта непосредственно перед call get_proc, проверено с помощью Immunity Debugger

5) здесь я выкладываю скриншот, представляющий ситуацию, когда у меня возникает нарушение прав доступа при попытке выполнить XOR для первого байта (красной линией я отметил свой введенный код, который выполняется в начале) введите описание изображения здесь

6) Мне известно о том, что по умолчанию сегмент кода доступен только для чтения и выполнения, но мое приложение для инъекций также добавляет разрешение на запись.

7) Я использую Windows 8.1 64-bit

И, наконец, вопросы:

А) Представлен ли код, делающий то, что я хочу?

Б) Достаточно ли добавить разрешение на запись в сегмент кода для выполнения этой операции (я знаю, что есть некоторые механизмы "защиты от записи", но я не знаю подробностей)?

Эксплойты часто используют эту технику (или, по крайней мере, раньше), поэтому мне интересно, почему это не работает. Кроме того, я должен сказать, что когда я удаляю только операции XOR, программа работает нормально (поэтому рассчитанные адреса верны).

РЕДАКТИРОВАТЬ: Вот ссылка на результат PEdump: PEdump

1 ответ

Решение

Я нашел решение своей проблемы. В общем: в коде ассемблера произошла ошибка - ссылка [cs:edx] в операции xor неправильно, должно быть просто [edx], Зачем?

Кажется, что теперь регистры сегментов делают не то, что мы (или, по крайней мере, я) думаем. Я слышал, что ранее они использовались в качестве базового адреса для каждого сегмента и инструкции [cs:addr] было смещение в сегменте кода.

Но если вы посмотрите поближе на значения регистров сегментов на фотографии, которую я предоставил, вы увидите, что эти регистры на самом деле являются некоторыми дескрипторами, которые ссылаются в основном на адрес 0xFFFFFFFF! Когда я удалил cs из инструкции это сработало! Но затем я загрузил двоичный файл в отладчик, и, как ни странно, он был переведен в ds:[edx]! Опять же, почему DS (сегмент данных)? Тот, который я не знаю. Но урок из этой проблемы должен состоять в том, чтобы не использовать эти регистры.

Если вы не согласны или у вас есть какие-либо разъяснения, пожалуйста, прокомментируйте этот ответ.

Другие вопросы по тегам