-
ZwQuerySystemInformation 安然运居心得 Delphi 版
添加时间:2013-7-25 点击量:作为 DELPHI 版本,须要引用 jwaNative, JwaWinType ,他们是 JEDI API 的一项目组。JEDI 官网有。
先给出 2 个帮助函数 和 一些布局体。
type
PRecord = ^TRecord;
TRecord = record
end;
PSystemInformationList = ^TSystemInformationList;
TSystemInformationList = record
Count: ULONG;
List: array [0 .. 0] of TRecord;
end;
PSYSTEM_HANDLE_Informations = ^TSYSTEM_HANDLE_Informations;
_SYSTEM_HANDLE_Informations = record
Count: ULONG;
SH: array [0 .. 0] of _SYSTEM_HANDLE_INFORMATION;
end;
TSYSTEM_HANDLE_Informations = _SYSTEM_HANDLE_Informations;
SYSTEM_HANDLE_Informations = _SYSTEM_HANDLE_Informations;
PNM_INFO = ^TNM_INFO;
_NM_INFO = record
hFile: THandle;
Info: _FILE_NAME_Information;
Name: array [0 .. MAX_PATH - 1] of WideChar;
end;
TNM_INFO = _NM_INFO;
NM_INFO = _NM_INFO;
Function GetSystemInformationClassSize(Const ATableType: SYSTEM_INFORMATION_CLASS; Const Count: ULONG): ULONG;
begin
Result := 0;
case ATableType of
SystemBasicInformation:
Result := ¥002C;
SystemProcessorInformation:
Result := ¥0000C;
SystemPerformanceInformation:
Result := ¥0138;
// SystemTimeInformation: Result := ¥0020;
// SystemPathInformation: Result := ¥0;
// SystemProcessInformation: Result := ¥00C8 + Count;
// SystemCallInformation: Result := ¥0018 + (Count ¥0004);
SystemConfigurationInformation:
Result := ¥0018;
// SystemProcessorCounters: Result := ¥0030 + Count;//per cpu
SystemGlobalFlag:
Result := ¥0004; // (fails if size != 4)
// SystemCallTimeInformation: Result := ¥0;
SystemModuleInformation:
Result := ¥0004 + (Count Sizeof(SYSTEM_MODULE_INFORMATION)); //(n 0 x011C)
SystemLockInformation:
Result := ¥0004 + (Count Sizeof(SYSTEM_LOCK_INFORMATION)); //(n 0 x0024)
// SystemStackTraceInformation: Result := ¥0;
// SystemPagedPoolInformation: Result := ¥0;
// SystemNonPagedPoolInformation: Result := ¥0;
SystemHandleInformation:
Result := ¥0004 + (Count Sizeof(SYSTEM_HANDLE_INFORMATION)); //(n 0 x0010)
// SystemObjectTypeInformation: Result := ¥0038+ + (Count ¥0030);// +)
SystemPageFileInformation:
Result := ¥0018 + (Count Sizeof(SYSTEM_PAGEFILE_INFORMATION));
// SystemVdmInstemulInformation: Result := ¥0088;
// SystemVdmBopInformation: Result := ¥0;
SystemCacheInformation:
Result := ¥0024;
SystemPoolTagInformation:
Result := ¥0004 + (Count Sizeof(SYSTEM_POOL_TAG_INFORMATION)); // (n 0 x001C)
// SystemInterruptInformation: Result := ¥0000 + Count;//, or 0 x0018 per cpu
SystemDpcInformation:
Result := ¥0014;
// SystemFullMemoryInformation: Result := ¥0;
// SystemLoadDriver: Result := ¥0018;//, set mode only
// SystemUnloadDriver: Result := ¥0004;//, set mode only
// SystemTimeAdjustmentInformation: Result := ¥000C;//, 0 x0008 writeable
// SystemSummaryMemoryInformation: Result := ¥0;
// SystemNextEventIdInformation: Result := ¥0;
// SystemEventIdsInformation: Result := ¥0;
SystemCrashDumpInformation:
Result := ¥0004;
SystemExceptionInformation:
Result := ¥0010;
SystemCrashDumpStateInformation:
Result := ¥0004;
// SystemDebuggerInformation: Result := ¥0002;
SystemContextSwitchInformation:
Result := ¥0030;
SystemRegistryQuotaInformation:
Result := ¥000C;
// SystemAddDriver: Result := ¥0008;//, set mode only
// SystemPrioritySeparationInformatio: Result := ¥0004;//, set mode only
// SystemPlugPlayBusInformation: Result := ¥0;
// SystemDockInformation: Result := ¥0;
// SystemPowerInfo: Result := ¥0060;// (XP only!)
// SystemProcessorSpeedInformation: Result := ¥000C;// (XP only!)
SystemTimeZoneInformation:
Result := ¥00AC;
SystemLookasideInformation:
Result := Count ¥0020;
SystemSetTimeSlipEvent:
Result := ¥0;
SystemCreateSession:
Result := ¥0;
SystemDeleteSession:
Result := ¥0;
SystemInvalidInfoClass1:
Result := ¥0;
SystemRangeStartInformation:
Result := ¥0004; // (fails if size != 4)
SystemVerifierInformation:
Result := ¥0;
SystemAddVerifier:
Result := ¥0;
SystemSessionProcessesInformation:
Result := ¥0;
end;
end;
Function GetSystemInformationClassHasCount(Const ATableType: SYSTEM_INFORMATION_CLASS): BOOL;
begin
Result := False;
case ATableType of
// SystemProcessInformation,
// SystemCallInformation,
// SystemProcessorCounters,
SystemModuleInformation,
SystemLockInformation,
SystemHandleInformation,
// SystemObjectTypeInformation,
//SystemPageFileInformation, //如同这个还不断定。
// SystemInterruptInformation,
SystemPoolTagInformation:
Result := True;
end;
//可以 和 GetSystemInformationClassSize 共同应用。
end;上方的 NM_INFO 和本文无关。
大师 可以 便利的应用 GetSystemInformationTable 来 获取所需的体系信息数据。
Function GetSystemInformationTable(hHeap: THandle; Const ATableType: SYSTEM_INFORMATION_CLASS; var buffSize: ULONG): PVOID;
var
OldPrivilegeAttributes: ULONG;
hFile, hQuery: THandle;
Status: NTSTATUS;
cbBuffer: Cardinal;
AVOID: PVOID;
MinBufSize,
ReturnLength: ULONG;
PReturnLength: PULONG;
begin
buffSize := 0;
Result := nil;
if not EnableDebugPrivilege(GetCurrentProcess, True, OldPrivilegeAttributes) then
Exit;
try
ReturnLength := 0;
cbBuffer := 0;
AVOID := nil;
PReturnLength := Addr(ReturnLength);
Status := ZwQuerySystemInformation(ATableType, AVOID, 0, PReturnLength);
if (ReturnLength > 0) then // ReturnLength 一个布局的大小。
begin
cbBuffer := ReturnLength;
MinBufSize := ReturnLength;
AVOID := HeapAlloc(hHeap, 0 or HEAP_GENERATE_EXCEPTI, cbBuffer);
if not Assigned(AVOID) then
Exit;
try
ZeroMemory(AVOID, cbBuffer);
Status := ZwQuerySystemInformation(ATableType, AVOID, cbBuffer, PReturnLength);
if NTSTATUS_SUCCESS(Status) then
begin
Result := AVOID;
buffSize := cbBuffer;
end
else if (Status = STATUS_INFO_LENGTH_MISMATCH) and GetSystemInformationClassHasCount(ATableType) then
begin
//调试中,下一秒,也许就不敷用了。不调试,可能也须要多申请些空间
//cbBuffer := GetSystemInformationClassSize(ATableType, PSystemInformationList(AVOID).Count + 100);
cbBuffer := Sizeof(PSystemInformationList(AVOID).Count) +
(MinBufSize - Sizeof(PSystemInformationList(AVOID).Count)) (PSystemInformationList(AVOID).Count + 100);
HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTI, AVOID);
AVOID := HeapAlloc(hHeap, 0 or HEAP_GENERATE_EXCEPTI, cbBuffer);
if not Assigned(AVOID) then
Exit;
try
ZeroMemory(AVOID, cbBuffer);
Status := ZwQuerySystemInformation(ATableType, AVOID, cbBuffer, PReturnLength);
if NTSTATUS_SUCCESS(Status) then
begin
Result := AVOID;
buffSize := cbBuffer;
end
else
begin
HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTI, AVOID);
end;
finally
end;
end
else
begin
HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTI, AVOID);
cbBuffer := ¥10000;
repeat
AVOID := HeapAlloc(hHeap, 0 or HEAP_GENERATE_EXCEPTI, cbBuffer);
if not Assigned(AVOID) then
Exit;
ZeroMemory(AVOID, cbBuffer);
Status := ZwQuerySystemInformation(ATableType, AVOID, cbBuffer, PReturnLength);
if (Status = STATUS_INFO_LENGTH_MISMATCH) then
begin
HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTI, AVOID);
cbBuffer := cbBuffer 2;
end;
if cbBuffer > ¥1000000 then
begin
Exit;
end;
until (Status <> STATUS_INFO_LENGTH_MISMATCH);
if NTSTATUS_SUCCESS(Status) then
begin
Result := AVOID;
buffSize := cbBuffer;
end
else
begin
HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTI, AVOID);
end;
end;
finally
end;
end
else
begin
Result := nil;
buffSize := 0;
end;
finally
SetDebugPrivilege(GetCurrentProcess, OldPrivilegeAttributes, OldPrivilegeAttributes);
end;
end;第一次 ZwQuerySystemInformation,主如果为了返回 ReturnLength,这个是 最小数据大小,一般对于单个的数据,就直接用这个值。然则对于多个的数据,这个值就是 每一个数据项的大小加上 4 。
第二次调用 ZwQuerySystemInformation,返回了一个数据区,若是多个的数据,必然会 Status = STATUS_INFO_LENGTH_MISMATCH,所以须要第三次调用。大小有 2 种办法获取(具体看代码)。
若是不断定是不是 多个数据,然则又呈现空间不敷用的景象,就须要用收集上大师常见的轮回增大空间的办法了。
别的 hHeap := GetProcessHeap; 可以获得 hHeap ,并且空间的申请,不必然非要用这个,也可以用 GetMem 等。
最后补上 权限提拔函数。
Function SetDebugPrivilege(Const hProcess: THandle; Const PrivilegeAttributes: ULONG;
var OldPrivilegeAttributes: ULONG): Boolean;
var
hToken: THandle;
tp: TOKEN_PRIVILEGES;
NewPrivilegeAttributes: ULONG;
ReturnLength: ULONG;
hProcessToken: THandle;
begin
hToken := NULL_Handle;
Result := False;
OldPrivilegeAttributes := SE_PRIVILEGE_ENABLED_BY_DEFAULT;
NewPrivilegeAttributes := PrivilegeAttributes;
hProcessToken := hProcess;
if hProcessToken = NULL_Handle then
begin
hProcessToken := GetCurrentProcess;
end;
if (OpenProcessToken(hProcessToken, TOKEN_ADJUST_PRIVILEGES, hToken)) // 获得过程接见令牌的句柄
then
begin
try
tp.PrivilegeCount := 1;
LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid); // 查询过程的权限,获取一个权限对应的LUID值
OldPrivilegeAttributes := tp.Privileges[0].Attributes;
tp.Privileges[0].Attributes := NewPrivilegeAttributes;
Result := AdjustTokenPrivileges(hToken, False, tp, sizeof(tp), nil, ReturnLength); // 断定令牌权限,对这个接见令牌进行批改
finally
CloseHandle(hToken);
end;
end;
end;
// 提拔当前过程具有权限
Function EnableDebugPrivilege(Const hProcess: THandle; Const Enable: Boolean;
var OldPrivilegeAttributes: ULONG): Boolean;
var
hToken: THandle;
tp: TOKEN_PRIVILEGES;
ReturnLength: ULONG;
hProcessToken: THandle;
begin
hToken := NULL_Handle;
Result := False;
OldPrivilegeAttributes := SE_PRIVILEGE_ENABLED_BY_DEFAULT;
hProcessToken := hProcess;
if hProcessToken = NULL_Handle then
begin
hProcessToken := GetCurrentProcess;
end;
if (OpenProcessToken(hProcessToken, TOKEN_ADJUST_PRIVILEGES, hToken)) // 获得过程接见令牌的句柄
then
begin
try
tp.PrivilegeCount := 1;
LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid); // 查询过程的权限,获取一个权限对应的LUID值
OldPrivilegeAttributes := tp.Privileges[0].Attributes;
if Enable then
begin
tp.Privileges[0].Attributes := tp.Privileges[0].Attributes or SE_PRIVILEGE_ENABLED;
// tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
end
else
begin
tp.Privileges[0].Attributes := tp.Privileges[0].Attributes and (not SE_PRIVILEGE_ENABLED);
// tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED_BY_DEFAULT;
// tp.Privileges[0].Attributes := 0;
end;
Result := AdjustTokenPrivileges(hToken, False, tp, sizeof(tp), nil, ReturnLength); // 断定令牌权限,对这个接见令牌进行批改
finally
CloseHandle(hToken);
end;
end;
end;
原来,再大的房子,再大的床,没有相爱的人陪伴,都只是冰冷的物质。而如果身边有爱人陪伴,即使房子小,床小,也觉得无关紧要,因为这些物质上面有了爱的温度,成了家的元素。—— 何珞《婚房》#书摘#