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

这是个古老的话题,没有技术含量,只不过看到网上很多驱动代码在获取进程名时总喜欢去读偏移 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。具体可以参考我以前写的彻底改掉进程名》。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux设备驱动,由于多个进程或线程可能会同时访问设备,因此需要进行并发控制以确保设备的正确性和稳定性。以下是一些常用的Linux设备驱动的并发控制方法: 1. 互斥锁(mutex):互斥锁是用于保护临界区的一种机制,当一个进程或线程进入临界区时,其他进程或线程必须等待其退出后才能进入。Linux内核提供了多种不同类型的互斥锁,如spinlock、semaphore等,开发者可以根据实际需求选择不同的锁类型。 2. 读写锁(rwlock):读写锁是一种特殊的互斥锁,它允许同时有多个读者访问共享资源,但只允许一个写者访问。读写锁可以提高并发性能,但也需要考虑读写锁的开销。 3. 自旋锁(spinlock):自旋锁是一种忙等待的锁,当一个进程或线程无法获取锁时,它会一直循环尝试获取锁,直到获取成功。自旋锁对于短时间的临界区保护非常有效,但长时间的自旋会浪费CPU资源。 4. 原子操作(atomic):原子操作是一种不可分割的操作,可以保证操作的完整性和一致性。在Linux设备驱动,原子操作通常用于对共享变量的操作,如增减计数器等。 除了以上方法,还有一些高级的并发控制技术,如RCU、信号量(semaphore)等,它们可以根据具体的应用场景来选择使用。在开发Linux设备驱动时,需要根据实际情况选择合适的并发控制方法,并注意避免死锁和竞争条件等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值