ZwQuerySystemInformation 安全使用心得 Delphi 版
作为 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 版的更多相关文章
- 十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)
//注意:Delphi2010以下版本默认的字符编码是ANSI,VS2010的默认编码是UTF-8,delphi版得到的字符串须经过Utf8ToAnsi()转码才能跟C#版得到的字符串显示结果一致. ...
- 通过崩溃地址找错误行数之Delphi版
通过崩溃地址找错误行数之Delphi版2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小]核心提示:什么是 MAP 文件?简单地讲, M ...
- Delphi版IP地址与整型互转
Delphi版IP地址与整型互转 unit Unit11; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphic ...
- 从内存中加载DLL Delphi版(转)
源:从内存中加载DLL DELPHI版 原文 : http://www.2ccc.com/article.asp?articleid=5784 MemLibrary.pas //从内存中加载DLL D ...
- 雪花算法(snowflake)delphi版
雪花算法简单描述: + 最高位是符号位,始终为0,不可用. + 41位的时间序列,精确到毫秒级,41位的长度可以使用69年.时间位还有一个很重要的作用是可以根据时间进行排序. + 10位的机器标识,1 ...
- 二维码生成delphi版
二维码生成delphi版 生成二维码的软件,代码从C语言转换过来(源地址:http://fukuchi.org/works/qrencode/),断断续续的差不多花了一周时间来转换和调试.在转换过程中 ...
- 从内存中加载DLL DELPHI版
//从内存中加载DLL DELPHI版 unit MemLibrary; interface uses Windows; function memLoadLibrary(pLib: Pointer): ...
- [转载]《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化
Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬如 Sy ...
- 内存中加载DLL DELPHI版
//从内存中加载DLL DELPHI版 unit MemLibrary; interface uses Windows; function memLoadLibrary(pLib: Pointer): ...
随机推荐
- HDU1541 树状数组
Stars Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- jcl-over-slf4j log桥接工具简介
ava 界里有许多实现日志功能的工具,最早得到广泛使用的是 log4j,许多应用程序的日志部分都交给了 log4j,不过作为组件开发者,他们希望自己的组件不要紧紧依赖某一个工具,毕竟在同一个时候还有很 ...
- 编写一个简单的jdbc例子程序
package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Res ...
- Git系列教程一 入门与简介
一.版本控制引入 可能我们都会有这样的经历:创建了一个文件,并对它做了多次更改,当我们想回到其中的某一次更改的时候,由于时间太长记不得那次更改的内容,于是我们在每次大的更改的时候,会创建一个文件的副本 ...
- Bootstrap的字体文件woff2 报错
在iis上看到网站有个404,于是强迫症来了... 百度了许久,知道了解决办法,记下来,是网站默认没有支持这种字体 在 Web.config 的 system.webServer 节点中添加: 带标签 ...
- app活动页面上的痛点
app项目上需要做一个小的活动,先看下页面布局 需求是这5个板块逐个展示,展示一块的时候,页面整体向上滚动一定的距离. 刚开始考虑的时候,是准备依赖css3属性的transition实现的,包括顺序延 ...
- yii2 model层中配置常量与list
- C语言中printf的规范输出
1.调用格式为 printf("<格式化字符串>", <参量表>); 其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原样输出; 另 ...
- 用mac的terminal通过公私钥和ssh登录Linux
刚开始使用mac,会觉得很难用,在网上找的方法也差强人意,经过自己的实践,找到下面这种方法,很好用,步骤也很简单 1.在mac本的个人目录下创建一个文件夹:.ssh. 在这个文件夹下使用ssh- ...
- pdf拆分与合并
1.引用iTextSharp,用于拆分和合并pdf文件 using iTextSharp.text; using iTextSharp.text.pdf; 2.合并pdf //outMergeFile ...