Статьи InLine Patching Protected Applications

Discussion in 'Статьи' started by taha, 27 Apr 2007.

  1. taha

    taha Elder - Старейшина

    Joined:
    20 Aug 2006
    Messages:
    399
    Likes Received:
    330
    Reputations:
    251
    InLine Patching Protected Applications
    by Hooking API Functions

    SUB Z3R0 | Spirit Of The Wind | Seek’n Destroy TeaM 2oo6


    Не хотел постить, ибо я то это знаю. Но если реверсом интересуется хотябы 43 человека, что следует из "популярности" моей статьи, то почему бы и нет. =\\
    За**ло бороться с фильтром!! Если у кого картинки не отображаются, то листайте оригинал http://www.tuts4you.com/download.php?view.320!!!

    InLine Patching давольно слабо освещён в рунете, что очень плохо... Ведь это довольно простой метод, который может сильно сохранить силы и время реверсера. Он позволяет исправлять код защищёной программы без ее распаковки. Может понадобиться если возникают проблемы с дампом или восставлением импорта.. Я решил заткнуть эту брешь и перевести этот tutorial. Это интересный тутор, специально для новичков. Профи не найдут ничего нового.. Я перевел только теорию и два примера, имхо с практикой можно разобраться самому. Тем более что в архиве лежат примеры. Кстати перевод получился давольно свободным.. Я мыcлю так - главное донести суть некоторых предложений, а это, думаю, будет проще сделать на великом и могучем.
    + небольшие комментарии

    Введение:
    Для понимания InLine Patching нам необходимо знать ответы на эти вопросы:

    Вопрос: Что делает пакер/протектор с программой?

    Ответ: Он сжимает (ASPack, UPX) или криптует (TheMida, tElock), либо и то и другое (ASProtect, Armadillo), настоящий код программы и добавляет свой код в конец файла. Затем перемещвет EP (точку входа) на свой код.

    Вопрос: Как работают пакеры?

    Ответ:
    1. Выделить для себя память. (может не выделять)
    2. Дешифровка и запись совего кода в выделенную память
    3. Дешифровка и запись настоящего кода программы
    4. В некоторых случаях протектор эмулирует API функции
    5. Фиксирует таблицу импорта
    6. Выполняет переход на оригинальный код программы OEP.

    Заметка: Вторая часть может происходить два и более раз, что затруднит создание InLine patch’a.

    Хорошо, теперь Вы знаете теорию пакеров, узнайте торию инлайн патчинга через ответы на эти вопросы:

    Вопрос: Что такое Inline patching?

    Ответ: Inline patching – это трюк исправления запакованной программы без её распаковки!

    Вопрос: Как такое может быть?

    Ответ: Чтобы это сделать, нам необходимо провести инекцию кода после восстановления/дешифровки/распаковки оригинального кода программы и перед выполнением оного. (тоесть когда программа уже распакована но перехода на OEP ещё небыло, либо было но программа далеко не ушла) Одна из серьёзных проблем Inline patching’а – это поиск CRC* значений часто высчитывающихся с помощью чтения файла через (CreateFile – ReadFile и тп) API.
    *CRC – проверка на целостность кода, обычно высчитывается хэш файла и производится сравнение с этолоном

    Вопрос: Как мы можем перехватить API функцию?

    Ответ: Я знаю два способа перехвата API функций:
    Простой путь:
    1. Читаем первые 5/6 байт API функции и записываем их по адресу “X”.
    2. Записываем переход** на адрес “X” вместо первых 5/6 байт API функции.
    3. Записываем наш код по адресу “X”+5/6.
    4. В конец записываем переход на адрес API функции + 5/6 байт.
    ** Вы можете использовать: jmp [xxxx] (6 byte) / jmp xxxx (5 byte) / push xxxx ret (6 byte)

    Наглядная иллюстрация данного метода:

    [​IMG]

    Это хорошо, но работает не на всех API и системах Windows.

    Трудный путь:
    1. Чтение первых 5/6 байт API функции и сохранение их.
    2. Запись перехода на адрес “X” вместо первых 5/6 байт API функции.
    3. Запись нашего кода в X, затем добавление кода который сохранит и измененит адрес возврата*** на код Y. Востановление оригинальных 5/6 байт функции.
    4. Код Y выполняет действие 2 и переходит на настоящий адрес возврата.
    *** адрес возврата – когда происходит выполнение комманды call, в стек кладётся адрес следущей комманды. Иначе как бы ret узнавал куда возвратить управление?

    Наглядная иллюстрация данного метода:

    [​IMG]

    Это чётко работает на всех API и всех Windows.

    От меня: На самом деле есть действительно трудный метод. Но для этого нужно будет разобраться с дизассемблерами длин. Сделать что то подобное, что делает PESPin для обфускации.

    Вопрос: Что у тебя за метод?

    Ответ: Мой метод научит Вас перехватывать API, обходить проверку CRC и патчить программу (после дешифрации оригинального кода программы)

    Вопрос: Как ты это делаешь?

    Ответ: Чтобы провести InLine Patching моим методом нам необходимо проделать следущие шаги:

    Первый шаг: Обход проверки CRC одним из этих методов
    a) Перехват ReadFile/MapViweOfFile и перезапись настоящих байт в буфер (можно использовать для ASProtect)
    b) Следующий метод - подмена настоящего CRC вместо того что посчитает функция

    Второй шаг: Перехват таких API как (GetModuleHandleA, GetVersion, ThunRTMain). Эти функции обычно находятся в каждой прорамме и выполняются недалеко от OEP. (В некоторых случаях придётся создать счётчик вызовов этих функций. Программа не будет исправляться/патчится до тех пор, пока функция не будет вызываться недалеко от OEP)

    ASProtect 2.xx InLinePatching By Hook Method
    Откроем наше приложение (JhonWho InLineMe) в ToPo …

    [​IMG]

    Хорошо, 815 байт будет достаточно! Чтож мы используем выбранную секцию ... Свободное место с 4898D1 … поменяем EP на 898D1.

    Давайте подумаем что мы имеем в этом случае:
    1. Свободное место измененое ASPR, мы перейдем к выделеной памяти для установки нашего hook’а.
    2. Запишем наш код в выделеную память и пофиксим адреса

    [​IMG]

    3. Перехватим “MapViewOfFile”, чтобы “надуть” CRC
    Мы установим hook на MapViewOfFile... Измним AccessMode на 1 (File_Map_Copy)… изменим адрес возврата из MapViewOfFile на наш код (после выполнения MapViewOfFile мы перейдем к исправлению его буфера (buffer помещается в eax))… затем после сравнения EP Мапированного файла с нашей EP (898D1), мы перезапишем OEP (1000) пакера

    4. Перехват “GetModuleHandle”, исправление nag screen:
    Первый вызов GetModuleHandle имеет параметр hModule равный нулю и расположен в секции кода. Значит это вызов из настоящего кода программы.. Скорее всего программа уже распакованна в памяти пакером, а следовательно самое время патчить =)

    [​IMG]

    Программа запускается! Yes! Наг скрин был удалён!

    tElock 0.98+ InLinePatching By Hook Method
    Во-первых создадим резервную копию файла, затем откроем наше приложение (SnD UnpackMe) в ToPo…

    Хорошо, добавим 400 байт в новую секцию файла...

    Изменим EP на адрес добавленых байт: 66BD6

    Для начала мы имеем поиск CRC:
    Откроем файл в Olly… установите breakpoint на CloseHandle… Запустите и ждите пока olly не остановится... нажмите Ctrl-F9 для перехода к ret… затем жмите F8 и Вы увидете этот код:

    [​IMG]

    Установим breakpoint на 4659DE, запустим (F9)… запишите EAX – это CRC

    Давайте подумаем что мы имеем в этом случае:
    1. tElock, защищая файлы, не использует GetProcAddress в создании своей таблицы импорта... он ищет адреса в таблице экспорта kernel32.. Вы можете также добавить GetProcAddress в таблицу импорта вручную или исползуя LordPE…
    2. На рисунке выше можно заметить, что мы можем написать “mov eax,04e468f32 | jmp 4659DE” по адресу возврата CloseHandle.
    3. Перехват GetModuleHandle и исправление нужных байт... Первый вызов GetModuleHandle имеет параметр hModule равный нулю и расположен в секции кода. Значит это вызов из настоящего кода программы.. Скорее всего программа уже распакованна в памяти пакером, а следовательно самое время патчить =)

    Код который найдет GetProcAddress и перехватит CloseHandle и GetModuleHandle…

    [​IMG]

    Hook Callbacks…

    [​IMG]

    Запускаем файл..

    [​IMG]

    Готово!!
     
    #1 taha, 27 Apr 2007
    Last edited: 27 Apr 2007