要想获取进程的完整路径,使用PSAPI提供的函数 GetModuleFileNameEx() 就可以轻松的办到
下面是一个例子:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*
用户态使用 psapi 函数进程进程查询
*/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
stdio.h
"
#include
"
windows.h
"
#include
"
psapi.h
"
#pragma
comment(lib,"psapi.lib")
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
需要额外添加 psapi.h 以及 psapi.lib
//
存在一定的问题,system进程不能列出来(当然这个可以根据pid来判别.system的pid是4),
//
卡巴斯基的进程也不行,看来本身还是有缺陷
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
提升进程权限
bool
AdjustPurview()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
TOKEN_PRIVILEGES TokenPrivileges;
BOOL bRet;
HANDLE hToken;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &TokenPrivileges.Privileges[0].Luid);
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
bRet = AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, 0, NULL, NULL);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
CloseHandle(hToken);
return bRet == TRUE;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
PrintProcessNameAndID( DWORD processID )
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
char szProcessName[MAX_PATH] = "........";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
AdjustPurview();
//取得进程的句柄
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE,
processID );
//取得进程名称
if ( hProcess )
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//HMODULE hMod;
//DWORD cbNeeded;
//if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
GetModuleFileNameEx(hProcess,NULL,szProcessName,MAX_PATH);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//回显进程名称和ID
printf( " %-20d%-20s", processID , szProcessName);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
CloseHandle( hProcess );
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
main( )
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DWORD aProcesses[1024], cbNeeded, cProcesses;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
unsigned int i;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//枚举系统进程ID列表
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//计算进程数量
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
cProcesses = cbNeeded / sizeof(DWORD);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 输出每个进程的名称和ID
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for ( i = 0; i < cProcesses; i++ )
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
PrintProcessNameAndID( aProcesses[i] );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
呵呵,方便快捷的实现了进程完整路径的获取,其中比较关键的一句就是 GetModuleFileNameEx(),那么GetModuleFileNameEx()又是如何实现的呢?逆向分析了一下这个函数,发现它就是从进程的PEB中进行检索找出进程完整路径的.
首先来分析一下PEB(进程环境块),其中包含了大量的信息,有多少的信息呢?我们使用内核调试器直接欣赏一下
kd> !peb
PEB at 7ffd9000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: No
ImageBaseAddress: 01000000
Ldr 00181e90
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 00181f28 . 001824e0
Ldr.InLoadOrderModuleList: 00181ec0 . 001824d0
Ldr.InMemoryOrderModuleList: 00181ec8 . 001824d8
Base TimeStamp Module
1000000 44b01112 Jul 09 04:09:54 2006 D:/Program Files/Debugging Tools
for Windows/kd.exe
7c920000 4121457c Aug 17 07:38:36 2004 C:/WINDOWS/system32/ntdll.dll
7c800000 4121457d Aug 17 07:38:37 2004 C:/WINDOWS/system32/kernel32.dll
77be0000 412145fe Aug 17 07:40:46 2004 C:/WINDOWS/system32/msvcrt.dll
2000000 44b011b8 Jul 09 04:12:40 2006 D:/Program Files/Debugging Tools
for Windows/dbgeng.dll
3000000 44b01174 Jul 09 04:11:32 2006 D:/Program Files/Debugging Tools
for Windows/dbghelp.dll
77da0000 4121454d Aug 17 07:37:49 2004 C:/WINDOWS/system32/ADVAPI32.dll
77e50000 41214569 Aug 17 07:38:17 2004 C:/WINDOWS/system32/RPCRT4.dll
77bd0000 41214577 Aug 17 07:38:31 2004 C:/WINDOWS/system32/VERSION.dll
1d00000 44b011d1 Jul 09 04:13:05 2006 D:/Program Files/Debugging Tools
for Windows/symsrv.dll
SubSystemData: 00000000
ProcessHeap: 00080000
ProcessParameters: 00020000
WindowTitle: '"D:/Program Files/Debugging Tools for Windows/livekd.exe"'
ImageFile: 'D:/Program Files/Debugging Tools for Windows/kd.exe'
CommandLine: 'kd.exe -z C:/WINDOWS/system32/livekd.dmp'
DllPath: 'D:/Program Files/Debugging Tools for Windows;C:/WINDOWS/syste
m32;C:/WINDOWS/system;C:/WINDOWS;.;d:/perl/bin;C:/WINDOWS/system32;C:/WINDOWS;C:
/WINDOWS/System32/Wbem;D:/Program Files/MySQL/MySQL Server 4.1/bin;C:/Program Fi
les/Microsoft SQL Server/80/Tools/BINN;D:/Program Files/Microsoft Visual Studio/
Common/Tools/WinNT;D:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin;D
:/Program Files/Microsoft Visual Studio/Common/Tools;D:/Program Files/Microsoft
Visual Studio/VC98/bin'
Environment: 00010000
=C:=C:/Documents and Settings/galihoo
ALLUSERSPROFILE=C:/Documents and Settings/All Users
APPDATA=C:/Documents and Settings/galihoo/Application Data
CLIENTNAME=Console
CommonProgramFiles=C:/Program Files/Common Files
COMPUTERNAME=PERSON-GALIHOO
ComSpec=C:/WINDOWS/system32/cmd.exe
DDKROOT=D:/WINDDK/2600
DRIVERNETWORKS=D:/PROGRA~1/COMPUW~1/SOFTIC~1/DRIVER~2
DRIVERWORKS=D:/PROGRA~1/COMPUW~1/SOFTIC~1/DRIVER~1
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=/Documents and Settings/galihoo
include=D:/Program Files/Microsoft Visual Studio/VC98/atl/include;D:/Pro
gram Files/Microsoft Visual Studio/VC98/mfc/include;D:/Program Files/Microsoft V
isual Studio/VC98/include
lib=D:/Program Files/Microsoft Visual Studio/VC98/mfc/lib;D:/Program Fil
es/Microsoft Visual Studio/VC98/lib
LOGONSERVER=//PERSON-GALIHOO
MSDevDir=D:/Program Files/Microsoft Visual Studio/Common/MSDev98
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=D:/Program Files/Debugging Tools for Windows/winext/arcade;d:/perl/
bin;C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem;D:/Program Files/MyS
QL/MySQL Server 4.1/bin;C:/Program Files/Microsoft SQL Server/80/Tools/BINN;D:/P
rogram Files/Microsoft Visual Studio/Common/Tools/WinNT;D:/Program Files/Microso
ft Visual Studio/Common/MSDev98/Bin;D:/Program Files/Microsoft Visual Studio/Com
mon/Tools;D:/Program Files/Microsoft Visual Studio/VC98/bin
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
perl=D:/perl/bin/
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 8 Stepping 1, AuthenticAMD
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0801
ProgramFiles=C:/Program Files
PROMPT=$P$G
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:/WINDOWS
TEMP=C:/DOCUME~1/galihoo/LOCALS~1/Temp
TMP=C:/DOCUME~1/galihoo/LOCALS~1/Temp
USERDOMAIN=PERSON-GALIHOO
USERNAME=galihoo
USERPROFILE=C:/Documents and Settings/galihoo
VS71COMNTOOLS=E:/Program Files/Microsoft Visual Studio 7/Common7/Tools/
VTOOLSD=D:/PROGRA~1/COMPUW~1/SOFTIC~1/VtoolsD
windir=C:/WINDOWS
WORKPATH=D:/WINDDK/MyDrivers
_NT_SYMBOL_PATH=H:/XP_SP2_Symbols
看到了吧,进程映象的基地址,进程中加载的所有的映象,以及各种环境变量都可以从PEB顺藤摸瓜找到
PEB的结构
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
typedef
struct
_PEB
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
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;
PPVOID KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PPVOID 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;
PPVOID *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;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
PEB,
*
PPEB;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
PPEB_LDR_DATA 对我们来说比较重要,看看里面都有什么东西
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
typedef
struct
_PEB_LDR_DATA
...
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
}
PEB_LDR_DATA,
*
PPEB_LDR_DATA;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
后面三个字段都是双向环形链表,链表上的节点由进程中所有的模块的信息组成,遍历这三个链表就可以得到所有的模块,只不过他们在链表中排列的位置不一样, 链表节点指向的实体内容是如下的结构
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
typedef
struct
_LDR_MODULE
...
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
}
LDR_MODULE,
*
PLDR_MODULE;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
看看 FullDllName ,它就是我们要找得东西
实现的步骤:
1
. 获得 peb,(可以使用 native api NtQueryInformationProcess 进行获取)
2
. 获得LoaderData (peb
+
0xc
)
3
. 获得InMemoryOrderModuleList
(LoaderData
+
0x14
,选择第二个链表,不知道为什么,GetModuleFileNameEx就是这么实现的)
4
. 获得FullDllName
(InMemoryOrderModuleList是双向链表的一个节点,它刚好指向进程的实体映象,因此可以使用 InMemoryOrderModuleList
+
0x1c
就可以得到FullDllName)
5
. 获得真正的完整路径,
kd
>
dt UNICODE_STRING
+
0x000
Length : Uint2B
+
0x002
MaximumLength : Uint2B
+
0x004
Buffer : Ptr32 Uint2B
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
关键函数代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
通过进程ID,然后读取此进程的PEB,得到进程的模块
int
GetFullPathByID(DWORD dwID)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
// 打开进程
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
FALSE,dwID);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (hProcess == NULL) ...{
int k = GetLastError();
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
PROCESS_BASIC_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DWORD LoaderData = 0;
DWORD InMemoryOrderModuleList = 0;
UNICODE_STRING usImagePath;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
WCHAR ImagePath[MAX_PATH] = ...{0};
usImagePath.MaximumLength = MAX_PATH;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 定义函数指针
LONG (WINAPI *PNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 获取函数地址
PNtQueryInformationProcess = (LONG(WINAPI*)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG))
GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQueryInformationProcess" );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 获取 peb
if (PNtQueryInformationProcess( hProcess,
ProcessBasicInformation,
&pi,
sizeof(pi),
NULL) == 0
)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
// 读取 LoaderData
if (!ReadProcessMemory(hProcess,
(PVOID *)((DWORD)pi.PebBaseAddress+0xc),
&LoaderData,
sizeof(DWORD),
NULL)
)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("LoaderData Failed ");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 读取 InMemoryOrderModuleList
if (!ReadProcessMemory(hProcess,
(PVOID *)((DWORD)LoaderData+0x14),
&InMemoryOrderModuleList,
sizeof(DWORD),
NULL)
)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("InMemoryOrderModuleList Failed ");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 读取 FullDllName
if (!ReadProcessMemory(hProcess,
(PVOID *)((DWORD)InMemoryOrderModuleList+0x1c),
&usImagePath,
sizeof(UNICODE_STRING),
NULL)
)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("usImagePath Failed ");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// 读取 真正的路径
if (!ReadProcessMemory(hProcess,
usImagePath.Buffer,
&ImagePath,
MAX_PATH,
NULL)
)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("ImagePath Failed ");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
char chImagePath[MAX_PATH] = ...{0};
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//转换成ANSI
WideCharToMultiByte(CP_ACP,0,ImagePath,-1,chImagePath,MAX_PATH,NULL,NULL);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
printf("%-10d%s ",dwID,chImagePath);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
其实另外还可以通过PEB结构中的ProcessParameters来进行路径的获取,其结构定义如下
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
typedef
struct
_RTL_USER_PROCESS_PARAMETERS
...
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingPositionLeft;
ULONG StartingPositionTop;
ULONG Width;
ULONG Height;
ULONG CharWidth;
ULONG CharHeight;
ULONG ConsoleTextAttributes;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopName;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
}
RTL_USER_PROCESS_PARAMETERS,
*
PRTL_USER_PROCESS_PARAMETERS;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ImagePathName 就是完整路径,呵呵,其实这个ImagePathName和上面InMemoryOrderModuleList的FullDllName,他们所指向的缓冲区是一个地方,可以自己玩玩..
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ps:这个东西比较老,也没有多大的意义,微软都提供了 GetModuleFileNameEx 这个api,用它就够简单了,呵呵,搞到耍
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
by:galihoo