Skip to content

Instantly share code, notes, and snippets.

@hackpascal
Created April 15, 2017 09:50
Show Gist options
  • Save hackpascal/5e3b309310c9b362303d0d92cc3adc1d to your computer and use it in GitHub Desktop.
Save hackpascal/5e3b309310c9b362303d0d92cc3adc1d to your computer and use it in GitHub Desktop.
简单的检测调试器的方法
#include <Windows.h>
#include <winternl.h>
extern "C"
__declspec(dllimport) NTSTATUS WINAPI NtSetInformationThread(
_In_ HANDLE ThreadHandle,
_In_ THREADINFOCLASS ThreadInformationClass,
_In_ PVOID ThreadInformation,
_In_ ULONG ThreadInformationLength
);
#pragma comment(lib, "ntdll.lib")
#define NtCurrentThread (HANDLE) -2
#define ThreadHideFromDebugger (THREADINFOCLASS) 0x11
bool PebNtGlobalFlagsApproach()
{
int result = 0;
__asm
{
// 进程的PEB
mov eax, fs:[30h]
// 控制堆操作函数的工作方式的标志位
mov eax, [eax + 68h]
// 操作系统会加上这些标志位FLG_HEAP_ENABLE_TAIL_CHECK,
// FLG_HEAP_ENABLE_FREE_CHECK and FLG_HEAP_VALIDATE_PARAMETERS,
// 它们的并集就是x70
//
// 下面的代码相当于C/C++的
// eax = eax & 0x70
and eax, 0x70
mov result, eax
}
return result != 0;
}
LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pei)
{
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)
pei->ContextRecord->Eax);
// 修改寄存器eip的值
pei->ContextRecord->Eip += 2;
// 告诉操作系统,继续执行进程剩余的指令(指令保存在eip里),而不是关闭进程
return EXCEPTION_CONTINUE_EXECUTION;
}
bool UnhandledExceptionFilterApproach()
{
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
__asm
{
// 将eax清零
xor eax, eax
// 触发一个除零异常
div eax
}
return false;
}
bool Int3Test()
{
__try
{
__asm int 3;
return true;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
return false;
}
bool IceBPTest()
{
__try
{
__asm _emit 0xf1;
return true;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
return false;
}
bool NtSetInformationThreadTest()
{
NTSTATUS ntStat;
BOOLEAN check = FALSE;
//invalid parameter
ntStat = NtSetInformationThread(NtCurrentThread, ThreadHideFromDebugger, &check, sizeof(ULONG));
if (ntStat >= 0) //it must fail
return true;
//invalid handle
ntStat = NtSetInformationThread((HANDLE)0xFFFFF, ThreadHideFromDebugger, 0, 0);
if (ntStat >= 0) //it must fail
return true;
ntStat = NtSetInformationThread(NtCurrentThread, ThreadHideFromDebugger, 0, 0);
if (ntStat >= 0)
return false;
else
return true;
}
bool NtQueryInformationThreadTest()
{
NTSTATUS ntStat;
BOOLEAN check = FALSE;
//only available >= VISTA
ntStat = NtQueryInformationThread(NtCurrentThread, ThreadHideFromDebugger, &check, sizeof(BOOLEAN), 0);
if (ntStat >= 0)
{
if (!check)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
return false;
}
int main()
{
BOOL b;
if (IsDebuggerPresent())
printf("[FAIL] IsDebuggerPresent 检测到调试器\n");
else
printf("[ OK ] IsDebuggerPresent 未检测到调试器\n");
if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &b))
{
if (b)
printf("[FAIL] CheckRemoteDebuggerPresent 检测到调试器\n");
else
printf("[ OK ] CheckRemoteDebuggerPresent 未检测到调试器\n");
}
else
{
printf("[PASS] CheckRemoteDebuggerPresent 检测失败\n");
}
if (PebNtGlobalFlagsApproach())
printf("[FAIL] NtGlobal 标志位 检测到调试器\n");
else
printf("[ OK ] NtGlobal 标志位 未检测到调试器\n");
//*
if (UnhandledExceptionFilterApproach())
printf("[FAIL] SEH 异常触发 检测到调试器\n");
else
printf("[ OK ] SEH 异常触发 未检测到调试器\n");
//*/
if (Int3Test())
printf("[FAIL] int 3 检测到调试器\n");
else
printf("[ OK ] int 3 未检测到调试器\n");
if (IceBPTest())
printf("[FAIL] Ice Breakpoint (int1) 检测到调试器\n");
else
printf("[ OK ] Ice Breakpoint (int1) 未检测到调试器\n");
if (NtSetInformationThreadTest())
printf("[FAIL] NtSetInformationThread 检测到调试器\n");
else
printf("[ OK ] NtSetInformationThread 已尝试脱离调试器\n");
if (NtQueryInformationThreadTest())
printf("[FAIL] NtQueryInformationThread 检测到调试器\n");
else
printf("[ OK ] NtQueryInformationThread 未检测到调试器\n");
system("pause");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment