[FASM] Учебный пример техники сплайсинга в Windows

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by movsd, 8 May 2012.

  1. movsd

    movsd New Member

    Joined:
    6 May 2012
    Messages:
    2
    Likes Received:
    0
    Reputations:
    0
    Моя учебная программа, может быть кому поможет понять ассемблер и сплайсинг:
    Code:
    format PE GUI 4.0
    include 'win32ax.inc'
    
    .data
    szMsg           db      "Hello, It`s test!", 0h
    szTitle         db      "Matrix is Anywere!", 0h
    szHackMsg       db      "Matrix Has You!", 0h
    SpliceData      db      02ch dup(0)
    
    .code
    proc    SetSplicingHookByAddr32 addrOldFnc, addrNewFnc, addrBuffer
            pusha
            pushfd
            mov     edi, [addrBuffer]
            mov     ebx, edi
            mov     edx, [addrNewFnc]
            mov     esi, [addrOldFnc]
            mov     ecx, 04h
            cld
            rep     movsd
            mov     Byte [ebx+010h], 0e9h
            mov     edx, [addrNewFnc]
            sub     edx, [addrOldFnc]
            sub     edx, 05h
            mov     DWord [ebx+011h], edx
            mov     eax, [addrNewFnc]
            mov     DWord [ebx+020h], eax
            mov     eax, [addrOldFnc]
            mov     DWord [ebx+024h], eax
            lea     eax, [ebx+028h]
            invoke  VirtualProtectEx, -1, DWord [addrOldFnc], 010h, PAGE_EXECUTE_READWRITE, eax
            mov     edi, [addrOldFnc]
            lea     esi, [ebx+010h]
            mov     ecx, 04h
            rep     movsd
            invoke  VirtualProtectEx, -1, DWord [addrOldFnc], 010h, DWord [ebx+028h], NULL
            popfd
            popa
            ret
    endp
    
    proc    UnsetSplicing32         addrBuffer
            pusha
            pushf
            mov     ebx, [addrBuffer]
            invoke  VirtualProtectEx, -1, DWord [ebx+024h], 010h, PAGE_EXECUTE_READWRITE, NULL
            cld
            mov     ecx, 04h
            mov     edi, [ebx+024h]
            lea     esi, [ebx+0h]
            rep     movsd
            invoke  VirtualProtectEx, -1, DWord [ebx+024h], 010h, DWord [ebx+028h], NULL
            popf
            popa
            ret
    endp
    
    proc    ReSplicing32    addrBuffer
            pusha
            pushf
            mov     ebx, [addrBuffer]
            invoke  VirtualProtectEx, -1, DWord [ebx+024h], 010h, PAGE_EXECUTE_READWRITE, NULL
            cld
            mov     ecx, 04h
            mov     edi, [ebx+024h]
            lea     esi, [ebx+010h]
            rep     movsd
            invoke  VirtualProtectEx, -1, DWord [ebx+024h], 010h, DWord [ebx+028h], NULL
            popf
            popa
            ret
    endp
    
    macro   stdcallOldFnc32    addrBuffer, [args]
    {
            reverse
            push    args
            common
            mov     ebx, addrBuffer
            call    DWord [ebx+024h]
    }
    
    Start:
                    invoke  MessageBoxA, 0h, szMsg, szTitle, 0h
                    stdcall SetSplicingHookByAddr32, [MessageBoxA], NewMessageBoxA, SpliceData
                    invoke  MessageBoxA, 0h, szMsg, szTitle, 0h
                    invoke  ExitProcess, 0h
    
    proc            NewMessageBoxA  P1, P2, P3, P4
                    stdcall UnsetSplicing32, SpliceData
                    stdcallOldFnc32 SpliceData, [P1], szHackMsg, szHackMsg, [P4]
                    stdcall ReSplicing32, SpliceData
                    ret
    endp
    
    .end Start
     
  2. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    809
    Reputations:
    231
    Джва раза прочел, но не разобрался с ассемблером и сплайсингом.
    Какие-то непонятные волшебные оффсеты и значения
    Code:
    mov     Byte [ebx+010h], 0e9h
    ...
    mov     DWord [ebx+024h], eax
    lea     eax, [ebx+028h]
    
    Потом какой-то макрос нипанятный:
    Code:
    macro   stdcallOldFnc32    addrBuffer, [args]
    {
            reverse
            push    args
            common
            mov     ebx, addrBuffer
            call    DWord [ebx+024h]
    }
    
    Где подробные комментарии то?
     
    _________________________
  3. slesh

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

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Это ппц. А теперь давай рассмотрим такую ситуацию:
    1) функция оригинал выполняется долго, к примеру работа с сетью
    2) Или твоя обработка хука длится долго
    3) в системе есть 2 и более потока
    4) одновременно оба потока вызывают похуканную функцию.

    Итог: Первая функция хукается отлично, а вторая срабатывает в обход хука. И всё дело в том, что перехват снимается на момент вызова оригинала.
    В общем самая быдлокодерская реализация хука.

    Автору следует подумать о таких методах как:
    1) Сплайсинг с использованием DLE и трамплинов
    2) Хук IAT и EAT

    Иначе толку не будет. Такое метод подходит только для каких-то своих тестовых нужд.
     
  4. DooD

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

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    450
    Reputations:
    288
    с использованием структур все делается проще и красивее имхо.
     
  5. Adio

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

    Joined:
    23 May 2005
    Messages:
    1,646
    Likes Received:
    147
    Reputations:
    18
    А вообще зачем вам АСМ ? вот вы тут разбираетесь, хуки то се, вам он зачем ? ну знаете вы - применяете где то свои знание если не секрет ? - кроме малвари
     
  6. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    809
    Reputations:
    231
    А вы используете исключительно лицензионный софт? Если нет, то откуда такие вопросы?
     
    _________________________
  7. Adio

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

    Joined:
    23 May 2005
    Messages:
    1,646
    Likes Received:
    147
    Reputations:
    18
    Ну его и так хватает я думаю - не лиц - тем более много тимов типа х форса и т д... Т.е разве что хобби - из лиц делать не лиц патчи итд.. как бы ради интереса сложности..
     
  8. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    а как же программировать на сишке не зная асма хотя бы на базовом уровне ? очень удобно при отлаживании сишки переключиться в режим дизассемблера это как лупа точки останова можно ставить в таких местах куда без дизассемблера не дотянуться выполнять такие ветки которые отладчик на уровне исходного кода просто проскакивает (это когда условие и выражение на одной строке) то что нагенерил компилятор хорошо видно и если накосячил то в дизассемблере сразу видно где ну и не мало важно это просто интересно смотреть что же там сгенерировал компилятор

    кстати вы пробовали без переключения в дизассемблер отлаживать макросы нет ? попробуйте
     
  9. movsd

    movsd New Member

    Joined:
    6 May 2012
    Messages:
    2
    Likes Received:
    0
    Reputations:
    0
    Сплайсинг - техника перехвата функций системы в виндовз. Детальнее про него можно прочитать на Wasm.ru. Сейчас я расскажу только о конкретной его реализации. Эта программа перехватывает MessageBoxA, и заменяет его тело и заголовок на свои. Для удобства я разбил код на несколько процедур и макросов, а все данные о перехватываемой функции храню в структуре.
    процедура SetSplicingHookByAddr32 получает адрес перехватываемой функции, адрес новой функции и адрес структуры.
    Она заполняет структуру, первые 16 байт заполняеться первыми 16 оригинальными байтам перехватываемой функции, а вторые 16 байт используються для создания "трамплина" на новую функцию. После создания "трамплина" в структуре он заменяет первые 16 байт оригинальной функции. Для записи трамплина нам необходимо изменить аттрибуты страницы памяти на запись, чтение и выполнение.
    Процедура UnsetSplicing32 восстанавливает оригинальные байты перехватываемой функции.
    Процедура ReSplicing32 восстанавливает трамплин из структуры.
    Макрос stdcallOldFnc32 я написал для удобства вызова оригинальной функции - т.е. это тот же макрос stdcall, но адрес функции он берет из структуры, переданной ему в качестве параметра. А вообще я хотел поупражняться с макроязыком ФАСМА.
    Схема работы проста:
    * Заполнить структуру и установить трамплин га новую процедуру
    В новой процедуре:
    * Восстановить оригинальные байты
    * Запусить оригинальную функцию
    * Заново записать трамплин
    * Вернуть нужное значение

    Особенности программы, которые может не понять высокоуровневый программист:
    Трамплин это инструкия процессора JMP DWORD XXXX, где ХХХХ - нужный адрес(в нашем случае адрес новой функции). Эта функция использует относительную аддресацию, поэтому мы должны рассчитать разницу между необходимым адресом прерхода и аддресом команды JMP, учев и ее размер (5байт).

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

    Кстати, если тут такая оживленная дискуссия, то я хотел бы услышать о достоинствах и недостатках перехвата функций методом SEH/VEH и другими отладочными средствами из Ring3 без изменения самого кода.
     
  10. slesh

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

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Поищи тут, sn0w когда-то описывал алгоритм перехвата на основе аппаратных точек остановки там было описано про достоинства и недостатки.