Let's write a Beacon Object File for Havoc C2 - Part 3
Learn how to handle user choices in a Beacon Object File (BOF).
In this series of posts, I will create a Beacon Object File (BOF) that works with Havoc C2. I will start by implementing simple functionality and gradually increase the level of complexity.
If this is the first time you are learning about BOFs, I recommend that you read my posts, Enhancing C2 agent via Beacon Object Files (BOF) and Creating a simple beacon object file for Havoc C2 for a quick introduction to BOF and BOF development.
Follow my journey of 100 Days of Red Team on WhatsApp, Telegram or Discord.
In this part, I will cover how to handle user choices in a BOF. I will expand on the message box BOF developed previously. In the last part, we upgraded our message box BOF to accept a user defined message and display it in a message box on the target machine.
Now, lets add the functionality to let users choose whether they want to specify a custom message or display a hard-coded message. To do this, we will enable the BOF to accept two arguments. The first argument will specify the type of message the user wants to display, “custom” or “static”. The second argument is optional and will come into picture only if the value of the first argument is “custom”. It will let the user specify a custom message. We will also add sanity checks, both in the Python script and the BOF code. Actual check for user choice will be implemented in the BOF.
Note: Another way to approach this is to handle the user choice in the Python script itself and then call either of the previously developed BOFs based on the value of the first argument. Feel free to try it as an exercise.
To be able to understand the choice made by user, we need a way to compare strings and we already know that a lot of common functions (e.g., strlen, strcmp, etc.) are not available via a BOF. Therefore, to use a function like strcmp in a BOF we will need to include its prototype in the BOF code:
WINBASEAPI int __cdecl MSVCRT$strcmp(const char* _Str1, const char* _Str2);
The code for the updated BOF which handles user choice is as follows. Here I am using strcmp()
to understand user’s choice (“custom” or “static”) and accordingly invoke the MessageBoxA API to display the message.
The code is available here.
Save the code in .c file and use the following command to compile (use the beacon.h file available here):
x86_64-w64-mingw32-gcc -c message-box3.c -o message-box3.o -w
Next, let’s update the Python script to register the command to invoke this BOF. In the Python script, I have added sanity checks to validate the value of first argument and to perform an empty check for the second argument if the value of the first argument is “custom”.
The code is available here.
To load this in Havoc C2, go to Scripts → Script Manager → Load Script and select the message-box.py file.
To see the help for the message-box3
command, use
help message-box3
Now, lets run the command to display a static message:
message-box3 static
Finally, lets run the command to display a custom message:
message-box3 custom "This is a custom message from 100 Days of Red Team"
Note: The message-box3 BOF will not work properly when executed via the inline-execute command. There is a discrepancy in the way Havoc C2 handles arguments passed via inline-execute command. I will cover that in a later post.
The code for Message Box BOFs is available in 100 Days of Red Team GitHub repository.
Red Team Notes
- To handle user choice within a BOF we may need to rely on functions (strlen, strcmp etc.) that are not natively available within BOF. To use these functions, we need to include their prototype in the BOF code.
Follow my journey of 100 Days of Red Team on WhatsApp, Telegram or Discord.