gpt4 book ai didi

windows - 如何获取 NtQueryInformationProcess 所需的缓冲区大小?

转载 作者:可可西里 更新时间:2023-11-01 11:23:14 24 4
gpt4 key购买 nike

NtQueryInformationProcess的ReturnLength参数说明如下:

ReturnLength

A pointer to a variable in which the function returns the size of the requested information. If the function was successful, this is the size of the information written to the buffer pointed to by the ProcessInformation parameter, but if the buffer was too small, this is the minimum size of buffer needed to receive the information successfully.

特别感兴趣的部分是:如果缓冲区太小,这是成功接收信息所需的最小缓冲区大小。

我希望函数返回特定信息类所需的缓冲区大小。

我尝试了以下方法:

 // for static linking

function NtQueryInformationProcess(ProcessHandle : THANDLE;
ProcessInformationClass : DWORD;
ProcessInformation : PPEB;
ProcessInformationLength : DWORD;
ReturnLength : PDWORD)
: NTSTATUS; stdcall; external ntdll;

// for dynamic linking

type
TNtQueryInformationProcess
= function (ProcessHandle : THANDLE;
ProcessInformationClass : DWORD;
ProcessInformation : PPEB;
ProcessInformationLength : DWORD;
ReturnLength : PDWORD) : NTSTATUS; stdcall;

var
ProcessHandle : THANDLE;

Peb : TPEB;
BufferSize : DWORD;
ReturnLength : DWORD;
NtResult : NTSTATUS;
NtdllHandle : HMODULE;
NtQueryInformationProcessPtr : TNtQueryInformationProcess;

begin
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
GetCurrentProcessId());

ZeroMemory(@Peb, sizeof(Peb));
BufferSize := sizeof(PROCESS_BASIC_INFORMATION);
ReturnLength := 0;

NtResult := NtQueryInformationProcess(ProcessHandle,
ProcessBasicInformation,
@Peb,
BufferSize,
@ReturnLength);

writeln('NTSTATUS : ', IntToHex(NtResult, 0));
writeln('ReturnLength : ', ReturnLength);

// try calling the function by address

NtdllHandle := LoadLibrary('ntdll.dll');

pointer(NtQueryInformationProcessPtr) := GetProcAddress(NtdllHandle,
'NtQueryInformationProcess');

// reinitialize just to be safe

ZeroMemory(@Peb, sizeof(Peb));
BufferSize := sizeof(PROCESS_BASIC_INFORMATION);
ReturnLength := 0;

NtResult := NtQueryInformationProcessPtr(ProcessHandle,
ProcessBasicInformation,
@Peb,
BufferSize,
@ReturnLength);

writeln('NTSTATUS : ', IntToHex(NtResult, 0));
writeln('ReturnLength : ', ReturnLength);

writeln('program end.');
readln;
end.

当我将缓冲区的大小设置为 ProcessBasicInformation 的正确大小时,一切都按预期工作,但是,如果我将 BufferSize 设置为零(例如)希望函数在 ReturnLength 变量中返回必要的缓冲区大小,我得到正如预期的那样返回 0xC0000004(大小不匹配)但是,ReturnLength 变量未设置为成功获取 ProcessBasicInformation 所需的大小。

鉴于 ReturnLength 参数的描述,我希望 API 将 ReturnLength 设置为请求的信息类所需的任何大小。

我的问题是:代码中是否存在错误,或者 API 是否没有按照记录工作?还是我误解了 ReturnLength 参数的描述?

感谢您的帮助。

最佳答案

许多 Win32 API 旨在通过使用 nil 指针调用它并为 ReturnLength 指定 0 来告诉您正确的缓冲区大小。 Nt api 的工作方式通常有点不同:

您只需向它传递一个任意大小的缓冲区,它会通过返回 STATUS_INFO_LENGTH_MISMATCH 告诉您是否需要更多。

我还建议使用 Jedi Api Library而不是自己翻译 (Nt Api) 函数/ header 。

编辑:似乎您正在尝试读取 ProcessBasicInformation 类,该类具有固定大小并且不返回指向 PEB 的指针而是返回指向 PROCESS_BASIC_INFORMATION 的指针结构/记录。

这是您尝试执行的操作的示例:

// uses JwaNative

function TDebugThread.ReadPEB: Boolean;
var
nts: NTSTATUS;
pbi: PROCESS_BASIC_INFORMATION;
dwBytes: DWORD;
begin
Result := False;
nts := NtQueryInformationProcess(pi.hProcess,
ProcessBasicInformation, @pbi, SizeOf(pbi), @dwBytes);

if nts <> STATUS_SUCCESS then
Exit;

New(PEB);
Result := ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, PEB, SizeOf(PEB^),
@dwBytes);

end;

下面是一个使用 NtQuerySystemInformation 的示例(完整示例可以在我的 GitHub repository 上找到)。

