////// UPDATED & RECODED /////// полезная и хитрая вещь, если довести до ума. но тут будет просто концепт. итак, сплайсы, экзепшн хуки - все они изменяют начало функции. но есть возможность перехвата без изменения оригинального кода. для этого мы используем отладочные регистры - dr0-3. при попадании потока на указанный в отладочном регистре адрес, будет вызван обработчик исключений, перехваченный сплайсом KiUserExceptionDispatcher. затем обработчик исключений перенаправит поток на наш трамплин и на сам перехватчик. из минусов - не больше 4х перехватов на поток итак, к0д winmain =) полный дистрибутив тут (сам движок (извините без комментов пока - просто не успел) и необходимые наборы утилит в исходном коде) http://www.rapidshare.ru/1343901 а это код вин маин) Code: #include <windows.h> #include "hwhook.h" #pragma optimize("gsy", on) #pragma comment(linker, "/MERGE:.rdata=.data") #pragma comment(linker,"/MERGE:.text=.data") #pragma comment(linker,"/SECTION:.data,ERW") #pragma comment(linker, "/BASE:0x77500000") #pragma comment(linker, "/ENTRY:WinMain") #pragma comment(lib, "ntdll.lib") PHARDWARE_HOOK_ENTRY pdhhWinExec; UINT WINAPI My_WinExec(LPSTR cmd, UINT show) { MessageBox(0,"This is a hook of WinExec =)",0,0); //lstrcpy(cmd, "notepad.exe"); // call notepad instead of anything return ((UINT(WINAPI*)(LPSTR,UINT))pdhhWinExec->trampoline)(cmd, show); } ////////////////////////////////////////////////////////////////////////// int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // init hook InitializeHardwareHook(); // hook it pdhhWinExec = HardwareHookFunction(GetProcAddress(GetModuleHandle("kernel32.dll"), "WinExec"), My_WinExec, GetCurrentThreadId()); // test WinExec("calc.exe", SW_SHOW); HardwareUnhookFunction(pdhhWinExec); MessageBox(0, "now unhooked...", 0, 0); WinExec("calc.exe", SW_SHOW); MessageBox(0, "yo =)", 0, 0); return 0; } думаю тут вопросов не будет) что я видоизменил, - да вообшем то все! в аттаче на рапиде (выше) доделанная сборка, альфа ясен пень, держащая как хук так и анхук в удобоваримой форме, и без асма, которая держит функции с любым числом аргументов, также держит мультихук - когда одна и таже функция одновременно перехватывается несколькими обработчиками, расположенными в разных потоках. не исключаю что там кривости есть, но не успел, очень торопился на собаку) включенные утилиты (едины с проектом): - дизассемблер длин - двигло сплайса (трамплинный перехват) - двигло инжекта тела в другой процесс по фиксированной базе - утилита поиска памяти по паттерну с маской - и тд
не получается переварить ) ибо пока только научился инжектить dll в удаленный процесс... щас как раз втыкаю про перехваты. ну вопрос собственно... я как понимаю это SEH ? потом устанавливать хук надо откуда из программы установщика или уже в теле процесса... (ну я думаю GetThreadContext наверно можно и удаленного получить)... и еще если процесс запускает треады новые в них будут работать эти исключения? извини за тупые вопросы - я просто еще СОВСЕМ не разобрался с этим делом
всегда порывался так сделать, но меня всегда останавливали 1) "а вдруг" кто-то порешит запустить на <= win2000 2) "а вдруг" таки кто-то додумался наконец, что вех - удобная вещь и со вздохом по старинке писался VirtualProtect
1) нет, то что было до UPDATE - был VEH. на данный момент перехватывается обработчик всех исключений KiUserExceptionDispatcher из ntdll, который я сомневаюсь что проверяет большинство антималвара. но ранний вариант - добавление обработчика через AddVectoredException.. тоже имеет право на жизнь 2) пример: HardwareHookFunction(GetProcAddress(GetModuleHandl e("kernel32.dll"), "WinExec"), My_WinExec, GetCurrentThreadId()); устанавливается на ид потока указанного в параметрах функции в пределах текущего процесса
+ еще одна ВЕЩЬ... Code: /* * * многие протекторы проверяют отладочные регистры на предмет наличия аппаратных * точек останова (hardware breakpoint). * конечноже, в ассемблере есть инструкции работы с этими регистрами, такие как mov eax, dr0 * или mov dr0, eax и тд. но то что нам на руку - все они являются превилигированными * и напрямую могут вызываться лишь в режиме ядра. в ином случае такой код будет * вызывать программные исключения и при отсутствии обработчика - крах программы. * поэтому все они используют функцию GetThreadContext() для получения информации * о текущем состоянии регистров (и прочей информации) потока. используя один регистр, * из 4х доступных для потока, под перехват и модификацию GetThreadContext(), как приведено в * примере ниже, мы полностью исключим возможность обнаружения перехвата. */ PHARDWARE_HOOK_ENTRY phheGetThreadContext; BOOL WINAPI xGetThreadContext(HANDLE h, LPCONTEXT ctx) { BOOL rc, dofake = FALSE; if(ctx->ContextFlags & CONTEXT_DEBUG_REGISTERS){ dofake = TRUE; dprintf("*** debug test detected ***"); } rc = ((BOOL(WINAPI*)(HANDLE, LPCONTEXT))phheGetThreadContext->trampoline)(h, ctx); if(dofake){ ctx->Dr0 = 0; ctx->Dr1 = 0; ctx->Dr2 = 0; ctx->Dr3 = 0; ctx->Dr7 = 0; } return rc; }
Не вызывает обработчик исключений GetThreadContext(). И даже ZwGetContextThread(). Так что "все они используют функцию GetThreadContext()" - не-а
хаха понял что ты имеешь ввиду, но написано о том что все они используют... - о протекторах хотя конечно не все, тк если о самом обработчике, то да, в нем также есть доступ к ContextRecord-> DrX и тд. и вот например таким кодом можно его задетектить Code: ////////////////////////////////////////////////////////////////////////// LONG WINAPI GblGbl(EXCEPTION_POINTERS* pExceptionInfo) { if(pExceptionInfo->ExceptionRecord->ExceptionCode!=EXCEPTION_INT_DIVIDE_BY_ZERO) return EXCEPTION_CONTINUE_SEARCH; if(pExceptionInfo->ContextRecord->Dr0){ MessageBoxA(0,"HOOK DETECTED",0,0); return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; } PHARDWARE_HOOK_ENTRY pwe; UINT WINAPI xWinExec(LPSTR lp, UINT n) { MessageBoxA(0,"hook of winexec", 0,0); return ((UINT(WINAPI*)(LPSTR,UINT))pwe->trampoline)(lp,n); } ////////////////////////////////////////////////////////////////////////// int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { AddVectoredExceptionHandler(0x31338,GblGbl); InitializeHardwareHook(); pwe = HardwareHookFunction(WinExec, xWinExec, GetCurrentThreadId(), 0); int a =1, b=1; b--; a = a/b; WinExec("cmd", 0); return a; } получим messagebox(hook detected)
Кстати, такая защита от антиотладки неподходит ) Дело в том, что я могу специально задания значения к примеру Dr7 Затем заново запросить контекст и сново проверить значение регистров. Также нужно желательно запоминать както. И фильтровать собственные установки и те которые поставили в проге. P.S. лучше юзай GhbGhb вместо GblGbl
Вот нет бы посмотреть откуда эта инфа берётся у обработчика и надуть всех - так надо вех впихнуть. Ну да, вех он и есть вех