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

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   BaseFiberStart Hooker (https://forum.antichat.xyz/showthread.php?t=111675)

0x0c0de 17.03.2009 21:04

BaseFiberStart Hooker
 
Ничего принципиально нового, но кому-то вероятно будет интересно. Речь здесь пойдет о волокнах. Поток в винде начинается с BaseThreadStartThunk, процесс с BaseProcessStartThunk, а волокно с BaseFiberStart. Значит, чтобы выполнить свой код до запуска кода волокна надо изменить эту неэкспортируемую функу BaseFiberStart. Сделать это просто, особенно в случае с волокнами. Кратко поясню как

Посмотрим на прототип функции CreateFiber

Код:


LPVOID WINAPI CreateFiber(
  __in      SIZE_T dwStackSize,
  __in      LPFIBER_START_ROUTINE lpStartAddress,
  __in_opt  LPVOID lpParameter
);


Возвращаемое значение - адрес волокна. Что такое адрес волокна? А вот тут уже msdn ничего не скажет. Ну ок, берем IDA и начинаем дизасмить kernel32.dll.

Для начала разберемся с WindowsXP SP3

CreateFiber вызывает CreateFiberEx, а в CreateFiberEx вызывается _BaseInitializeContext@20. BaseInitializeContext как раз и определяет какой адрес записать BaseThreadStartThunk, BaseProcessStartThunk или BaseFiberStart. В качестве первого параметра эта функция принимает указатель на структуру CONTEXT.

Как видим в структуре CONTEXT BaseFiberStart кладется по смещению 0B8h.

Код:

ifFiber:                                ; CODE XREF: BaseInitializeContext(x,x,x,x,x)+4C4F j
.text:7C82FF6E                mov    dword ptr [eax+0B8h], offset _BaseFiberStart@0 ; BaseFiberStart()
.text:7C82FF78                jmp    loc_7C8104A4

Однако, взглянув на код вызова BaseInitializeContext можно увидеть, что на самом деле структура CONTEXT сама находиться по смещению 0x14h в другой структуре, которую и возвращает функция CreateFiber. А значит адрес BaseFiberStart находиться в этой структуре по смещению 0x14 + 0xb8 = 0xCC.

Код:

.text:7C830031                push    2
.text:7C830033                mov    [esi+10h], ecx
.text:7C830036                push    [ebp+var_C]
.text:7C830039                push    [ebp+arg_C]
.text:7C83003C                push    eax
.text:7C83003D                lea    eax, [esi+14h]
.text:7C830040                push    eax
.text:7C830041                call    _BaseInitializeContext@20 ; BaseInitializeContext(x,x,x,x,x)
.text:7C830046                mov    eax, esi


Таким образом мы вызываем CreateFiber, берем адрес волокна и меняем адрес по смещению 0xCC. Но на самом деле это круто только для WinXP. В висте и семерке все несколько иначе:

CreateFiber->CreateFiberEx-> _BaseInitializeFiberContext@16

А там уже по смещению 0xC4 кладется адрес, а по этому адресу уже лежит BaseFiberStart.

Код:

.text:77E02070                mov    [esi+0C4h], eax
.text:77E02076                mov    dword ptr [eax], offset _BaseFiberStart@0 ; BaseFiberStart()

Так что теперь непосредственно 0xC4 + 0x14 = 0xd8. И меняем адрес по этому адресу. Вот такие дела.

И непосредственно кодес

Код:

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

extern "C"
{
LPVOID WINAPI CreateFiber(
  __in      SIZE_T dwStackSize,
  __in      PVOID lpStartAddress,
  __in_opt  LPVOID lpParameter
);


VOID WINAPI DeleteFiber(
  __in  LPVOID lpFiber
);


VOID WINAPI SwitchToFiber(
  __in  LPVOID lpFiber
);

LPVOID WINAPI ConvertThreadToFiber(
  __in_opt  LPVOID lpParameter
);

BOOL WINAPI ConvertFiberToThread(void);

}

PVOID pMainFiber,TrueBaseFiberStart;

VOID _declspec(naked) NewBaseFiberStart(VOID)
{
        MessageBox(0,L"Fiber hooked",L"Hooked",0);

        _asm
        {
                jmp [TrueBaseFiberStart]

                ret
        }
}


VOID StartFiber(VOID)
{
        PVOID pCurFiber;

        printf("StartFiber: I am in fiber\n");

        pCurFiber = GetCurrentFiber();

        printf("StartFiber: current fiber 0x%08X\n",pCurFiber);

        SwitchToFiber(pMainFiber);
}

BOOL HookBaseFiberStart(PVOID pFiber,PVOID pAddressNewBaseFiberStart,PDWORD pdwSaveAddress)
{

        BOOL bRes=FALSE;

        DWORD dwVersion;

        dwVersion = GetVersion();

                //учитываем на какой системе мы

                switch(LOBYTE(LOWORD(dwVersion)))
                {

                        // модифицируем  _BaseFiberStart

                        case 5:

                                // до Vista
                                _asm
                                {

                                        mov edi,pFiber

                                        mov esi,dword ptr [edi + 0xcc]

                                        mov eax,pdwSaveAddress
                                       
                                        mov dword ptr [eax], esi

                                        mov esi,pAddressNewBaseFiberStart

                                        mov dword ptr [edi + 0xcc],esi


                                }

                                bRes = TRUE;

                                break;

                                // начиная с Vista
                        case 6:

                                _asm
                                {
                                        mov edi,pFiber

                                        mov esi,dword ptr [edi+ 0xD8]

                                        mov edi,dword ptr [esi]

                                        mov eax, pdwSaveAddress

                                        mov dword ptr [eax],edi

                                        mov edi,pAddressNewBaseFiberStart

                                        mov dword ptr [esi],edi
                                }

                                bRes = TRUE;

                                break;

                        default: break;
       
                }

return bRes;

}

int _tmain(int argc, _TCHAR* argv[])
{
        LPVOID pFiber;

        // создаем волокно

        pFiber = CreateFiber(0,&StartFiber,0);
       
        if(!pFiber)
        {
                printf ("Cannot create fiber\n");
        }
        else
        {
               
                if(!HookBaseFiberStart(pFiber,NewBaseFiberStart,(PDWORD)&TrueBaseFiberStart))
                {
                        return -1;
                }


                // делаем тред волокном, так как только волокно может запустить другое волокно

                pMainFiber = ConvertThreadToFiber(0);

                // запускаем наше свежесозданное волокно

                SwitchToFiber(pFiber);

                ConvertFiberToThread();

                // удаляем волокно

                printf("Deleting fiber 0x%08X...\n",pFiber);

                DeleteFiber(pFiber);
        }


        Sleep(-1);

        return 0;
}


В принципе можно применить в какой-нибудь защите.

De-visible 17.03.2009 21:09

Я походу нуб, не понял вообще о чем речь... эх...


Время: 04:24