Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Перехват функций на основе генерации исключений (https://forum.antichat.xyz/showthread.php?t=138990)

sn0w 02.09.2009 18:45

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

особые спасиба кезу, который как всегда помог советом и делом =)

вообщем, кодоманы, это для вас ;)

сорсы с билдом тут - webfile.ru/3886408
пасс 123123


а это кусок движка:
Код:

//////////////////////////////////////////////////////////////////////////
//        (c) Exception hook engine by sn0w. big thx to kez for good advices ;)
//        (c) cih.[ms] community, 2009
//////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "alldefs.h"

//////////////////////////////////////////////////////////////////////////
// анхук не поддерживается, пока. впадлу бля)
//////////////////////////////////////////////////////////////////////////

LIST_ENTRY  exception_list_head;

//////////////////////////////////////////////////////////////////////////

#define InitializeListHead(ListHead) (\
        (ListHead)->Flink = (ListHead)->Blink = (ListHead))

#define InsertHeadList(ListHead,Entry) {\
        PLIST_ENTRY _EX_Flink;\
        PLIST_ENTRY _EX_ListHead;\
        _EX_ListHead = (ListHead);\
        _EX_Flink = _EX_ListHead->Flink;\
        (Entry)->Flink = _EX_Flink;\
        (Entry)->Blink = _EX_ListHead;\
        _EX_Flink->Blink = (Entry);\
        _EX_ListHead->Flink = (Entry);\
}

//////////////////////////////////////////////////////////////////////////

PHOOK_ENTRY        find_hook_entry(LPVOID real_address)
{
        PLIST_ENTRY                current_list;
        PHOOK_ENTRY                pcurr_hook;

        current_list = exception_list_head.Flink;

        while(current_list != &exception_list_head){
                pcurr_hook = CONTAINING_RECORD(current_list, HOOK_ENTRY, list_entry);

                if ((DWORD)pcurr_hook->real_address == (DWORD)real_address)
                        return pcurr_hook;
               
                current_list = current_list->Flink;
        }

        return NULL;
}

//////////////////////////////////////////////////////////////////////////

VOID (WINAPI * Real_KiUserExceptionDispatcher)(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextFrame);
VOID WINAPI My_KiUserExceptionDispatcher(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextFrame)
{

    if(ExceptionRecord->ExceptionCode == STATUS_PRIVILEGED_INSTRUCTION){
                PHOOK_ENTRY hhk;
                hhk = find_hook_entry(ExceptionRecord->ExceptionAddress);

                if(hhk){
                        ContextFrame->Eip = (DWORD)hhk->handler;
                        NtContinue(ContextFrame, FALSE);
                }

    }

    Real_KiUserExceptionDispatcher(ExceptionRecord,ContextFrame);
}

//////////////////////////////////////////////////////////////////////////

__declspec(naked) VOID WINAPI Stub_KiUserExceptionDispatcher(IN PEXCEPTION_RECORD ExceptionRecord,
                                                                                                                        IN PCONTEXT ContextFrame)
{
        __asm{
                sub        esp, 4
                jmp        My_KiUserExceptionDispatcher
        }
}

//////////////////////////////////////////////////////////////////////////

inline void generate_pushret_code(LPVOID at_address, LPVOID to_address)
{
        *(LPBYTE)at_address = 0x68;
        *(DWORD*)((LPBYTE)at_address + 1) = (DWORD)to_address;
        *((LPBYTE)at_address + 5) = 0xC3;
}

//////////////////////////////////////////////////////////////////////////

PHOOK_ENTRY        ExceptionHookFunction(LPVOID function, LPVOID handler)
{
        BYTE privileged_opcodes[] = {0xFA, 0xFB, 0xEE, 0xEF, 0xEC, 0x6C, 0x6F};
       
        LPVOID                trampoline;
        DWORD                first_inst_len, protection;
        PHOOK_ENTRY phhk;
               
        get_instruction_length(function, &first_inst_len);
       
        trampoline = valloc(first_inst_len + 6);
        memcpy(trampoline, function, first_inst_len);
        generate_pushret_code((LPVOID)((LPBYTE)trampoline + first_inst_len), (LPVOID)((LPBYTE)function + first_inst_len));
       
        phhk = (PHOOK_ENTRY)valloc(sizeof(HOOK_ENTRY));       
        phhk->handler = handler;
        phhk->real_address = function;
        phhk->trampoline = trampoline;

        InsertHeadList(&exception_list_head, &phhk->list_entry);
       
        VirtualProtect(function, first_inst_len, PAGE_EXECUTE_READWRITE, &protection);
        *(LPBYTE)function = privileged_opcodes[brandom(0, sizeof(privileged_opcodes) - 1)];
        VirtualProtect(function, first_inst_len, protection, &protection);

        return phhk;
}

//////////////////////////////////////////////////////////////////////////

