此模块可以搜索内存中存在的PE结构~~ 方便抓取内存中的PE文件。
Option Explicit
Private Const FILE_SHARE_READ = &H1
Private Const FILE_MAP_READ = 4
Private Const PAGE_READONLY = &H2
Private Const SYNCHRONIZE As Long = &H100000
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Type UNICODE_STRING
uLength As Integer
uMaximumLength As Integer
pBuffer(3) As Byte
End Type
Private Type SYSTEM_HANDLE
UniqueProcessId As Integer
CreatorBackTraceIndex As Integer
ObjectTypeIndex As Byte
HandleAttributes As Byte
HandleValue As Integer
pObject As Long
GrantedAccess As Long
End Type
Private Type SYSTEM_HANDLE_INFORMATION
uCount As Long
aSH() As SYSTEM_HANDLE
End Type
Private Type CLIENT_ID
UniqueProcess As Long
UniqueThread As Long
End Type
Private Enum SYSTEM_INFORMATION_CLASS
SystemBasicInformation
SystemProcessorInformation '// obsolete...delete
SystemPerformanceInformation
SystemTimeOfDayInformation
SystemPathInformation
SystemProcessInformation
SystemCallCountInformation
SystemDeviceInformation
SystemProcessorPerformanceInformation
SystemFlagsInformation
SystemCallTimeInformation
SystemModuleInformation
SystemLocksInformation
SystemStackTraceInformation
SystemPagedPoolInformation
SystemNonPagedPoolInformation
SystemHandleInformation
SystemObjectInformation
SystemPageFileInformation
SystemVdmInstemulInformation
SystemVdmBopInformation
SystemFileCacheInformation
SystemPoolTagInformation
SystemInterruptInformation
SystemDpcBehaviorInformation
SystemFullMemoryInformation
SystemLoadGdiDriverInformation
SystemUnloadGdiDriverInformation
SystemTimeAdjustmentInformation
SystemSummaryMemoryInformation
SystemMirrorMemoryInformation
SystemPerformanceTraceInformation
SystemObsolete0
SystemExceptionInformation
SystemCrashDumpStateInformation
SystemKernelDebuggerInformation
SystemContextSwitchInformation
SystemRegistryQuotaInformation
SystemExtendServiceTableInformation
SystemPrioritySeperation
SystemVerifierAddDriverInformation
SystemVerifierRemoveDriverInformation
SystemProcessorIdleInformation
SystemLegacyDriverInformation
SystemCurrentTimeZoneInformation
SystemLookasideInformation
SystemTimeSlipNotification
SystemSessionCreate
SystemSessionDetach
SystemSessionInformation
SystemRangeStartInformation
SystemVerifierInformation
SystemVerifierThunkExtend
SystemSessionProcessInformation
SystemLoadGdiDriverInSystemSpace
SystemNumaProcessorMap
SystemPrefetcherInformation
SystemExtendedProcessInformation
SystemRecommendedSharedDataAlignment
SystemComPlusPackage
SystemNumaAvailableMemory
SystemProcessorPowerInformation
SystemEmulationBasicInformation
SystemEmulationProcessorInformation
SystemExtendedHandleInformation
SystemLostDelayedWriteInformation
SystemBigPoolInformation
SystemSessionPoolTagInformation
SystemSessionMappedViewInformation
SystemHotpatchInformation
SystemObjectSecurityMode
SystemWatchdogTimerHandler
SystemWatchdogTimerInformation
SystemLogicalProcessorInformation
SystemWow64SharedInformation
SystemRegisterFirmwareTableInformationHandler
SystemFirmwareTableInformation
SystemModuleInformationEx
SystemVerifierTriageInformation
SystemSuperfetchInformation
SystemMemoryListInformation
SystemFileCacheInformationEx
MaxSystemInfoClass '// MaxSystemInfoClass should always be the last enum
End Enum
Private Enum PROCESSINFOCLASS
ProcessBasicInformation = 0
ProcessQuotaLimits
ProcessIoCounters
ProcessVmCounters
ProcessTimes
ProcessBasePriority
ProcessRaisePriority
ProcessDebugPort
ProcessExceptionPort
ProcessAccessToken
ProcessLdtInformation
ProcessLdtSize
ProcessDefaultHardErrorMode
ProcessIoPortHandlers
ProcessPooledUsageAndLimits
ProcessWorkingSetWatch
ProcessUserModeIOPL
ProcessEnableAlignmentFaultFixup
ProcessPriorityClass
ProcessWx86Information
ProcessHandleCount
ProcessAffinityMask
ProcessPriorityBoost
ProcessDeviceMap
ProcessSessionInformation
ProcessForegroundInformation
ProcessWow64Information
ProcessImageFileName
ProcessLUIDDeviceMapsEnabled
ProcessBreakOnTermination
ProcessDebugObjectHandle
ProcessDebugFlags
ProcessHandleTracing
ProcessIoPriority
ProcessExecuteFlags
ProcessResourceManagement
ProcessCookie
ProcessImageInformation
MaxProcessInfoClass
End Enum
Private Const STATUS_INFO_LENGTH_MISMATCH = &HC0000004
Private Type PROCESS_BASIC_INFORMATION
ExitStatus As Long 'NTSTATUS
PebBaseAddress As Long 'PPEB
AffinityMask As Long 'ULONG_PTR
BasePriority As Long 'KPRIORITY
UniqueProcessId As Long 'ULONG_PTR
InheritedFromUniqueProcessId As Long 'ULONG_PTR
End Type
Private Enum SE_OBJECT_TYPE
SE_UNKNOWN_OBJECT_TYPE = 0
SE_FILE_OBJECT
SE_SERVICE
SE_PRINTER
SE_REGISTRY_KEY
SE_LMSHARE
SE_KERNEL_OBJECT
SE_WINDOW_OBJECT
SE_DS_OBJECT
SE_DS_OBJECT_ALL
SE_PROVIDER_DEFINED_OBJECT
SE_WMIGUID_OBJECT
End Enum
Private Const ERROR_PARTIAL_COPY = 299
Private Declare Function NtQueryInformationProcess Lib "ntdll.dll" (ByVal ProcessHandle As Long, _
ByVal ProcessInformationClass As PROCESSINFOCLASS, _
ByVal ProcessInformation As Long, _
ByVal ProcessInformationLength As Long, _
ByRef ReturnLength As Long) As Long
'枚举Kernel Module函数
Private Declare Function NtQuerySystemInformation Lib "ntdll.dll" (ByVal SystemInformationClass As SYSTEM_INFORMATION_CLASS, _
ByVal pSystemInformation As Long, _
ByVal SystemInformationLength As Long, _
ByRef ReturnLength As Long) As Long
Private Declare Function NtDuplicateObject Lib "ntdll.dll" (ByVal SourceProcessHandle As Long, _
ByVal SourceHandle As Long, _
ByVal TargetProcessHandle As Long, _
ByRef TargetHandle As Long, _
ByVal DesiredAccess As Long, _
ByVal HandleAttributes As Long, _
ByVal Options As Long) As Long
Private Const DUPLICATE_CLOSE_SOURCE = &H1
Private Const DUPLICATE_SAME_ACCESS = &H2
Private Const DUPLICATE_SAME_ATTRIBUTES = &H4
Private Declare Function NtOpenProcess Lib "ntdll.dll" (ByRef ProcessHandle As Long, _
ByVal AccessMask As Long, _
ByRef ObjectAttributes As OBJECT_ATTRIBUTES, _
ByRef ClientID As CLIENT_ID) As Long
Private Type OBJECT_ATTRIBUTES
Length As Long
RootDirectory As Long
ObjectName As Long
Attributes As Long
SecurityDescriptor As Long
SecurityQualityOfService As Long
End Type
Private Type IO_STATUS_BLOCK
Status As Long
uInformation As Long
End Type
Private Const PROCESS_VM_READ = &H10
Private Const PROCESS_QUERY_INFORMATION As Long = (&H400)
Private Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)
Private Const PROCESS_DUP_HANDLE As Long = (&H40)
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function NtClose Lib "ntdll.dll" (ByVal ObjectHandle As Long) As Long
Private Declare Function ImageRvaToVa Lib "dbghelp" (ByRef NtHeaders As Any, Base As Any, ByVal Rva As Long, ByRef LastRvaSection As Any) As Long
Private Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" (ByVal hFile As Long, lpFileMappigAttributes As Any, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "kernel32" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long
Public Declare Function UnmapViewOfFile Lib "kernel32" (lpBaseAddress As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub RtlZeroMemory Lib "kernel32" (Destination As Any, ByVal Length As Long)
Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Enum ImageSignatureTypes
IMAGE_DOS_SIGNATURE = &H5A4D ''\\ MZ
IMAGE_OS2_SIGNATURE = &H454E ''\\ NE
IMAGE_OS2_SIGNATURE_LE = &H454C ''\\ LE
IMAGE_VXD_SIGNATURE = &H454C ''\\ LE
IMAGE_NT_SIGNATURE = &H4550 ''\\ PE00
End Enum
Private Type IMAGE_DOS_HEADER
Magic As Integer
cblp As Integer
cp As Integer
crlc As Integer
cparhdr As Integer
minalloc As Integer
maxalloc As Integer
ss As Integer
sp As Integer
csum As Integer
ip As Integer
cs As Integer
lfarlc As Integer
ovno As Integer
res(3) As Integer
oemid As Integer
oeminfo As Integer
res2(9) As Integer
lfanew As Long
End Type
Private Type IMAGE_FILE_HEADER
Machine As Integer
NumberOfSections As Integer
TimeDateStamp As Long
PointerToSymbolTable As Long
NumberOfSymbols As Long
SizeOfOtionalHeader As Integer
Characteristics As Integer '标志Dll
End Type
Private Type IMAGE_DATA_DIRECTORY
DataRVA As Long
DataSize As Long
End Type
Private Type IMAGE_OPTIONAL_HEADER
Magic As Integer
MajorLinkVer As Byte
MinorLinkVer As Byte
CodeSize As Long
InitDataSize As Long
unInitDataSize As Long
EntryPoint As Long
CodeBase As Long
DataBase As Long
ImageBase As Long
SectionAlignment As Long
FileAlignment As Long
MajorOSVer As Integer
MinorOSVer As Integer
MajorImageVer As Integer
MinorImageVer As Integer
MajorSSVer As Integer
MinorSSVer As Integer
Win32Ver As Long
ImageSize As Long
HeaderSize As Long
Checksum As Long
Subsystem As Integer
DLLChars As Integer
StackRes As Long
StackCommit As Long
HeapReserve As Long
HeapCommit As Long
LoaderFlags As Long
RVAsAndSizes As Long
DataEntries(15) As IMAGE_DATA_DIRECTORY
End Type
Private Type IMAGE_NT_HEADERS
Signature As Long
FileHeader As IMAGE_FILE_HEADER
OptionalHeader As IMAGE_OPTIONAL_HEADER
End Type
Private Type IMAGE_SECTION_HEADER
SectionName(7) As Byte
Address As Long
VirtualAddress As Long
SizeOfData As Long
PData As Long
PReloc As Long
PLineNums As Long
RelocCount As Integer
LineCount As Integer
Characteristics As Long
End Type
Private Type IMAGE_IMPORT_DESCRIPTOR
Characteristics As Long
TimeDateStamp As Long
ForwarderChain As Long
pName As Long
FirstThunk As Long
End Type
Private Type IMAGE_EXPORT_DIRECTORY
Characteristics As Long
TimeDateStamp As Long
MajorVersion As Integer
MinorVersion As Integer
pName As Long
Base As Long
NumberOfFunctions As Long
NumberOfNames As Long
AddressOfFunctions As Long
AddressOfNames As Long
AddressOfNameOrdinals As Long
End Type
Private Type IMAGE_THUNK_DATA32
AddressOfData As Long 'IMAGE_IMPORT_BY_NAME
End Type
Public Type MAP_INFO
hFile As Long
hMap As Long
End Type
'判断Nt系列函数是否调用成功
Private Function NT_SUCCESS(ByVal nStatus As Long) As Boolean
NT_SUCCESS = (nStatus >= 0)
End Function
'通过进程PID获取进程句柄此方法可以不躲过拦截NtOpenProcess方法获取进程句柄
Public Function GetHandleByProcessId(ByVal dwProcessId As Long) As Long
Dim ntStatus As Long
Dim objCid As CLIENT_ID
Dim objOa As OBJECT_ATTRIBUTES
Dim lngHandles As Long
Dim i As Long
Dim objBasic As PROCESS_BASIC_INFORMATION
Dim objInfo() As SYSTEM_HANDLE
Dim hProcessToDup As Long, hProcessHandle As Long
Dim bytBuffer() As Byte
Dim nSize As Long
nSize = 1
Do
ReDim bytBuffer(nSize)
ntStatus = NtQuerySystemInformation(SystemHandleInformation, VarPtr(bytBuffer(0)), nSize, 0&)
If (Not NT_SUCCESS(ntStatus)) Then
If (ntStatus <> STATUS_INFO_LENGTH_MISMATCH) Then
Erase bytBuffer
Exit Function
End If
Else
Exit Do
End If
nSize = nSize * 2
ReDim bytBuffer(nSize)
Loop
objOa.Length = Len(objOa)
CopyMemory lngHandles, bytBuffer(0), 4
ReDim objInfo(lngHandles - 1)
CopyMemory objInfo(0), bytBuffer(4), Len(objInfo(0)) * lngHandles
Erase bytBuffer
For i = 0 To lngHandles - 1
If objInfo(i).ObjectTypeIndex = 5 Then ' And objInfo(i).UniqueProcessId = dwProcessId Then
objCid.UniqueProcess = objInfo(i).UniqueProcessId
ntStatus = NtOpenProcess(hProcessToDup, PROCESS_DUP_HANDLE, objOa, objCid)
If (NT_SUCCESS(ntStatus)) Then
ntStatus = NtDuplicateObject(hProcessToDup, objInfo(i).HandleValue, -1, hProcessHandle, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ATTRIBUTES)
If (NT_SUCCESS(ntStatus)) Then
ntStatus = NtQueryInformationProcess(hProcessHandle, ProcessBasicInformation, VarPtr(objBasic), Len(objBasic), 0)
If (NT_SUCCESS(ntStatus)) Then
If (objBasic.UniqueProcessId = dwProcessId) Then
GetHandleByProcessId = hProcessHandle
NtClose hProcessToDup
Exit Function
End If
End If
End If
NtClose hProcessToDup
End If
End If
Next
End Function
Private Sub DumpMemFile(ByVal hProcess As Long, ByVal dwAddr As Long, pNtHeaders As IMAGE_NT_HEADERS, ByVal strDumpFile As String)
Dim dwImageSize As Long
Dim bytBuffer() As Byte
Dim hFile As Long
dwImageSize = pNtHeaders.OptionalHeader.ImageSize
ReDim bytBuffer(dwImageSize - 1)
If ReadProcessMemory(hProcess, ByVal dwAddr, bytBuffer(0), dwImageSize, ByVal 0&) Then
hFile = CreateFile(ByVal strDumpFile, ByVal &H40000000, 0, ByVal 0&, ByVal 4, ByVal 0&, ByVal 0&)
If hFile = -1 Then Exit Sub
Call WriteFile(hFile, bytBuffer(0), dwImageSize, dwImageSize, ByVal 0&)
NtClose hFile
Erase bytBuffer
End If
End Sub
Public Function ScanPeStruct(ByVal dwProcessId As Long) As Boolean
Dim ntStatus As Long
Dim objBasic As PROCESS_BASIC_INFORMATION
Dim objFlink As Long
Dim objPEB As Long, objLdr As Long
Dim objBaseAddress As Long
Dim bytBuffer() As Byte
Dim strModuleName As String, objName As Long
Dim objCid As CLIENT_ID
Dim objOa As OBJECT_ATTRIBUTES
Dim hProcess As Long
Dim lngRet As Long
Dim pNTHeader As IMAGE_NT_HEADERS
Dim pDosHear As IMAGE_DOS_HEADER
Dim lngImageSize As Long, i As Long, dwScanBase As Long
Dim dwStartAddr As Long
objOa.Length = Len(objOa)
objCid.UniqueProcess = dwProcessId
ntStatus = NtOpenProcess(hProcess, PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, objOa, objCid)
If hProcess = 0 Then
hProcess = GetHandleByProcessId(dwProcessId)
If hProcess = 0 Then Exit Function
End If
ntStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, VarPtr(objBasic), Len(objBasic), ByVal 0&)
If (NT_SUCCESS(ntStatus)) Then
objPEB = objBasic.PebBaseAddress
lngRet = ReadProcessMemory(hProcess, ByVal objPEB + &HC, objLdr, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objLdr + &HC, objFlink, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objFlink + &H18, objBaseAddress, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
If objBaseAddress > 0 Then
lngRet = ReadProcessMemory(hProcess, ByVal objBaseAddress, pDosHear, LenB(pDosHear), ByVal 0&)
If lngRet = 0 Then GoTo RET
If pDosHear.Magic <> &H5A4D Then If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objBaseAddress + pDosHear.lfanew, pNTHeader, LenB(pNTHeader), ByVal 0&)
If lngRet = 0 Then GoTo RET
If pNTHeader.Signature <> IMAGE_NT_SIGNATURE Then GoTo RET
lngImageSize = pNTHeader.OptionalHeader.ImageSize
ReDim bytBuffer(lngImageSize - 1)
lngRet = ReadProcessMemory(hProcess, ByVal objBaseAddress, bytBuffer(0), lngImageSize, ByVal 0&)
If lngRet = 0 Then GoTo RET
dwStartAddr = pNTHeader.OptionalHeader.DataEntries(2).DataRVA
If dwStartAddr = 0 Then dwStartAddr = 1024
RtlZeroMemory pDosHear, LenB(pDosHear)
RtlZeroMemory pNTHeader, LenB(pNTHeader)
For i = dwStartAddr To lngImageSize - 1024
If bytBuffer(i) = Asc("M") And bytBuffer(i + 1) = Asc("Z") Then
CopyMemory pDosHear, bytBuffer(i), LenB(pDosHear)
If pDosHear.Magic = &H5A4D Then
If Abs(pDosHear.lfanew) < lngImageSize - 1024 Then
CopyMemory pNTHeader, bytBuffer(i + pDosHear.lfanew), LenB(pNTHeader)
If pNTHeader.Signature = IMAGE_NT_SIGNATURE Then
frmMain.List1.AddItem "地址是:" & Hex(objBaseAddress + i) & "发现PE结构"
If objBaseAddress + i <> objBaseAddress Then
DumpMemFile hProcess, objBaseAddress + i, pNTHeader, App.Path & "\" & Hex(objBaseAddress + i)
dwStartAddr = pNTHeader.OptionalHeader.DataEntries(2).DataRVA
If dwStartAddr = 0 Then dwStartAddr = 1024
i = i + dwStartAddr
End If
End If
RtlZeroMemory pNTHeader, LenB(pNTHeader)
End If
End If
RtlZeroMemory pDosHear, LenB(pDosHear)
End If
Next
End If
End If
RET:
If hProcess Then NtClose hProcess
Erase bytBuffer
If lngRet = 1 Then ScanPeStruct = True
End Function
Public Function DumpMainModuleFile(ByVal dwProcessId As Long) As Boolean
Dim ntStatus As Long
Dim objBasic As PROCESS_BASIC_INFORMATION
Dim objFlink As Long
Dim objPEB As Long, objLdr As Long
Dim objBaseAddress As Long
Dim bytBuffer() As Byte
Dim strModuleName As String, objName As Long
Dim objCid As CLIENT_ID
Dim objOa As OBJECT_ATTRIBUTES
Dim hProcess As Long
Dim lngRet As Long
Dim pNTHeader As IMAGE_NT_HEADERS
Dim pDosHear As IMAGE_DOS_HEADER
Dim pSections() As IMAGE_SECTION_HEADER
Dim hFile As Long, dwWrites As Long
Dim dwWriteSize As Long
objOa.Length = Len(objOa)
objCid.UniqueProcess = dwProcessId
ntStatus = NtOpenProcess(hProcess, PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, objOa, objCid)
If hProcess = 0 Then
hProcess = GetHandleByProcessId(dwProcessId)
If hProcess = 0 Then Exit Function
End If
ntStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, VarPtr(objBasic), Len(objBasic), ByVal 0&)
If (NT_SUCCESS(ntStatus)) Then
objPEB = objBasic.PebBaseAddress
lngRet = ReadProcessMemory(hProcess, ByVal objPEB + &HC, objLdr, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objLdr + &HC, objFlink, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objFlink + &H18, objBaseAddress, 4, ByVal 0&)
If lngRet = 0 Then GoTo RET
If objBaseAddress > 0 Then
lngRet = ReadProcessMemory(hProcess, ByVal objBaseAddress, pDosHear, LenB(pDosHear), ByVal 0&)
If lngRet = 0 Then GoTo RET
If pDosHear.Magic <> &H5A4D Then If lngRet = 0 Then GoTo RET
lngRet = ReadProcessMemory(hProcess, ByVal objBaseAddress + pDosHear.lfanew, pNTHeader, LenB(pNTHeader), ByVal 0&)
If lngRet = 0 Then GoTo RET
If pNTHeader.Signature <> IMAGE_NT_SIGNATURE Then GoTo RET
DumpMemFile hProcess, objBaseAddress, pNTHeader, App.Path & "\" & Hex(objBaseAddress)
End If
End If
RET:
If hProcess Then NtClose hProcess
Erase bytBuffer
If lngRet = 1 Then DumpMainModuleFile = True
End Function