Release v2.2 - Rinnegan

Brute Ratel v2.2 (codename Rinnegan) is now available for download. This release introduces several new features to the badger, so it’s strongly recommended to review the private release videos, and the documentation before using it. The Badger component was rewritten to support several new evasion functionalities. The user interface - Commander has also undergone changes to the core and now supports all the latest Debian/Ubuntu/Kali distribution as the core is now QT6.9, instead of the earlier 5.15. This means there would be full support for Ubuntu 24.04 Out-Of-Box or any latest distro with Gnome/KDE/Xfce etc.

In addition to the updates to the Badger showcased in the private 2.2 release video, this blog highlights the publicly shareable aspects of the release. These details have been carefully selected to ensure they do not compromise the confidentiality of sensitive Badger features, features that, in the past, have been leveraged by certain cybersecurity EDR vendors to develop detection signatures against the product.

  • Removed YARA signatures targeting indirect syscall techniques.
  • Implemented Task 65 API to retrieve comprehensive API metadata associated with listeners and badgers.
  • Eliminated the os_type field from listener and badger profiles.
  • Renamed the -sp option to -sample in the Ratel server CLI for better clarity.
  • Removed the artifact field from command metadata. Introduced detectionSeverity and detectionClass attributes in the help command within Commander to display telemetry data generated by the badger for each command.
  • The local IP field in the Commander used to display all IP address of the host on which the badger was executed. Its been reworked to display only the IP address which is used to establish the server connection. Other host IPs can still be retrieved using the ipstats command.
  • Excluded ws2_32.dll from the default set of preloaded libraries.
  • Resolved a server crash issue caused by malformed keying responses.
  • Modified the memexec command-line hooking strategy for improved stealth.
  • Corrected the scstart command to use only the SERVICE_START access flag when initiating services.
  • Renamed server_confs to sample_config for consistency and clarity.
  • Introduced a global dispatch variable (g_dispatch) in badger_exports.h to be used with BadgerDispatch and BadgerDispatchW, eliminating the need to explicitly pass dispatch to every function.
  • Added new BOF APIs: BadgerAddPrivilege and BadgerSetToken. (See documentation for usage details.)
  • Integrated 32 new API scripts along with a new Python library bruteratel.py, featuring asyncio-based WebSocket support to streamline Ratel API interaction.
  • Upgraded Commander to Qt version 6.9.
  • Revised default LDAP Sentinel queries to minimize YARA detection risks.
  • Updated sharpinline to evade stack-based detections in specific CLR invocation scenarios.
  • Added a conditional check in sharpinline to detect the presence of a custom AMSI.dll. If detected, AMSI function hooking is bypassed to avoid interference. (customer request)
  • Introduced four new commands — set_dotnet_store, clear_dotnet_store, list_dotnet_store, and sharpinline_dotnet_store — enabling secure in-memory storage and execution of up to 10 encrypted .NET assemblies without repeated dotnet file uploads. (See documentation for usage details.)
  • Added set working_hours, get working_hours, clear working_hours commands to configure badger callbacks during specific hours and days of the week (Sunday to Saturday).

Several heavy internal changes were made to the badger’s architecture to make it harder to detect. However, one of the main highlight of this release is the python library ‘bruteratel.py’. This library, alongside the 32 API scripts are now available in the api directory within the BRc4 package. The scripts released with this package are:

api_add_badger_profile.py api_build_stage.py api_list_badger_profile.py api_list_listener.py
api_add_badger.py api_download_file.py api_list_badgers.py api_manage_autoruns.py
api_add_listener.py api_host_file.py api_list_cmd_queue.py api_manage_clickscript.py
api_build_badger.py api_list_archive.py api_list_hosted.py api_manage_creds.py
api_manage_stager.py api_mitre_activity.py api_remove_badger_profile.py api_remove_badger.py
api_remove_cmd_queue.py api_remove_hosted_file.py api_remove_listener.py api_riot_control.py
api_send_badger_cmd.py api_server_backup.py api_user_activity.py  

All these APIs are self-explanatory when executed. For example, the api_list_listener.py, when executed returns the following information:

ninja@darkvortex: python3 api_list_listener.py -h
usage: api_list_listener.py [-h] -user  -password  -handler

List available listeners on the ratel server

optional arguments:
  -h, --help  show this help message and exit
  -user       api server username
  -password   api server password
  -handler    api server handler host and port. Eg: 127.0.0.1:8443

Example:
 python3 api_list_listener.py -user ninja -password pass@123 -handler 172.16.219.1:8443

ninja@darkvortex: python3 api_list_listener.py -u ninja -p pass@123 -handler 172.16.219.1:8443
[+] Authentication success
[+] listeners:
  -  doh-c2
  -  primary-c2

The API scripts serve as lightweight wrappers around the core bruteratel.py library. A quick inspection reveals that the script simply imports the bruteratel module and invokes the br_connect_handler and br_list_listeners functions from it.

import argparse
import asyncio
import bruteratel

async def main():
    parser = argparse.ArgumentParser(
        description="List available listeners on the ratel server",
        epilog="Example:\n python3 api_list_listener.py -user ninja -password pass@123 -handler 172.16.219.1:8443",
        formatter_class=argparse.RawTextHelpFormatter
    )
    parser.add_argument('-user',     type=str, required=True, help="api server username", metavar='')
    parser.add_argument('-password', type=str, required=True, help="api server password", metavar='')
    parser.add_argument('-handler',  type=str, required=True, help="api server handler host and port. Eg: 127.0.0.1:8443", metavar='')
    args = parser.parse_args()

    wsClient = await bruteratel.br_connect_handler(args.user, args.password, args.handler)
    print("[+] Authentication success")

    listenerlist = await bruteratel.br_list_listeners(wsClient)
    if listenerlist is not None:
        print("[+] listeners:")
        for i in listenerlist:
            print("  - ", i)
    else:
        print("[-] Error listing listeners")

    await wsClient.close(1000)

if __name__ == "__main__":
    asyncio.run(main())

The br_connect_handler function accepts the username, password, and connection details, and uses AsyncIO to establish a WebSocket connection with the Ratel server. Upon successful connection, it returns a WebSocket client object, which can be passed to other functions within the library to perform various actions. Each function may return a different type of output depending on its purpose.

This is as hard as it gets to call a function from the bruteratel library. The other features are described in more detail in the private discord channel of BRc4 and the documentation. Stay tuned and Happy Hacking.