美文网首页
获取打开的文件的全路径(1)

获取打开的文件的全路径(1)

作者: 看点书 | 来源:发表于2018-05-24 17:55 被阅读0次

方法一:(后续参见方法二)

获取进程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结构体。

enter description hereenter description here

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

enter description hereenter description here
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); 

到这完整的进程命令行信息就获取到了。通过字符串处理就可以得到相应的打开的文件的全路径了 。

代码工程链接:https://github.com/scuzhangzhang/GetFileFullPath

相关文章

网友评论

      本文标题:获取打开的文件的全路径(1)

      本文链接:https://www.haomeiwen.com/subject/ponsjftx.html