min722922 发表于 2014-6-3 15:59:26

进程隐藏与进程保护(SSDT Hook 实现)(三)

文章目录:

1. 引子:
2. 获取当前系统下所有进程:
3. 服务管理(安装,启动,停止,卸载):
4. 应用程序和内核程序通信:
5. 小结:

1. 引子:

关于这个 SSDT Hook 实现进程隐藏和进程保护呢,这是最后一篇博文了,
在文章的结尾处呢你可以下载到整个项目的实例程序以及代码,
程序可以在 XP、Server、Win7 上运行的,当然我是说的 32 位操作系统。

《进程隐藏与进程保护(SSDT Hook 实现)(一)》呢把 SSDT Hook 的原理说得差不多了,
地址:
《进程隐藏与进程保护(SSDT Hook 实现)(二)》则把 SSDT Hook 的实现说得差不多了,
地址:
这一篇博文介绍的则是在 Ring3 下编写 MFC 应用程序,并且让应用程序与内核程序通信,
即由应用程序将需要隐藏的进程或者是需要保护的进程的 PID 传递给内核程序,
然后在内核程序中就会将传递进来的这个 PID 进行隐藏或者保护 ~
在这里再给出这个应用程序的一张截图:



2. 获取当前系统下所有进程:

前面提到过,要想获取到系统下的所有进程,有三种方法,
第一种即是使用 ToolHelp 来获取,
第二种则是使用 PSAPI 来获取,
第三种则是使用 ntdll.dll 中的未文档化的 NtQuerySystemInformation 之类的 API 来获取(比较麻烦)。
而在这里我使用最简单的方式,即通过 PSAPI 中的 EnumProcesses 这个 API 来获取,
EnumProcesses API 可以获取到当前系统下所有进程的 PID,并且将 PID 存放在作为输出参数的数组当中,
其原型如下(可以看 MSDN):
   1:BOOL WINAPI EnumProcesses(   2:    __out         DWORD* pProcessIds,   3:    __in          DWORD cb,   4:    __out         DWORD* pBytesReturned   5:);   6:   

代码中使用(将获取到所有的 PID,然后将 PID 保存到 vector 容器中):
   1://遍历当前所有的进程,并且将进程 ID 填充到容器 vectorPID 中   2:void CSSDTProcessDlg::FillPIDVector()   3:{   4:      DWORD dwPIDArray;   5:      DWORD dwNeededBytes;   6:      DWORD dwProcCount;   7:      8:      dwNeededBytes = 0;   9:      dwProcCount = 0;10:      memset(dwPIDArray, 0, sizeof(DWORD) * MAX_PROCESS_COUNT);11:      if(NULL != EnumProcesses(dwPIDArray, sizeof(dwPIDArray), &dwNeededBytes))12:      {13:          dwProcCount = dwNeededBytes / sizeof(DWORD);14:      }15:   16:      BubbleSort(dwPIDArray, dwProcCount);17:   18:      ClearVector();19:      for(int i=0; i<dwProcCount; i++)20:      {21:          PROCESS_BIND procBind;22:          procBind.dwPID = dwPIDArray;23:          if(dwPIDArray == 0)24:          {25:            procBind.state = ProcessStateUnknown;26:          }27:          else28:          {29:            procBind.state = ProcessStateGeneral;30:          }31:          this->m_vctAllProcess.push_back(procBind);32:      }33:}


3. 服务管理(安装,启动,停止,卸载):

