很多时候我们都要用到从PID到进程名的转换。
先总结一下相关的一些常用函数。
GetCurrentProcessId
GetWindowProcessID
这是两个最常用的获得PID的函数。
再看看如何通过PID获得进程名
先用OpenProcess把进程打开,然后一般用下面的一些方法来获得
1.用快照函数CreateToolhelp32Snapshot,然后枚举进程,比较
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0)
Process32First/Process32Next
2.用GetModuleFileNameEx(当前进程用GetModuleFileName,多一个进程句柄参数)
DWORD GetModuleFileNameEx(
HANDLE hProcess,
HMODULE hModule,
LPTSTR lpFilename,
DWORD nSize
);
需要注意的是这个函数在PSAPI.dll里面
3.用GetProcessImageFileName(WinXP以后新加的一个函数,在psapi.dll中)
DWORD GetProcessImageFileName(
HANDLE hProcess,
LPTSTR lpImageFileName,
DWORD nSize
);
该函数仅在WinXP,Win2003以后支持
说到这里我们就该说说WinNT对进程名的存储和管理了
下面以WinXP SP2 5.1.2600.2180 中的ntkrnlpa.exe为例,涉及到绝对偏移的地方不同版本可能会有所不同,请大家执行研究。
第一个地方,在_EPROCESS中有个成员UCHAR ImageFileName[ 16 ];
偏移174h的位置,这里存的是进程的短文件名,少数地方用,
比如SoftIce的addr和proc命令,如果名称超过16个字符直接截断
第二个地方,PEB中的PPEB_LDR_DATA Ldr成员
或者_RTL_USER_PROCESS_PARAMETERS* ProcessParameters。
关于PEB的获取方法FS:30h,进程外用NtQueryInformationProcess传递
PROCESS_BASIC_INFORMATION获取,具体参数自行参考MSDN
ProcessParameters在PEB中偏移10h的位置,一般都是20000h这个值
ProcessParameters中38h的位置是进程主模块,40h为进程命令行(注:Unicode)
通过Ldr也是可以获得的,位置在PEB偏移0Ch的位置,LDR中0Ch的位置是
InLoadOrderModuleList(双链表),通过这个可以枚举到该进程所有的模块名
到这里我们已经可以轻松的欺骗用GetModuleFileName/GetModuleFileNameEx获得进程名的方式了
第三个地方,EPROCESS中有个成员SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo,该结构其实就是个UniCode指针,不过这个地方不是一直都有的。当执行过NtQueryInformationProcess (ProcHandle,ProcessImageFileName,....)后就有了。GetProcessImageFileName就是直接调用NtQueryInformationProcess来获得进程名的。
好了,大概明白了后我们来看看NtQueryInformationProcess的代码NtQueryInformationProcess中处理ProcessImageFileName的代码是这样的先用ObReferenceObjectByHandle把进程句柄转换成PEPROCESS,然后将PEPROCESS传递给SeLocateProcessImageName,SeLocateProcessImageName会判断SeAuditProcessCreationInfo成员是否已经初始化,没有则调用
PsReferenceProcessFilePointer(该函数其实就是取的EPROCESS结构中SectionObject对应的文件句柄)获得进程对应的文件句柄,并将文件句柄传递
SeInitializeProcessAuditName,SeInitializeProcessAuditName最后调用ObQueryNameString将文件句柄转换成文件名。
到这里后我们可以直接在驱动中调用一次NtQueryInformationProcess,然后去修改EPROCESS中的SeAuditProcessCreationInfo成员即可完成进程名的伪装了
先总结一下相关的一些常用函数。
GetCurrentProcessId
GetWindowProcessID
这是两个最常用的获得PID的函数。
再看看如何通过PID获得进程名
先用OpenProcess把进程打开,然后一般用下面的一些方法来获得
1.用快照函数CreateToolhelp32Snapshot,然后枚举进程,比较
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0)
Process32First/Process32Next
2.用GetModuleFileNameEx(当前进程用GetModuleFileName,多一个进程句柄参数)
DWORD GetModuleFileNameEx(
HANDLE hProcess,
HMODULE hModule,
LPTSTR lpFilename,
DWORD nSize
);
需要注意的是这个函数在PSAPI.dll里面
3.用GetProcessImageFileName(WinXP以后新加的一个函数,在psapi.dll中)
DWORD GetProcessImageFileName(
HANDLE hProcess,
LPTSTR lpImageFileName,
DWORD nSize
);
该函数仅在WinXP,Win2003以后支持
说到这里我们就该说说WinNT对进程名的存储和管理了
下面以WinXP SP2 5.1.2600.2180 中的ntkrnlpa.exe为例,涉及到绝对偏移的地方不同版本可能会有所不同,请大家执行研究。
第一个地方,在_EPROCESS中有个成员UCHAR ImageFileName[ 16 ];
偏移174h的位置,这里存的是进程的短文件名,少数地方用,
比如SoftIce的addr和proc命令,如果名称超过16个字符直接截断
第二个地方,PEB中的PPEB_LDR_DATA Ldr成员
或者_RTL_USER_PROCESS_PARAMETERS* ProcessParameters。
关于PEB的获取方法FS:30h,进程外用NtQueryInformationProcess传递
PROCESS_BASIC_INFORMATION获取,具体参数自行参考MSDN
ProcessParameters在PEB中偏移10h的位置,一般都是20000h这个值
ProcessParameters中38h的位置是进程主模块,40h为进程命令行(注:Unicode)
通过Ldr也是可以获得的,位置在PEB偏移0Ch的位置,LDR中0Ch的位置是
InLoadOrderModuleList(双链表),通过这个可以枚举到该进程所有的模块名
到这里我们已经可以轻松的欺骗用GetModuleFileName/GetModuleFileNameEx获得进程名的方式了
第三个地方,EPROCESS中有个成员SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo,该结构其实就是个UniCode指针,不过这个地方不是一直都有的。当执行过NtQueryInformationProcess (ProcHandle,ProcessImageFileName,....)后就有了。GetProcessImageFileName就是直接调用NtQueryInformationProcess来获得进程名的。
好了,大概明白了后我们来看看NtQueryInformationProcess的代码NtQueryInformationProcess中处理ProcessImageFileName的代码是这样的先用ObReferenceObjectByHandle把进程句柄转换成PEPROCESS,然后将PEPROCESS传递给SeLocateProcessImageName,SeLocateProcessImageName会判断SeAuditProcessCreationInfo成员是否已经初始化,没有则调用
PsReferenceProcessFilePointer(该函数其实就是取的EPROCESS结构中SectionObject对应的文件句柄)获得进程对应的文件句柄,并将文件句柄传递
SeInitializeProcessAuditName,SeInitializeProcessAuditName最后调用ObQueryNameString将文件句柄转换成文件名。
到这里后我们可以直接在驱动中调用一次NtQueryInformationProcess,然后去修改EPROCESS中的SeAuditProcessCreationInfo成员即可完成进程名的伪装了