Ничего принципиально нового, но кому-то вероятно будет интересно. Речь здесь пойдет о волокнах. Поток в винде начинается с BaseThreadStartThunk, процесс с BaseProcessStartThunk, а волокно с BaseFiberStart. Значит, чтобы выполнить свой код до запуска кода волокна надо изменить эту неэкспортируемую функу BaseFiberStart. Сделать это просто, особенно в случае с волокнами. Кратко поясню как Посмотрим на прототип функции CreateFiber Code: 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. Code: 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. Code: .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. Code: .text:77E02070 mov [esi+0C4h], eax .text:77E02076 mov dword ptr [eax], offset _BaseFiberStart@0 ; BaseFiberStart() Так что теперь непосредственно 0xC4 + 0x14 = 0xd8. И меняем адрес по этому адресу. Вот такие дела. И непосредственно кодес Code: #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; } В принципе можно применить в какой-нибудь защите.