Other Topics
Cobalt Strike operators and scripts communicate global events to the shared event log. Aggressor Scripts may respond to this information too. The event log events begin with event_
. To list for global notifications, use the event_notify hook.
on event_notify { println("I see: $1"); }
To post a message to the shared event log, use the &say function.
say("Hello World");
To post a major event or notification (not necessarily chit-chat), use the &elog function. The deconfliction server will automatically timestamp and store this information. This information will also show up in Cobalt Strike's Activity Report.
elog("system shutdown initiated");
Timers
If you'd like to execute a task periodically, then you should use one of Aggressor Script's timer events. These events are heartbeat_X, where X is 1s, 5s, 10s, 15s, 30s, 1m, 5m, 10m, 15m, 20m, 30m, or 60m.
on heartbeat_10s { println("I happen every 10 seconds"); }
Dialogs
Aggressor Script provides several functions to present and request information from the user. Use &show_message to prompt the user with a message. Use &show_error to prompt the user with an error.
bind Ctrl+M { show_message("I am a message!"); }
Use &prompt_text to create a dialog that asks the user for text input.
prompt_text("What is your name?", "Joe Smith", { show_message("Please $1 $+ , pleased to meet you"); });
The &prompt_confirm function is similar to &prompt_text, but instead it asks a yes/no question.
Custom Dialogs
Aggressor Script has an API to build custom dialogs. &dialog creates a dialog. A dialog consists of rows and buttons. A row is a label, a row name, a GUI component to take input, and possibly a helper to set the input. Buttons close the dialog and trigger a callback function. The argument to the callback function is a dictionary mapping each row's name to the value in its GUI component that takes input. Use &dialog_show to show a dialog, once it's built.
Here's a dialog that looks like Site Management -> Host File from Cobalt Strike:
sub callback { println("Dialog was actioned. Button: $2 Values: $3"); } $dialog = dialog("Host File", %(uri => "/download/file.ext", port => 80, mimetype => "automatic"), &callback); dialog_description($dialog, "Host a file through Cobalt Strike's web server"); drow_file($dialog, "file", "File:"); drow_text($dialog, "uri", "Local URI:"); drow_text($dialog, "host", "Local Host:", 20); drow_text($dialog, "port", "Local Port:"); drow_combobox($dialog, "mimetype", "Mime Type:", @("automatic", "application/octet-stream", "text/html", "text/plain")); dbutton_action($dialog, "Launch"); dbutton_help($dialog, "https://www.cobaltstrike.com/help-host-file"); dialog_show($dialog);
Let's walk through this example: The &dialog call creates the Host File dialog. The second parameter to &dialog is a dictionary that sets default values for the uri
, port
, and mimetype
rows.
The third parameter is a reference to a callback function. Aggressor Script will call this function when the user clicks
the Launch button.
&dialog_description places a description at the top of the dialog.
This dialog has five rows. The first row, made by &drow_file, has the label "File:", the name "file", and it takes input as a text field. There is a helper button to choose a file and populate the text field.
The others rows are conceptually similar. &dbutton_action and &dbutton_help create buttons that are centered at the bottom of the dialog.
&dialog_show shows the dialog.
Here's the dialog:
figure 73 - A scripted dialog.