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;


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