동적 디 버 깅 기술 총화

1. 이상 - SEH
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void AD_BreakPoint()
{
    printf("SEH : BreakPoint
"); __asm { // install SEH push handler push DWORD ptr fs:[0] mov DWORD ptr fs:[0], esp //INT 3 CPU , ( ntdll.dll KiUserExceptionDispatcher)。 // generating exception int 3 // 1) debugging // go to terminating code mov eax, 0xFFFFFFFF jmp eax // process terminating!!! // 2) not debugging // go to normal code handler: mov eax, dword ptr ss:[esp+0xc] mov ebx, normal_code mov dword ptr ds:[eax+0xb8], ebx xor eax, eax retn normal_code: // remove SEH pop dword ptr fs:[0] add esp, 4 } printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { AD_BreakPoint(); return 0; }

메모: OD 의 이상 옵션 은 int 3 인 터 럽 트 를 무시 합 니 다. 선택 하지 않 아야 합 니 다. strongOD 플러그 인 옵션 은 사용 하지 않 는 것 이 좋 습 니 다. 명령 에 들 어 갈 수 있 습 니 다.
 mov eax, 0xFFFFFFFF
jmp eax           

OD 는 int 3 에서 끊 을 수 없습니다 (F2). 그렇지 않 으 면 이상 주소 int 3 로 순환 합 니 다.
2. 이상 - setUnhandled 예외 필터
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

LPVOID g_pOrgFilter = 0;

LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS pExcept)
{
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)g_pOrgFilter);

    // 8900    MOV DWORD PTR DS:[EAX], EAX
    // FFE0    JMP EAX
    pExcept->ContextRecord->Eip += 4;

    return EXCEPTION_CONTINUE_EXECUTION;
}

