Created
April 15, 2017 09:50
-
-
Save hackpascal/5e3b309310c9b362303d0d92cc3adc1d to your computer and use it in GitHub Desktop.
简单的检测调试器的方法
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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