Skip to content

Instantly share code, notes, and snippets.

@EspressoCake
Created January 6, 2022 21:58
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save EspressoCake/7ba2371d9d6f7d3a6b0077563f819d36 to your computer and use it in GitHub Desktop.
Save EspressoCake/7ba2371d9d6f7d3a6b0077563f819d36 to your computer and use it in GitHub Desktop.
####################################################################################
# Author(s): Justin Lucas (@the_bit_diddler) and Fletcher Davis (@gymR4T) #
# Date: January 6, 2022 #
####################################################################################
####################################################################################
# Notes: This script is meant to be headless via ./agscript .... #
# It will keep track of initial beacon metadata, in case #
# they are cleared from the UI. #
# #
# 1) To have the JSON metadata generated: #
# - From the "Event Log" window: !fetch_json_archive #
# #
# 2) To pull the JSON log: #
# - Retrieve the logfile from the teamserver, via the provided path #
####################################################################################
global('%beaconHashmap');
# Initialize to nothing, keeping it all tidy
%beaconHashmap = %();
on beacon_initial {
$beacon = binfo($1);
if ($1 in keys(%beaconHashmap)) {
} else {
$beacon['initial_hit'] = ticks();
$beacon['admin_session'] = fetchIsAdmin($1);
%beaconHashmap[$1] = $beacon;
}
}
sub enrichArchiveLog {
local('$logitem');
local('@carray');
local('$cTime');
local('$attributeIndex');
$attributeIndex = 1;
foreach $logitem (archives()) {
if ( ($logitem['type'] ne "checkin") && ($logitem['type'] ne "webhit") && ("bid" in keys($logitem)) ) {
local('$currentData');
# Replace double quotes to keep JSON from breaking
$currentData = replace($logitem['data'], '"', "'");
# Replace backslashes with forward-slashes to keep JSON from breaking
$currentData = replace($currentData, '\\\\', '/');
$logitem['data'] = $currentData;
$cTime = $logitem['when'];
$logitem['when_friendly'] = dstamp($logitem['when']);
$logitem['index_value'] = $attributeIndex;
if ( strlen(binfo($logitem['bid'], "computer")) > 0 ) {
$logitem['host_context_admin'] = fetchIsAdmin($logitem['bid']);
$logitem['host_computername'] = binfo($logitem['bid'], "computer");
$logitem['host_external'] = binfo($logitem['bid'], "external");
$logitem['host_internal'] = binfo($logitem['bid'], "internal");
$logitem['host_listener'] = binfo($logitem['bid'], "listener");
$logitem['host_os_distribution'] = binfo($logitem['bid'], "os");
$logitem['host_os_build_version'] = binfo($logitem['bid'], "build");
$logitem['host_os_build_revision'] = binfo($logitem['bid'], "ver");
$logitem['host_process_id'] = binfo($logitem['bid'], "pid");
$logitem['host_process_name'] = binfo($logitem['bid'], "process");
$logitem['host_session_type'] = binfo($logitem['bid'], "session");
$logitem['host_username'] = binfo($logitem['bid'], "user");
if ($logitem['bid'] in keys(%beaconHashmap)) {
if (($cTime - %beaconHashmap[$logitem['bid']]['initial_hit']) < 0) {
%beaconHashmap[$logitem['bid']]['initial_hit'] = $cTime;
}
$logitem['host_initial_compromise'] = %beaconHashmap[$logitem['bid']]['initial_hit'];
$logitem['host_initial_compromise_friendly'] = dstamp(%beaconHashmap[$logitem['bid']]['initial_hit']);
$logitem['host_action_delta'] = $cTime - %beaconHashmap[$logitem['bid']]['initial_hit'];
}
} else if ( $logitem['bid'] in keys(%beaconHashmap) ) {
$logitem['host_context_admin'] = %beaconHashmap[$logitem['bid']]['admin_session'];
$logitem['host_computername'] = %beaconHashmap[$logitem['bid']]['computer'];
$logitem['host_external'] = %beaconHashmap[$logitem['bid']]['external'];
$logitem['host_internal'] = %beaconHashmap[$logitem['bid']]['internal'];
$logitem['host_listener'] = %beaconHashmap[$logitem['bid']]['listener'];
$logitem['host_os_distribution'] = %beaconHashmap[$logitem['bid']]['os'];
$logitem['host_os_build_version'] = %beaconHashmap[$logitem['bid']]['build'];
$logitem['host_os_build_revision'] = %beaconHashmap[$logitem['bid']]['ver'];
$logitem['host_process_id'] = %beaconHashmap[$logitem['bid']]['pid'];
$logitem['host_process_name'] = %beaconHashmap[$logitem['bid']]['process'];
$logitem['host_session_type'] = %beaconHashmap[$logitem['bid']]['session'];
$logitem['host_username'] = %beaconHashmap[$logitem['bid']]['user'];
if (($cTime - %beaconHashmap[$logitem['bid']]['initial_hit']) < 0) {
%beaconHashmap[$logitem['bid']]['initial_hit'] = $cTime;
}
$logitem['host_initial_compromise'] = %beaconHashmap[$logitem['bid']]['initial_hit'];
$logitem['host_initial_compromise_friendly'] = dstamp(%beaconHashmap[$logitem['bid']]['initial_hit']);
$logitem['host_action_delta'] = $cTime - %beaconHashmap[$logitem['bid']]['initial_hit'];
}
$attributeIndex++;
add(@carray, $logitem, size(@carray));
}
}
return @carray;
}
sub fetchIsAdmin {
if (-isadmin $1) {
return "1";
}
return "0";
}
sub writer {
local('$handle');
local('$filename');
local('$currentTick');
$currentTick = ticks();
$handle = openf(">" . script_resource("/") . $currentTick . "_output.json");
println($handle, $1);
closef($handle);
return "JSON-formatted history written to: " . script_resource("/") . $currentTick . "_output.json";
}
sub stringifyHashmap {
local('$individualItem');
local('$individualKeys');
local('$stringRepresentation');
local('$endOfObject');
local('$cindex');
$endOfObject = size($1) - 1;
$cindex = 0;
$stringRepresentation = '[' . "\n";
foreach $individualItem ($1) {
$stringRepresentation .= "\t" . '{' . "\n";
local('$keylength');
$keylength = size(keys($individualItem));
foreach $individualKeys (keys($individualItem)) {
if ($individualKeys ne keys($individualItem)[$keylength - 1]) {
$stringRepresentation .= "\t\t" . '"' . $individualKeys . '": "' . $individualItem[$individualKeys] . '"' . ",\n";
} else {
$stringRepresentation .= "\t\t" . '"' . $individualKeys . '": "' . $individualItem[$individualKeys] . '"' . "\n";
}
}
if ($cindex == $endOfObject) {
$stringRepresentation .= "\t" . '}' . "\n";
} else {
$stringRepresentation .= "\t" . '},' . "\n";
}
$cindex++;
}
$stringRepresentation .= ']' . "\n";
return $stringRepresentation;
}
sub orchestrateTransition {
local('$cval');
$cval = enrichArchiveLog();
return writer(stringifyHashmap($cval));
}
on event_public {
local('$user $content $when');
$user = $1;
$content = $2;
$when = $3;
if ($2 ismatch '!fetch_json_archive') {
say("Generating JSON archive for you now, " . $user);
privmsg($user, orchestrateTransition());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment