作为 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 * 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 := ;  
  Result := nil;  
  if not EnableDebugPrivilege(GetCurrentProcess, True, OldPrivilegeAttributes) then
    Exit;  
  try
    ReturnLength := ;  
    cbBuffer := ;  
    AVOID := nil;  
    PReturnLength := Addr(ReturnLength);  
    Status := ZwQuerySystemInformation(ATableType, AVOID, , PReturnLength);  
    if (ReturnLength > ) then // ReturnLength 一个结构的大小。  
    begin
      cbBuffer := ReturnLength;  
      MinBufSize := ReturnLength;  
      AVOID := HeapAlloc(hHeap,  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 + );  
          cbBuffer := Sizeof(PSystemInformationList(AVOID).Count) +  
            (MinBufSize - Sizeof(PSystemInformationList(AVOID).Count)) * (PSystemInformationList(AVOID).Count + );  
          HeapFree(hHeap,  or HEAP_GENERATE_EXCEPTIONS, AVOID);  
          AVOID := HeapAlloc(hHeap,  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,  or HEAP_GENERATE_EXCEPTIONS, AVOID);  
            end;  
          finally
          end;  
        end
        else
        begin
          HeapFree(hHeap,  or HEAP_GENERATE_EXCEPTIONS, AVOID);  
          cbBuffer := $;  
          repeat
            AVOID := HeapAlloc(hHeap,  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,  or HEAP_GENERATE_EXCEPTIONS, AVOID);  
              cbBuffer := cbBuffer * ;  
            end;  
            if cbBuffer > $ 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,  or HEAP_GENERATE_EXCEPTIONS, AVOID);  
          end;  
        end;  
      finally
      end;  
    end
    else
    begin
      Result := nil;  
      buffSize := ;  
    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 := ; 
      LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[].Luid); // 查询进程的权限,获取一个权限对应的LUID值 
      OldPrivilegeAttributes := tp.Privileges[].Attributes; 
      tp.Privileges[].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 := ; 
      LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[].Luid); // 查询进程的权限,获取一个权限对应的LUID值 
      OldPrivilegeAttributes := tp.Privileges[].Attributes; 
      if Enable then
      begin
        tp.Privileges[].Attributes := tp.Privileges[].Attributes or SE_PRIVILEGE_ENABLED; 
        // tp.Privileges[].Attributes := SE_PRIVILEGE_ENABLED; 
      end
      else
      begin
        tp.Privileges[].Attributes := tp.Privileges[].Attributes and (not SE_PRIVILEGE_ENABLED); 
        // tp.Privileges[].Attributes := SE_PRIVILEGE_ENABLED_BY_DEFAULT; 
        // tp.Privileges[].Attributes := ; 
      end; 
      Result := AdjustTokenPrivileges(hToken, False, tp, sizeof(tp), nil, ReturnLength); // 判断令牌权限,对这个访问令牌进行修改 
    finally
      CloseHandle(hToken); 
    end; 
  end; 
end;

特别声明
禁止 win2003 (楚凡) QQ635887 使用本人修改的控件。

禁止 qiuyan81 (苦恋树) QQ46494153 使用本人修改的内容。

禁止 gfuchao QQ82715485 使用本人修改的内容。

禁止 supersk QQ未知,使用本人修改的版本。

禁止 yesin119 QQ未知,使用本人修改的版本。

禁止 263378440 使用本人修改的版本。

禁止 yanse 使用本人修改的版本。

禁止 www123 使用本人修改的版本

禁止 eliyh 使用本人修改的版本

禁止 ltshdp、ltsh(禁卫军) 使用本人修改的版本

禁止 zwjchinazwj (蒲石) 使用本人修改的版本

禁止 zhipu QQ:2001972 使用本人修改的版本

禁止 jackalan (nVicen) QQ:875271757 使用本人修改的版本

禁止 kencc2016 (小宇) QQ:2601759381 使用本人修改的版本

以上用户名均为 2CCC 的

禁止 QQ:191909837 使用本人修改的版本
禁止 QQ 81604691 使用本人修改的版本

当然,如果你们脸皮比较厚,就偷偷的用吧。

凡是想要骂我的,都可以偷偷的用,反正我是控制不了。
只要你们不鄙视自己就行。

