CyberArsenal

Welcome to the forum. We focus on computer and network security as well as reverse engineering - you should sign up to see content and better yet participate. There is no payment, credits system, reply-to-reveal, or any of that here. We want quality over quantity. This is an experiment and the idea is to build a good natured and mature/professional community. Please be kind and share! Thanks.

Hak5 Cloud C2 Analysis + Cracking method

sky

SKID
Staff member
Hello everyone, today I want to share an analysis of the Hak5 Cloud C2 tool.

What's Hak5 Cloud C2?

As stated on their website:
SHIP HAK5 GEAR. GET ON-SITE RESULTS.
PENTEST ANYWHERE, RIGHT FROM THE WEB

Cloud C² makes it easy for pentesters and security teams to deploy and manage Hak5 gear from the cloud.

CLOUD C² IS THE INTERSECTION OF OUR HARDWARE MASTERY, SOFTWARE EXPERTISE, AND ETERNAL AMBITION TO PROVIDE SMARTER PENTEST TOOLS.

In a nutshell, this software will help you be more easily and remotely 'persistent' during engagements, red team evaluations and pentests, while using your hardware tools like:
  • WiFi Pineapple
  • LAN Turtle
  • Packet Squirrel
  • Screen Crab
  • Shark Jack
  • Key Croc
More infos

How does it works?

This tool launches a web server with apis and a web user interface to manage the limited (no longer :p ) set of hardware tools.

How to setup

Take your server / pc / whatever you have ready and replace the current c2-<x.x.x>_<arch>_<os>(.exe) you used with the patched one and then do it:

Bash:
./c2_executable -hostname <your-current-ip>

And proceed with the installation at: http://<your-current-ip>:8080
You will be redirected to the configuration page.

At this point, enter your data and, as far as the licence is concerned, use the correct installation token (displayed on the terminal at first start-up) and any code.

Once the installation is complete, stop the executable and run HAK-C2-License-Toolkit and enter the crack.

Restart the executable again and you're done!


Licensing Analysis

The licence is managed with Internet support.
At installation, start-up and at certain times, it checks the licence with the API server.

I tried to force the analysis of a licence string, but it was not so easy.
I tried reversing the signature checking algorithm and, although I succeeded, it was not very helpful.
So I tried another approach, forcing the licence to the database and patching the entire licence checking function to return it.

At first glance, I noticed multiple calls to a certain local DB, but couldn't figure out which one it was.
After some research and deeper analysis, I discovered that the database in question is BoltDB ( More Info ), in a nutshell:


Bolt is a pure Go key/value store inspired by Howard Chu's LMDB project. The goal of the project is to provide a simple, fast, and reliable database for projects that don't require a full database server such as Postgres or MySQL.

Together with BoltDB, all data is encoded using Golang's native encoding, called GOB.
Writing the read function is quite simple, as all that is needed is to write a wrapper to connect to and read the data from the 'c2.db' database.
Or you can use the official CLI tool from BoltDB here.

I am now able to read the data and am presented with this list of buckets:


apilog
chatmessages
db_version
devices
log
migrations
news
notifications
roles
settings
setup
sites
status
unreadmessages
users

status and setup are the ones that look most promising, so let's see their keys:

Status:

Setup:
license
privateKey
publicKey
token

NOTE:
When running the tool for the first time without configuration, the licence key is not created, but when writing to a bucket/key that does not exist, it is created at the time of the update.
The tool is built on golang, so it may be difficult to reverse it at first, but fear not, we'll take care of it.
Now let's take a look at the licence verification class, which is 'github.com/hak5/cc-server/licence.Verify'.
In order it does:
  1. Check the licence key and version with their apis at: https://c2.hak5.org/api/v2/verify?key=XXXX-XXXX-XXXX-XXXX&product=productType
  2. Obtaining the content of the response and verifying its signature
    1. Load public key into memory
    2. Check signature
    3. Returns whether it is valid or not
  3. If the signature matches, a new licence variable is started following the licence struct.
  4. If a valid licence is returned, it is updated/saved in the database.
We now know how the licence works, but we have no idea how the licence structure is constructed.
From IDA we can get a good idea of the licence structure, but it is not perfect, as can be seen:

Code:
00000000 licence_License struc ; (sizeof=0x30, align=0x8, copyof_1893)
00000000                                         ; XREF: github.com_hak5_cc_server_database._ptr_Db.upgradeLicenseDBModel/r
00000000                                         ; github.com_hak5_cc_server_database._ptr_Db.ValidateAndSyncCurrentLicense/r ...
00000000 Key             string ?                ; XREF: github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel:loc_1416CE2/w
00000000                                         ; github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+185/w ...
00000010 Type            dq ?                    ; XREF: github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+14B/w
00000010                                         ; github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+195/w ...
00000018 UserLimit       dq ?                    ; XREF: github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+157/w
00000018                                         ; github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+1E1/r ...
00000020 DeviceLimit     dq ?                    ; XREF: github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+163/w
00000020                                         ; github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+19D/w ...
00000028 SiteLimit       dq ?                    ; XREF: github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+16F/w
00000028                                         ; github_com_hak5_cc_server_database__ptr_Db_upgradeLicenseDBModel+1F1/r ...
00000030 licence_License ends


Although we have the main variables used within the struct, we still don't know how to parse them from Database.
Since the software is written in Golang, I used a tool called Redress, from GoRe ToolKit [GORETK] ( More Infos ) to help me understand some of the information in the binary, such as the License and Status structures, so that I could analyse them from the BoltDB database and GOB decoding.

NOTE:
You can obtain the structures of a certain golang binary with this command:
Bash:
redress types struct <binary>

Here are the two structures:

