/*
 * args_bof.c -- BOF demonstrating argument parsing
 * Step 03: Shows how to use BeaconDataParse, BeaconDataExtract,
 *          BeaconDataInt, and BeaconFormatPrintf.
 *
 * Compile:
 *   x86_64-w64-mingw32-gcc -c args_bof.c -o args_bof.o
 *
 * Run with COFFLoader (hex-encoded argument buffer):
 *   COFFLoader.exe go args_bof.o <hex_args>
 *
 * The argument buffer format (from Cobalt Strike):
 *   [4-byte total_size] [4-byte str_len] [string_data] [4-byte int_value]
 */

#include <windows.h>
#include "beacon.h"

DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetCurrentProcessId(void);

void go(char* args, int len) {
    datap parser;
    BeaconDataParse(&parser, args, len);

    /* Extract a length-prefixed string */
    int hostname_len;
    char* hostname = BeaconDataExtract(&parser, &hostname_len);

    /* Extract a 4-byte integer */
    int port = BeaconDataInt(&parser);

    /* Display results using BeaconPrintf */
    BeaconPrintf(CALLBACK_OUTPUT, "[*] PID: %d\n", KERNEL32$GetCurrentProcessId());

    if (hostname && hostname_len > 0) {
        BeaconPrintf(CALLBACK_OUTPUT, "[*] Target: %s:%d\n", hostname, port);
    } else {
        BeaconPrintf(CALLBACK_ERROR, "[!] No arguments provided\n");
        BeaconPrintf(CALLBACK_OUTPUT, "[*] Usage: provide hostname (string) and port (int)\n");
    }

    /* Demonstrate formatp usage */
    formatp buffer;
    BeaconFormatAlloc(&buffer, 256);
    BeaconFormatPrintf(&buffer, "%-20s %s\n", "Parameter", "Value");
    BeaconFormatPrintf(&buffer, "%-20s %s\n", "---------", "-----");
    BeaconFormatPrintf(&buffer, "%-20s %s\n", "Hostname",
                       hostname ? hostname : "(none)");
    BeaconFormatPrintf(&buffer, "%-20s %d\n", "Port", port);

    int out_len;
    char* output = BeaconFormatToString(&buffer, &out_len);
    BeaconOutput(CALLBACK_OUTPUT, output, out_len);
    BeaconFormatFree(&buffer);
}
