文章目錄:
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
版權所有,歡迎轉載,但轉載請註明: 轉載自 Zachary.XiaoZhen - 夢想的天空