关键字:
R3
Peb.Ldr,PEB_LDR_DATA
NtQuerySystemInformation,ZwQueryInformationProcess,
CreateToolhelp32Snapshot,EnumProcesses,EnumProcessModules
ReadProcessMemory,NtReadProcessMemory
kernel32.dll,psapi.dll,ntdll.dll
R0
PsIdleProcess
EPROCESS.Peb, EPROCESS.ActiveProcessLinks, EPROCESS.Pcb.ThreadListHead(即KPROCESS.ThreadListHead)
EPROCESS.ThreadListHead
NtQuerySystemInformation(从PsIdleProcess进程开始通过EPROCESS.ActiveProcessLinks遍历进程,通过EPROCESS.Pcb.ThreadListHead遍历线程)
NtQueryInformationProcess(通过ObReferenceObjectByHandle 得到EPORCESS再得到PEB,用于模块遍历)ObReferenceObjectByHandle(通过R3传过来的进程句柄得到EPROCESS)
NtReadProcessMemory(跨进程读PEB)
注意,如果是取自身进程的PEB地址,可以直接通过PTEB = fs:0x18,PPEB=PTEB->ProcessEnvironmentBlock或者PPEB=fs:0x30取得。无需跨进程读,也无需进内核(如GetModuleFileName就是如此)
typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB; typedef struct _PEB_LDR_DATA { DWORD Length; UCHAR Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; }PEB_LDR_DATA,*PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; DWORD SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; DWORD Flags; WORD LoadCount; WORD TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; DWORD CheckSum; DWORD TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
获取所有进程信息
关键: NtQuerySystemInformation(ntdll.dll) ---> 内核通过EPROCESS.ActiveProcessLinks遍历,从PsIdleProcess开始
1. 进程枚举:
https://docs.microsoft.com/zh-cn/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes
https://docs.microsoft.com/zh-cn/windows/win32/toolhelp/traversing-the-thread-list
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
//th32ProcessID=0表示当前线程, CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
CreateToolhelp32Snapshot (kernel32.dll)
NtQuerySystemInformation (ntdll.dll)
------------------------------------------------------------------------------
NtQuerySystemInformation (ntoskrnl.exe) //EPROCESS.ActiveProcessLinks
ExpGetProcessInformation R0枚举所有进程(以及线程,直接通过EPROCESS.Pcb.ThreadListHead遍历线程)
PsGetNextProcess 直接通过EPROCESS.ActiveProcessLinks获取下一个进程
2. 进程id枚举:
https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes
BOOL EnumProcesses(
DWORD *lpidProcess,
DWORD cb,
LPDWORD lpcbNeeded
);
EnumProcesses (psapi.dll / kernle32.dll)
NtQuerySystemInformation (ntdll.dll)
------------------------------------------------------------------------------
NtQuerySystemInformation (ntoskrnl.exe) //EPROCESS.ActiveProcessLinks
3. 直接调用NtQuerySystemInformation(声明即可使用)/ZwQuerySystemInformation(GetProcAddress)
NTSTATUS NtQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
NtQuerySystemInformation(SystemProcessInformation, ...); //SystemInformationClass.SystemProcessInformation = 5
获取单个进程信息(进程模块枚举)
关键: NtQueryInformationProcess(ntdll.dll) ---> 内核Handle->EPROCESS->Peb
//ProcessInformationClass .ProcessBasicInformation = 0
//(Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a unique value used by the system to identify the specified process. )
1. 调用EnumProcessModules获取所有模块
https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process
BOOL EnumProcessModules(
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded
);
EnumProcessModules(psapi.dll / kernle32.dll)
NtQueryInformationProcess (ntdll.dll) and ReadProcessMemory (kernel32.dll)
------------------------------------------------------------------------------
NtQueryInformationProcess (ntoskrnl.exe)
ObReferenceObjectByHandle (Handle->EPORCESS->Peb)
2.
https://docs.microsoft.com/zh-cn/windows/win32/toolhelp/traversing-the-module-list
//CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
CreateToolhelp32Snapshot --> RtlQueryProcessDebugInformation(ntdll.dll) --> RtlQueryProcessModuleInformation --> LdrQueryProcessModuleInformationEx --> LdrQueryInLoadOrderModuleList
--> LdrQueryProcessPeb and LdrReadMemory
--> ZwQueryInformationProcess and NtReadVirtualMemory
------------------------------------------------------------------------------
NtQueryInformationProcess (ntoskrnl.exe)
ObReferenceObjectByHandle (Handle->EPORCESS->Peb)
3. 直接调用ZwQueryInformationProcess(声明即可使用)/NtQueryInformationProcess(GetProcAddress)
NTSTATUS WINAPI ZwQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, ProcessInformation, ...);
ReadProcessMemory(ProcessInformation, ...);
4.
BOOL GetProcessInformation(
HANDLE hProcess,
PROCESS_INFORMATION_CLASS ProcessInformationClass,
LPVOID ProcessInformation,
DWORD ProcessInformationSize
);
(>win8)???
pid handle eprocess
1、pid->handle
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID clientid;
InitializeObjectAttributes(&ObjectAttributes, 0 ,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
clientid.UniqueProcess = (HANDLE)pid;
clientid.UniqueThread=0;
ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &ObjectAttributes, &clientid);
handle即为所求
2、handle->pid
PROCESS_BASIC_INFORMATION pbi;
Status = ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, (PVOID)&pbi, sizeof(ProcessBasicInformation), NULL);
pid = pbi.UniqueProcessId;
pid即为所求。
3、pid->eprocess
PEPROCESS process;
PsLookupProcessByProcessId((HANDLE)pid, &process);
ObDereferenceObject(process);
process即为所求eprocess的指针。
4、handle->eprocess
Status = ObReferenceObjectByHandle (ProcessHandle,
PROCESS_TERMINATE,
PsProcessType,
KeGetPreviousModeByThread(&Self->Tcb),
&Process,
NULL);
或
handle->pid->eprocess。
5、eprocess->pid
_EPROCESS.UniqueProcessId即为所求,虽然声明类型为HANDLE,但实际上是pid
6、eprocess->handle
Status = ObOpenObjectByPointer(
Process,
Attributes,
&AccessState,
0,
PsProcessType,
PreviousMode,
&Handle
);
或eprocess->pid->handle