void InitializeExceptionHook()
{
        InitializeListHead(&exception_list_head);

        SpliceHookFunction((DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"), "KiUserExceptionDispatcher"),
                        Stub_KiUserExceptionDispatcher, (DWORD*)&Real_KiUserExceptionDispatcher);

}

//////////////////////////////////////////////////////////////////////////


flacs 03.09.2009 11:47

В принципе тоже самое можно и реализовать с помощью DebugAPI
Так же пищем в начало функции ($CC), при обработке дебага EXCEPTION_EVENT-> EXCEPTION_BREAKPOINT, проводим перехват с помощью OpenThread/SetThreadContext
и обработичке перехвата вызываем нужную функцию.
Недостаток лишь в том, что оно палиться через kernel32.dll! IsDebuggerPresent, хотя можно эту функцию перехватить и вернуть false

sn0w 04.09.2009 09:41

вот такой стаб для IsDebuggerPresent =)

Код:

LPVOID lpdbg;
        DWORD prot;
        char code[] = {0x33, 0xc0, 0xc3}; // xor eax, eax; retn;
        lpdbg = GetProcAddress(GetModuleHandle("kernel32.dll"), "IsDebuggerPresent");
        VirtualProtect(lpdbg, sizeof(code), PAGE_EXECUTE_READWRITE, &prot);
        memcpy(lpdbg, code, sizeof(code));
        VirtualProtect(lpdbg, sizeof(code), prot, &prot);

и она никогда не вернет значение того что прога под отладчиком. другой вопрос что ее инструкции

Код:

        mov    eax, dword ptr fs:[18]
        mov    eax, dword ptr ds:[eax+30]
        movzx  eax, byte ptr ds:[eax+2]

могут использоваться где угодно в программе

slesh 04.09.2009 09:58

А нахера патчить IsDebuggerPresent? Если её код
Код:

mov eax, fs:[18h]; // адрес TEB
mov eax, [eax+30h] // адрес PEB
movzx eax, [eax+2h] // флаг BeingDebugged
ret

Так что можно просто изменить значения в BeingDebugged и всё будет норм и менее паливно. Хотя с другой стороны - привязка к структуре TEB и PEB

sn0w 04.09.2009 10:17

вот добавил анхук

Код:

void ExceptionUnhookFunction(LPVOID real_address)
{
        PLIST_ENTRY        pcurr_entry;
        PHOOK_ENTRY        pcurr_item;

        pcurr_item = find_hook_entry(real_address);
        if(!pcurr_item) return;

        //repair function
        DWORD prot, len;
       
        len = get_instruction_length(pcurr_item->trampoline);
       
        VirtualProtect(real_address, len, PAGE_EXECUTE_READWRITE, &prot);
        memcpy(real_address, pcurr_item->trampoline, len);
        VirtualProtect(real_address, len, prot, &prot);

        vfree(pcurr_item->trampoline);

        pcurr_entry = &pcurr_item->list_entry;
        RemoveEntryList(pcurr_entry);

        vfree(pcurr_item);
}


sn0w 04.09.2009 10:20

Цитата:

Сообщение от slesh
А нахера патчить IsDebuggerPresent? Если её код
Код:

mov eax, fs:[18h]; // адрес TEB
mov eax, [eax+30h] // адрес PEB
movzx eax, [eax+2h] // флаг BeingDebugged
ret

Так что можно просто изменить значения в BeingDebugged и всё будет норм и менее паливно. Хотя с другой стороны - привязка к структуре TEB и PEB


или так

greki_hoy 16.04.2010 13:33

Цитата:

Сообщение от sn0w
Собственно очередная техника перехвата любых функций. только в начало пишется не джамп - а привелегированная инструкция, система генерирует исключение - а обработчик то уже тоже перехвачен. поэтому управление получает наш заранее подготовленный перехватчик. недоработок много - в частности не доделал снятие этого хука - но в этом ничего сложного нет. можете и сами.

особые спасиба кезу, который как всегда помог советом и делом =)

вообщем, кодоманы, это для вас ;)

сорсы с билдом тут - webfile.ru/3886408
пасс 123123


а это кусок движка:
Код:

//////////////////////////////////////////////////////////////////////////
//        (c) Exception hook engine by sn0w. big thx to kez for good advices ;)
//        (c) cih.[ms] community, 2009
//////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "alldefs.h"

//////////////////////////////////////////////////////////////////////////
// анхук не поддерживается, пока. впадлу бля)
//////////////////////////////////////////////////////////////////////////

LIST_ENTRY  exception_list_head;

//////////////////////////////////////////////////////////////////////////

#define InitializeListHead(ListHead) (\
        (ListHead)->Flink = (ListHead)->Blink = (ListHead))

#define InsertHeadList(ListHead,Entry) {\
        PLIST_ENTRY _EX_Flink;\
        PLIST_ENTRY _EX_ListHead;\
        _EX_ListHead = (ListHead);\
        _EX_Flink = _EX_ListHead->Flink;\
        (Entry)->Flink = _EX_Flink;\
        (Entry)->Blink = _EX_ListHead;\
        _EX_Flink->Blink = (Entry);\
        _EX_ListHead->Flink = (Entry);\
}

//////////////////////////////////////////////////////////////////////////

PHOOK_ENTRY        find_hook_entry(LPVOID real_address)
{
        PLIST_ENTRY                current_list;
        PHOOK_ENTRY                pcurr_hook;

        current_list = exception_list_head.Flink;

        while(current_list != &exception_list_head){
                pcurr_hook = CONTAINING_RECORD(current_list, HOOK_ENTRY, list_entry);

                if ((DWORD)pcurr_hook->real_address == (DWORD)real_address)
                        return pcurr_hook;
               
                current_list = current_list->Flink;
        }

        return NULL;
}

//////////////////////////////////////////////////////////////////////////

VOID (WINAPI * Real_KiUserExceptionDispatcher)(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextFrame);
VOID WINAPI My_KiUserExceptionDispatcher(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextFrame)
{

    if(ExceptionRecord->ExceptionCode == STATUS_PRIVILEGED_INSTRUCTION){
                PHOOK_ENTRY hhk;
                hhk = find_hook_entry(ExceptionRecord->ExceptionAddress);

                if(hhk){
                        ContextFrame->Eip = (DWORD)hhk->handler;
                        NtContinue(ContextFrame, FALSE);
                }

    }

    Real_KiUserExceptionDispatcher(ExceptionRecord,ContextFrame);
}

//////////////////////////////////////////////////////////////////////////

__declspec(naked) VOID WINAPI Stub_KiUserExceptionDispatcher(IN PEXCEPTION_RECORD ExceptionRecord,
                                                                                                                        IN PCONTEXT ContextFrame)
{
        __asm{
                sub        esp, 4
                jmp        My_KiUserExceptionDispatcher
        }
}

//////////////////////////////////////////////////////////////////////////

inline void generate_pushret_code(LPVOID at_address, LPVOID to_address)
{
        *(LPBYTE)at_address = 0x68;
        *(DWORD*)((LPBYTE)at_address + 1) = (DWORD)to_address;
        *((LPBYTE)at_address + 5) = 0xC3;
}

//////////////////////////////////////////////////////////////////////////

PHOOK_ENTRY        ExceptionHookFunction(LPVOID function, LPVOID handler)
{
        BYTE privileged_opcodes[] = {0xFA, 0xFB, 0xEE, 0xEF, 0xEC, 0x6C, 0x6F};
       
        LPVOID                trampoline;
        DWORD                first_inst_len, protection;
        PHOOK_ENTRY phhk;
               
        get_instruction_length(function, &first_inst_len);
       
        trampoline = valloc(first_inst_len + 6);
        memcpy(trampoline, function, first_inst_len);
        generate_pushret_code((LPVOID)((LPBYTE)trampoline + first_inst_len), (LPVOID)((LPBYTE)function + first_inst_len));
       
        phhk = (PHOOK_ENTRY)valloc(sizeof(HOOK_ENTRY));       
        phhk->handler = handler;
        phhk->real_address = function;
        phhk->trampoline = trampoline;

        InsertHeadList(&exception_list_head, &phhk->list_entry);
       
        VirtualProtect(function, first_inst_len, PAGE_EXECUTE_READWRITE, &protection);
        *(LPBYTE)function = privileged_opcodes[brandom(0, sizeof(privileged_opcodes) - 1)];
        VirtualProtect(function, first_inst_len, protection, &protection);

        return phhk;
}

//////////////////////////////////////////////////////////////////////////

void InitializeExceptionHook()
{
        InitializeListHead(&exception_list_head);

        SpliceHookFunction((DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"), "KiUserExceptionDispatcher"),
                        Stub_KiUserExceptionDispatcher, (DWORD*)&Real_KiUserExceptionDispatcher);

}

//////////////////////////////////////////////////////////////////////////


2sn0w - fix InsertHeadList
Код:


#if 0
#define InsertHeadList(ListHead,Entry) {\
        PLIST_ENTRY _EX_Flink;\
        PLIST_ENTRY _EX_ListHead;\
        _EX_ListHead = (ListHead);\
        _EX_Flink = _EX_ListHead->Flink;\
        (Entry)->Flink = _EX_Flink;\
        (Entry)->Blink = _EX_ListHead;\
        _EX_Flink->Blink = (Entry);\
        _EX_ListHead->Flink = (Entry);\
}
#endif

#define InsertHeadList(ListHead,Entry) do { \
        LIST_ENTRY *E_Entry = (Entry); \
        LIST_ENTRY *E_ListHead = (ListHead); \
        E_Entry->Flink = E_ListHead->Flink; \
        E_Entry->Blink = E_ListHead; \
        E_ListHead->Flink->Blink = E_Entry; \
        E_ListHead->Flink = E_Entry; \
} while (0)

побочный эффект в макросе 4 раза вычисляется второй аргумент плюс без do {} while (0) нельзя вставить
что то в список в условии if else или придется не ставить точку с запятой после InsertHeadList


Время: 19:53