在 Windows 内核程序中,现在大体可以分为三类了,
第一类是 NT 式驱动程序;
第二类为 WDM 驱动程序;
第三类为 WDF 驱动程序;
其中,对于 NT 式驱动程序,其安装方式是很简单的,因为你可以将 NT 式驱动程序看做一个服务,
既然是服务的话,自然在 Windows 中可以通过 SCM API 来完成其安装,启动,停止和卸载等功能 ~
而至于 WDM 和 WDF 的话,如果其中涉及到了设备的话,还必须使用 INF 文件来实现安装 ~
而我们前面的那个 SSDT 内核程序就是基于 NT 式的驱动程序,所以可以通过 SCM API 来实现上面的这些功能,
至于如何使用 SCM API 来完成服务的安装、启动、停止和卸载功能的话,
下面就只是将服务的安装 API、启动 API、停止 API 和卸载 API 贴出来了 ~
至于这些代码的细细道来的话,可以参加上面给出的那篇博文的 ~
   1://=====================================================================================//   2://Name: bool InstallSvc()                                                            //   3://                                                                                     //   4://Descripion: 安装服务                                                               //   5://            lpszSvcName 为服务名称,                                                 //   6://            lpszDisplay 为显示在服务控制管理器中的名称,                           //   7://            lpszSvcBinaryPath 为服务映像文件所在路径,                               //   8://            dwSvcType 为服务类型                                                   //   9://            dwStartType 为服务启动类型                                             //10://=====================================================================================//11:bool CSSDTProcessDlg::InstallSvc(LPTSTR lpszSvcName, LPTSTR lpszDisplayName,12:          LPTSTR lpszSvcBinaryPath, DWORD dwSvcType, DWORD dwStartType)13:{14:      SC_HANDLE hSCM = NULL;15:      SC_HANDLE hSvc = NULL;16:   17:      AdjustProcessTokenPrivilege();18:   19:      hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);20:      if(NULL == hSCM)21:      {22:          OutputErrorMessage(TEXT("InstallSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !"));23:   24:          return FALSE;25:      }26:   27:      for(int i = 0; i < 3 && (NULL == hSvc); i++)28:      {29:          //SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIVE_PROCESS30:          hSvc = CreateService(hSCM, lpszSvcName, lpszDisplayName, SERVICE_ALL_ACCESS,   31:            dwSvcType, dwStartType, SERVICE_ERROR_NORMAL,   32:            lpszSvcBinaryPath, NULL, NULL, NULL, NULL, NULL);33:          if(NULL != hSvc)34:          {35:            if(NULL != hSvc)36:            {37:                  CloseServiceHandle(hSvc);38:            }39:            CloseServiceHandle(hSCM);40:            return TRUE;41:          }42:      }43:   44:      OutputErrorMessage(TEXT("InstallSvc - CreateService Failed , Error Code Is %d , Error Message Is %s !"));45:   46:      CloseServiceHandle(hSCM);47:   48:      return FALSE;49:}50:   51:   52://=====================================================================================//53://Name: bool UnInstallSvc()                                                            //54://                                                                                     //55://Descripion: 实现卸载服务                                                             //56://=====================================================================================//57:bool CSSDTProcessDlg::UnInstallSvc(LPTSTR lpszSvcName)58:{59:      SC_HANDLE hSCM = NULL;60:      SC_HANDLE hSvc = NULL;61:      bool rtResult = FALSE;62:   63:      AdjustProcessTokenPrivilege();64:   65:      hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);66:      if(NULL == hSCM)67:      {68:          OutputErrorMessage(TEXT("UnInstallSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !"));69:   70:          return FALSE;71:      }72:   73:      hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS);74:      if(NULL == hSvc)75:      {76:          OutputErrorMessage(TEXT("UnInstallSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !"));77:   78:          CloseServiceHandle(hSCM);79:   80:          return FALSE;81:      }82:   83:      rtResult = DeleteService(hSvc);84:   85:      CloseServiceHandle(hSvc);86:      CloseServiceHandle(hSCM);87:   88:      return rtResult;89:}90:   91:   92://=====================================================================================//93://Name: bool StartSvc()                                                                //94://                                                                                     //95://Descripion: 实现启动服务                                                             //96://=====================================================================================//97:bool CSSDTProcessDlg::StartSvc(LPTSTR lpszSvcName)98:{99:      SC_HANDLE hSCM = NULL; 100:      SC_HANDLE hSvc = NULL; 101:      bool rtResult = FALSE; 102:    103:      AdjustProcessTokenPrivilege(); 104:    105:      hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 106:      if(NULL == hSCM) 107:      { 108:          OutputErrorMessage(TEXT("StartSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !")); 109:    110:          return FALSE; 111:      } 112:    113:      hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS); 114:      if(NULL == hSvc) 115:      { 116:          OutputErrorMessage(TEXT("StartSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !")); 117:    118:          CloseServiceHandle(hSCM); 119:    120:          return FALSE; 121:      } 122:    123:      rtResult = StartService(hSvc, NULL, NULL); 124:    125:      CloseServiceHandle(hSvc); 126:      CloseServiceHandle(hSCM); 127:    128:      if(FALSE == rtResult) 129:      { 130:          if(ERROR_SERVICE_ALREADY_RUNNING == GetLastError()) 131:          { 132:            return TRUE; 133:          } 134:          else 135:          { 136:            OutputErrorMessage(TEXT("StartSvc - StartService Failed , Error Code Is %d , Error Message Is %s !")); 137:    138:            return FALSE; 139:          } 140:      } 141:      else 142:      { 143:          return TRUE; 144:      } 145:} 146:    147:    148://=====================================================================================// 149://Name: bool StopSvc()                                                               // 150://                                                                                     // 151://Descripion: 实现停止服务                                                             // 152://=====================================================================================// 153:bool CSSDTProcessDlg::StopSvc(LPTSTR lpszSvcName) 154:{ 155:      SC_HANDLE hSCM = NULL; 156:      SC_HANDLE hSvc = NULL; 157:      bool rtResult = FALSE; 158:    159:      SERVICE_STATUS svcStatus; 160:    161:      AdjustProcessTokenPrivilege(); 162:    163:      hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 164:      if(NULL == hSCM) 165:      { 166:          OutputErrorMessage(TEXT("StopSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !")); 167:    168:          return FALSE; 169:      } 170:    171:      hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS); 172:      if(NULL == hSvc) 173:      { 174:          OutputErrorMessage(TEXT("StopSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !")); 175:    176:          CloseServiceHandle(hSCM); 177:    178:          return FALSE; 179:      } 180:    181:      rtResult = ControlService(hSvc, SERVICE_CONTROL_STOP, &svcStatus); 182:      if(rtResult == FALSE) 183:      { 184:          OutputErrorMessage(TEXT("StopSvc - ControlService Failed , Error Code Is %d , Error Message Is %s !")); 185:      } 186:      CloseServiceHandle(hSvc); 187:      CloseServiceHandle(hSCM); 188:    189:      return rtResult; 190:}

