发布于:2018-10-26 15:51 | 150659次阅读 作者: 外部投稿 | 原作者: Jianxiong2333
#include #include #include /********************************************************************************* *Function:NtGlobalFlags //函数名称 *Description:查询进程环境块(PEB) //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回true时检测到调试器,否则无调试器。 //函数返回值的说明 *Others:Z NtGlobalFlag字段位于PEB(进程环境块)0x68的偏移处,//其他说明 64位机器则是在偏移0xBC位置.该字段的默认值为0。 当调试器正在运行时, 该字段会被设置为一个特定的值. 绕过这种检测的方法十分简单,调试时将其值置0即可,不建议使用。 **********************************************************************************/ bool NtGlobalFlags() { __asm { mov eax, fs:[30h] mov eax, [eax + 68h] and eax, 0x70 test eax, eax jne rt_label jmp rf_label } rt_label: return true; rf_label: return false; }
/********************************************************************************* *Function:IsDebuggerPresent //函数名称 *Description:查询进程环境块(PEB)IsDebugged标志。//函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回非零时检测到调试器,否则无调试器。 //函数返回值的说明 *Others:破解方法同样调试时将其值置0即可 //其他说明 **********************************************************************************/ BOOL CheckDebug_Is()
{
return IsDebuggerPresent();
}
/********************************************************************************* *Function:CheckRemoteDebuggerPresent //函数名称 *Description:查询进程环境块(PEB)IsDebugged标志。//函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回非零时检测到调试器,否则无调试器。 //函数返回值的说明 *Others:它不仅可以探测系统其他进程是否被调试, //其他说明 通过传递自身进程句柄还可以探测自身是否被调试。 同IsDebuggerPresent几乎一致。 **********************************************************************************/ BOOL CheckDebug_CRDP() { BOOL ret; CheckRemoteDebuggerPresent(GetCurrentProcess(), &ret); return ret; }
/********************************************************************************* *Function:CheckDebug_rdtsc //函数名称 *Description:使用 rdtsc 指令的时钟检测。 //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回非零时检测到调试器,否则无调试器。 //函数返回值的说明 *Others:被调试时,进程的运行速度大大降低, //其他说明 利用rdtsc指令(操作码0x0F31),它返回至系统重新启动以来的时钟数, 并且将其作为一个64位的值存入EDX:EAX中。恶意代码运行两次rdtsc指令, 然后比较两次读取之间的差值。时间戳如果存在滞后,则可以认为存在调试器。 **********************************************************************************/ BOOL CheckDebug_rdtsc() { DWORD time1, time2; __asm { rdtsc mov time1, eax rdtsc mov time2, eax } if (time2 - time1 < 0xff) { return FALSE; } else { return TRUE; } }
/********************************************************************************* *Function:CheckDebug_0xCC //函数名称 *Description:触发调试器中断 //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回非零时触发中断成功,否则无调试器。 //函数返回值的说明 *Others:因为调试器使用INT 3来设置软件断点,插入 //其他说明 0xCC(INT 3)欺骗调试器使其认为这些0xCC机器码是自己设置的断点。 **********************************************************************************/ BOOL CheckDebug_0xCC() { __try { __asm int 3 } __except (1) { return FALSE; } return TRUE; }
/********************************************************************************* *Function:AD_SetUnhandledExceptionFilter //函数名称 *Description:异常-SetUnhandledExceptionFilter //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:调试中将异常抛给调试器,否则无调试器。 //函数返回值的说明 *Others:已经通过测试,无调试器返回0 //其他说明 **********************************************************************************/ 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; } BOOL AD_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 } return FALSE; }
/********************************************************************************* *Function:NtQueryInformationProcessApproach //函数名称 *Description: 检查进程调试 //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:进程被调试返回 -1 值端口,否则非。 //函数返回值的说明 *Others:已经通过测试,非公开函数。 //其他说明 它的第二个参数可以用来查询进程的调试端口,需要 使用LoadLibrary和GetProceAddress的方法获取调用地址 **********************************************************************************/ typedef NTSTATUS(WINAPI *NtQueryInformationProcessPtr)( HANDLE processHandle, PROCESSINFOCLASS processInformationClass, PVOID processInformation, ULONG processInformationLength, PULONG returnLength);
bool NtQueryInformationProcessApproach()
{ int debugPort = 0;
HMODULE hModule = LoadLibrary(TEXT("Ntdll.dll ")); NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hModule, "NtQueryInformationProcess");
if (NtQueryInformationProcess(GetCurrentProcess(), (PROCESSINFOCLASS)7, &debugPort, sizeof(debugPort), NULL)) printf("[ERROR NtQueryInformationProcessApproach] NtQueryInformationProcess failed\n");//调用失败 else return debugPort == -1;
return false; }
/********************************************************************************* *Function:CloseHandleException //函数名称 *Description: 仅在调试器下运行时产生无效句柄 //函数功能,性能等的描述 *Calls: //被本函数调用的函数清单 *Called By: //调用本函数的清单 *Input: //输入参数的说明,包括每个参数的作用、取值说明及参数间关系 *Output: //输出参数的说明 *Return:返回非零为调试器存在。 //函数返回值的说明 *Others:已经通过测试,查找传递给CloseHandle() //其他说明 的无效句柄。CloseHandle将自动终结程序 (调试器产生无效句柄) **********************************************************************************/ BOOL CloseHandleException(void) { HANDLE hInvalid = (HANDLE)0xDEADBEEF; // 无效句柄 DWORD found = FALSE;
__try { CloseHandle(hInvalid); } __except (EXCEPTION_EXECUTE_HANDLER) { found = TRUE; }
if (found) { return TRUE; } else return FALSE; }
int main(void) { if (NtGlobalFlags()) { printf("NtGlobalFlags()检测到调试\n"); } if (CheckDebug_Is()) { printf("IsDebuggerPresent()检测到调试\n"); } if (CheckDebug_CRDP()) { printf("CheckRemoteDebuggerPresent()检测到调试\n"); } if (CheckDebug_0xCC()) { printf("CheckDebug_0xCC()检测到调试\n");//让调试器中断 } if (CheckDebug_rdtsc()) { printf("CheckDebug_rdtsc()检测到调试\n");//检测时钟时间异常 } if (NtQueryInformationProcessApproach()) { printf("NtQueryInformationProcessApproach()检测到调试\n");//检测到调试器 } if (CloseHandleException()) { printf("CloseHandleException()检测到调试\n"); } if (AD_SetUnhandledExceptionFilter()) { printf("AD_SetUnhandledExceptionFilter()已终结调试\n");//抛出异常给调试器 }
getchar();
} 来源:Jianxiong2333—邮件投稿 GSLAB网站投稿文章仅代表作者本人的观点,与本网站立场无关。 *转载请注明来自游戏安全实验室(GSLAB.QQ.COM) |
最新评论
发表评论