驱动中获取进程名的正确方法

来源:互联网 发布:网站域名备案查询 编辑:程序博客网 时间:2024/05/21 20:03
这是个古老的话题,没有技术含量,只不过看到网上很多驱动代码在获取进程名时总喜欢去读偏移 EPROCESS.ImageFileName,感觉比较误导新人。

这个方法其实很不科学,硬编码偏移带来的兼容性问题以及16字节截断的问题(Win7过后是15字节)就不用说了,关键是这个 EPROCESS.ImageFileName 其实并不靠谱

咱们可以做个实验,随便打开一个程序,比如记事本notepad.exe。然后看看ImageFileName:

procname1.png


似乎没什么问题。接下来关闭这个notepad.exe,再将可执行程序改个名,比如改成xxx.exe:

procname2.png


再次双击运行,再看看ImageFileName:

procname3.png


发现问题了吧?在内核中 EPROCESS.ImageFileName 只不过是个参考信息,准确的路径在 EPROCESS.SeAuditProcessCreationInfo.ImageFileName 这个地方:

procname4.png


不过硬编码偏移始终不是一个好方法,正确的方法是召唤 ZwQueryProcessInformation(其实原理就是EPROCESS.SeAuditProcessCreationInfo.ImageFileName)。下面贴一段我自己常用的进程名获取函数(其实从某个主动防御的代码中逆向出来的):

  1. PUNICODE_STRING GetProcNameByEproc(IN PEPROCESS pEproc)
  2. /*++
  3. Routine Description:
  4. 获取指定进程的完整进程名
  5. Arguments:
  6. pEproc - 指定进程的EPROCESS地址
  7. Return Value:
  8. 成功则返回进程名,失败返回NULL
  9. Comments:
  10. 该函数返回的进程名,由调用则负责释放(ExFreePool)。
  11. --*/
  12. {
  13. NTSTATUS NtStatus;
  14. HANDLE hProc = NULL;
  15. PBYTE pBuf = NULL;
  16. ULONG ulSize = 32;
  17. PAGED_CODE();
  18. //
  19. // 1. pEproc --> handle
  20. //
  21. NtStatus = ObOpenObjectByPointer( pEproc,
  22. OBJ_KERNEL_HANDLE,
  23. NULL,
  24. 0,
  25. NULL,
  26. KernelMode,
  27. &hProc
  28. );
  29. if (!NT_SUCCESS(NtStatus))
  30. return NULL;
  31. //
  32. // 2. ZwQueryInformationProcess
  33. //
  34. while ( TRUE )
  35. {
  36. pBuf = ExAllocatePoolWithTag(NonPagedPool, ulSize, ALLOC_TAG);
  37. if ( !pBuf ) {
  38. ZwClose(hProc);
  39. return NULL;
  40. }
  41. NtStatus = ZwQueryInformationProcess( hProc,
  42. ProcessImageFileName,
  43. pBuf,
  44. ulSize,
  45. &ulSize);
  46. if ( NtStatus != STATUS_INFO_LENGTH_MISMATCH )
  47. break;
  48. ExFreePool(pBuf);
  49. }
  50. ZwClose(hProc);
  51. if ( !NT_SUCCESS(NtStatus) ) {
  52. ExFreePool(pBuf);
  53. return NULL;
  54. }
  55. //
  56. // 3. over
  57. //
  58. return (PUNICODE_STRING)pBuf;
  59. }


进程名使用完毕后记得 ExFreePool。


其实非要用硬编码的话,除了 EPROCESS.ImageFileNameEPROCESS 和 PROCESS.SeAuditProcessCreationInfo.ImageFileName 还有其它地方也可以获得进程名,例如 PEB 里的ldr。具体可以参考我以前写的彻底改掉进程名》。

0 0
原创粉丝点击