那么服务的安装和启动放在那里比较合适,而服务的关闭和卸载又放在那里比较合适呢 ?
由于这个应用程序采用 MFC 开发,自然可以在 OnInitDialog()中安装和启动服务比较合适,
而后可以在对话框类的析构函数中关闭和卸载掉服务 ~
安装和启动服务:
   1:      wstring wStrSysPath = GetSysFilePath();   2:      BOOL bResult = InstallSvc(((LPTSTR)(LPCTSTR)SSDT01_SERVICE_NAME),    3:                              ((LPTSTR)(LPCTSTR)SSDT01_SERVICE_NAME),    4:                              ((LPTSTR)(LPCTSTR)wStrSysPath.c_str()),    5:                              SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START);   6:      if(FALSE == bResult)   7:      {   8:          MessageBox(_TEXT(" Install SSDT Service Failed , Application Auto Exit !"),   9:                     _TEXT("Application Error"), MB_OK | MB_ICONSTOP);10:          CDialogEx::OnCancel();          11:          return FALSE;12:      }13:      else14:      {15:          bResult = StartSvc(SSDT01_SERVICE_NAME);16:          if(FALSE == bResult)17:          {18:            MessageBox(_TEXT(" Start SSDT Service Failed , Application Auto Exit !"),   19:                         _TEXT("Application Error"), MB_OK | MB_ICONSTOP);20:            CDialogEx::OnCancel();21:            return FALSE;22:          }23:      }

