Delphi 获取进程命令行参数方法
适合D2007 x86版本
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit2: TEdit;
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
USHORT = Word;
UNICODE_STRING = packed record
Length: USHORT;
MaximumLength: USHORT;
Buffer: PWideString;
end;
RTL_USER_PROCESS_PARAMETERS = packed record
Reserved1: array[0..15] of Byte;
Reserved2: array[0..9] of Pointer;
ImagePathName: UNICODE_STRING;
CommandLine: UNICODE_STRING;
end;
PRTL_USER_PROCESS_PARAMETERS = ^RTL_USER_PROCESS_PARAMETERS;
PEB = packed record
Reserved1: array[0..1] of Byte;
BeingDebugged: ByteBool;
Reserved2: Byte;
Reserved3: array[0..1] of Pointer;
Ldr: Pointer;
ProcessParameters: PRTL_USER_PROCESS_PARAMETERS;
Reserved4: array[0..103] of Byte;
Reserved5: array[0..51] of Pointer;
end;
PPEB = ^PEB;
PROCESS_BASIC_INFORMATION = packed record
ExitStatus: DWORD;
PebBaseAddress: PPEB;
AffinityMask: DWORD;
BasePriority: DWORD;
uUniqueProcessId: ULong;
uInheritedFromUniqueProcessId: ULong;
end;
TProcessBasicInformation = PROCESS_BASIC_INFORMATION;
function NtQueryInformationProcess(ProcessHandle: THandle;ProcessInformationClass: Byte;ProcessInformation: Pointer;
ProcessInformationLength: ULONG;ReturnLength: PULONG): DWORD; stdcall; external 'ntdll.dll';
var
Form1: TForm1;
implementation
{$R *.dfm}
//only match x86 not support x64 bit application
function GetProcessCmdLine(PID: Cardinal): string;
const
ProcessBasicInformation = 0;
var
h: THandle;
pbi: TProcessBasicInformation;
ret: Cardinal;
r: Cardinal;
ws: WideString;
aPEB: PEB;
ProcPar: RTL_USER_PROCESS_PARAMETERS;
begin
Result := '';
if PID = 0 then PID := GetCurrentProcessID;
try
h := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if h = 0 then Exit;
try
ret := NtQueryInformationProcess(h, ProcessBasicInformation, @pbi, SizeOf(pbi), @r);
if ret = 0 then
repeat
if (not ReadProcessMemory(h, pbi.PebBaseAddress, @aPEB, SizeOf(aPEB), r)) or (r <> SizeOf(aPEB)) then
break;
if (not ReadProcessMemory(h, aPEB.ProcessParameters, @ProcPar, SizeOf(ProcPar), r)) or (r <> SizeOf(ProcPar)) then
break;
SetLength(ws, ProcPar.CommandLine.Length div 2);
if (not ReadProcessMemory(h, ProcPar.CommandLine.Buffer, PWideChar(ws), ProcPar.CommandLine.Length, r)) or (r <> ProcPar.CommandLine.Length) then
break;
Result := ws;
until True;
finally
CloseHandle(h);
end;
finally
end;
end;
function EnableDebugPriv: Boolean; //提升进程权限为DEBUG权限
var
hToken: THandle;
tp: TTokenPrivileges;
rl: Cardinal;
begin
Result := false;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken);
if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then
begin
tp.PrivilegeCount:=1;
tp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(hToken, false, tp, SizeOf(tp), nil, rl);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
EnableDebugPriv;
Memo1.Text:=GetProcessCmdLine(StrToInt(Edit2.Text));
end;
end.
效果如下图:
以下代码适合X64位进程(32位兼容)编译环境XE2
function GetProcessCmdLine64(PID: Cardinal): string;
var
pbi : PROCESS_BASIC_INFORMATION64;
pfnNtQueryInformationProcess : TNtQueryInformationProcess;
pfnNtReadVirtualMemory : TNtReadVirtualMemory64;
dwSize:DWORD;
size:UINT64;
iReturn:Integer;
pAddrPEB:PVOID64;
PEB:__PEB64;
stBlock:_RTL_USER_PROCESS_PARAMETERS64;
PathBuffer : PByte;
hProcess:Cardinal;
CmdLine:string;
begin
Result := '';
@pfnNtQueryInformationProcess := GetProcAddress(GetModuleHandle('ntdll.dll'),'NtWow64QueryInformationProcess64');
@pfnNtReadVirtualMemory := GetProcAddress(GetModuleHandle('ntdll.dll'),'NtWow64ReadVirtualMemory64');
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if ( Assigned(pfnNtQueryInformationProcess) ) then
begin
pAddrPEB := 0;
iReturn := pfnNtQueryInformationProcess(hProcess,0,@pbi,sizeof(pbi),PULONG(@dwSize));
pAddrPEB := pbi.PebBaseAddress;
// NtQueryInformationProcess returns a negative value if it fails
if (iReturn >= 0) then
begin
// 1. Find the Process Environment Block
size := dwSize;
if ( ERROR_SUCCESS <> pfnNtReadVirtualMemory(hProcess, pAddrPEB, @PEB, sizeof(PEB), PUINT64(@size)) ) then
begin
// Call GetLastError() if you need to know why
Exit;
end;
// 2. From this PEB, get the address of the block containing
// a pointer to the CmdLine
if ( ERROR_SUCCESS <> pfnNtReadVirtualMemory(hProcess, PEB.ProcessParameters, @stBlock, sizeof(stBlock), PUINT64(@size))) then
begin
// Call GetLastError() if you need to know why
Exit;
end;
{ // 3. Get the ImagePathName
PathBuffer := GetMemory(stBlock.ImagePathName.MaximumLength);
FillChar(PathBuffer^,stBlock.ImagePathName.MaximumLength,0);
if ( ERROR_SUCCESS = pfnNtReadVirtualMemory(hProcess, stBlock.ImagePathName.Buffer, PVOID(PathBuffer), stBlock.ImagePathName.Length*sizeof(Char), PUINT64(@size))) then
begin // Call GetLastError() if you need to know why
SetString(ImagePath,PChar(PathBuffer),stBlock.ImagePathName.Length div 2);
Result := True; }
end;
// 4. Get the CmdLine
// FreeMemory(PathBuffer);
PathBuffer := GetMemory(stBlock.CmdLine.MaximumLength);
FillChar(PathBuffer^,stBlock.CmdLine.MaximumLength,0);
if ( ERROR_SUCCESS = pfnNtReadVirtualMemory(hProcess, stBlock.CmdLine.Buffer, PVOID(PathBuffer), stBlock.CmdLine.Length*sizeof(Char), PUINT64(@size))) then
begin // Call GetLastError() if you need to know why
SetString(CmdLine,PChar(PathBuffer),stBlock.CmdLine.Length div 2);
Result := CmdLine;
end;
FreeMemory(PathBuffer);
end;
end;
效果:
本文来自博客园,作者:IT情深,转载请注明原文链接:https://www.cnblogs.com/wh445306/p/16751809.html