|
本帖最后由 tangptr@126.com 于 2015-10-10 22:09 编辑
首先先说一下为什么仅支持XP,因为这段纯VB的代码使用了ZwSystemDebugControl,因此只能支持XP。
如果我们要用DKOM实现取得路径,势必要取得EPROCESS,而Ring3下取得EPROCESS只能通过查询句柄的方式,故我们构造函数ZwLookupProcessByProcessId来实现PsLookupProcessByProcessId的功能,代码如下
- Public Sub ZwLookupProcessByProcessId(ByVal ProcessId As Long, ByRef Process As Long)
- Dim st As Long
- Dim PID As Long
- Dim NumOfHandle As Long
- Dim i As Long
- st = 0
- Dim bytBuf() As Byte
- Dim arySize As Long: arySize = 1
- Do
- ReDim bytBuf(arySize)
- st = ZwQuerySystemInformation(SystemHandleInformation, VarPtr(bytBuf(0)), arySize, 0&)
- If (Not NT_SUCCESS(st)) Then
- If (st <> STATUS_INFO_LENGTH_MISMATCH) Then
- Erase bytBuf
- Exit Sub
- End If
- Else
- Exit Do
- End If
- arySize = arySize * 2
- ReDim bytBuf(arySize)
- Loop
- NumOfHandle = 0
- Call CopyMemory(VarPtr(NumOfHandle), VarPtr(bytBuf(0)), Len(NumOfHandle))
- Dim h_info() As SYSTEM_HANDLE_TABLE_ENTRY_INFO
- ReDim h_info(NumOfHandle)
- Call CopyMemory(VarPtr(h_info(0)), VarPtr(bytBuf(0)) + Len(NumOfHandle), Len(h_info(0)) * NumOfHandle)
- For i = LBound(h_info) To UBound(h_info)
- With h_info(i)
- ReadKernelMemory VarPtr(PID), .pObject + &H84, 4
- If PID = ProcessId And .ObjectTypeIndex = 5 Then
- Process = .pObject
- End If
- End With
- Next
- End Sub
复制代码
解决了EPROCESS的问题,接下来便是找到存储路径的位置,首先先查看EPROCESS的结构
注意偏移+0x1f4的位置,这是个嵌入EPROCESS的SE_AUDIT_PROCESS_CREATION_INFO结构体,这个结构体很简单,只包含一个指针,指向OBJECT_NAME_INFORMATION,这个结构体也很简单,只包含一个嵌入的UNICODE_STRING,结构查看结果如下:
- lkd> dt _SE_AUDIT_PROCESS_CREATION_INFO 864b6f94
- nt!_SE_AUDIT_PROCESS_CREATION_INFO
- +0x000 ImageFileName : 0x85dec4a8 _OBJECT_NAME_INFORMATION
- lkd> dt _OBJECT_NAME_INFORMATION 85dec4a8
- nt!_OBJECT_NAME_INFORMATION
- +0x000 Name : _UNICODE_STRING "\Device\HarddiskVolume1\Program Files\Microsoft Visual Studio\VB98\VB6.EXE"
复制代码
大家可以看到,这个路径是NT风格的,至于如何从NT风格转换到DOS风格,Tesla.Angela发表过文章《[抄袭]发个兼容R3/R0的NtPathToDosPath+DosPathToNtPath(C语言版|A+W)》,其链接是http://www.m5home.com/bbs/thread-7622-1-1.html可以看出其根本原理是用Win32API函数QueryDosDevice函数从A枚举到Z,看看哪个符合NT路径,于是代码就很简单了,如下
- Public Sub NtPathToDosPath(ByVal NtPath As String, ByRef DosPath As String)
- Dim i As Long
- Dim DosDevice As String
- Dim MyNtPath As String
- MyNtPath = Space(255)
- For i = 65 To 26 + 65 Step 1
- DosDevice = Chr(i) & ":"
- If QueryDosDevice(DosDevice, MyNtPath, 64) Then
- If Left(MyNtPath, Len(NtPath)) = NtPath Then
- DosPath = DosDevice
- Exit Sub
- End If
- End If
- Next i
- End Sub
复制代码
接下来就要从中取得UNICODE_STRING并根据UNICODE_STRING->Buffer取得字符串,代码如下
- Public Sub GetProcessImagePath(ByVal Process As Long, ByRef FilePath As String)
- Dim ObjName As Long
- Dim UniName As UNICODE_STRING
- Dim MyBuff() As Integer
- Dim TmpPath As String
- Dim NtDev As String, DosDev As String
- Dim FileName As String
- Dim i As Long
- ReadKernelMemory VarPtr(ObjName), Process + &H1F4, 4
- ReadKernelMemory VarPtr(UniName), ObjName, 8
- ReDim MyBuff(UniName.Length / 2 - 1)
- ReadKernelMemory VarPtr(MyBuff(0)), UniName.pBuffer, UniName.Length
- For i = 0 To UniName.Length / 2 - 1
- TmpPath = TmpPath & ChrW(MyBuff(i))
- Next i
- SplitPath TmpPath, NtDev, FileName
- NtPathToDosPath NtDev, DosDev
- FilePath = DosDev & "" & FileName
- End Sub
复制代码
效果很不错,即便是带有进程保护的软件依旧能取得路径,比如Call Hook NtOpenProcess->ObOpenObjectByPointer的PCHunter。而且即便有汉字也能正确取得。如图所示:
Demo
只要修改硬编码,并编写一个读写内核内存的驱动程序,就可以通用于32位NT系列。
p.s:假设Hovi.Delphic还更新UTM4XP的话,强烈建议修改掉其获取进程路径的方式。改成我这样的{:soso_e113:} |
评分
-
查看全部评分
|