ZwQuerySystemInformation 安全使用心得 Delphi 版的更多相关文章

  1. 十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)

    //注意:Delphi2010以下版本默认的字符编码是ANSI,VS2010的默认编码是UTF-8,delphi版得到的字符串须经过Utf8ToAnsi()转码才能跟C#版得到的字符串显示结果一致. ...

  2. 通过崩溃地址找错误行数之Delphi版

    通过崩溃地址找错误行数之Delphi版2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小]核心提示:什么是 MAP 文件?简单地讲, M ...

  3. Delphi版IP地址与整型互转

    Delphi版IP地址与整型互转 unit Unit11; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphic ...

  4. 从内存中加载DLL Delphi版(转)

    源:从内存中加载DLL DELPHI版 原文 : http://www.2ccc.com/article.asp?articleid=5784 MemLibrary.pas //从内存中加载DLL D ...

  5. 雪花算法(snowflake)delphi版

    雪花算法简单描述: + 最高位是符号位,始终为0,不可用. + 41位的时间序列,精确到毫秒级,41位的长度可以使用69年.时间位还有一个很重要的作用是可以根据时间进行排序. + 10位的机器标识,1 ...

  6. 二维码生成delphi版

    二维码生成delphi版 生成二维码的软件,代码从C语言转换过来(源地址:http://fukuchi.org/works/qrencode/),断断续续的差不多花了一周时间来转换和调试.在转换过程中 ...

  7. 从内存中加载DLL DELPHI版

    //从内存中加载DLL DELPHI版 unit MemLibrary; interface uses Windows; function memLoadLibrary(pLib: Pointer): ...

  8. [转载]《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化

    Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬如 Sy ...

  9. 内存中加载DLL DELPHI版

    //从内存中加载DLL DELPHI版 unit MemLibrary; interface uses Windows; function memLoadLibrary(pLib: Pointer): ...

随机推荐

  1. HTML当中特殊字符的表示

    (回车换行) <br> (空格符)   &(AND符号) & <(左尖括号.小于号) < >(右尖括号.大于号) > °(度) ° •(间隔符) • ...

  2. Hadoop_UDF示例

    UDF:  一进一出 Eclipse端 1. 继承UDF 2. 实现evaluate方法(可重裁实现多个evaluate方法,以实现不同需求) 3. 导出类jar包,注意指定main方法 Hive端 ...

  3. Python实战:下载鬼灵报告有声小说

    在家无聊,想看看小说,不过看的眼睛痛,就想着下个有声小说来听听.但风上找到的都是要一集一集下,还得重命名,122集啊,点到什么时候. 写个批处理下载的脚本.记录下过程. 一.老套路了,找到下载URL. ...

  4. 通过hexo+NexT构建静态博客

    一般的教程网上有很多,主要讲下我遇到的问题以及解决方法: 一.hexo建立的文档无法上传github deploy: type: git repository: https://github.com/ ...

  5. python与正则表达式

    匹配一个字符: . 任意非\n字符 [...] \d \D digit \s \S space \w \W word 匹配前一个字符的多个: * 0->> + 1->> ? 0 ...

  6. Javascript初学篇章_1(概念/数据类型)

    Javascript是一门脚本语言,主要由浏览器来执行.它可以说是页面的灵魂,让页面活过来.与之前学的HTML5+CSS样式的不同之处就在于,JS能让静态网页成为一个动态网页,实现与用户的互动. Ja ...

  7. python使用mysql数据库

    一,安装mysql 如果是windows 用户,mysql 的安装非常简单,直接下载安装文件,双击安装文件一步一步进行操作即可. Linux 下的安装可能会更加简单,除了下载安装包进行安装外,一般的l ...

  8. 【RabbitMQ】Publish/Subscribe

    Publish/Subscribe 在上一节我们创建了一个work queue.背后的设想为每个任务被分发给明确的消费者.这节内容我们将做一些完全不同的事情 -- 我们将发送一条消息给多个消费者.这种 ...

  9. sublime work flow

    Tools -> Developer -> New Snippet <snippet> <content><![CDATA[ }() { ${} } ]]&g ...

  10. 细说SaaS BI国际市场众生相,你准备好了么?

    SaaS商业智能(BI)历程 在笔者看来,SaaS BI(也有称SaaS 商业智能.云BI)算是一个慢热的概念.远在十几前年便已经提出并有公司践行.而随着SaaS服务从早期的CRM.ERP.HR等领域 ...