方法一:(后续参见方法二)
获取进程PEB中的命令行参数信息(问题:如果先打开文件比如word.exe再打开文件,会出现获取不到的情况)
步骤:
1 遍历进程获取打开文件的可执行文件的进程
HANDLE hSnapProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapProcess == INVALID_HANDLE_VALUE)
{
return;
}
PROCESSENTRY32W ProcessEntry;
ProcessEntry.dwSize = sizeof(ProcessEntry);
BOOL bret = Process32FirstW(hSnapProcess, &ProcessEntry);
WCHAR wszProcessInfo[MAX_PATH] = { 0 };
do
{
WCHAR Name[MAX_PATH] = { 0 };
if (!lstrcmp(ProcessEntry.szExeFile, L"POWERPNT.EXE")| !lstrcmp(ProcessEntry.szExeFile, L"WINWORD.EXE"))
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessEntry.th32ProcessID);
do something
CloseHandle(hProcess);
}
} while (Process32NextW(hSnapProcess, &ProcessEntry));
2 利用ntdll.dll中一个未公开的函数NtQueryInformationProcess,获取进程信息然后去读对方进程ReadProcessMemory,函数原型如下:
NTSTATUS WINAPI NtQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
第一个参数是进程句柄,第二个参数是获取的进程的信息类型,这里我们选择ProcessBasicInformation,
msdn 的声明如下,会返回一个PEB结构体。

第三个参数是输出参数,当参数2是ProcessBasicInformation时,会返回一个
PROCESS_BASIC_INFORMATION 结构,结构如下,

status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
&pbi,
sizeof(PROCESS_BASIC_INFORMATION),
&ReturnLength);
3 获取到PROCESS_BASIC_INFORMATION结构体以后,由上可以看出的它的第二个成员就是指向进程PEB结构体的指针,此时调用ReadProcessMemory,获取进程PEB,
ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(PEB), 0) ReadProcessMemory的函数原型如下:
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead
);
4.通过ReadProcessMemory 获取进程的PEB以后,PEB的结构如下:
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID* KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID* ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID* *ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;
如图标红位置为进程的参数信息,再次调用ReadProcessMemory 获取参数信息,
ReadProcessMemory(hProcess, peb.ProcessParameters, &upps, sizeof(RTL_USER_PROCESS_PARAMETERS), 0))
其中upps是一个RTL_USER_PROCESS_PARAMETERS 的结构体,定义如下:
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
HANDLE ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StandardInput;
HANDLE StandardOutput;
HANDLE StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS];
ULONG EnvironmentSize;
ULONG EnvironmentVersion;
PVOID PackageDependencyData; //8+
ULONG ProcessGroupId;
// ULONG LoaderThreads;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
如上标红位置为命令行信息,UNICODE_STRING同样是一个结构体,定义如下:
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
再次调用ReadProcessMemory获取命令行字符串信息,存入buffer中
ReadProcessMemory(hProcess, upps.CommandLine.Buffer, buffer, upps.CommandLine.Length, 0);
到这完整的进程命令行信息就获取到了。通过字符串处理就可以得到相应的打开的文件的全路径了 。
网友评论