登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 39|回复: 0

Win64驱动开发教程04-驱动程序与应用程序通信

[复制链接]

68

主题

2

回帖

91

积分

网站编辑

积分
91
发表于 7 天前 | 显示全部楼层 |阅读模式

在正式讲解内核编程之前,先讲讲如何编程实现加载驱动。加载驱动的标准方法只有一种,就是利用服务管理器函数加载。也就是我今天主要讲的 SCM 加载法。不过在继续讲之前,我还要想吹吹牛,讲讲加载驱动的故事。
加载驱动的方法其实有很多,在 2000/XP 这些古老的 NT5 系统上,公开的至少也有两种,一种是直接使用 NtLoadDriver 函数(SCM 加载法最终也是调用了此函数,不过我这里指的是不使用 SCM 系列函数,而是自己写入注册表项并直接调用 NtLoadDriver),另外一种是使用NtSetSystemInformation 来加载驱动。第二种加载驱动的方法非常“直接”,什么注册表项都不用写,把参数填写正确就能加载了。在第二种方法没公开之前,很多病毒都是用这种方法来对抗 HIPS(当然公开了之后很快就被和谐掉了)。除了这两种方法之外,据说还存在“地下方法”加载驱动,就是利用一些极少人关注的函数(比如 GDIXXX 这种看起来和加载驱动毫无关联的函数)来加载驱动。这些加载驱动的方法可以称为“漏洞”,在黑市上能卖很多钱,在被封杀之前,一个好用的漏洞换一套在广州市中心的房产绝对不是梦。所以大家想致富的话,就多挖掘一下驱动加载漏洞,挖到了好用漏洞就等于
挖到了房子。扯淡到此结束,下面详细讲解一下 SCM 加载驱动的要领。使用 SCM 系列函数加载卸载驱动的过程并不复杂,总体流程是:打开 SCM 管理器(获得 SCM 句柄)->创建驱动服务(获得服务句柄,如果服务已经存在,此步则变成打开服务)->启动服务->停止服务->移除服务->关闭服务句柄->关闭 SCM 句柄。如果要与驱动通信,则用 CreateFile 打开驱动的符号链接(可以理解成获得一个“通信句柄”),然后使用 DeviceIoControl 与驱动进行信息交互。如果曾经打开过驱动的符号链接,则必须在卸载驱动前关闭“通信句柄”,否则再次加载相同的驱动时会有一些麻烦。
DeviceIoControl 的参数也很好理解,只有 5 个重要参数:控制码,输入缓冲区,输入长度,输出缓冲区,输出长度。但这个控制码(以下简称 IOCTL)则是大有玄机的,这里则必须讲清楚。仔细看回 KrnlHW64.sys 的代码,里面关于 IOCTL 的定义是这么写的:
  1. #define IOCTL_IO_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,
  2. FILE_ANY_ACCESS)
  3. #define IOCTL_SAY_HELLO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED,
  4. FILE_ANY_ACCESS)
复制代码
  1. DWORD CTL_CODE_GEN(DWORD lngFunction)
  2. {
  3. //const DWORD FILE_DEVICE_UNKNOWN = 0x22;
  4. //const DWORD METHOD_BUFFERED = 0;
  5. //const DWORD FILE_ANY_ACCESS = 0;
  6. return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4)
  7. | METHOD_BUFFERED;
  8. }
复制代码


1.png