Code:
/* License struct */
type licence.License struct {
    Key         string `json:"key"`
    Type        uint64 `json:"type"`
    UserLimit   uint64 `json:"user_limit"`
    DeviceLimit uint64 `json:"device_limit"`
    SiteLimit   uint64 `json:"site_limit"`
}

/* Status struct */
type models.Status struct {
    Hostname        string `json:"hostname"`
    Uptime          int64  `json:"uptime"`
    Version         string `json:"version"`
    UpdateAvailable bool   `json:"update_available"`
    UpdateChangelog string `json:"update_changelog"`
    UpdateVersion   string `json:"update_version"`
    UpdateDownload  string `json:"update_link"`
    Updating        bool   `json:"updating"`
    HostOS          string `json:"host_os"`
    Edition         string `json:"edition"`
    UserLimit       uint64 `json:"user_limit"`
    DeviceLimit     uint64 `json:"device_limit"`
    SiteLimit       uint64 `json:"site_limit"`
}

Now we know what to do, in order:
  1. Patch to the binary to force licence.Verify to always return
  2. Perform the first configuration
  3. Force the update of data within the DB, namely the STATUS and LICENSE keys.
  4. Enjoy!

So, to help me with this task, I wrote a "toolkit" (a lot of code) in golang to help me read/write and automate the actions on the BoltDB we have.
You can have a look at the official Bolt repository to understand how it works and how to work with it, I will skip this part because it is already in the toolkit code.

Binary Patch

All we have to do is replace the beginning of the function license.Verify with a return, so that it returns immediately.
(Using a nop instead of licence.Verify may cause crashes or memory management problems).

Here is a screenshot of the line that will be patched:
1702310152267.png

As you can see, we are going to replace the first line: cmp rsp, [r14+10h] with a simple retn.
From the HEX view, you can see that the operation is: 49 3B 66 10
We will then force it to return, replacing it with the well-known hexadecimal opcode C3, meaning retn:

NOTE:
We will replace all 4 hexadecimal opcodes to make it cleaner, so we will type C3 90 90, opcode 90 is just a nop, so we will not risk execution problems anyway.

Before:
1702310289740.png

After:
1702310598404.png

1702310643805.png


In this way, we force the tool never to check the licence and not to make any server-side calls.

After Binary Patch:

Now the tool will never check the licence, so we can set arbitrary values for our licences and it will work.
I will not dwell on how to work with BoltDB and GOB coding, as I assume you are able to read and study how they work.

I will only explain some parts of the "licence toolkit" I wrote with comments:

Code:
[..SNIP..]
/* Here we create a new variable containing a License struct */
license := License{
                    Key:         "Pwn3rzs",
                    Type:        2,
                    UserLimit:   uint64(10000),
                    DeviceLimit: uint64(10000),
                    SiteLimit:   uint64(10000),
                }
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
[..SNIP..]

/* Then we encode the struct as a gob buffer and we put the buffer inside the BoltDB setup bucket and license key */
bucketz := tx.Bucket([]byte("setup"))
[..SNIP..]
data := bucketz.Put([]byte("license"), buf.Bytes())
[..SNIP..]

/* After we inserted the license, we retrieve the Status data from the BoltDB */
var statusView Status
bucketz = tx.Bucket([]byte("status"))
v := bucketz.Get([]byte("status"))
decoder := gob.NewDecoder(bytes.NewReader(v))
[..SNIP..]

/* We then update the data inside, just the license one */
statusView.DeviceLimit = uint64(10000)
statusView.UserLimit = uint64(10000)
statusView.Edition = "teams"
statusView.SiteLimit = uint64(10000)
encoder = gob.NewEncoder(&buf)
_ = encoder.Encode(statusView)

/* We then encode it back to GOB encoded buffer and update the data inside the database */
 _ = bucketz.Put([]byte("status"), buf.Bytes())

/* And we are done !!! */

Now it's time to fire up our Hak5 Unlimited C2 and have some fun!

NOTE:
If for ANY reason, the licence should be cancelled or corrupted, simply redo the process with our 'toolkit'!

I hope you enjoyed this different content and that it not only intrigued you, but also helped you better understand how certain software can work.
Sometimes there is not only a need for patches/adjustments, but simply to 'undo' the licence checks and force it through a file/database.

If you have any questions, feel free to ask in the comments below!

We will release the patched binaries as soon as possible, but we are very busy lately!

Here you go the files:

c2-3.3.0_armv5_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_armv5_linux

c2-3.3.0_armv6_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_armv6_linux

c2-3.3.0_armv7_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_armv7_linux

c2-3.3.0_armv8_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_armv8_linux

c2-3.3.0_i386_windows.exe:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_i386_windows.exe

c2-3.3.0_i386_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_i386_linux

c2-3.3.0_amd64_windows.exe:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_amd64_windows.exe

c2-3.3.0_amd64_linux:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_amd64_linux

c2-3.3.0_amd64_darwin:
https://ponies.cloud/c2/hak5-cloud-c2/c2-3.3.0_amd64_darwin

HAK5-C2-Toolkit-win-i386:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-win-i386

HAK5-C2-Toolkit-lin-amd64:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-lin-amd64

HAK5-C2-Toolkit-lin-386:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-lin-386

HAK5-C2-Toolkit-win-amd64:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-win-amd64

HAK5-C2-Toolkit-mac-arm64:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-mac-arm64

HAK5-C2-Toolkit-mac-amd64:
https://ponies.cloud/c2/hak5-cloud-c2/HAK5-C2-Toolkit-mac-amd64

Or on Github:
https://github.com/Pwn3rzs/HAK5-C2-License-Toolkit/releases/tag/v3.3.0
 
Last edited:
Many thanks to you for sharing this information, looking forward to seeing the next one !
 
  • Love
Reactions: sky
Top