XueTr和天琊的“察看线程”里都能看到线程所属的模块,但是自己却一直想不出来如何实现。苦恼了很久,后来参考了倒霉蛋儿的一篇文章,使用的GetMappedFileNameA来实现的上述功能,但是我试了半天总是出错,vb6.exe直接挂掉了,于是只能放弃GetMappedFileNameA,后来我就想,有的线程函数一定是在模块里的,那么线程函数的地址一定大于模块的基址,小于(模块的基址+模块的大小),正好倒霉蛋儿的代码里有获取线程入口地址的方法,于是就有了办法,遍历模块,然后一个个进行上述判断,如果匹配就记录下该模块。
为了图方便,我使用了Tesla.Angela的HdEnumModules(因为LdrModule结构里的模块信息比较详细),写了个easy的函数获取线程所属模块,一共有三个参数,第一个是线程所属进程的句柄,第二个是线程句柄,第三个是线程线程入口函数的地址(传0自动获取),函数代码如下,各种声明就不贴了。。
Dim lPtr As Long
Dim pbi As PROCESS_BASIC_INFORMATION
Dim tPEB_LDR_DATA As PEB_LDR_DATA
Dim tLDR_MODULE As LDR_MODULE
Dim tBLDR_MODULE As LDR_MODULE
Dim tFLDR_MODULE As LDR_MODULE
Dim modPath As String * 260
'获得PEB
ZwQueryInformationProcess hProcess, ProcessBasicInformation, pbi, Len(pbi), 0
'获得线程的入口地址
If Not StartAddr Then
ZwQueryInformationThread hThread, ThreadQuerySetWin32StartAddress, ByVal VarPtr(StartAddr), Len(StartAddr), 0
End If
'PEB指针
lPtr = pbi.PebBaseAddress
'如果地址无误
If lPtr Then
'如果成功读取到数据
If Not ReadProcessMemory(hProcess, ByVal lPtr + 12, lPtr, &H4, 0&) = 0 Then
'找到链表头
ReadProcessMemory hProcess, ByVal lPtr, ByVal VarPtr(tPEB_LDR_DATA), Len(tPEB_LDR_DATA), 0
ReadProcessMemory hProcess, ByVal tPEB_LDR_DATA.InLoadOrderModuleList.Flink, ByVal VarPtr(tLDR_MODULE), Len(tLDR_MODULE), 0
'继续读取数据直到DLL基址为0
Do While tLDR_MODULE.BaseAddress <> 0
If StartAddr > tLDR_MODULE.BaseAddress And StartAddr < tLDR_MODULE.BaseAddress + tLDR_MODULE.SizeOfImage Then
GetModuleFileNameEx hProcess, tLDR_MODULE.BaseAddress, modPath, 260
FxGetThreadModuleFileName = modPath
Exit Function
End If
ReadProcessMemory hProcess, ByVal tLDR_MODULE.InLoadOrderModuleList.Flink, ByVal VarPtr(tLDR_MODULE), Len(tLDR_MODULE), 0
Loop
End If
End If
End Function