详解PID到进程名的转换及伪装

很多时候我们都要用到从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成员即可完成进程名的伪装了 
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