首页 > 新闻动态 >  

新闻动态
NEWS

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;


原来,再大的房子,再大的床,没有相爱的人陪伴,都只是冰冷的物质。而如果身边有爱人陪伴,即使房子小,床小,也觉得无关紧要,因为这些物质上面有了爱的温度,成了家的元素。—— 何珞《婚房》#书摘#
分享到: