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

xiaoxiao2021-02-28  86

文章目录:

                 

1. 引子:

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

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

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

5. 小结:

                

1. 引子:

                         

关于这个 SSDT Hook 实现进程隐藏和进程保护呢,这是最后一篇博文了,

在文章的结尾处呢你可以下载到整个项目的实例程序以及代码,

程序可以在 XP、Server、Win7 上运行的,当然我是说的 32 位操作系统。       

                  

《进程隐藏与进程保护(SSDT Hook 实现)(一)》呢把 SSDT Hook 的原理说得差不多了,

博文地址:http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html

《进程隐藏与进程保护(SSDT Hook 实现)(二)》则把 SSDT Hook 的实现说得差不多了,

博文地址:http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html

             

这一篇博文介绍的则是在 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[MAX_PROCESS_COUNT]; 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[i]; 23: if(dwPIDArray[i] == 0) 24: { 25: procBind.state = ProcessStateUnknown; 26: } 27: else 28: { 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 来完成服务的安装、启动、停止和卸载功能的话,

可以参见笔者的另外一篇博文《Windows 服务(附服务开发辅助工具)》,

博文地址为:http://www.cnblogs.com/BoyXiao/archive/2011/08/07/2130208.html

下面就只是将服务的安装 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_PROCESS 30: 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: else 14: { 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 lpOverlapped 10: ); 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[10]; 12: CHAR outBuffer[10]; 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: //隐藏 dwPID 27: 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: else 37: { 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: else 44: { 45: MessageBox(_TEXT(" Hide Process Failed ! "), _TEXT("Warning"), MB_OK | MB_ICONERROR); 46: } 47: } 48: else 49: { 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: else 62: { 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: else 69: { 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[10]; 87: CHAR outBuffer[10]; 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 位的操作系统虽然我没有做过测试,但是我估摸着会蓝屏的 ~ 有兴趣的可以去蓝一次 ~

           

下载 Demo Source Code

                                    

注:原文链接的源码下载地址失效了,我在其他地方下载到了源码,应该是另一位朋友找不到源码,按照博客的教程写出来的, 

http://download.csdn.net/detail/liujiayu2/9865256

           

版权所有,迎转载,但转载请注明: 转载自  Zachary.XiaoZhen - 梦想的天空

转载请注明原文地址: https://www.6miu.com/read-74273.html

最新回复(0)