{ TProcessList }
constructor TProcessList.Create(const AOwnsObjects: Boolean = True);
var
Current: PSystemProcesses;
SystemProcesses : PSystemProcesses;
dwSize: DWORD;
nts: NTSTATUS;
begin
inherited Create(AOwnsObjects);

dwSize := 200000;
SystemProcesses := AllocMem(dwSize);

nts := NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
SystemProcesses, dwSize, @dwSize);

while nts = STATUS_INFO_LENGTH_MISMATCH do
begin
ReAllocMem(SystemProcesses, dwSize);
nts := NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
SystemProcesses, dwSize, @dwSize);
end;

if nts = STATUS_SUCCESS then
begin
Current := SystemProcesses;
while True do
begin
Self.Add(TProcess.Create(Current^));
if Current^.NextEntryDelta = 0 then
Break;

Current := PSYSTEM_PROCESSES(DWORD_PTR(Current) + Current^.NextEntryDelta);
end;
end;

FreeMem(SystemProcesses);
end;

编辑:回答@ScienceAmateur 的评论,以下测试代码始终为 ReturnLength 返回 0:

uses
Windows,
System.SysUtils,
Rtti,
JwaNative,
JwaWinType,
JwaNtSecApi,
JwaNtStatus;


function NtStatusErrorMessage(const nts: NTSTATUS): String;
begin
Result := SysErrorMessage(LsaNtStatusToWinError(nts));
end;

var
nts: NTSTATUS;
pic: PROCESS_INFORMATION_CLASS;
Buffer: Pointer;
pil: DWORD;
ReturnLength: DWORD;
begin
for pic := Low(PROCESS_INFORMATION_CLASS) to High(PROCESS_INFORMATION_CLASS) do
begin
Buffer := nil;
pil := 0;
ReturnLength := 0;
nts := NtQueryInformationProcess(GetCurrentProcess,
ProcessBasicInformation, Buffer, pil, @ReturnLength);
WriteLn(Format('%s: returned 0x%.8x and ReturnLength: %d', [TRttiEnumerationType.GetName(pic), nts, ReturnLength]));
end;

WriteLn('Finished.');

if DebugHook <> 0 then
ReadLn;

输出:

ProcessBasicInformation: returned 0xC0000004 and ReturnLength: 0
ProcessQuotaLimits: returned 0xC0000004 and ReturnLength: 0
ProcessIoCounters: returned 0xC0000004 and ReturnLength: 0
ProcessVmCounters: returned 0xC0000004 and ReturnLength: 0
ProcessTimes: returned 0xC0000004 and ReturnLength: 0
ProcessBasePriority: returned 0xC0000004 and ReturnLength: 0
ProcessRaisePriority: returned 0xC0000004 and ReturnLength: 0
ProcessDebugPort: returned 0xC0000004 and ReturnLength: 0
ProcessExceptionPort: returned 0xC0000004 and ReturnLength: 0
ProcessAccessToken: returned 0xC0000004 and ReturnLength: 0
ProcessLdtInformation: returned 0xC0000004 and ReturnLength: 0
ProcessLdtSize: returned 0xC0000004 and ReturnLength: 0
ProcessDefaultHardErrorMode: returned 0xC0000004 and ReturnLength: 0
ProcessIoPortHandlers: returned 0xC0000004 and ReturnLength: 0
ProcessPooledUsageAndLimits: returned 0xC0000004 and ReturnLength: 0
ProcessWorkingSetWatch: returned 0xC0000004 and ReturnLength: 0
ProcessUserModeIOPL: returned 0xC0000004 and ReturnLength: 0
ProcessEnableAlignmentFaultFixup: returned 0xC0000004 and ReturnLength: 0
ProcessPriorityClass: returned 0xC0000004 and ReturnLength: 0
ProcessWx86Information: returned 0xC0000004 and ReturnLength: 0
ProcessHandleCount: returned 0xC0000004 and ReturnLength: 0
ProcessAffinityMask: returned 0xC0000004 and ReturnLength: 0
ProcessPriorityBoost: returned 0xC0000004 and ReturnLength: 0
ProcessDeviceMap: returned 0xC0000004 and ReturnLength: 0
ProcessSessionInformation: returned 0xC0000004 and ReturnLength: 0
ProcessForegroundInformation: returned 0xC0000004 and ReturnLength: 0
ProcessWow64Information: returned 0xC0000004 and ReturnLength: 0
ProcessImageFileName: returned 0xC0000004 and ReturnLength: 0
ProcessLUIDDeviceMapsEnabled: returned 0xC0000004 and ReturnLength: 0
ProcessBreakOnTermination: returned 0xC0000004 and ReturnLength: 0
ProcessDebugObjectHandle: returned 0xC0000004 and ReturnLength: 0
ProcessDebugFlags: returned 0xC0000004 and ReturnLength: 0
ProcessHandleTracing: returned 0xC0000004 and ReturnLength: 0
MaxProcessInfoClass: returned 0xC0000004 and ReturnLength: 0

关于windows - 如何获取 NtQueryInformationProcess 所需的缓冲区大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55084802/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com