为了方便大家,我已经把这套东西整合成了一个类。
  1. #include <advapi32.h>
  2. #pragma comment(lib,”advapi32.lib”)
  3. class cDrvCtrl
  4. {
  5. public:
  6. cDrvCtrl()//初始化各个变量
  7. {
  8. m_pSysPath = NULL;
  9. m_pServiceName = NULL;
  10. m_pDisplayName = NULL;
  11. m_hSCManager = NULL;
  12. m_hService = NULL;
  13. m_hDriver = INVALID_HANDLE_VALUE;
  14. }
  15. ~cDrvCtrl()//清除垃圾
  16. {
  17. CloseServiceHandle(m_hService);
  18. CloseServiceHandle(m_hSCManager);
  19. CloseHandle(m_hDriver);
  20. }
  21. public:
  22. DWORD m_dwLastError; //最后的错误
  23. PCHAR m_pSysPath; //驱动路径
  24. PCHAR m_pServiceName; //服务名
  25. PCHAR m_pDisplayName; //显示名
  26. HANDLE m_hDriver; //驱动句柄
  27. SC_HANDLE m_hSCManager; //SCM句柄
  28. SC_HANDLE m_hService; //服务句柄
  29. BOOL Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName); //安装驱动服务
  30. BOOL Start();//启动驱动服务
  31. BOOL Stop();//停止驱动服务
  32. BOOL Remove();//移除驱动服务
  33. BOOL Open(PCHAR pLinkName); //打开驱动句柄
  34. BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD
  35. OutBuffLen); //IO控制
  36. };
  37. //打开已经存在的服务
  38. BOOL cDrvCtrl::GetSvcHandle(PCHAR pServiceName)
  39. {
  40. m_pServiceName = pServiceName;
  41. m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  42. if (NULL == m_hSCManager)
  43. {
  44. m_dwLastError = GetLastError();
  45. return FALSE;
  46. }
  47. m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
  48. if (NULL == m_hService)
  49. {
  50. CloseServiceHandle(m_hSCManager);
  51. return FALSE;
  52. }
  53. else
  54. {
  55. return TRUE;
  56. }
  57. }
  58. //安装服务服务
  59. BOOL cDrvCtrl::Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName)
  60. {
  61. m_pSysPath = pSysPath;
  62. m_pServiceName = pServiceName;
  63. m_pDisplayName = pDisplayName;
  64. m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  65. if (NULL == m_hSCManager)
  66. {
  67. m_dwLastError = GetLastError();
  68. return FALSE;
  69. }
  70. m_hService = CreateServiceA(m_hSCManager,m_pServiceName,m_pDisplayName,

  71. SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
  72. m_pSysPath,NULL,NULL,NULL,NULL,NULL);
  73. if (NULL == m_hService)
  74. {
  75. m_dwLastError = GetLastError();
  76. if (ERROR_SERVICE_EXISTS == m_dwLastError)
  77. {
  78. m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
  79. if (NULL == m_hService)
  80. {
  81. CloseServiceHandle(m_hSCManager);
  82. return FALSE;
  83. }
  84. }
  85. else
  86. {
  87. CloseServiceHandle(m_hSCManager);
  88. return FALSE;
  89. }
  90. }
  91. return TRUE;
  92. }
  93. //启动服务
  94. BOOL cDrvCtrl::Start()
  95. {
  96. if (!StartServiceA(m_hService,NULL,NULL))
  97. {
  98. m_dwLastError = GetLastError();
  99. return FALSE;
  100. }
  101. return TRUE;
  102. }
  103. //停止服务
  104. BOOL cDrvCtrl::Stop()
  105. {
  106. SERVICE_STATUS ss;
  107. if (!ControlService(m_hService,SERVICE_CONTROL_STOP,&ss))
  108. {
  109. m_dwLastError = GetLastError();
  110. return FALSE;
  111. }
  112. return TRUE;
  113. }
  114. //移除服务
  115. BOOL cDrvCtrl::Remove()
  116. {
  117. if (!DeleteService(m_hService))
  118. {
  119. m_dwLastError = GetLastError();
  120. return FALSE;
  121. }
  122. return TRUE;
  123. }
  124. //打开驱动的符号链接
  125. BOOL cDrvCtrl::Open(PCHAR pLinkName)//example: \\\\.\\xxoo
  126. {
  127. if (m_hDriver != INVALID_HANDLE_VALUE)
  128. return TRUE;
  129. m_hDriver = CreateFileA(pLinkName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
  130. FILE_ATTRIBUTE_NORMAL, 0);
  131. if(m_hDriver != INVALID_HANDLE_VALUE)
  132. return TRUE;
  133. else
  134. return FALSE;
  135. }
  136. DWORD cDrvCtrl::CTL_CODE_GEN(DWORD lngFunction)
  137. {
  138. return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) |
  139. METHOD_BUFFERED;
  140. }
  141. //和驱动实现通信的核心函数
  142. BOOL cDrvCtrl::IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff,
  143. DWORD OutBuffLen)
  144. {
  145. DWORD dw;
  146. return DeviceIoControl(m_hDriver, CTL_CODE_GEN
  147. (dwIoCode),InBuff,InBuffLen,OutBuff,OutBuffLen,&dw,NULL);
  148. }
复制代码
  1. int main()
  2. {
  3. BOOL b;
  4. cDrvCtrl dc;
  5. //设置驱动名称
  6. char szSysFile[MAX_PATH]={0};
  7. char szSvcLnkName[]="KrnlHW64";;
  8. GetAppPath(szSysFile);
  9. strcat(szSysFile,"KrnlHW64.sys");
  10. //安装并启动驱动
  11. b=dc.Install(szSysFile,szSvcLnkName,szSvcLnkName);
  12. b=dc.Start();
  13. printf("LoadDriver=%d\n",b);
  14. //“打开”驱动的符号链接
  15. dc.Open("\\\\.\\KrnlHW64");
  16. //使用控制码控制驱动(0x800:传入一个数字并返回一个数字)
  17. DWORD x=100,y=0;
  18. dc.IoControl(0x800,&x,sizeof(x),&y,sizeof(y));
  19. printf("INPUT=%ld\nOUTPUT=%ld\n",x,y);
  20. //使用控制码控制驱动(0x801:在DBGVIEW里显示HELLOWORLD)
  21. dc.IoControl(0x801,0,0,0,0);
  22. //关闭符号链接句柄
  23. CloseHandle(dc.m_hDriver);
  24. //停止并卸载驱动
  25. b=dc.Stop();
  26. b=dc.Remove();
  27. printf("UnloadDriver=%d\n",b);
  28. getchar();
  29. return 0;
  30. }
复制代码



QQ20250111-230846.png
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-1-18 09:45 , Processed in 0.059800 second(s), 29 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表