停止并且将服务卸载掉:
   1:      ~CSSDTProcessDlg()   2:      {   3:          //在析构函数中关闭 SSDT 设备句柄   4:          if(this->m_hDevice)   5:          {   6:            CloseHandle(this->m_hDevice);   7:          }   8:      9:          //当发生析构函数时,停止服务并且卸载服务10:          StopSvc(SSDT01_SERVICE_NAME);11:          UnInstallSvc(SSDT01_SERVICE_NAME);12:      }


4. 应用程序和内核程序通信:

由前面的第二篇博文,可以知道,应用程序和内核程序的通信我是通过 DeviceIoControl 来完成的,
开发过内核程序的都清楚,应用程序和内核程序的通信最普遍的也就通过三个 API 来实现,
一个 ReadFile,一个 WriteFile,一个 DeviceIoContrl,
当然其中属 DeviceIoControl 功能最为强大,完全可以用其替换掉 ReadFile 和 WriteFile,
DeviceIoControl 原型(详细信息可以参考 MSDN):
   1:BOOL WINAPI DeviceIoControl(   2:    __in          HANDLE hDevice,   3:    __in          DWORD dwIoControlCode,   4:    __in          LPVOID lpInBuffer,   5:    __in          DWORD nInBufferSize,   6:    __out         LPVOID lpOutBuffer,   7:    __in          DWORD nOutBufferSize,   8:    __out         LPDWORD lpBytesReturned,   9:    __in          LPOVERLAPPED lpOverlapped10:);11:   

至于如何实现应用程序和内核程序的通信的话,在我的 Demo 中是这样做处理的,
首先在 OnInitDialog 事件中通过 CreateFile 打开我们所安装的服务中创建的设备,
(在 NT 式驱动程序中我创建了一个设备,这个设备用来实现应用程序和内核程序的通信),
然后在对话框类中保存有一个全局变量,这个全局变量即代表所打开的这个设备的句柄,


既然这个全局变量是保存的我们的设备的句柄,自然我们需要来获取到设备的句柄,并且将句柄赋值给该全局变量,
而这个呢,又是在 OnInitDialog 中完成的 ~
   1:      this->m_hDevice = CreateFile(SSDT01_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0,    2:                                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);   3:      if(INVALID_HANDLE_VALUE == this->m_hDevice)   4:      {   5:          MessageBox(_TEXT(" Open SSDT Device Failed , Application Auto Exit !"),    6:                     _TEXT("Application Error"), MB_OK | MB_ICONSTOP);   7:      8:          CDialogEx::OnCancel();   9:          return FALSE;10:      }

有了这个设备句柄,我们就可以通过其来实现和内核程序的通信了,
因为通过在应用程序中调用 DeviceIoControl 可以产生 IRP_MJ_DEVICE_CONTROL 的 IRP,
然后该 IRP 可以被驱动程序中的 DeviceIoControl 分发函数所处理 ~
我们的应用程序只需要将我们所要隐藏或者是需要保护的进程的 PID 通过 DeviceIoControl 传递给内核程序即可 !!!
所以我们在应用程序中只需要调用 DeviceIoContrl 即可 ~
下面给出的代码比较凌乱(重点请看 DeviceIoControl 的调用)
   1://隐藏进程或者取消对进程的隐藏   2:void CSSDTProcessDlg::OnBnClickedBtnHideorunhide()   3:{   4:      int nIndex;   5:      DWORD dwPID;   6:      CString cStrText;   7:      CString cStrState;   8:         9:      DWORD dwOutput;10:      BOOL bRet;11:      CHAR inBuffer;12:      CHAR outBuffer;13:      memset(inBuffer, 0, 10);14:      memset(outBuffer, 0, 10);15:   16:      dwPID = this->GetDlgItemInt(IDC_STATIC_SELECTED_PID);17:      this->GetDlgItemText(ID_BTN_HIDEORUNHIDE, cStrText);18:   19:      ultoa(dwPID, inBuffer, 10);20:   21:      nIndex = QueryItemIndexByPID(dwPID);22:      cStrState = this->m_ListCtrlProcess.GetItemText(nIndex, 4);23:   24:      if(cStrText.CompareNoCase(_TEXT("Hide")) == 0)25:      {26:          //隐藏 dwPID27:          bRet = DeviceIoControl(this->m_hDevice, IO_INSERT_HIDE_PROCESS, inBuffer, 10,   28:               &outBuffer, 10, &dwOutput, NULL);29:          if(bRet)30:          {31:            this->SetDlgItemText(ID_BTN_HIDEORUNHIDE, _TEXT("UnHide"));32:            if(cStrState.CompareNoCase(_TEXT("Protect")) == 0)33:            {34:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("HideAndProtect"));35:            }36:            else37:            {38:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("Hide"));39:            }40:            MessageBox(_TEXT(" Hide Process Sucess !"), _TEXT("Information"), MB_OK |   41:                     MB_ICONINFORMATION);42:          }43:          else44:          {45:            MessageBox(_TEXT(" Hide Process Failed !"), _TEXT("Warning"), MB_OK | MB_ICONERROR);46:          }47:      }48:      else49:      {50:          //解除 dwPID 隐藏51:          bRet = DeviceIoControl(this->m_hDevice, IO_REMOVE_HIDE_PROCESS, inBuffer, 10,   52:               &outBuffer, 10, &dwOutput, NULL);53:          if(bRet)54:          {55:            this->SetDlgItemText(ID_BTN_HIDEORUNHIDE, _TEXT("Hide"));56:            if(cStrState.CompareNoCase(_TEXT("Protect")) == 0 ||   57:               cStrState.CompareNoCase(_TEXT("HideAndProtect"))== 0)58:            {59:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("Protect"));60:            }61:            else62:            {63:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("General"));64:            }65:            MessageBox(_TEXT(" UnHide Process Sucess !"), _TEXT("Information"), MB_OK |   66:                  MB_ICONINFORMATION);67:          }68:          else69:          {70:            MessageBox(_TEXT(" UnHide Process Failed !"), _TEXT("Warning"), MB_OK | MB_ICONERROR);71:          }72:      }73:}74:   75:   76://保护进程或者取消对进程的保护操作77:void CSSDTProcessDlg::OnBnClickedBtnProtectorunprotect()78:{79:      int nIndex;80:      DWORD dwPID;81:      CString cStrText;82:      CString cStrState;83:   84:      DWORD dwOutput;85:      BOOL bRet;86:      CHAR inBuffer;87:      CHAR outBuffer;88:      memset(inBuffer, 0, 10);89:      memset(outBuffer, 0, 10);90:   91:      dwPID = this->GetDlgItemInt(IDC_STATIC_SELECTED_PID);92:      this->GetDlgItemText(ID_BTN_PROTECTORUNPROTECT, cStrText);93:   94:      ultoa(dwPID, inBuffer, 10);95:   96:      nIndex = QueryItemIndexByPID(dwPID);97:      cStrState = this->m_ListCtrlProcess.GetItemText(nIndex, 4);98:   99:      if(cStrText.CompareNoCase(_TEXT("Protect")) == 0) 100:      { 101:          //保护 dwPID 保护 102:          bRet = DeviceIoControl(this->m_hDevice, IO_INSERT_PROTECT_PROCESS, inBuffer, 10,103:               &outBuffer, 10, &dwOutput, NULL); 104:          if(bRet) 105:          { 106:            this->SetDlgItemText(ID_BTN_PROTECTORUNPROTECT, _TEXT("UnProtect")); 107:            if(cStrState.CompareNoCase(_TEXT("Hide"))== 0) 108:            { 109:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("HideAndProtect")); 110:            } 111:            else 112:            { 113:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("Protect")); 114:            } 115:            MessageBox(_TEXT(" Protect Process Sucess !"), _TEXT("Information"), MB_OK |116:                  MB_ICONINFORMATION); 117:          } 118:          else 119:          { 120:            MessageBox(_TEXT(" Protect Process Failed !"), _TEXT("Warning"), MB_OK | MB_ICONERROR); 121:          } 122:      } 123:      else 124:      { 125:          //解除 dwPID 保护 126:          bRet = DeviceIoControl(this->m_hDevice, IO_REMOVE_PROTECT_PROCESS, inBuffer, 10,127:               &outBuffer, 10, &dwOutput, NULL); 128:          if(bRet) 129:          { 130:            this->SetDlgItemText(ID_BTN_PROTECTORUNPROTECT, _TEXT("Protect")); 131:            if(cStrState.CompareNoCase(_TEXT("Hide")) == 0 ||132:                   cStrState.CompareNoCase(_TEXT("HideAndProtect")) == 0) 133:            { 134:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("Hide")); 135:            } 136:            else 137:            { 138:                  this->m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT("General")); 139:            } 140:            MessageBox(_TEXT(" UnProtect Process Sucess !"), _TEXT("Information"), MB_OK |141:                  MB_ICONINFORMATION); 142:          } 143:          else 144:          { 145:            MessageBox(_TEXT(" UnProtect Process Failed !"), _TEXT("Warning"), MB_OK | MB_ICONERROR); 146:          } 147:      } 148:}         
5. 小结:

介绍这个应用程序呢,还真是不好写,因为感觉整个 Demo 里面却是没有什么好介绍的,
无非就是获取到所有的进程,然后通过一个 ListCtrl 来显示这些数据,
然后用户选择一个进程,单击一下隐藏呢,我就在这个按钮的消息处理函数中和内核程序通过 DeviceIoControl 通信一下,
将这个进程的 PID 传递给内核程序,其他的就都不需要理会了 ~ 所以转来转去的,也没什么好些的,干脆就写到这里得了,
等下将整个 Demo 打个包,直接提供下载,我这里说得口干舌燥也没什么用,感兴趣的自己下载了源码去慢慢玩得了 ~
最后再总结一个 SSDT Hook 的优点,那就是 SSDT Hook 无论你是 Windows XP 还是 Server 或者 Vista 或者 Win7,
你都是可以很好的运行程序的,所以你下载的 Demo 你可以放心的在上面的这些操作系统上运行,当然 64 位的除外,
64 位的操作系统虽然我没有做过测试,但是我估摸着会蓝屏的 ~ 有兴趣的可以去蓝一次 ~

奈·Douma 发表于 2014-7-12 01:39:40

看看,楼主您辛苦了。。。

酸酸de快乐 发表于 2014-7-26 22:28:54

感恩无私的分享与奉献 :)

vp2008 发表于 2014-8-9 06:19:52

过来看看的

luori 发表于 2014-8-19 08:40:47

谢谢楼主,共同发展

习惯了、最初 发表于 2014-8-28 12:39:03

看看顺便顶一下

Jessica Alba 发表于 2014-9-4 11:49:10

看看顺便顶一下

uvgmn 发表于 2014-12-21 15:51:53

看起来不错

ymgsk123 发表于 2014-12-27 17:21:35

纯粹路过,没任何兴趣,仅仅是看在老用户份上回复一下

zhuzhuli 发表于 2014-12-30 06:44:23

珍爱生命,果断回帖。
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 进程隐藏与进程保护(SSDT Hook 实现)(三)