void AD_SetUnhandledExceptionFilter()
{
    printf("SEH : SetUnhandledExceptionFilter()
"); //SetUnhandledExceptionFilter() Top Level Exception Filter 。 // , , Kernel32.dll //UnhandledExceptionFilter() 。UnhandledExceptionFilter() //ntdll.dll NtQueryInformationProcess() , // , ( , )。 // , Top Level Exception Filter 。 g_pOrgFilter = (LPVOID)SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)ExceptionFilter); __asm { xor eax, eax; mov dword ptr [eax], eax jmp eax } printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { AD_SetUnhandledExceptionFilter(); return 0; }

3.Timing Check
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void DynAD_RDTSC()
{
//Timing Check                  ,   。
//1.Counter based method
//	RDTSC     (RD==READ TSC == Time Stamp Counter)
//		x86 CPU       TSC(Time Stamp Counter,      ) 64    。
//		CPU   Clock Cycle(    )  ,     TSC.RDTSC       ,
//		   TSC   EDX:EAX   )。
  //		OD    Olly Advanced->options     2 Anti-RDSTC(          ),          。
  //	kernel32!QueryPerformanceCounter()/ntdll!NtQueryPerformanceCounter()
  //	kernel32!GetTickCount()
  //2.Time based method
  //	timeGetTime()
  //	_ftime()
  
    DWORD dwDelta = 0;

    printf("Timing Check (RDTSC method)");

    __asm {
		pushad
		//0F31      rdtsc
		rdtsc
		push edx
		push eax
		//         (        )
		xor eax, eax
		mov ecx, 0x3e8

_LOOP_START:
		inc eax
		loop _LOOP_START

		rdtsc
		pop esi			// eax
		pop edi			// edx
		// check high order bits
		cmp edx, edi
		ja _DEBUGGER_FOUND
		// check low order bits
		sub eax, esi
        mov dwDelta, eax
		cmp eax, 0xffffff
		jb _DEBUGGER_NOT_FOUND

        // debugger found -> crash!!!
_DEBUGGER_FOUND:
		xor eax, eax
		mov [eax], eax

        // debugger not found
_DEBUGGER_NOT_FOUND:
		popad
	}
    
    printf(" : delta = %X (ticks)
", dwDelta); printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { DynAD_RDTSC(); return 0; }

4. 함정 표식
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void DynAD_SingleStep()
{
   //     EFLAGS     9 (Index8)   。
   //TF    1 ,CPU       (Single Step)  。       ,CPU  1     
  //    EXCEPTION_SINGLE_STEP(0x80000004)  ,          。       
  //    。
    printf("Trap Flag (Single Step)
"); __asm { // install SEH push handler push DWORD ptr fs:[0] mov DWORD ptr fs:[0], esp // EFLAGS, pushfd or dword ptr ss:[esp], 0x100 popfd // nop , EXCEPTION_SINGLE_STEP ,OD nop F7,F8,F9 。 // KiUserExceptionDispatcher mov eax,0xFFFFFFFF //1) , SEH //2) , , F7,F8,F9 mov eax,0xFFFFFFFF nop // 1) debugging // go to terminating code mov eax, 0xFFFFFFFF jmp eax // process terminating!!! // 2) not debugging // go to normal code handler: mov eax, dword ptr ss:[esp+0xc] mov ebx, normal_code mov dword ptr ds:[eax+0xb8], ebx xor eax, eax retn normal_code: // remove SEH pop dword ptr fs:[0] add esp, 4 } printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { DynAD_SingleStep(); return 0; }
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void DynAD_INT2D()
{
	//INT 2D                 ,             。   
	//           ,    。
	//INT 2D            
	//1.        INT2D   (F7,F8),              ,                  。   ,       。
	//2.        INT2D   (F7,F8),                ,      ,      (            ,OD BUG)。
    BOOL bDebugging = FALSE;

    __asm {
        // install SEH
        push handler
        push DWORD ptr fs:[0]
        mov DWORD ptr fs:[0], esp
        
        //           ,  EFlags   TF=1,      SEH    
        int 0x2d

        nop
        mov bDebugging, 1
        jmp normal_code

handler:
        mov eax, dword ptr ss:[esp+0xc]
        mov dword ptr ds:[eax+0xb8], offset normal_code
        mov bDebugging, 0
        xor eax, eax
        retn

normal_code:
        //   remove SEH
        pop dword ptr fs:[0]
        add esp, 4
    }

    printf("Trap Flag (INT 2D)
"); if( bDebugging ) printf(" => Debugging!!!

"); else printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { DynAD_INT2D(); return 0; }

5.0 xcC 탐지
#include "stdio.h"
#include "windows.h"
#include "tchar.h"

DWORD g_dwOrgChecksum = 0xF5934986;

int _tmain(int argc, TCHAR* argv[]);

void DynAD_Checksum()
{
    BOOL bDebugging = FALSE;
    DWORD dwSize = 0;
    printf("Checksum
"); __asm { mov ecx, offset _tmain mov esi, offset DynAD_Checksum sub ecx, esi // ecx : loop count (buf size) xor eax, eax // eax : checksum xor ebx, ebx _CALC_CHECKSUM: movzx ebx, byte ptr ds:[esi] add eax, ebx rol eax, 1 inc esi loop _CALC_CHECKSUM cmp eax, g_dwOrgChecksum je _NOT_DEBUGGING mov bDebugging, 1 _NOT_DEBUGGING: } if( bDebugging ) printf(" => Debugging!!!

"); else printf(" => Not debugging...

"); } int _tmain(int argc, TCHAR* argv[]) { DynAD_Checksum(); return 0; }

요약:
1. CC int 3 명령 (둘 사이 에 빈 칸 이 없 음 을 주의 하 세 요).
2. CD 2D int 2d 명령
3.
pushfd
or [esp],100 
popfd
EFlags 레지스터 TF = 1.
이 세 가지 방법 은 모두 디 버 거 특유 의 성질 을 이용 한 것 입 니 다. (1. 무시 2. 정지점 까지 계속 실행 합 니 다. 3. 명령 을 실행 한 후에 끊 긴 명령 은 ntdll! KiUserException Dispatcher () 를 실행 하지 않 았 습 니 다.

좋은 웹페이지 즐겨찾기