al-khaser Anti Debug

  • 格式:doc
  • 大小:44.00 KB
  • 文档页数:4

al-khaserAnti Debug这一部分主要是通过各种函数去确定当前进程是否处于被调试的状态。

VO ID exec_check(int(*callback)(), TCHAR* szMsg)两参数,第一参数是一个回调函数指针第二参数是一个需要输出打印的字符串功能通过回调函数的返回值以及第二参数szMsg,在函数print_results(result, szMsg)进行具体的判断输出打印并记录到日志中exec_check(&IsDebuggerPresentAPI, TEXT("Checking IsDebuggerPresent API () "));/*这是一个Win32 Debugging API ,用于判断进程是否被调试*/exec_check(&IsDebuggerPresentPEB, TEXT("Checking PEB.BeingDebugged "));/*从进程中获得PEB 判断pPeb->BeingDebugged 是否被置为1,从而判断是否被调试 */ Process Environement Block (BeingDebugged)exec_check(&CheckRemoteDebuggerPresentAPI, TEXT("Checking CheckRemoteDebuggerPresentAPI () "));/*这是一个Win32 Debugging API ,同时可用于检查被监控线程是否被调试,*/exec_check(&NtGlobalFlag, TEXT("Checking PEB.NtGlobalFlag "));Process Environement Block (NtGlobalFlag)/*从PEB中取NTGlobalFlag,当进程被调试时,NTGlobalFlag会被置为FLG_HEAP_ENABLE_TAIL_CHECK (0x10), FLG_HEAP_ENABLE_FREE_CHECK(0x20), 和FLG_HEAP_VALIDATE_PARAMETERS(0x40),0x70 = FLG_HEAP_ENABLE_TAIL_CHECK |FLG_HEAP_ENABLE_FREE_CHECK |FLG_HEAP_VALIDATE_PARAMETERS*/exec_check(&HeapFlags,TEXT("Checking ProcessHeap.Flags "));ProcessHeap (Flags)Flags在不同版本的操作系统中位置不一,通过IsWindowsVistaOrGreater()判断大概版本/*先获得ProcessHeap的地址,由于pHeapFlags在不同版本的操作系统中位置不一,需要IsWindowsVistaOrGreater()判断大概版本,从而利用pProcessHeap与偏移获得pHeapFlags的地址 */exec_check(&HeapForceFlags,TEXT("Checking ProcessHeap.ForceFlags "));ProcessHeap (ForceFlags)ForceFlags在不同版本的操作系统中位置不一,通过IsWindowsVistaOrGreater()判断大概版本/*先获得ProcessHeap的地址,由于ForceFlags在不同版本的操作系统中位置不一,需要IsWindowsVistaOrGreater()判断大概版本,从而利用pProcessHeap与偏移获得pHeapFlags的地址 */exec_check(&NtQueryInformationProcess_ProcessDebugPort,TEXT("Checking NtQueryInformationProcess with ProcessDebugPort "));- NtQueryInformationProcess (ProcessDebugPort)返回IsRemotePresent/*该函数调用NtQuerySystemInformation来获得IsRemotePresent,当函数成功时IsRemotePresent不为0*/exec_check(&NtQueryInformationProcess_ProcessDebugFlags,TEXT("Checking NtQueryInformationProcess with ProcessDebugFlags "));/*该函数调用NtQuerySystemInformation来获得NoDebugInherit,当函数成功时返回值为STATUS_SUCCESS,NoDebugInherit被置为0,表示正在被调试*/exec_check(&NtQueryInformationProcess_ProcessDebugObject,TEXT("Checking NtQueryInformationProcess with ProcessDebugObject "));/*该函数调用NtQuerySystemInformation来获得当前进程调试对象句柄,当函数成功hDebugObject不为0表示正在被调试 */exec_check(&NtSetInformationThread_ThreadHideFromDebugger,TEXT("Checking NtSetInformationThread with ThreadHideFromDebugger "));/*将ThreadInformationClass设置为0x11(ThreadHideFromDebugger),用于隐藏调试器中的线程,调用之后调试器与该线程不再关联*/exec_check(&CloseHandle_InvalideHandle,TEXT("Checking CloseHandle with an invalide handle ")); /*当进程被调试时,调用CloseHandle并传入无效句柄,会得到一个STATUS_INVALID_HANDLE的异常,函数返回TRUE*/exec_check(&UnhandledExcepFilterTest,TEXT("Checking UnhandledExcepFilterTest "));/*当一个未知异常发生,且没有记录的应对方法时,UnhandledExceptionFilter()会最后被调用三种返回值//EXCEPTION_EXECUTE_HANDLER equ 1 表示我已经处理了异常,可以优雅地结束了//EXCEPTION_CONTINUE_SEARCH equ 0 表示我不处理,其他人来吧,于是windows调用默认的处理程序显示一个错误框,并结束//EXCEPTION_CONTINUE_EXECUTION equ -1 表示错误已经被修复,请从异常发生处继续执行RaiseException(EXCEPTION_FLT_DIVIDE_BY_ZERO, 0, 0, NULL);该函数启用一个进程并使用结构化异常处理来处理私有的,软件生成的和应用程序定义的异常。

一个异常处理程序在引发异常并导致异常调度的时候需要经过以下步骤的处理:1.如果有调试器,系统首先尝试通知进程的调试器。

2.如果这一进程不被调试,或者相关的调试器不处理异常,系统将尝试通过搜索发生异常的线程的堆栈来定位一个基于帧的异常处理程序。

系统首先会搜索当前栈帧,然后继续向后搜索栈帧。

3.如果没有找到基于帧的异常处理程序,或没有基于帧的异常处理程序处理该异常,系统将会第二次尝试通知进程的调试器。

4.如果该进程仍未被调试,或者相关的调试器不处理异常,系统以异常类型为基础提供默认的处理程序。

对于大多数异常,默认动作是调用ExitProcess函数。

即当进程被调试时,会通知进程的调试器,而不会调用UnhandledExceptionFilter*/exec_check(&OutputDebugStringAPI,TEXT("Checking OutputDebugString "));/*This Works only in Windows XP/2000OutputDebugString()用于输出字符串给调试器显示。

我们通过GetLastError是否被置为Val,来判断是否有调试器与进程关联。

*/exec_check(&HardwareBreakpoints,TEXT("Checking Hardware Breakpoints "));/*硬件断点,intel下的,用Dr0-Dr7七个寄存器控制,在CONTEXT结构体中可以查询这些寄存器的状态*/exec_check(&SoftwareBreakpoints,TEXT("Checking Software Breakpoints "));/*软件断点 INT 3 获得函数地址和大小,以字节为单位查询是否存在0xCC */exec_check(&Interrupt_0x2d,TEXT("Checking Interupt 0x2d "));/*AddVectoredExceptionHandler()注册一个定向的情况处理__int2d()是一个用asm写的函数,利用指令 2D 测试进程是否被调试,当进程没有关联调试器,会返回一个异常,当情况为异常断点时需要我们手动将Rip或Eip++*/exec_check(&Interrupt_3,TEXT("Checking Interupt 1 "));/*AddVectoredExceptionHandler()注册一个定向的情况处理__debugbreak() Microsoft专用将在代码中引起断点,并在其中提示用户运行调试程序。

当进程没有关联调试器,会返回一个异常,当情况为异常断点时不需要我们手动将Rip或Eip++,原因Int 2D instruction already increased EIP/RIP*/exec_check(&MemoryBreakpoints_PageGuard,TEXT("Checking Memory Breakpoints PAGE GUARD: ")); /*分配一块动态内存,将RET写入内存中,然后将这块内存标记成保护,再以函数的形式调用该地址。