HavocUI Python API Widget Class

go back / p4p1


Created on Wen. 10 Oct 2023



Another month an other pull request. Implementing cool stuff in the havoc python API was so fun last month I made the executive decision to continue. Implemented a new thing for me this time around a python class in c++.

I structured this blog post in 3 parts, the first section is for documentation, the second section is a quick example of using these functions and the final section is how I built the class. I ended up reviewing the code the next day and structured this addition to Havoc in 2 separate pull requests with the first one setting up the overall logic and then the second one defining the Widgets that would be directly in the UI and the dialog that will be used to create special pop-ups.

Documentation

widget = havocui.Widget("title of widget")

Definition of a widget sent the title as the argument. So that if the widget is set as a tab this title is shown for the Tab name.

dialog = havocui.Dialog("title of widget")

Creates a dialog window where you can add different widgets.

dialog.close()

Close the dialog window.

dialog.exec()

Open the dialog window

widget.addLabel("label text")

Add a label inside of the widget to have descriptive text inside of the widget. ALSO WORKS WITH THE DIALOG CLASS

widget.addButton("button text", button_callback)

Add a button to the widget with a callback function to be called when the button is clicked.
ALSO WORKS WITH THE DIALOG CLASS

widget.addCheckbox("checkbox text", checkbox_callback)

Add a checkbox to the widget with a callback function to be called when the checkbox is selected or unselected.
ALSO WORKS WITH THE DIALOG CLASS

widget.addCombobox(combo_box_callback, "option 1", "option 2", "option 3")

Add a combo box to the widget with a callback function to be called when the combo box option is selected. During the call to the callback function the function will be sent an argument with the number of the option.
ALSO WORKS WITH THE DIALOG CLASS

widget.addLineedit("placeholder", callback_when_finished_edit)

Adds a LineEdit input to retrieve from the user text. The callback function is called when the user has finished editing the line.
ALSO WORKS WITH THE DIALOG CLASS

widget.addCalendar(calendar_callback)

Adds a calendar to the widget to retrieve a date from the user. The callback function receives a string as argument of the date selected on the calendar.
ALSO WORKS WITH THE DIALOG CLASS

widget.setSmallTab()

Set the specified widget as a small tab to the right.

widget.setBottomTab()

Set the specified widget as a bottom tab.

Example

I decided to have a quick example to demonstrate how these API extensions could be used this time around to have a concrete use case. I decided to go with a simple script that would search on a selected instance for specific file types. During engagements I don't always remember the powershell command and instead of searching for it I though having this process automated could look kinda cute:

Here provided is the source code of the extension and also a quick screenshot of it running. You just need to select the instance and it will run the selected file type search for you directly in the instance output:

How I built it

To build these API calls I had a bit of a design contemplation. Logically the best was to go with classes since you would need to interact with the widgets / dialogs to add components and QT has a great parent feature system where you can using the parents inherit how the design will be. In this scenario with a lot of research (thx chat GPT and the rest of the Havoc source code) I put together the classes quite simply by looking at a few chat GPT example copy pasting the Demon class and replacing the calls to the functionality I wanted.

If you look at the first pull request. You can see that my original implementation was for the Dialog

Now that was because I just wanted to get something working up and running fast but a bit gross on my end. Since everything worked I decided to send it out in a PR directly just not to loose progress. But after sleeping on it I just thought the next day it was a bit of a dumb implementation. I then reworked it with a Dialog class and Widget class to really make the difference.

I also discovered through the source code that there are two functions to create new tabs on the right and the bottom. These functions are great so if I could have a class that generates a custom widget I could then import those in the python class and have widgets directly on the tab system instead of having them inside of a pop-up dialog to inherently give users more leverage on the GUI directly.


From here the next step would be to figure out how to implement the Vertical and Horizontal layout stuff and also things like tables and other QT elements. There are also a few errors where the library does not catch python errors so it will stop execution flow randomly. But I'll leave that for an other day!

I hope you enjoyed this blog post do follow me on github and linkedIn to see my latest advancements in penetration testing and red team stuff. I've also been learning sales on my spare time to change a bit from cyber security and I thought I could do a few blog posts about it once I get more concrete experience!

p3ng0s
arch linux iso

A linux distribution with my entire config pre-installed. Great for learning linux and pentesting with a steep learning curve.

wiki | repo
Questions / Feedback
For any questions or feedback you can contact me on LinkedIn or twitter / X. I also use twitter as a platform to update on new posts!
Donate
sponsor me image

If you like the content of my website you can help me out by donating through my github sponsors page.