学习雨盾的源码,看到了在驱动程序中得到当前进程的完整路径和进程名的代码,网上搜了一下,文档不少,学习。。。
《摘自http://www.chinaitpower.com/A/2001-10-09/1177.html 作者:xstudio 时间:2001-10-09 10:09 出处:互联网 责编:chinaitpower 》
首先利用 PsGetCurrentProcess 或 IoGetCurrentProcess 函数得到当前进程的句柄,这个句柄是指向 _EPROCESS 结构的指针, _EPROCESS 的结构如下:
typedef struct _EPROCESS
{
KPROCESS Pcb;
NTSTATUS ExitStatus;
KEVENT LockEvent;
DWORD LockCount;
QWORD CreateTime;
QWORD ExitTime;
PVOID LockOwner;
DWORD UniqueProcessId;
QWORD ActiveProcessLinks;
DWORD QuotaPeakPoolUsage [2]; // NP, P
DWORD QuotaPoolUsage [2]; // NP, P
DWORD PagefileUsage;
DWORD CommitCharge;
DWORD PeakPagefileUsage;
DWORD PeakVirtualSize;
QWORD VirtualSize;
DWORD Vm [12];
DWORD LastProtoPteFault;
DWORD DebugPort;
DWORD ExceptionPort;
DWORD ObjectTable;
DWORD Token;
DWORD WorkingSetLock [8];
DWORD WorkingSetPage;
BOOLEAN ProcessOutswapEnabled;
BOOLEAN ProcessOutswapped;
BOOLEAN AddressSpaceInitialized;
BOOLEAN AddressSpaceDeleted;
DWORD AddressCreationLock [9];
DWORD ForkInProgress;
DWORD VmOperation;
DWORD VmOperationEvent;
DWORD PageDirectoryPte;
QWORD LastFaultCount;
PVOID VadRoot;
DWORD VadHint;
DWORD CloneRoot;
DWORD NumberOfPrivatePages;
DWORD NumberOfLockedPages;
WORD w184;
BOOLEAN ExitProcessCalled;
BOOLEAN CreateProcessReported;
HANDLE SectionHandle;
struct _PEB *Peb; // offset 0x1B0
PVOID SectionBaseAddress;
PVOID QuotaBlock;
NTSTATUS LastThreadExitStatus;
PROCESS_WS_WATCH_INFORMATION WorkingSetWatch;
DWORD InheritedFromUniqueProcessId;
ACCESS_MASK GrantedAccess;
DWORD DefaultHardErrorProcessing;
DWORD LdtInformation;
DWORD VadFreeHint;
DWORD VdmObjects;
KMUTANT ProcessMutant;
BYTE ImageFileName [16]; // offset 0x1FC
DWORD VmTrimFaultValue [2];
PVOID Win32Process;
DWORD d1F8;
DWORD d1FC;
}
EPROCESS,
* PEPROCESS,
**PPEPROCESS;
从上面这个结构可以看出,进程名称就是 ImageFileName ,只要用 _EPROCESS 的基地址加上偏移地址 0x1FC 就可以得到进程名称的地址,代码如下:
char *ProcessName = (char*)PsGetCurrentProcess() + 0x1FC;
KdPrint((“Current Process Name: %s/n”, ProcessName));
要得到完整路径还需要利用 _EPROCESS 结构中的 _PEB 结构指针来得到 ProcessParameters 的地址。 ProcessParameters 保存着进程的完整路径。可以通过 DDK 附带的 WinDbg 工具打开一个可执行程序,然后用 !peb 命令来显示 _PEB 的结构信息。如下所示:
———————————————————————————————————————
> !peb
Debugger extension library [F:/WINNT/system32/ntsdexts] loaded
PEB at 7FFDF000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 00400000
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 131f88 . 132998
Ldr.InLoadOrderModuleList: 131ee0 . 132988
Ldr.InMemoryOrderModuleList: 131ee8 . 132990
00400000 D:/NtSysInfo.exe
77F80000 F:/WINNT/System32/ntdll.dll
77E60000 F:/WINNT/system32/KERNEL32.dll
77DF0000 F:/WINNT/system32/USER32.dll
77F40000 F:/WINNT/system32/GDI32.DLL
76AF0000 F:/WINNT/system32/comdlg32.dll
70BD0000 F:/WINNT/system32/SHLWAPI.DLL
77D90000 F:/WINNT/system32/ADVAPI32.dll
77D20000 F:/WINNT/system32/RPCRT4.DLL
71700000 F:/WINNT/system32/COMCTL32.DLL
77560000 F:/WINNT/system32/SHELL32.DLL
78000000 F:/WINNT/system32/MSVCRT.DLL
777C0000 F:/WINNT/System32/WINSPOOL.DRV
SubSystemData: 0
ProcessHeap: 130000
ProcessParameters: 20000
WindowTitle: 'D:/NtSysInfo.exe'
ImageFile: 'D:/NtSysInfo.exe'
CommandLine: '"D:/NtSysInfo.exe" '
DllPath: 'D:/;.;F:/WINNT/System32;F:/WINNT/system;F:/WINNT;F:/WINNT/system32;F:/WINNT;F:/WINNT/System32/Wbem;J:/WINDOWS;J:/WINDOWS/COMMAND;E:/WINDOWS/SYSTEM/WBEM;J:/WINDOWS;J:/WINDOWS/COMMAND;E:/WINDOWS/SYSTEM/WBEM;J:/WINDOWS;J:/WINDOWS/
COMMAND'
Environment: 0x10000
从 WinDbg 输出的 PEB 结构信息可以看出 ProcessParameters 的地址为 0x20000 , ImageFile 字段就是进程的完整路径。那么 PorcessParamters 的地址又保存在 _PEB 结构的什么地方呢? _PEB 结构的基地址为 0x7ffdf000 ,通过 WinDbg 的“ db 0x7ffdf000 ” 命令显示 0x7ffdf000 地址的信息可以发现 ProcessParameters 的地址保存在 _PEB 结构的 0x10 偏移量处,内容为 0x20000 。
继续用“ db 0x20000 ”命令显示 ProcessParameters 地址的内容,偏移量为 0x3C 处保存完整路径的地址, 0x3C 处的内容如果是: 0x20670 ,利用“ db 0x20670 ”即可显示出完整路径。完整路径用 UNICODE 格式保存。
我们利用程序模拟上面的步骤则可以得到当前进程的完整路径,代码如下:
PCWSTR GetCurrentProcessFileName()
{
DWORD dwAddress = (DWORD)PsGetCurrentProcess();
if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
return NULL;
dwAddress += 0x1B0;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += 0x10;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += 0x3C;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
KdPrint((“Current Process Full Path Name: %ws/n”, (PCWSTR)dwAddress));
return (PCWSTR)dwAddress;
}
Windows NT 与 Windows 2000 的 _EPROCESS 结构略有不同,所以偏移地址也不相同,故此上面的程序不能正常运行于 Windows NT 。要想在 Windows NT 下获得进程名和完整路径可以用类似的方法得出正确的偏移地址,进而编写出正确的程序。