ZwQuerySystemInformation 安全使用心得 Delphi 版
2013-07-24 14:27
351 查看
作为 DELPHI 版本,需要引用 jwaNative, JwaWinType ,他们是 JEDI API 的一部分。JEDI 官网有下载。
先给出 2 个辅助函数 和 一些结构体。
上面的 NM_INFO 和本文无关。
大家 可以 方便的使用 GetSystemInformationTable 来 获取所需的系统信息数据。
第一次 ZwQuerySystemInformation,主要是为了返回 ReturnLength,这个是 最小数据大小,一般对于单个的数据,就直接用这个值。但是对于多个的数据,这个值就是 每一个数据项的大小加上 4 。
第二次调用 ZwQuerySystemInformation,返回了一个数据区,如果多个的数据,肯定会 Status = STATUS_INFO_LENGTH_MISMATCH,所以需要第三次调用。大小有 2 种办法获取(具体看代码)。
如果不确定是不是 多个数据,但是又出现空间不够用的情况,就需要用网络上大家常见的循环增大空间的办法了。
另外 hHeap := GetProcessHeap; 可以得到 hHeap ,而且空间的申请,不一定非要用这个,也可以用 GetMem 等。
最后补上 权限提升函数。
先给出 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 * 0x011C) SystemLockInformation: Result := $0004 + (Count * Sizeof(SYSTEM_LOCK_INFORMATION)); //(n * 0x0024) // SystemStackTraceInformation: Result := $0; // SystemPagedPoolInformation: Result := $0; // SystemNonPagedPoolInformation: Result := $0; SystemHandleInformation: Result := $0004 + (Count * Sizeof(SYSTEM_HANDLE_INFORMATION)); //(n * 0x0010) // 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 * 0x001C) // SystemInterruptInformation: Result := $0000 + Count;//, or 0x0018 per cpu SystemDpcInformation: Result := $0014; // SystemFullMemoryInformation: Result := $0; // SystemLoadDriver: Result := $0018;//, set mode only // SystemUnloadDriver: Result := $0004;//, set mode only // SystemTimeAdjustmentInformation: Result := $000C;//, 0x0008 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_EXCEPTIONS, 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_EXCEPTIONS, AVOID); AVOID := HeapAlloc(hHeap, 0 or HEAP_GENERATE_EXCEPTIONS, 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_EXCEPTIONS, AVOID); end; finally end; end else begin HeapFree(hHeap, 0 or HEAP_GENERATE_EXCEPTIONS, AVOID); cbBuffer := $10000; repeat AVOID := HeapAlloc(hHeap, 0 or HEAP_GENERATE_EXCEPTIONS, 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_EXCEPTIONS, 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_EXCEPTIONS, 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;
相关文章推荐
- ZwQuerySystemInformation 安全使用心得 Delphi 版。
- ZwQuerySystemInformation的使用
- 此网页不允许使用基本类型“System.Web.UI.MasterPage”该类型未注册为安全类型
- ZwQuerySystemInformation枚举内核模块及简单应用
- System.Threading.Timer使用心得
- “System Volume Information”文件夹里的NTFS木马(安全问题)
- System.Threading.Timer使用心得
- delphi中关于使用CreateOleObject方法控制word的一些心得。将word放入到pannel中
- Delphi使用心得------持续更新中
- Delphi中的Set类型的使用心得
- 通过ZwQuerySystemInformation获取EPROCESS
- NtQuerySystemInformation的使用
- Delphi中TDateTime使用心得
- System.Threading.Timer使用心得
- 【WitchHat.cn心得】Silverlight中,即使使用HttpWebRequest也抛System.Security.SecurityException
- Delphi中TDateTime使用心得
- 关于ZwQuerySystemInformation
- Delphi中关于IdTcpServer与IdTcpClient使用心得
- 关于在DELPHI6中使用正则表达式的一些心得
- System.Threading.Timer使用心得