对Windows内核空间操作的一些说明
作者:ZwelL
首先对被我误导的人说声对不起了。我在论坛中发的那篇贴(用户态隐藏进程的通用版本)真是乱七八糟(-_-我也是受害者)。在XP和WINDOWS 2003中用那种方法都是行不通的,而且在20043中的偏移也是错的。这里我先把XPSP2和2003中的EPROCESS整理出来给大家看一下:
typedef struct _EPROCESS_2K3
{
/*+0x000*/ KPROCESS_2K3 Pcb;
/*+0x06c*/ EX_PUSH_LOCK ProcessLock;
/*+0x070*/ LARGE_INTEGER CreateTime;
/*+0x078*/ LARGE_INTEGER ExitTime;
/*+0x080*/ EX_RUNDOWN_REF RundownProtect;
/*+0x084*/ PVOID UniqueProcessId;
/*+0x088*/ LIST_ENTRY ActiveProcessLinks;
/*+0x090*/ ULONG QuotaUsage[3];
/*+0x09c*/ ULONG QuotaPeak[3];
/*+0x0a8*/ ULONG CommitCharge;
/*+0x0ac*/ ULONG PeakVirtualSize;
/*+0x0b0*/ ULONG VirtualSize;
/*+0x0b4*/ LIST_ENTRY SessionProcessLinks;
/*+0x0bc*/ PVOID DebugPort;
/*+0x0c0*/ PVOID ExceptionPort;
/*+0x0c4*/ PHANDLE_TABLE ObjectTable;
/*+0x0c8*/ EX_FAST_REF Token;
/*+0x0cc*/ ULONG WorkingSetPage;
/*+0x0d0*/ KGUARDED_MUTEX AddressCreationLock;
/*+0x0f0*/ KSPIN_LOCK HyperSpaceLock;
/*+0x0f4*/ PETHREAD_2K3 ForkInProgress;
/*+0x0f8*/ ULONG HardwareTrigger;
/*+0x0fc*/ PMM_AVL_TABLE PhysicalVadRoot;
/*+0x100*/ PVOID CloneRoot;
/*+0x104*/ ULONG NumberOfPrivatePages;
/*+0x108*/ ULONG NumberOfLockedPages;
/*+0x10c*/ PVOID Win32Process;
/*+0x110*/ PEJOB Job;
/*+0x114*/ PSECTION_OBJECT SectionObject;
/*+0x118*/ PVOID SectionBaseAddress;
/*+0x11c*/ PEPROCESS_QUOTA_BLOCK QuotaBlock;
/*+0x120*/ PPAGEFAULT_HISTORY WorkingSetWatch;
/*+0x124*/ PVOID Win32WindowStation;
/*+0x128*/ PVOID InheritedFromUniqueProcessId;
/*+0x12c*/ PVOID LdtInformation;
/*+0x130*/ PVOID VadFreeHint;
/*+0x134*/ PVOID VdmObjects;
/*+0x138*/ PVOID DeviceMap;
/*+0x13c*/ PVOID Spare0[3];
union {
/*+0x148*/HARDWARE_PTE PageDirectoryPte;
/*+0x148*/ULONGLONG Filler;
};
/*+0x150*/ PVOID Session;
/*+0x154*/ UCHAR ImageFileName[16];
/*+0x164*/ LIST_ENTRY JobLinks;
/*+0x16c*/ PVOID LockedPagesList;
/*+0x170*/ LIST_ENTRY ThreadListHead;
/*+0x178*/ PVOID SecurityPort;
/*+0x17c*/ PVOID PaeTop;
/*+0x180*/ ULONG ActiveThreads;
/*+0x184*/ ULONG GrantedAccess;
/*+0x188*/ ULONG DefaultHardErrorProcessing;
/*+0x18c*/ NTSTATUS LastThreadExitStatus;
/*+0x190*/ PPEB Peb;
/*+0x194*/ EX_FAST_REF PrefetchTrace;
/*+0x198*/ LARGE_INTEGER ReadOperationCount;
/*+0x1a0*/ LARGE_INTEGER WriteOperationCount;
/*+0x1a8*/ LARGE_INTEGER OtherOperationCount;
/*+0x1b0*/ LARGE_INTEGER ReadTransferCount;
/*+0x1b8*/ LARGE_INTEGER WriteTransferCount;
/*+0x1c0*/ LARGE_INTEGER OtherTransferCount;
/*+0x1c8*/ ULONG CommitChargeLimit;
/*+0x1cc*/ ULONG CommitChargePeak;
/*+0x1d0*/ PVOID AweInfo;
/*+0x1d4*/ SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo;
/*+0x1d8*/ MMSUPPORT_2K3 Vm;
/*+0x238*/ LIST_ENTRY MmProcessLinks;
/*+0x240*/ ULONG ModifiedPageCount;
/*+0x244*/ ULONG JobStatus;
union{
/*+0x248*/ ULONG Flags;
struct{
/*+0x248*/ ULONG CreateReported : 1;
/*+0x248*/ ULONG NoDebugInherit : 1;
/*+0x248*/ ULONG ProcessExiting : 1;
/*+0x248*/ ULONG ProcessDelete : 1;
/*+0x248*/ ULONG Wow64SplitPages : 1;
/*+0x248*/ ULONG VmDeleted : 1;
/*+0x248*/ ULONG OutswapEnabled : 1;
/*+0x248*/ ULONG Outswapped : 1;
/*+0x248*/ ULONG ForkFailed : 1;
/*+0x248*/ ULONG Wow64VaSpace4Gb : 1;
/*+0x248*/ ULONG AddressSpaceInitialized :2;
/*+0x248*/ ULONG SetTimerResolution : 1;
/*+0x248*/ ULONG BreakOnTermination : 1;
/*+0x248*/ ULONG SessionCreationUnderway :1;
/*+0x248*/ ULONG WriteWatch : 1;
/*+0x248*/ ULONG ProcessInSession : 1;
/*+0x248*/ ULONG OverrideAddressSpace : 1;
/*+0x248*/ ULONG HasAddressSpace : 1;
/*+0x248*/ ULONG LaunchPrefetched : 1;
/*+0x248*/ ULONG InjectInpageErrors : 1;
/*+0x248*/ ULONG VmTopDown : 1;
/*+0x248*/ ULONG ImageNotifyDone : 1;
/*+0x248*/ ULONG PdeUpdateNeeded : 1;
/*+0x248*/ ULONG VdmAllowed : 1;
/*+0x248*/ ULONG Unused : 7;
};
};
/*+0x24c*/ NTSTATUS ExitStatus;
/*+0x250*/ USHORT NextPageColor;
union {
struct {
/*+0x252*/ UCHAR SubSystemMinorVersion;
/*+0x253*/ UCHAR SubSystemMajorVersion;
};
/*+0x252*/ USHORT SubSystemVersion;
};
/*+0x254*/ UCHAR PriorityClass;
/*+0x258*/ MM_AVL_TABLE VadRoot;
} EPROCESS_2K3, *PEPROCESS_2K3;
typedef struct _EPROCESS_XP_SP2
{
/*+0x000*/_KPROCESS_XP Pcb;
/*+0x06c*/_EX_PUSH_LOCK ProcessLock;
/*+0x070*/_LARGE_INTEGER CreateTime;
/*+0x078*/_LARGE_INTEGER ExitTime;
/*+0x080*/_EX_RUNDOWN_REF RundownProtect;
/*+0x084*/PVOID UniqueProcessId;
/*+0x088*/_LIST_ENTRY ActiveProcessLinks;
/*+0x090*/ULONG QuotaUsage[3];
/*+0x09c*/ULONG QuotaPeak[3];
/*+0x0a8*/ULONG CommitCharge;
/*+0x0ac*/ULONG PeakVirtualSize;
/*+0x0b0*/ULONG VirtualSize;
/*+0x0b4*/_LIST_ENTRY SessionProcessLinks;
/*+0x0bc*/PVOID DebugPort;
/*+0x0c0*/PVOID ExceptionPort;
/*+0x0c4*/PHANDLE_TABLE ObjectTable;
/*+0x0c8*/_EX_FAST_REF Token;
/*+0x0cc*/_FAST_MUTEX WorkingSetLock;
/*+0x0ec*/ULONG WorkingSetPage;
/*+0x0f0*/_FAST_MUTEX AddressCreationLock;
/*+0x110*/ULONG HyperSpaceLock;
/*+0x114*/PETHREAD ForkInProgress;
/*+0x118*/ULONG HardwareTrigger;
/*+0x11c*/PVOID VadRoot;
/*+0x120*/PVOID VadHint;
/*+0x124*/PVOID CloneRoot;
/*+0x128*/ULONG NumberOfPrivatePages;
/*+0x12c*/ULONG NumberOfLockedPages;
/*+0x130*/PVOID Win32Process;
/*+0x134*/PEJOB Job;
/*+0x138*/PVOID SectionObject;
/*+0x13c*/PVOID SectionBaseAddress;
/*+0x140*/PEPROCESS_QUOTA_BLOCK QuotaBlock;
/*+0x144*/PPAGEFAULT_HISTORY WorkingSetWatch;
/*+0x148*/PVOID Win32WindowStation;
/*+0x14c*/PVOID InheritedFromUniqueProcessId;
/*+0x150*/PVOID LdtInformation;
/*+0x154*/PVOID VadFreeHint;
/*+0x158*/PVOID VdmObjects;
/*+0x15c*/PVOID DeviceMap;
/*+0x160*/_LIST_ENTRY PhysicalVadList;
/*+0x168*/_HARDWARE_PTE PageDirectoryPte;
/*+0x168*/Uint8B Filler;
/*+0x170*/PVOID Session;
/*+0x174*/UChar ImageFileName[16];
/*+0x184*/_LIST_ENTRY JobLinks;
/*+0x18c*/PVOID LockedPagesList;
/*+0x190*/_LIST_ENTRY ThreadListHead;
/*+0x198*/PVOID SecurityPort;
/*+0x19c*/PVOID PaeTop;
/*+0x1a0*/ULONG ActiveThreads;
/*+0x1a4*/ULONG GrantedAccess;
/*+0x1a8*/ULONG DefaultHardErrorProcessing;
/*+0x1ac*/Int4B LastThreadExitStatus;
/*+0x1b0*/Ptr32 _PEB Peb;
/*+0x1b4*/_EX_FAST_REF PrefetchTrace;
/*+0x1b8*/_LARGE_INTEGER ReadOperationCount;
/*+0x1c0*/_LARGE_INTEGER WriteOperationCount;
/*+0x1c8*/_LARGE_INTEGER OtherOperationCount;
/*+0x1d0*/_LARGE_INTEGER ReadTransferCount;
/*+0x1d8*/_LARGE_INTEGER WriteTransferCount;
/*+0x1e0*/_LARGE_INTEGER OtherTransferCount;
/*+0x1e8*/ULONG CommitChargeLimit;
/*+0x1ec*/ULONG CommitChargePeak;
/*+0x1f0*/PVOID AweInfo;
/*+0x1f4*/_SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo;
/*+0x1f8*/_MMSUPPORT Vm;
/*+0x238*/ULONG LastFaultCount;
/*+0x23c*/ULONG ModifiedPageCount;
/*+0x240*/ULONG NumberOfVads;
/*+0x244*/ULONG JobStatus;
/*+0x248*/ULONG Flags;
/*+0x248*/ULONG CreateReported : 1;
/*+0x248*/ULONG NoDebugInherit : 1;
/*+0x248*/ULONG ProcessExiting : 1;
/*+0x248*/ULONG ProcessDelete : 1;
/*+0x248*/ULONG Wow64SplitPages : 1;
/*+0x248*/ULONG VmDeleted : 1;
/*+0x248*/ULONG OutswapEnabled : 1;
/*+0x248*/ULONG Outswapped : 1;
/*+0x248*/ULONG ForkFailed : 1;
/*+0x248*/ULONG HasPhysicalVad : 1;
/*+0x248*/ULONG AddressSpaceInitialized : 2;
/*+0x248*/ULONG SetTimerResolution : 1;
/*+0x248*/ULONG BreakOnTermination : 1;
/*+0x248*/ULONG SessionCreationUnderway : 1;
/*+0x248*/ULONG WriteWatch : 1;
/*+0x248*/ULONG ProcessInSession : 1;
/*+0x248*/ULONG OverrideAddressSpace : 1;
/*+0x248*/ULONG HasAddressSpace : 1;
/*+0x248*/ULONG LaunchPrefetched : 1;
/*+0x248*/ULONG InjectInpageErrors : 1;
/*+0x248*/ULONG VmTopDown : 1;
/*+0x248*/ULONG Unused3 : 1;
/*+0x248*/ULONG Unused4 : 1;
/*+0x248*/ULONG VdmAllowed : 1;
/*+0x248*/ULONG Unused : 5;
/*+0x248*/ULONG Unused1 : 1;
/*+0x248*/ULONG Unused2 : 1;
/*+0x24c*/Int4B ExitStatus;
/*+0x250*/Uint2B NextPageColor;
/*+0x252*/UChar SubSystemMinorVersion;
/*+0x253*/UChar SubSystemMajorVersion;
/*+0x252*/Uint2B SubSystemVersion;
/*+0x254*/UChar PriorityClass;
/*+0x255*/UChar WorkingSetAcquiredUnsafe;
/*+0x258*/ULONG Cookie;
}EPROCESS_XP_SP2, *PEPROCESS_XP_SP2
关于如何在xp和2003中读写内核空间,TK大哥已经说的很清楚了,用ZwSystemDebugControl函数的8,9调用号就可以了。
这里给大家一个写的示例程序,大家改一下放到程序中,再做一下系统的判断就可以达到通用性了。
/*
Write data in kernel POC
Author:ZwelL
Idea from:TK
*/
#include <windows.h>
#include <Aclapi.h>
#include <stdio.h>
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
typedef LONG NTSTATUS;
typedef struct _MEMORY_CHUNKS {
ULONG Address;
PVOID Data;
ULONG Length;
}MEMORY_CHUNKS, *PMEMORY_CHUNKS;
typedef NTSTATUS (NTAPI * PZwSystemDebugControl) (
int ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
HMODULE g_hNtDLL = NULL;
PZwSystemDebugControl ZwSystemDebugControl = NULL;
BOOL InitNTDLL()
{
g_hNtDLL = LoadLibrary( "ntdll.dll" );
if ( !g_hNtDLL )
{
return FALSE;
}
ZwSystemDebugControl =
(PZwSystemDebugControl)GetProcAddress (g_hNtDLL, "ZwSystemDebugControl");
return TRUE;
}
VOID CloseNTDLL()
{
if(g_hNtDLL != NULL)
{
FreeLibrary(g_hNtDLL);
}
}
BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;
CloseHandle (hToken);
return rv;
}
int main(int argc, char **argv)
{
if (InitNTDLL())
{
EnablePrivilege(SE_DEBUG_NAME);
MEMORY_CHUNKS QueryBuff;
ULONG ReturnLength;
char *Buff= "x11x11x11x11";
QueryBuff.Address = (ULONG)0x804ed5cc; //在2003中是第一个服务调用号的函数指针,指向80592290
//大家可以改成链表的地址
QueryBuff.Data = Buff;
QueryBuff.Length = 0x4;
ZwSystemDebugControl
(
0x9,
&QueryBuff,
sizeof(MEMORY_CHUNKS), //必须是0x0C
NULL,
0,
&ReturnLength
);
CloseNTDLL();
}
return 0;
}
这里我还对TK大哥在04峰会上讲的内容做了验证,发现SessionProcessLinks在XP和2003中都是可以用来权举进程的,但是在2000中都为0x00000000,
也就是说,在2000中不能通过它进行进程检查了,只能通过WorkingSetExpansionLinks来权举进程。这里TK大哥也没做说明,前面一直没怀疑过TK大哥的准确性,
花了很长时间去执行,都没成功,用WINDBG一看就出来了。哎,看来什么事还得自己验证一下啊。5555。。。下面是对TK大哥讲的内容的实现代码:
/*
用ring3代码枚举Windows进程的演示代码
Enum process in ring3 POC
Author:ZwelL
Idea from:TK
*/
#include <windows.h>
#include <Aclapi.h>
#include <stdio.h>
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define BASEADDRLEN 10
#define W2K_SESSION_LST_OFFSET 0X118
#define WXP_SESSION_LST_OFFSET 0X0b4
#define W2K3_SESSION_LST_OFFSET 0X0b4
#define W2K_ACTIVE_LST_OFFSET 0X0a0
#define WXP_ACTIVE_LST_OFFSET 0X088
#define W2K3_ACTIVE_LST_OFFSET 0X088
#define W2K_SESSION_TO_NAME_OFFSET 0X1fc-0x118
#define WXP_SESSION_TO_NAME_OFFSET 0X0C0
#define W2K3_SESSION_TO_NAME_OFFSET 0X154-0XB4
#define W2K_ACTIVE_LST_TO_NAME_OFFSET W2K_SESSION_TO_NAME_OFFSET+W2K_SESSION_LST_OFFSET-W2K_ACTIVE_LST_OFFSET
#define WXP_ACTIVE_LST_TO_NAME_OFFSET WXP_SESSION_TO_NAME_OFFSET+WXP_SESSION_LST_OFFSET-WXP_ACTIVE_LST_OFFSET
#define W2K3_ACTIVE_LST_TO_NAME_OFFSET W2K3_SESSION_TO_NAME_OFFSET+W2K3_SESSION_LST_OFFSET-W2K3_ACTIVE_LST_OFFSET
#define W2K_WORK_LST_OFFSET 0X0f4
#define W2K_IMAGE_NAME_OFFSET 0X1fc
typedef LONG NTSTATUS;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _MEMORY_CHUNKS {
ULONG Address;
PVOID Data;
ULONG Length;
}MEMORY_CHUNKS, *PMEMORY_CHUNKS;
typedef enum _SYSDBG_COMMAND {
//以下5个在Windows NT各个版本上都有
SysDbgGetTraceInformation = 1,
SysDbgSetInternalBreakpoint = 2,
SysDbgSetSpecialCall = 3,
SysDbgClearSpecialCalls = 4,
SysDbgQuerySpecialCalls = 5,
// 以下是NT 5.1 新增的
SysDbgDbgBreakPointWithStatus = 6,
//获取KdVersionBlock
SysDbgSysGetVersion = 7,
//从内核空间拷贝到用户空间,或者从用户空间拷贝到用户空间
//但是不能从用户空间拷贝到内核空间
SysDbgCopyMemoryChunks_0 = 8,
//SysDbgReadVirtualMemory = 8,
//从用户空间拷贝到内核空间,或者从用户空间拷贝到用户空间
//但是不能从内核空间拷贝到用户空间
SysDbgCopyMemoryChunks_1 = 9,
//SysDbgWriteVirtualMemory = 9,
//从物理地址拷贝到用户空间,不能写到内核空间
SysDbgCopyMemoryChunks_2 = 10,
//SysDbgReadVirtualMemory = 10,
//从用户空间拷贝到物理地址,不能读取内核空间
SysDbgCopyMemoryChunks_3 = 11,
//SysDbgWriteVirtualMemory = 11,
//读写处理器相关控制块
SysDbgSysReadControlSpace = 12,
SysDbgSysWriteControlSpace = 13,
//读写端口
SysDbgSysReadIoSpace = 14,
SysDbgSysWriteIoSpace = 15,
//分别调用RDMSR@4和_WRMSR@12
SysDbgSysReadMsr = 16,
SysDbgSysWriteMsr = 17,
//读写总线数据
SysDbgSysReadBusData = 18,
SysDbgSysWriteBusData = 19,
SysDbgSysCheckLowMemory = 20,
// 以下是NT 5.2 新增的
//分别调用_KdEnableDebugger@0和_KdDisableDebugger@0
SysDbgEnableDebugger = 21,
SysDbgDisableDebugger = 22,
//获取和设置一些调试相关的变量
SysDbgGetAutoEnableOnEvent = 23,
SysDbgSetAutoEnableOnEvent = 24,
SysDbgGetPitchDebugger = 25,
SysDbgSetDbgPrintBufferSize = 26,
SysDbgGetIgnoreUmExceptions = 27,
SysDbgSetIgnoreUmExceptions = 28
} SYSDBG_COMMAND, *PSYSDBG_COMMAND;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemLookasideInformation,
SystemSetTimeSlipEvent,
SystemCreateSession,
SystemDeleteSession,
SystemInvalidInfoClass4,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation
} SYSTEM_INFORMATION_CLASS;
typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION )
(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
typedef NTSTATUS (CALLBACK* ZWOPENSECTION)(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
typedef VOID (CALLBACK* RTLINITUNICODESTRING)(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
typedef NTSTATUS (NTAPI * PZwSystemDebugControl) (
SYSDBG_COMMAND ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
RTLINITUNICODESTRING RtlInitUnicodeString;
ZWOPENSECTION ZwOpenSection;
HMODULE g_hNtDLL = NULL;
PVOID g_pMapPhysicalMemory = NULL;
HANDLE g_hMPM = NULL;
PZwSystemDebugControl ZwSystemDebugControl = NULL;
BOOL InitNTDLL()
{
g_hNtDLL = LoadLibrary( "ntdll.dll" );
if ( !g_hNtDLL )
{
return FALSE;
}
RtlInitUnicodeString =
(RTLINITUNICODESTRING)GetProcAddress( g_hNtDLL, "RtlInitUnicodeString");
ZwOpenSection =
(ZWOPENSECTION)GetProcAddress( g_hNtDLL, "ZwOpenSection");
ZwQuerySystemInformation =
( ZWQUERYSYSTEMINFORMATION )GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation" );
ZwSystemDebugControl =
(PZwSystemDebugControl)GetProcAddress (g_hNtDLL, "ZwSystemDebugControl");
return TRUE;
}
VOID CloseNTDLL()
{
if(g_hNtDLL != NULL)
{
FreeLibrary(g_hNtDLL);
}
}
HANDLE OpenPhysicalMemory()
{
NTSTATUS status;
UNICODE_STRING physmemString;
OBJECT_ATTRIBUTES attributes;
RtlInitUnicodeString( &physmemString, L"\\Device\\PhysicalMemory" );
attributes.Length = sizeof(OBJECT_ATTRIBUTES);
attributes.RootDirectory = NULL;
attributes.ObjectName = &physmemString;
attributes.Attributes = 0;
attributes.SecurityDescriptor = NULL;
attributes.SecurityQualityOfService = NULL;
status = ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes);
if(status == STATUS_ACCESS_DENIED){
status = ZwOpenSection(&g_hMPM,READ_CONTROL|WRITE_DAC,&attributes);
//SetPhyscialMemorySectionCanBeWrited(g_hMPM);
CloseHandle(g_hMPM);
status =ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes);
}
if( !NT_SUCCESS( status ))
{
return NULL;
}
g_pMapPhysicalMemory = MapViewOfFile(
g_hMPM,
4,
0,
0x30000,
0x1000);
if( g_pMapPhysicalMemory == NULL )
{
return NULL;
}
return g_hMPM;
}
PVOID LinearToPhys(PULONG BaseAddress,PVOID addr)
{
ULONG VAddr=(ULONG)addr,PGDE,PTE,PAddr;
if(VAddr>=0x80000000 && VAddr<0xa0000000)
{
PAddr=VAddr-0x80000000;
return (PVOID)PAddr;
}
PGDE=BaseAddress[VAddr>>22];
if ((PGDE&1)!=0)
{
ULONG tmp=PGDE&0x00000080;
if (tmp!=0)
{
PAddr=(PGDE&0xFFC00000)+(VAddr&0x003FFFFF);
}
else
{
PGDE=(ULONG)MapViewOfFile(g_hMPM, FILE_MAP_ALL_ACCESS, 0, PGDE & 0xfffff000, 0x1000);
PTE=((PULONG)PGDE)[(VAddr&0x003FF000)>>12];
if ((PTE&1)!=0)
{
PAddr=(PTE&0xFFFFF000)+(VAddr&0x00000FFF);
UnmapViewOfFile((PVOID)PGDE);
}
else return 0;
}
}
else return 0;
return (PVOID)PAddr;
}
BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;
CloseHandle (hToken);
return rv;
}
void GetString(PVOID addr, char *returnstr)
{
OSVERSIONINFO OSVersionInfo;
PCHAR ret;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&OSVersionInfo);
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion >= 5 &&
OSVersionInfo.dwMinorVersion >= 1) //Windows XP以上
{
MEMORY_CHUNKS QueryBuff;
ULONG ReturnLength;
char Buff[0x30] = {0};
QueryBuff.Address = (ULONG)addr;
QueryBuff.Data = Buff; //在此是读出缓冲
QueryBuff.Length = sizeof(Buff);
EnablePrivilege(SE_DEBUG_NAME);
ZwSystemDebugControl
(
SysDbgCopyMemoryChunks_0,
&QueryBuff,
sizeof(MEMORY_CHUNKS), //必须是0x0C
NULL,
0,
&ReturnLength
);
strcpy(returnstr, Buff);
}
else
{
ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr);
PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, FILE_MAP_ALL_ACCESS, 0, phys & 0xfffff000, 0x1000);
if (tmp==0)
{
printf("getdata wrongn");
return;
}
strcpy(returnstr, (PCHAR)&tmp[(phys & 0xFFF)>>2]);
UnmapViewOfFile(tmp);
}
}
ULONG GetData(PVOID addr)
{
OSVERSIONINFO OSVersionInfo;
ULONG ret;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&OSVersionInfo);
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion >= 5 &&
OSVersionInfo.dwMinorVersion >= 1) //Windows XP以上
{
MEMORY_CHUNKS QueryBuff;
ULONG ReturnLength;
char Buff[0x300] = {0};
QueryBuff.Address = (ULONG)addr;
QueryBuff.Data = Buff; //在此是读出缓冲
QueryBuff.Length = sizeof(Buff);
EnablePrivilege(SE_DEBUG_NAME);
ZwSystemDebugControl
(
SysDbgCopyMemoryChunks_0,
&QueryBuff,
sizeof(MEMORY_CHUNKS), //必须是0x0C
NULL,
0,
&ReturnLength
);
ret = *(PULONG)Buff;
}
else
{
ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr);
PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, FILE_MAP_ALL_ACCESS, 0, phys & 0xfffff000, 0x1000);
if (tmp==0)
{
printf("getdata wrongn");
return 0;
}
ret=tmp[(phys & 0xFFF)>>2];
UnmapViewOfFile(tmp);
}
return ret;
}
DWORD MyGetModuleBaseAddress( char * pModuleName)
{
PSYSTEM_MODULE_INFORMATION pSysModule;
ULONG uReturn;
ULONG uCount;
PCHAR pBuffer = NULL;
PCHAR pName = NULL;
NTSTATUS status;
UINT ui;
CHAR szBuffer[BASEADDRLEN];
DWORD pBaseAddress;
status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, BASEADDRLEN, &uReturn );
pBuffer = ( PCHAR )malloc(uReturn);
if ( pBuffer )
{
status = ZwQuerySystemInformation( SystemModuleInformation, pBuffer, uReturn, &uReturn );
if( NT_SUCCESS(status) )
{
uCount = ( ULONG )*( ( ULONG * )pBuffer );
pSysModule = ( PSYSTEM_MODULE_INFORMATION )( pBuffer + sizeof( ULONG ) );
if(pModuleName == NULL)
{
for ( ui = 0; ui < uCount; ui++ )
{
printf("%s ntBase address: 0x%08xn", pSysModule->ImageName, pSysModule->Base);
pSysModule ++;
}
}
else
{
for ( ui = 0; ui < uCount; ui++ )
{
pName = strstr( pSysModule->ImageName, pModuleName );
if( pName )
{
//printf("%s ntBase address: 0x%08xn", pSysModule->ImageName, pSysModule->Base);
pBaseAddress = (DWORD)pSysModule->Base;
free( pBuffer );
return pBaseAddress;
}
pSysModule ++;
}
}
}
free( pBuffer );
}
return NULL;
}
int main(int argc, char **argv)
{
int SESSION_TO_NAME_OFFSET=0;
int SESSION_LST_OFFSET=0;
int ACTIVE_LST_TO_NAME_OFFSET=0;
int ACTIVE_LST_OFFSET=0;
char imagename[0x30];
OSVERSIONINFO OSVersionInfo;
HMODULE hDll;
LPVOID lpps;
PVOID firstaddr;
PVOID nowaddr;
if (InitNTDLL())
{
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&OSVersionInfo);
if (OSVersionInfo.dwMajorVersion == 5)
{
if(OSVersionInfo.dwMinorVersion == 0)
{
//SESSION_TO_NAME_OFFSET=W2K_SESSION_TO_NAME_OFFSET;
//SESSION_LST_OFFSET=W2K_SESSION_LST_OFFSET;
//ACTIVE_LST_TO_NAME_OFFSET=W2K_ACTIVE_LST_TO_NAME_OFFSET;
//ACTIVE_LST_OFFSET=W2K_ACTIVE_LST_OFFSET;
//如果用SESSIONLST的话,将会读到0x00000000
SESSION_TO_NAME_OFFSET=W2K_IMAGE_NAME_OFFSET-W2K_WORK_LST_OFFSET;
SESSION_LST_OFFSET=W2K_WORK_LST_OFFSET;
ACTIVE_LST_TO_NAME_OFFSET=W2K_ACTIVE_LST_TO_NAME_OFFSET;
ACTIVE_LST_OFFSET=W2K_ACTIVE_LST_OFFSET;
if (OpenPhysicalMemory()==0)
{
printf("OpenPhysicalMemory wrongn");
return -1;
}
}
else if(OSVersionInfo.dwMinorVersion == 1)
{
SESSION_TO_NAME_OFFSET=WXP_SESSION_TO_NAME_OFFSET;
SESSION_LST_OFFSET=WXP_SESSION_LST_OFFSET;
ACTIVE_LST_TO_NAME_OFFSET=WXP_ACTIVE_LST_TO_NAME_OFFSET;
ACTIVE_LST_OFFSET=WXP_ACTIVE_LST_OFFSET;
}
else if(OSVersionInfo.dwMinorVersion == 2)
{
SESSION_TO_NAME_OFFSET=W2K3_SESSION_TO_NAME_OFFSET;
SESSION_LST_OFFSET=W2K3_SESSION_LST_OFFSET;
ACTIVE_LST_TO_NAME_OFFSET=W2K3_ACTIVE_LST_TO_NAME_OFFSET;
ACTIVE_LST_OFFSET=W2K3_ACTIVE_LST_OFFSET;
}
}
else
{
printf("The OS version is not be supported...n");
return -1;
}
hDll = LoadLibrary("ntoskrnl.exe");
lpps = GetProcAddress(hDll, "PsInitialSystemProcess");
lpps=(LPVOID)(MyGetModuleBaseAddress("ntoskrnl.exe")+(DWORD)lpps-(DWORD)hDll);
printf("PsInitialSystemProcess address : 0x%08Xnn", lpps);
FreeLibrary(hDll);
printf("OS version: %1d.%1dn", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion);
printf("ActiveProcessLinks Offset : 0x%03Xn", ACTIVE_LST_OFFSET);
if(OSVersionInfo.dwMinorVersion == 0)
printf("SessionProcessLinks Offset : 0x%03Xn", SESSION_LST_OFFSET);
else
printf("WorkingSetExpansionLinks Offset : 0x%03Xn", SESSION_LST_OFFSET);
printf("ImageFileName Offset : 0x%03Xnn", ACTIVE_LST_OFFSET+ACTIVE_LST_TO_NAME_OFFSET);
firstaddr=(LPVOID)(GetData(lpps)+ACTIVE_LST_OFFSET);
//GetString((PVOID)((DWORD)firstaddr+ACTIVE_LST_TO_NAME_OFFSET),imagename);
//printf("EPROCESS : 0x%08X : %sn", (DWORD)firstaddr-ACTIVE_LST_OFFSET, imagename);
if(OSVersionInfo.dwMinorVersion == 0)
{
firstaddr=(LPVOID)((DWORD)firstaddr-ACTIVE_LST_OFFSET+SESSION_LST_OFFSET);
}
else
{
firstaddr=(LPVOID)(GetData(firstaddr));
GetString((PVOID)((DWORD)firstaddr+ACTIVE_LST_TO_NAME_OFFSET),imagename);
printf("EPROCESS : 0x%08X : %sn", (DWORD)firstaddr-ACTIVE_LST_OFFSET, imagename);
firstaddr=(LPVOID)(GetData(firstaddr));
firstaddr=(LPVOID)((DWORD)firstaddr-ACTIVE_LST_OFFSET+SESSION_LST_OFFSET);
}
nowaddr=firstaddr;
do
{
if((DWORD)nowaddr>0xffff0000)
break;
GetString((PVOID)((DWORD)nowaddr+SESSION_TO_NAME_OFFSET), imagename);
printf("EPROCESS : 0x%08X : %sn", (DWORD)nowaddr-SESSION_LST_OFFSET, imagename);
nowaddr=(LPVOID)GetData(nowaddr);
}
while(firstaddr!=nowaddr && nowaddr>0);
getchar();
UnmapViewOfFile(g_pMapPhysicalMemory);
CloseHandle(g_hMPM);
CloseNTDLL();
}
return 0;
}
参考资料:
1. 用ring3代码可靠地枚举Windows进程 -TK
http://www.xfocus.net/projects/Xcon/2004/Xcon2004_tk.pdf
---
Welcome to my blog: