查看进程是否被注入线程(不在系统模块)

有些进程被注入了某些恶意的线程(也可能不是恶意的)

首先我们拿到该进程的进程模块,用来对比进程中线程的模块是否在这里面

把这些模块放入到vector里面

便利该进程的所有线程获取模块的起始地址和大小,很快就可以得到伪装线程。

#pragma region 依赖
typedef enum _THREADINFOCLASS{
    ThreadBasicInformation,
    ThreadTimes,
    ThreadPriority,
    ThreadBasePriority,
    ThreadAffinityMask,
    ThreadImpersonationToken,
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup,
    ThreadEventPair_Reusable,
    ThreadQuerySetWin32StartAddress,
    ThreadZeroTlsCell,
    ThreadPerformanceCount,
    ThreadAmILastThread,
    ThreadIdealProcessor,
    ThreadPriorityBoost,
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending,
    ThreadHideFromDebugger,
    ThreadBreakOnTermination,
    MaxThreadInfoClass
}THREADINFOCLASS;
typedef struct _CLIENT_ID{
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
}CLIENT_ID;
typedef struct _THREAD_BASIC_INFORMATION{
    LONG ExitStatus;
    PVOID TebBaseAddress;
    CLIENT_ID ClientId;
    LONG AffinityMask;
    LONG Priority;
    LONG BasePriority;
}THREAD_BASIC_INFORMATION,*PTHREAD_BASIC_INFORMATION;
extern "C" LONG (__stdcall *ZwQueryInformationThread)(
    IN HANDLE ThreadHandle,
    IN THREADINFOCLASS ThreadInformationClass,
    OUT PVOID ThreadInformation,
    IN ULONG ThreadInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    ) = NULL;
#pragma endregion

有些API或结构体是微软未公开的,但是被某些大牛给分析出来了,就比如ZwQueryInformationThread结构体。

 

当然,该检测是纯windows提供的API所写,某些“伪装者”可能利用一些方法,来隐藏自己。这时候需要写Windows驱动来检测,需要安装windows driver kit(WDK),这个以后再说把。

 

以下是本菜手写的API检测代码。

while (Process32Next(hProcessSnap,&process)){
		string s_szExeFile = process.szExeFile; // char* 转 string

		//if(s_szExeFile != "QQ.exe") continue;
		if(process.th32ProcessID == 0) continue;
		HANDLE hThreadSnap = INVALID_HANDLE_VALUE;			// 线程快照句柄 
		THREADENTRY32 te32;									// 线程快照信息
		// 创建线程快照
		hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
		if (hThreadSnap == INVALID_HANDLE_VALUE){cout << "创建线程快照失败" << endl;continue;}

		// 为快照分派内存空间
		te32.dwSize = sizeof(THREADENTRY32);

		// 获取第一个线程的信息
		if (!Thread32First(hThreadSnap, &te32)){cout << "线程信息获取失败" << endl;continue;}
		// 拿进程所有模块信息
		HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,process.th32ProcessID);
		if (INVALID_HANDLE_VALUE == hSnapshot){continue;}
		MODULEENTRY32 mi; 
		mi.dwSize = sizeof(MODULEENTRY32); 
		BOOL bRet = Module32First(hSnapshot,&mi);
		struct szMoudleStr{
			DWORD modBaseAddr;
			ULONG32 modBaseSize;
			char szModule[256];
		};
		vector<szMoudleStr>szMoudleVec;
		while (bRet){   
			szMoudleStr sms;
			sms.modBaseAddr = (ULONG32)mi.modBaseAddr;
			sms.modBaseSize = (DWORD)mi.modBaseSize;
			strcpy(sms.szModule, mi.szModule);
			szMoudleVec.push_back(sms);
			bRet = Module32Next(hSnapshot,&mi);
		}

		// 遍历线程
		while (Thread32Next(hThreadSnap, &te32)){
			if(te32.th32OwnerProcessID == process.th32ProcessID){
				HANDLE hThread = ::OpenThread (
					THREAD_ALL_ACCESS,		// 访问权限,THREAD_ALL_ACCESS :所有权限
					FALSE,					// 由此线程创建的进程不继承线程的句柄
					te32.th32ThreadID		// 线程 ID
					);
				if(hThread == NULL){
					cout << "线程打开失败 :" << GetLastError() << "process:" << process.szExeFile << process.th32ProcessID << endl;
					continue;
				}
				setlocale(LC_ALL,".ACP");
				HINSTANCE hNTDLL = ::GetModuleHandle("ntdll");	
				(FARPROC&)ZwQueryInformationThread  = ::GetProcAddress(hNTDLL,"ZwQueryInformationThread");
				PVOID startaddr;						// 用来接收线程入口地址
				ZwQueryInformationThread(
					hThread,							// 线程句柄
					ThreadQuerySetWin32StartAddress,	// 线程信息类型,ThreadQuerySetWin32StartAddress :线程入口地址
					&startaddr,							// 指向缓冲区的指针
					sizeof(startaddr),					// 缓冲区的大小
					NULL								
				);
				
				int allFlag = true;
				int WgFlag = 0;
				int dbgFlag = true;

				if(dbgFlag)cout << "startAddr :" <<  startaddr;
				for(int i = 0; i < szMoudleVec.size(); i++){
					if((ULONG32)startaddr >= szMoudleVec[i].modBaseAddr && (ULONG32)startaddr < szMoudleVec[i].modBaseAddr + szMoudleVec[i].modBaseSize){
						allFlag = false;
						if(dbgFlag){
							printf("///modname : %s ----", szMoudleVec[i].szModule);
							cout << hex << "为系统模块 ---modBaseAddr:" << szMoudleVec[i].modBaseAddr << " ,modEndAddr:" << szMoudleVec[i].modBaseAddr + szMoudleVec[i].modBaseSize << endl;
						}
					}else{
						WgFlag = i;
					}
				}
				if(allFlag == true){
					if(dbgFlag){

						printf("pid = %d不是系统模块%s", process.th32ProcessID, szMoudleVec[WgFlag].szModule);
						cout << hex << "///modBaseAddr:" << szMoudleVec[WgFlag].modBaseAddr << " ,modEndAddr:" << szMoudleVec[WgFlag].modBaseAddr + szMoudleVec[WgFlag].modBaseSize << endl;
					}
					return true;
				}
			}
		}
	}
    return false;

加油啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值