- UID
- 238621
注册时间2017-12-1
阅读权限90
最后登录1970-1-1
版主
TA的每日心情 | 开心 2019-3-15 11:00 |
---|
签到天数: 262 天 [LV.8]以坛为家I
|
翻译
原文地址:https://www.x86matthew.com/view_post?id=system_anti_debug
功能:使用NtQuerySystemInformation和DuplicateHandle的系统级反调试技术
我开发了一种反调试技术,它不加区别地针对用户模式调试器,而不是检测是否有个别进程被调试。
总的来说,这种方法的工作原理如下:
1. 使用带有SystemExtendedHandleInformation的NtQuerySystemInformation检索系统中所有打开的句柄列表。
2. 检查是否有进程包含一个活动的调试句柄。
3. 使用带有DUPLICATE_CLOSE_SOURCE标志的DuplicateHandle终止远程进程中的这个句柄。
4. 循环回到步骤#1。
使上述方法复杂化的一件事是在步骤2中识别调试句柄。每个句柄的类型都是通过NtQuerySystemInformation返回的ObjectTypeIndex字段来识别的,但这个值在不同版本的Windows中并不一致。
我们显然可以在一个查找表中硬编码各种可能的值,但通用的解决方案总是更好的。为了计算出当前操作系统的调试手柄类型索引,我采取了以下步骤:
1. 使用带有SystemExtendedHandleInformation的NtQuerySystemInformation检索系统中所有打开的句柄列表。
2. 为当前进程中发现的每个独特的对象类型设置一个标志(例如文件句柄、进程句柄、注册表键等)。
3. 调用PID为0的DebugActiveProcess。即使目标PID无效,DebugActiveProcess也会在当前进程中创建一个内部调试句柄。即使调用失败,该调试句柄也保持原位。
3. 重复步骤#1。
4. 循环浏览当前进程的最新句柄列表,并寻找在步骤#2中没有标记的对象类型的条目。假设这是一个单线程的应用程序,我们知道这将是之前由DebugActiveProcess创建的调试句柄。我们可以从这个条目的ObjectTypeIndex字段中提取调试句柄类型。
5. 使用CloseHandle手动关闭这个临时调试句柄。
下面是完整的程序代码:
- #include <stdio.h>
- #include <windows.h>
- #define SystemExtendedHandleInformation 64
- #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
- struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
- {
- ULONG Object;
- ULONG UniqueProcessId;
- ULONG HandleValue;
- ULONG GrantedAccess;
- USHORT CreatorBackTraceIndex;
- USHORT ObjectTypeIndex;
- ULONG HandleAttributes;
- ULONG Reserved;
- };
- struct SYSTEM_HANDLE_INFORMATION_EX
- {
- ULONG NumberOfHandles;
- ULONG Reserved;
- SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleList[1];
- };
- SYSTEM_HANDLE_INFORMATION_EX *pGlobal_SystemHandleInfo = NULL;
- DWORD dwGlobal_DebugObjectType = 0;
- DWORD GetSystemHandleList()
- {
- DWORD (WINAPI *NtQuerySystemInformation)(DWORD SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
- DWORD dwAllocSize = 0;
- DWORD dwStatus = 0;
- DWORD dwLength = 0;
- BYTE *pSystemHandleInfoBuffer = NULL;
- // get NtQuerySystemInformation function ptr
- NtQuerySystemInformation = (unsigned long (__stdcall *)(unsigned long,void *,unsigned long,unsigned long *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
- if(NtQuerySystemInformation == NULL)
- {
- return 1;
- }
- // free previous handle info list (if one exists)
- if(pGlobal_SystemHandleInfo != NULL)
- {
- free(pGlobal_SystemHandleInfo);
- }
- // get system handle list
- dwAllocSize = 0;
- for(;;)
- {
- if(pSystemHandleInfoBuffer != NULL)
- {
- // free previous inadequately sized buffer
- free(pSystemHandleInfoBuffer);
- pSystemHandleInfoBuffer = NULL;
- }
- if(dwAllocSize != 0)
- {
- // allocate new buffer
- pSystemHandleInfoBuffer = (BYTE*)malloc(dwAllocSize);
- if(pSystemHandleInfoBuffer == NULL)
- {
- return 1;
- }
- }
- // get system handle list
- dwStatus = NtQuerySystemInformation(SystemExtendedHandleInformation, (void*)pSystemHandleInfoBuffer, dwAllocSize, &dwLength);
- if(dwStatus == 0)
- {
- // success
- break;
- }
- else if(dwStatus == STATUS_INFO_LENGTH_MISMATCH)
- {
- // not enough space - allocate a larger buffer and try again (also add an extra 1kb to allow for additional handles created between checks)
- dwAllocSize = (dwLength + 1024);
- }
- else
- {
- // other error
- free(pSystemHandleInfoBuffer);
- return 1;
- }
- }
- // store handle info ptr
- pGlobal_SystemHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX*)pSystemHandleInfoBuffer;
- return 0;
- }
- DWORD GetDebugHandleObjectType(DWORD *pdwDebugObjectType)
- {
- DWORD dwHandleTypeList[128];
- DWORD dwHandleTypeCount = 0;
- DWORD dwCurrentHandleTypeAlreadyExists = 0;
- DWORD dwDebugObjectType = 0;
- DWORD dwFoundDebugObjectType = 0;
- // get initial handle list
- if(GetSystemHandleList() != 0)
- {
- return 1;
- }
- // store a list of handle types for this process
- for(DWORD i = 0; i < pGlobal_SystemHandleInfo->NumberOfHandles; i++)
- {
- // check if this handle is for the current process
- if(pGlobal_SystemHandleInfo->HandleList[i].UniqueProcessId != GetCurrentProcessId())
- {
- continue;
- }
- // check if this handle type already exists in the list
- dwCurrentHandleTypeAlreadyExists = 0;
- for(DWORD ii = 0; ii < dwHandleTypeCount; ii++)
- {
- if(dwHandleTypeList[ii] == pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex)
- {
- dwCurrentHandleTypeAlreadyExists = 1;
- break;
- }
- }
- // ignore if this handle type already exists in the list
- if(dwCurrentHandleTypeAlreadyExists != 0)
- {
- continue;
- }
- // add this handle type to the list
- if(dwHandleTypeCount >= (sizeof(dwHandleTypeList) / sizeof(DWORD)))
- {
- // not enough space in the list
- return 1;
- }
- dwHandleTypeList[dwHandleTypeCount] = pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex;
- dwHandleTypeCount++;
- }
- // DebugActiveProcess will create a debug handle for this process, even if the pid is invalid
- DebugActiveProcess(0);
- // get the latest handle list
- if(GetSystemHandleList() != 0)
- {
- return 1;
- }
- // compare against the old list to find the newly created debug handle type
- for(i = 0; i < pGlobal_SystemHandleInfo->NumberOfHandles; i++)
- {
- // check if this handle is for the current process
- if(pGlobal_SystemHandleInfo->HandleList[i].UniqueProcessId != GetCurrentProcessId())
- {
- continue;
- }
- // check if this handle type already existed before creating the debug handle
- dwCurrentHandleTypeAlreadyExists = 0;
- for(DWORD ii = 0; ii < dwHandleTypeCount; ii++)
- {
- if(dwHandleTypeList[ii] == pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex)
- {
- dwCurrentHandleTypeAlreadyExists = 1;
- break;
- }
- }
- if(dwCurrentHandleTypeAlreadyExists == 0)
- {
- // found the debug handle - store the object type
- dwFoundDebugObjectType = 1;
- dwDebugObjectType = pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex;
- // close the debug handle
- CloseHandle((HANDLE)pGlobal_SystemHandleInfo->HandleList[i].HandleValue);
- break;
- }
- }
- // ensure the debug handle type was found
- if(dwFoundDebugObjectType == 0)
- {
- return 1;
- }
- // store debug object type
- *pdwDebugObjectType = dwDebugObjectType;
- return 0;
- }
- DWORD CheckForDebuggerProcess(DWORD *pdwFoundDebugger, DWORD *pdwDebuggerPID, HANDLE *phRemoteDebugHandle)
- {
- DWORD dwFoundDebugger = 0;
- DWORD dwDebuggerPID = 0;
- HANDLE hRemoteDebugHandle = NULL;
- // get system handle list
- if(GetSystemHandleList() != 0)
- {
- return 1;
- }
- // check for debug handles
- for(DWORD i = 0; i < pGlobal_SystemHandleInfo->NumberOfHandles; i++)
- {
- if(pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex == dwGlobal_DebugObjectType)
- {
- // found a debugger - store PID
- dwFoundDebugger = 1;
- dwDebuggerPID = pGlobal_SystemHandleInfo->HandleList[i].UniqueProcessId;
- hRemoteDebugHandle = (HANDLE)pGlobal_SystemHandleInfo->HandleList[i].HandleValue;
- break;
- }
- }
- // store values
- *pdwFoundDebugger = dwFoundDebugger;
- *pdwDebuggerPID = dwDebuggerPID;
- *phRemoteDebugHandle = hRemoteDebugHandle;
- return 0;
- }
- int main()
- {
- HANDLE hDebuggerProcess = NULL;
- HANDLE hRemoteDebugHandle = NULL;
- HANDLE hClonedDebugHandle = NULL;
- DWORD dwFoundDebugger = 0;
- DWORD dwDebuggerPID = 0;
- printf("SystemAntiDebug - www.x86matthew.com\n\n");
- // find the debug handle object type
- if(GetDebugHandleObjectType(&dwGlobal_DebugObjectType) != 0)
- {
- return 1;
- }
- // wait for a debugger
- for(;;)
- {
- // check if a debugger is currently running on the system
- if(CheckForDebuggerProcess(&dwFoundDebugger, &dwDebuggerPID, &hRemoteDebugHandle) != 0)
- {
- return 1;
- }
- // check if a debugger was found
- if(dwFoundDebugger != 0)
- {
- // found a debugger
- printf("Found debugger - PID: %u\n", dwDebuggerPID);
- // open debugger process
- hDebuggerProcess = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDebuggerPID);
- if(hDebuggerProcess == NULL)
- {
- // failed to open process handle
- printf("Failed to open debugger process - PID: %u\n", dwDebuggerPID);
- }
- else
- {
- // close debugger handle from remote process and terminate the original handle
- if(DuplicateHandle(hDebuggerProcess, hRemoteDebugHandle, GetCurrentProcess(), &hClonedDebugHandle, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE) == 0)
- {
- // failed to duplicate handle
- printf("Failed to kill debugger - PID: %u\n", dwDebuggerPID);
- }
- else
- {
- // closed the target handle in the remote process successfully
- printf("Killed debugger successfully - PID: %u\n", dwDebuggerPID);
- // close local (cloned) debug handle
- CloseHandle(hClonedDebugHandle);
- }
- // close debugger process handle
- CloseHandle(hDebuggerProcess);
- }
- }
- // wait 500ms before searching again
- Sleep(500);
- }
- return 0;
- }
复制代码
由于反调试程序在后台运行,调试器将无法附加到任何其他进程:
|
|