перехват без модификации кода

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by sn0w, 21 Jan 2010.

  1. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,021
    Likes Received:
    1,200
    Reputations:
    327
    ////// 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;
    }
    
    
    
    думаю тут вопросов не будет)

    что я видоизменил, - да вообшем то все!

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

    включенные утилиты (едины с проектом):
    - дизассемблер длин
    - двигло сплайса (трамплинный перехват)
    - двигло инжекта тела в другой процесс по фиксированной базе
    - утилита поиска памяти по паттерну с маской
    - и тд
     
    #1 sn0w, 21 Jan 2010
    Last edited: 22 Jan 2010
    5 people like this.
  2. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    o_O не получается переварить ) ибо пока только научился инжектить dll в удаленный процесс... щас как раз втыкаю про перехваты.

    ну вопрос собственно... я как понимаю это SEH ? потом устанавливать хук надо откуда из программы установщика или уже в теле процесса... (ну я думаю GetThreadContext наверно можно и удаленного получить)... и еще если процесс запускает треады новые в них будут работать эти исключения?

    извини за тупые вопросы - я просто еще СОВСЕМ не разобрался с этим делом :)
     
    _________________________
  3. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    всегда порывался так сделать, но меня всегда останавливали
    1) "а вдруг" кто-то порешит запустить на <= win2000
    2) "а вдруг" таки кто-то додумался наконец, что вех - удобная вещь

    и со вздохом по старинке писался VirtualProtect
     
  4. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,021
    Likes Received:
    1,200
    Reputations:
    327
    1) нет, то что было до UPDATE - был VEH. на данный момент перехватывается обработчик всех исключений KiUserExceptionDispatcher из ntdll, который я сомневаюсь что проверяет большинство антималвара. но ранний вариант - добавление обработчика через AddVectoredException.. тоже имеет право на жизнь

    2) пример:
    HardwareHookFunction(GetProcAddress(GetModuleHandl e("kernel32.dll"), "WinExec"), My_WinExec, GetCurrentThreadId());

    устанавливается на ид потока указанного в параметрах функции в пределах текущего процесса
     
    #4 sn0w, 22 Jan 2010
    Last edited: 22 Jan 2010
  5. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,021
    Likes Received:
    1,200
    Reputations:
    327
    + еще одна ВЕЩЬ...


    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;
    }
    
     
  6. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    Не вызывает обработчик исключений GetThreadContext(). И даже ZwGetContextThread(). Так что "все они используют функцию GetThreadContext()" - не-а :)
     
  7. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,021
    Likes Received:
    1,200
    Reputations:
    327
    хаха понял что ты имеешь ввиду, но написано о том что все они используют... - о протекторах
    хотя конечно не все, тк

    если о самом обработчике, то да, в нем также есть доступ к 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)
     
    #7 sn0w, 29 Jan 2010
    Last edited: 29 Jan 2010
  8. slesh

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

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Кстати, такая защита от антиотладки неподходит )
    Дело в том, что я могу специально задания значения к примеру Dr7
    Затем заново запросить контекст и сново проверить значение регистров.
    Также нужно желательно запоминать както. И фильтровать собственные установки и те которые поставили в проге.

    P.S. лучше юзай GhbGhb вместо GblGbl ;)
     
    #8 slesh, 29 Jan 2010
    Last edited: 29 Jan 2010
  9. desTiny

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

    Joined:
    4 Feb 2007
    Messages:
    1,006
    Likes Received:
    444
    Reputations:
    94
    Вот нет бы посмотреть откуда эта инфа берётся у обработчика и надуть всех - так надо вех впихнуть. Ну да, вех он и есть вех :)