- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
原理:
调用ntdll的一个导出函数ZwQuerySystemInformation可以获取一些重要信息,函数定义如下:
1 NTSTATUS WINAPI ZwQuerySystemInformation(
2 _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
3 _Inout_ PVOID SystemInformation,
4 _In_ ULONG SystemInformationLength,
5 _Out_opt_ PULONG ReturnLength
6 );
不过msdn上说该函数在win8下已经不能使用了,用到的时候再说。
重点关注该函数的第一个参数SYSTEM_INFORMATION_CLASS是一个结构体,具体定义如下:
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation, // 0 Y N
SystemProcessorInformation, // 1 Y N
SystemPerformanceInformation, // 2 Y N
SystemTimeOfDayInformation, // 3 Y N
SystemNotImplemented1, // 4 Y N
SystemProcessesAndThreadsInformation, // 5 Y N
SystemCallCounts, // 6 Y N
SystemConfigurationInformation, // 7 Y N
SystemProcessorTimes, // 8 Y N
SystemGlobalFlag, // 9 Y Y
SystemNotImplemented2, // 10 Y N
SystemModuleInformation, // 11 Y N
SystemLockInformation, // 12 Y N
SystemNotImplemented3, // 13 Y N
SystemNotImplemented4, // 14 Y N
SystemNotImplemented5, // 15 Y N
SystemHandleInformation, // 16 Y N
SystemObjectInformation, // 17 Y N
SystemPagefileInformation, // 18 Y N
SystemInstructionEmulationCounts, // 19 Y N
SystemInvalidInfoClass1, // 20
SystemCacheInformation, // 21 Y Y
SystemPoolTagInformation, // 22 Y N
SystemProcessorStatistics, // 23 Y N
SystemDpcInformation, // 24 Y Y
SystemNotImplemented6, // 25 Y N
SystemLoadImage, // 26 N Y
SystemUnloadImage, // 27 N Y
SystemTimeAdjustment, // 28 Y Y
SystemNotImplemented7, // 29 Y N
SystemNotImplemented8, // 30 Y N
SystemNotImplemented9, // 31 Y N
SystemCrashDumpInformation, // 32 Y N
SystemExceptionInformation, // 33 Y N
SystemCrashDumpStateInformation, // 34 Y Y/N
SystemKernelDebuggerInformation, // 35 Y N
SystemContextSwitchInformation, // 36 Y N
SystemRegistryQuotaInformation, // 37 Y Y
SystemLoadAndCallImage, // 38 N Y
SystemPrioritySeparation, // 39 N Y
SystemNotImplemented10, // 40 Y N
SystemNotImplemented11, // 41 Y N
SystemInvalidInfoClass2, // 42
SystemInvalidInfoClass3, // 43
SystemTimeZoneInformation, // 44 Y N
SystemLookasideInformation, // 45 Y N
SystemSetTimeSlipEvent, // 46 N Y
SystemCreateSession, // 47 N Y
SystemDeleteSession, // 48 N Y
SystemInvalidInfoClass4, // 49
SystemRangeStartInformation, // 50 Y N
SystemVerifierInformation, // 51 Y Y
SystemAddVerifier, // 52 N Y
SystemSessionProcessesInformation // 53 Y N
} SYSTEM_INFORMATION_CLASS;
16号SystemHandleInformation即可获得系统句柄信息。
获取所以进程句柄后并不能直接操作这些句柄,因为每个进程的句柄都是独立存在的,所以需要调用DuplicateHandle将需要的进程句柄Dump到当前进程然后再进行操作,
BOOL WINAPI DuplicateHandle(
_In_ HANDLE hSourceProcessHandle,
_In_ HANDLE hSourceHandle,
_In_ HANDLE hTargetProcessHandle,
_Out_ LPHANDLE lpTargetHandle,
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwOptions
);
得到的lpTargetHandle保存着目标进程的句柄。然后调用NtQueryObject可以获取句柄的类型(mutex、File、Section等),以及句柄名称等等。
NTSTATUS NtQueryObject(
_In_opt_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_Out_opt_ PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
);
说了一大堆了,开始写代码吧,由于这里需要很多结构信息,因此我写了一个头文件来定义这些结构:
objEnum.h:
1 #include "ntsecapi.h"
2 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
3 typedef NTSTATUS (WINAPI *ZWQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
4 typedef enum _OBJECT_INFORMATION_CLASS {
5 ObjectBasicInformation,
6 ObjectNameInformation,
7 ObjectTypeInformation,
8 ObjectAllInformation,
9 ObjectDataInformation,
10 } OBJECT_INFORMATION_CLASS;
11 typedef NTSTATUS (NTAPI *NTQUERYOBJECT)(
12 HANDLE Handle,
13 OBJECT_INFORMATION_CLASS ObjectInformationClass,
14 PVOID ObjectInformation,
15 ULONG ObjectInformationLength,
16 PULONG ReturnLength
17 );
18 typedef struct _OBJECT_NAME_INFORMATION {
19 UNICODE_STRING Name;
20 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
21 typedef struct _SYSTEM_HANDLE_INFORMATION
22 {
23 ULONG ProcessId;
24 UCHAR ObjectTypeNumber;
25 UCHAR Flags;
26 USHORT Handle;
27 PVOID Object;
28 ACCESS_MASK GrantedAccess;
29 }SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
30
31 typedef struct _SYSTEM_HANDLE_INFORMATION_EX
32 {
33 ULONG NumberOfHandles;
34 SYSTEM_HANDLE_INFORMATION Information[1];
35 }SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
36 #define SystemHandleInformation 0x10 // 16
然后是两个函数:
1、GetSystemProcessHandeleInfo()可以获取当前系统的所有内核对象句柄信息并返回。
1 LPVOID GetSystemProcessHandleInfo()
2 {
3 ULONG cbBuffer = 0x4000;
4 LPVOID pBuffer = NULL;
5 NTSTATUS sts;
6 do
7 {
8 pBuffer = malloc(cbBuffer);
9 if(pBuffer == NULL)
10 {
11 cout<<"error alloc memory:"<<GetLastError()<<endl;
12 return NULL;
13 }
14 memset(pBuffer,0,cbBuffer);
15
16 sts = ZwQuerySystemInformation(SystemHandleInformation, pBuffer, cbBuffer, NULL);
17 if(sts == STATUS_INFO_LENGTH_MISMATCH)
18 {
19 free(pBuffer);
20 pBuffer = NULL;
21 cbBuffer = cbBuffer +0x4000; // 初始分配的空间不足+4000h
22 }
23 }while(sts == STATUS_INFO_LENGTH_MISMATCH);
24 return pBuffer;
25 }
2.EnumObjInfo()获取从返回的内核对象句柄信息中取出指定pid,指定句柄类型的内核对象,并打印:
void EnumObjInfo(LPVOID pBuffer,DWORD pid)
{
char szType[128] = {0};
char szName[512] = {0};
DWORD dwFlags = 0;
POBJECT_NAME_INFORMATION pNameInfo;
POBJECT_NAME_INFORMATION pNameType;
PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;
ULONG OldPID = 0;
for(DWORD i = 0; i < pInfo->NumberOfHandles; i++)
{
if(OldPID != pInfo->Information[i].ProcessId)
{
if(pInfo->Information[i].ProcessId==pid)
{
HANDLE newHandle;
DuplicateHandle(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo->Information[i].ProcessId),(HANDLE)pInfo->Information[i].Handle,GetCurrentProcess(),&newHandle,DUPLICATE_SAME_ACCESS,FALSE,DUPLICATE_SAME_ACCESS);
NTSTATUS status1=NtQueryObject(newHandle, ObjectNameInformation, szName, 512, &dwFlags);
NTSTATUS status2=NtQueryObject(newHandle, ObjectTypeInformation, szType, 128, &dwFlags);
if(strcmp(szName,"")&&strcmp(szType,"")&&status1!=0xc0000008&&status2!=0xc0000008)
{
pNameInfo = (POBJECT_NAME_INFORMATION)szName;
pNameType = (POBJECT_NAME_INFORMATION)szType;
printf("%wZ ",pNameType);
printf("%wZ \n",pNameInfo);
}
}
}
}
} |
|