├── .gitignore ├── Asktgt ├── asktgt.h ├── Asktgt.vcxproj.user ├── Asktgt.vcxproj.filters ├── asktgt.c └── Asktgt.vcxproj ├── Cerbere ├── tgt.c ├── network.h ├── handleArgs.h ├── asn1.h ├── helpers.h ├── handleArgs.c ├── helpers.c ├── Cerbere.vcxproj.filters ├── tgt.h ├── crypto.h ├── network.c ├── crypto.c ├── asn1.c └── Cerbere.vcxproj ├── Ptt ├── ptt.h ├── Ptt.vcxproj.user ├── Ptt.vcxproj.filters ├── ptt.c └── Ptt.vcxproj ├── README.md └── Cerbere.sln /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | **/x64/ -------------------------------------------------------------------------------- /Asktgt/asktgt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /Cerbere/tgt.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtterHacker/Cerbere/HEAD/Cerbere/tgt.c -------------------------------------------------------------------------------- /Cerbere/network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define WIN32_LEAN_AND_MEAN 3 | #include 4 | void sendBytes(char* server, char* port, PBYTE content, int contentSize); 5 | -------------------------------------------------------------------------------- /Asktgt/Asktgt.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Ptt/ptt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 5 | 6 | //typedef NTSTATUS(NTAPI *pLsaConnectUntrusted)(PHANDLE LsaHandle); 7 | //pLsaConnectUntrusted LsaConnectUntrusted; 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cerbere 2 | A project to play a little bit with Kerberos on Windows. 3 | - Inject ticket 4 | - Ask a tgt 5 | 6 | The project is not for production at all and the code is kinda messy. Will do some refactoring soon. 7 | 8 | # Resources 9 | The code is highly inspired from Rubeus and Mimikatz 10 | -------------------------------------------------------------------------------- /Cerbere/handleArgs.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | typedef struct _Args { 5 | char* key; 6 | char* value; 7 | } Args; 8 | 9 | 10 | int handleArgs(int argc, char** argv, Args** args); 11 | size_t strpos(char element, char* string); 12 | int Args_hasKey(Args* args, char* key); 13 | void Args_getKey(Args* args, char* key, char** value); 14 | -------------------------------------------------------------------------------- /Ptt/Ptt.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /ticket:thisismyticket /test:thisisatest /novalueparam 5 | WindowsLocalDebugger 6 | 7 | 8 | /ticket:thisismyticket /test:thisisatest /novalueparam 9 | WindowsLocalDebugger 10 | 11 | -------------------------------------------------------------------------------- /Cerbere/asn1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define ASN_BOOLEAN 0x01 5 | #define INTEGER 0x02 6 | #define BIT_STRING 0x03 7 | #define OCTET_STRING 0x04 8 | #define GENERALIZED_TIME 0x18 9 | #define GENERAL_STRING 0x1B 10 | #define SEQUENCE 0x30 11 | #define APPLICATION 0x60 12 | #define LIST 0xA0 13 | 14 | typedef struct _ASN { 15 | int tag; 16 | int isAsnContent; 17 | union { 18 | struct _ASN* asnContent; 19 | unsigned char* content; 20 | }; 21 | size_t contentSize; 22 | }ASN; 23 | 24 | size_t getAsnSize(ASN* asn, int includeLengthByte); 25 | void asn2byte(ASN* asn, unsigned char** result, size_t* size, size_t* pointer); 26 | void printAsn(ASN* asn); 27 | void addChild(ASN* parent, ASN* child); 28 | void newInteger(ASN* asn, int value); 29 | int isAsnContent(PBYTE pointer, int parentSize); 30 | PBYTE byte2asn(PBYTE asnByte, ASN* asn, int parentSize); 31 | int getListElementByIndex(ASN* asn, int element, ASN* result); -------------------------------------------------------------------------------- /Cerbere/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define DEBUG(x, ...) printf(x, ##__VA_ARGS__) 9 | 10 | 11 | static char encoding_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 12 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 13 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 14 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 15 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 16 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 17 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 18 | '4', '5', '6', '7', '8', '9', '+', '/' }; 19 | static char* decoding_table = NULL; 20 | static int mod_table[] = { 0, 2, 1 }; 21 | 22 | void build_decoding_table(); 23 | unsigned char* base64_decode(const char* data, size_t input_length, size_t* output_length); 24 | wchar_t* char2wc(const char* buff); -------------------------------------------------------------------------------- /Ptt/Ptt.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /Asktgt/Asktgt.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /Cerbere/handleArgs.c: -------------------------------------------------------------------------------- 1 | #include "handleArgs.h" 2 | #include 3 | #include 4 | 5 | size_t strpos(char element, char* string) { 6 | size_t result = -1; 7 | for (int i = 0; i < strlen(string); i++) { 8 | if (string[i] == element) { 9 | return i; 10 | } 11 | } 12 | return result; 13 | } 14 | 15 | int handleArgs(int argc, char** argv, Args** args) { 16 | *args = calloc(argc, sizeof(Args)); 17 | if (!(*args)) { 18 | printf("[x] Failed to allocate args structure\n"); 19 | exit(-1); 20 | } 21 | for (int i = 1; i < argc; i++) { 22 | if (strlen(argv[i]) > 0 && argv[i][0] == '/') { 23 | size_t pos = strpos(':', argv[i]); 24 | int isSwitch = pos == -1; 25 | if (pos == -1) { pos = strlen(argv[i]); } 26 | (*args)[i - 1].key = calloc(pos, sizeof(char)); 27 | if (!(*args)[i - 1].key) { 28 | printf("[x] Failed to allocate args key element\n"); 29 | exit(-1); 30 | } 31 | CopyMemory((*args)[i - 1].key, &argv[i][1], pos - 1); 32 | 33 | if (isSwitch) {continue;} 34 | 35 | (*args)[i - 1].value = calloc(strlen(argv[i]) - pos, sizeof(char)); 36 | if (!(*args)[i - 1].value) { 37 | printf("[x] Failed to allocate args value element\n"); 38 | exit(-1); 39 | } 40 | CopyMemory((*args)[i - 1].value, &argv[i][pos + 1], strlen(argv[i]) - pos - 1); 41 | } 42 | } 43 | } 44 | 45 | int Args_hasKey(Args* args, char* key) { 46 | Args* currentArg = args; 47 | while(currentArg->key){ 48 | if (strcmp(currentArg->key, key) == 0) { 49 | return 1; 50 | } 51 | currentArg += 1; 52 | } 53 | return 0; 54 | } 55 | 56 | void Args_getKey(Args* args, char* key, char** value) { 57 | Args* currentArg = args; 58 | while (currentArg->key) { 59 | if (strcmp(currentArg->key, key) == 0) { 60 | *value = calloc(strlen(currentArg->value)+1, sizeof(char)); 61 | CopyMemory(*value, currentArg->value, strlen(currentArg->value)); 62 | return; 63 | } 64 | currentArg += 1; 65 | } 66 | } -------------------------------------------------------------------------------- /Cerbere/helpers.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include "helpers.h" 3 | 4 | void build_decoding_table() { 5 | 6 | decoding_table = (char*)malloc(256); 7 | if (decoding_table == NULL) { 8 | DEBUG("[x] Cannot allocate memory for the decoding table\n"); 9 | exit(-1); 10 | } 11 | for (int i = 0; i < 64; i++) { 12 | decoding_table[(unsigned char)encoding_table[i]] = i; 13 | } 14 | } 15 | 16 | unsigned char* base64_decode(const char* data, size_t input_length, size_t* output_length) { 17 | 18 | if (decoding_table == NULL) build_decoding_table(); 19 | 20 | if (input_length % 4 != 0) return NULL; 21 | 22 | *output_length = input_length / 4 * 3; 23 | if (data[input_length - 1] == '=') { 24 | (*output_length)--; 25 | } 26 | if (data[input_length - 2] == '=') (*output_length)--; 27 | 28 | unsigned char* decoded_data = (unsigned char*)malloc(*output_length); 29 | if (decoded_data == NULL) return NULL; 30 | 31 | for (int i = 0, j = 0; i < input_length;) { 32 | 33 | DWORD sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; 34 | DWORD sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; 35 | DWORD sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; 36 | DWORD sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; 37 | 38 | DWORD triple = (sextet_a << 3 * 6) 39 | + (sextet_b << 2 * 6) 40 | + (sextet_c << 1 * 6) 41 | + (sextet_d << 0 * 6); 42 | 43 | if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; 44 | if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; 45 | if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; 46 | } 47 | 48 | return decoded_data; 49 | } 50 | 51 | wchar_t* char2wc(const char* buff) { 52 | const size_t cSize = strlen(buff) + 1; 53 | wchar_t* wc = malloc(cSize * sizeof(wchar_t)); 54 | mbstowcs(wc, buff, cSize); 55 | return wc; 56 | } -------------------------------------------------------------------------------- /Cerbere/Cerbere.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | -------------------------------------------------------------------------------- /Cerbere/tgt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "asn1.h" 4 | 5 | #define VALIDATE 0x00000001 6 | #define RENEW 0x00000002 7 | #define UNUSED29 0x00000004 8 | #define ENCTKTINSKEY 0x00000008 9 | #define RENEWABLEOK 0x00000010 10 | #define DISABLETRANSITEDCHECK 0x00000020 11 | #define UNUSED16 0x0000FFC0 12 | #define CONSTRAINED_DELEGATION 0x00020000 13 | #define CANONICALIZE 0x00010000 14 | #define CNAMEINADDLTKT 0x00004000 15 | #define OK_AS_DELEGATE 0x00040000 16 | #define REQUEST_ANONYMOUS 0x00008000 17 | #define UNUSED12 0x00080000 18 | #define OPTHARDWAREAUTH 0x00100000 19 | #define PREAUTHENT 0x00200000 20 | #define INITIAL 0x00400000 21 | #define RENEWABLE 0x00800000 22 | #define UNUSED7 0x01000000 23 | #define POSTDATED 0x02000000 24 | #define ALLOWPOSTDATE 0x04000000 25 | #define PROXY 0x08000000 26 | #define PROXIABLE 0x10000000 27 | #define FORWARDED 0x20000000 28 | #define FORWARDABLE 0x40000000 29 | #define RESERVED 0x80000000 30 | 31 | 32 | #define AS_REQ 10 33 | #define AS_REP 11 34 | #define TGS_REQ 12 35 | #define TGS_REP 13 36 | #define AP_REQ 14 37 | #define AP_REP 15 38 | #define TGT_REQ 16 // KRB-TGT-REQUEST for U2U 39 | #define TGT_REP 17 // KRB-TGT-REPLY for U2U 40 | #define SAFE 20 41 | #define PRIV 21 42 | #define CRED 22 43 | #define ERROR 30 44 | 45 | 46 | typedef struct _ASREQ { 47 | int pvno; 48 | int messageType; 49 | char* cname; 50 | char* realm; 51 | char* sname; 52 | time_t from; 53 | size_t till; // offset 54 | time_t rtime; 55 | int nonce; 56 | int etype; 57 | unsigned char* hostAddress; 58 | int kdcoptions; 59 | char* username; 60 | char* domain; 61 | char* password; 62 | char* service; 63 | char* resource; 64 | char* dcIp; 65 | } ASREQ; 66 | 67 | void initASREQ(ASN* asn); 68 | void addPvno(ASREQ* asreq, ASN* asn); 69 | void addMsgType(ASREQ* asreq, ASN* asn); 70 | void initPadata(ASN* asn, int size); 71 | void addEncTimestamp(ASREQ* asreq, ASN* asn); 72 | void addPacRequest(ASREQ* asreq, ASN* asn); 73 | void initKdcReqBody(ASN *asn); 74 | void addKdcOptions(ASREQ *asreq, ASN *asn); 75 | void addCname(ASREQ* asreq, ASN* asn); 76 | void addRealm(ASREQ* asreq, ASN* asn); 77 | void addPrincipalName(ASREQ* asreq, ASN* asn); 78 | void addExpirationDate(ASREQ* asreq, ASN* asn); 79 | void addNonce(ASREQ* asreq, ASN* asn); 80 | void addEtype(ASREQ* asreq, ASN* asn); 81 | void handleASREP(ASREQ* asreq, ASN* asreqAsn, PBYTE response, int responseSize); 82 | char* lookupKrbErrorCode(int errorCode); 83 | 84 | -------------------------------------------------------------------------------- /Cerbere.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32421.90 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ptt", "Ptt\Ptt.vcxproj", "{7FCCA2CA-938A-41B1-A04D-86D8606E917D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Asktgt", "Asktgt\Asktgt.vcxproj", "{702D109A-42C5-4E98-BD8C-81D4CBA10830}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cerbere", "Cerbere\Cerbere.vcxproj", "{0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Debug|x64.ActiveCfg = Debug|x64 21 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Debug|x64.Build.0 = Debug|x64 22 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Debug|x86.ActiveCfg = Debug|Win32 23 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Debug|x86.Build.0 = Debug|Win32 24 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Release|x64.ActiveCfg = Release|x64 25 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Release|x64.Build.0 = Release|x64 26 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Release|x86.ActiveCfg = Release|Win32 27 | {7FCCA2CA-938A-41B1-A04D-86D8606E917D}.Release|x86.Build.0 = Release|Win32 28 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Debug|x64.ActiveCfg = Debug|x64 29 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Debug|x64.Build.0 = Debug|x64 30 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Debug|x86.ActiveCfg = Debug|Win32 31 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Debug|x86.Build.0 = Debug|Win32 32 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Release|x64.ActiveCfg = Release|x64 33 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Release|x64.Build.0 = Release|x64 34 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Release|x86.ActiveCfg = Release|Win32 35 | {702D109A-42C5-4E98-BD8C-81D4CBA10830}.Release|x86.Build.0 = Release|Win32 36 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Debug|x64.ActiveCfg = Debug|x64 37 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Debug|x64.Build.0 = Debug|x64 38 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Debug|x86.ActiveCfg = Debug|Win32 39 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Debug|x86.Build.0 = Debug|Win32 40 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Release|x64.ActiveCfg = Release|x64 41 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Release|x64.Build.0 = Release|x64 42 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Release|x86.ActiveCfg = Release|Win32 43 | {0174F7CA-57E0-4C17-9612-E08D1E5DC4E6}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {03B98EF0-30FA-43CD-B54C-3D9E0186A81C} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /Asktgt/asktgt.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include "asktgt.h" 3 | #include "handleArgs.h" 4 | #include "windows.h" 5 | #include "asn1.h" 6 | #include "tgt.h" 7 | #include "time.h" 8 | #include "crypto.h" 9 | #include "network.h" 10 | 11 | void buildASREQ() { 12 | ASN asn; 13 | ASREQ asreq = { 14 | .pvno = 5, 15 | .messageType = 10, 16 | .password = "Password@123!", 17 | .kdcoptions = FORWARDABLE | RENEWABLE | RENEWABLEOK, 18 | .cname = "chen", 19 | .realm = "KANTO.LAB", 20 | .service = "krbtgt", 21 | .resource = "KANTO.LAB", 22 | .till = 4*3600, //valid for 4h 23 | .dcIp = "10.253.1.2", 24 | .etype = RC4_HMAC, 25 | }; 26 | initASREQ(&asn); 27 | addPvno(&asreq, &asn); 28 | addMsgType(&asreq, &asn); 29 | 30 | //KDC-REQ 31 | initPadata(&asn, 2); 32 | addEncTimestamp(&asreq, &asn); 33 | addPacRequest(&asreq, &asn); 34 | 35 | 36 | //KDC-BODY 37 | initKdcReqBody(&asn); 38 | addKdcOptions(&asreq, &asn); 39 | addCname(&asreq, &asn); 40 | addRealm(&asreq, &asn); 41 | addPrincipalName(&asreq, &asn); 42 | addExpirationDate(&asreq, &asn); 43 | addNonce(&asreq, &asn); 44 | addEtype(&asreq, &asn); 45 | 46 | printf("[+] ASREQ request : "); 47 | printAsn(&asn); 48 | 49 | size_t pointer = 0; 50 | size_t size = 0; 51 | char* result = NULL; 52 | PBYTE response = NULL; 53 | int responseSize = 0; 54 | asn2byte(&asn, &result, &size, &pointer); 55 | sendBytes(asreq.dcIp, "88", result, size, &response, &responseSize); 56 | 57 | printf("[+] KDC response : "); 58 | for (int i = 0; i < responseSize; i++) { 59 | printf("%02x", response[i]); 60 | } 61 | printf("\n"); 62 | handleASREP(&asreq, &asn, response, responseSize); 63 | return; 64 | } 65 | 66 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 67 | int main(int argc, char** argv) { 68 | loadCryptoFunctions(); 69 | buildASREQ(); 70 | return 0; 71 | 72 | ASN asn = { 73 | .tag = APPLICATION | 10, 74 | .isAsnContent = 1, 75 | .asnContent = calloc(100, sizeof(ASN)), 76 | }; 77 | ASN asnContent = { 78 | .tag = INTEGER, 79 | .content = "\x06", 80 | .isAsnContent = 0, 81 | .contentSize = 1, 82 | }; 83 | addChild(&asn, &asnContent); 84 | 85 | size_t pointer = 0; 86 | size_t size = 0; 87 | char* result = NULL; 88 | PBYTE response = NULL; 89 | int responseSize = 0; 90 | asn2byte(&asn, &result, &size, &pointer); 91 | printAsn(&asn); 92 | ASN resultAsn; 93 | byte2asn(result, &resultAsn, size); 94 | printAsn(&resultAsn); 95 | 96 | return 0; 97 | //Args* args; 98 | //handleArgs(argc, argv, &args); 99 | // 100 | //ASN asn = { 101 | //.tag = APPLICATION | 10, 102 | //.isAsnContent = 1, 103 | //.asnContent = calloc(100, sizeof(ASN)), 104 | //}; 105 | // 106 | //ASN asnContent = { 107 | // .tag = INTEGER, 108 | // .content = "\x06", 109 | // .isAsnContent = 0, 110 | // .contentSize = 1, 111 | //}; 112 | // 113 | //ASN asnContent1 = { 114 | //.tag = INTEGER, 115 | //.content = "\x10", 116 | //.isAsnContent = 0, 117 | //.contentSize = 1, 118 | //}; 119 | // 120 | //for (int i = 0; i < 65; i++) { 121 | // asn.asnContent[i] = asnContent; 122 | //} 123 | // 124 | //unsigned char* asnByte = NULL; 125 | //size_t size = 0; 126 | //size_t pointer = 0; 127 | //asn2byte(&asn, &asnByte, &size, &pointer); 128 | //for (int i = 0; i < size; i++) { 129 | // printf("%02x", asnByte[i]); 130 | //} 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /Ptt/ptt.c: -------------------------------------------------------------------------------- 1 | #include "ptt.h" 2 | #include "helpers.h" 3 | #include "ntsecapi.h" 4 | #include "handleArgs.h" 5 | 6 | #pragma comment (lib, "Secur32.lib") 7 | 8 | 9 | int getLuid(PLUID luid) { 10 | TOKEN_STATISTICS tokenStats; 11 | int tokenLength; 12 | 13 | HANDLE token; 14 | BOOL status = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); 15 | if (!status) { 16 | DEBUG("Cannot open the process token : %d\n", GetLastError()); 17 | return -1; 18 | } 19 | 20 | status = GetTokenInformation(token, TokenStatistics, &tokenStats, sizeof(TOKEN_STATISTICS), &tokenLength); 21 | if (!status) { 22 | DEBUG("Cannot get token information : %d\n", GetLastError()); 23 | return -1; 24 | } 25 | luid->HighPart = tokenStats.AuthenticationId.HighPart; 26 | luid->LowPart = tokenStats.AuthenticationId.LowPart; 27 | } 28 | 29 | int main(int argc, char** argv) { 30 | Args* args; 31 | handleArgs(argc, argv, &args); 32 | if (!Args_hasKey(args, "ticket")) { 33 | DEBUG("Usage : %s /ticket:b64ticket", argv[0]); 34 | return 0; 35 | } 36 | 37 | unsigned int kirbiSize; 38 | char* ticket; 39 | Args_getKey(args, "ticket", &ticket); 40 | unsigned char *kirbiTicket = base64_decode(ticket, strlen(ticket), &kirbiSize); 41 | if (kirbiSize == 0) { 42 | DEBUG("[x] Base64 decode failed \n"); 43 | return 0; 44 | } 45 | 46 | HANDLE lsaHandle = NULL; 47 | NTSTATUS status = LsaConnectUntrusted(&lsaHandle); 48 | if (!NT_SUCCESS(status) || !lsaHandle) { 49 | DEBUG("[x] Cannot connect to LSA provider : %lu\n", LsaNtStatusToWinError(status)); 50 | return 0; 51 | } 52 | 53 | LSA_STRING lsaString = { 54 | .Buffer = "kerberos", 55 | .Length = (USHORT)strlen("kerberos"), 56 | .MaximumLength = (USHORT)strlen("kerberos") + 1 57 | }; 58 | 59 | ULONG authenticationPackage = 0; 60 | status = LsaLookupAuthenticationPackage(lsaHandle, &lsaString, &authenticationPackage); 61 | if (!NT_SUCCESS(status)) { 62 | DEBUG("[x] Cannot run LsaAuthenticationPackage : %lu\n", LsaNtStatusToWinError(status)); 63 | return 0; 64 | } 65 | 66 | LUID targetLuid; 67 | getLuid(&targetLuid); 68 | KERB_SUBMIT_TKT_REQUEST request = { 69 | .MessageType = KerbSubmitTicketMessage, 70 | .KerbCredSize = kirbiSize, 71 | .KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST), 72 | .LogonId = targetLuid 73 | }; 74 | 75 | PVOID protocolReturnBuffer = NULL; 76 | ULONG protocolReturnBufferSize; 77 | NTSTATUS protocolStatus; 78 | size_t requestBufferSize = sizeof(request) + kirbiSize; 79 | unsigned char* requestBuff = calloc(requestBufferSize, sizeof(char)); 80 | if (!requestBuff) { 81 | DEBUG("[x]Cannot allocate request buffer\n"); 82 | return 0; 83 | } 84 | CopyMemory(requestBuff, &request, sizeof(request)); 85 | CopyMemory(requestBuff + request.KerbCredOffset, kirbiTicket, kirbiSize * sizeof(char)); 86 | 87 | status = LsaCallAuthenticationPackage( 88 | lsaHandle, 89 | authenticationPackage, 90 | requestBuff, 91 | requestBufferSize, 92 | protocolReturnBuffer, 93 | &protocolReturnBufferSize, 94 | &protocolStatus 95 | ); 96 | 97 | free(requestBuff); 98 | 99 | if (!NT_SUCCESS(status)) { 100 | DEBUG("[x] Failed to call authentication package : %lu\n", LsaNtStatusToWinError(status)); 101 | return 0; 102 | } 103 | if (!NT_SUCCESS(protocolStatus)) { 104 | DEBUG("[x] Failed to call authentication package : %lu\n", LsaNtStatusToWinError(protocolStatus)); 105 | return 0; 106 | } 107 | 108 | DEBUG("[+] Ticket injected !\n"); 109 | LsaDeregisterLogonProcess(lsaHandle); 110 | 111 | return 0; 112 | } -------------------------------------------------------------------------------- /Cerbere/crypto.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "NtSecAPI.h" 4 | 5 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 6 | 7 | #define DES_CBC_CRC 1 8 | #define DES_CBC_MD4 2 9 | #define DES_CBC_MD5 3 10 | #define DES3_CBC_MD5 5 11 | #define DES3_CBC_SHA1 7 12 | #define DSA_WITH_SHA1_CMSOID 9 13 | #define MD5_WITH_RSA_ENCRYPTION_CMSOID 10 14 | #define SHA1_WITH_RSA_ENCRYTPTION_CMSOID 11 15 | #define RC2_CBC_ENVOID 12 16 | #define RSA_ENCRYPTION_ENVOID 13 17 | #define tRSAES_OAEP_ENV_OID 14 18 | #define DES_EDE3_CBC_ENV_OID 15 19 | #define DES3_CBC_SHA1_KD 16 20 | #define AES128_CTS_HMAC_SHA1 17 21 | #define AES256_CTS_HMAC_SHA1 18 22 | #define RC4_HMAC 23 23 | #define RC4_HMAC_EXP 24 24 | #define SUBKEY_KEYMATERIAL 65 25 | #define OLD_EXP -135 26 | 27 | #define KRB_KEY_USAGE_AS_REQ_PA_ENC_TIMESTAMP 1 28 | #define KRB_KEY_USAGE_AS_REP_TGS_REP 2 29 | #define KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY 3 30 | #define KRB_KEY_USAGE_AS_REQ_AUTHORIZATION_SESSION 4 31 | #define KRB_KEY_USAGE_AS_DATA_ENCRYPTED_NO_SPEC 16 32 | 33 | typedef CONST UNICODE_STRING* PCUNICODE_STRING; 34 | 35 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_INITIALIZE) (LPCVOID pbKey, ULONG KeySize, ULONG MessageType, PVOID* pContext); 36 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_ENCRYPT) (PVOID pContext, LPCVOID pbInput, ULONG cbInput, PVOID pbOutput, ULONG* cbOutput); 37 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_DECRYPT) (PVOID pContext, LPCVOID pbInput, ULONG cbInput, PVOID pbOutput, ULONG* cbOutput); 38 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_FINISH) (PVOID* pContext); 39 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_HASHPASSWORD_NT5) (PCUNICODE_STRING Password, PVOID pbKey); 40 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_HASHPASSWORD_NT6) (PCUNICODE_STRING Password, PCUNICODE_STRING Salt, ULONG Count, PVOID pbKey); 41 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_RANDOMKEY) (LPCVOID Seed, ULONG SeedLength, PVOID pbKey); 42 | typedef NTSTATUS(WINAPI* PKERB_ECRYPT_CONTROL) (ULONG Function, PVOID pContext, PUCHAR InputBuffer, ULONG InputBufferSize); 43 | 44 | 45 | typedef NTSTATUS(WINAPI* pRtlInitAnsiString)(STRING* DestinationString, char* SourceString); 46 | typedef NTSTATUS(WINAPI* pRtlAnsiStringToUnicodeString)(PUNICODE_STRING DestinationString, STRING* SourceString, BOOLEAN AllocateDestinationString); 47 | typedef NTSTATUS(WINAPI* pRtlInitUnicodeString)(PUNICODE_STRING, PCWSTR); 48 | 49 | pRtlInitAnsiString RtlInitAnsiString; 50 | pRtlAnsiStringToUnicodeString RtlAnsiStringToUnicodeString; 51 | pRtlInitUnicodeString RtlInitUnicodeString; 52 | 53 | 54 | 55 | typedef struct _KERB_ECRYPT { 56 | ULONG EncryptionType; 57 | ULONG BlockSize; 58 | ULONG ExportableEncryptionType; 59 | ULONG KeySize; 60 | ULONG HeaderSize; 61 | ULONG PreferredCheckSum; 62 | ULONG Attributes; 63 | PCWSTR Name; 64 | PKERB_ECRYPT_INITIALIZE Initialize; 65 | PKERB_ECRYPT_ENCRYPT Encrypt; 66 | PKERB_ECRYPT_DECRYPT Decrypt; 67 | PKERB_ECRYPT_FINISH Finish; 68 | union { 69 | PKERB_ECRYPT_HASHPASSWORD_NT5 HashPassword_NT5; 70 | PKERB_ECRYPT_HASHPASSWORD_NT6 HashPassword_NT6; 71 | }; 72 | PKERB_ECRYPT_RANDOMKEY RandomKey; 73 | PKERB_ECRYPT_CONTROL Control; 74 | PVOID unk0_null; 75 | PVOID unk1_null; 76 | PVOID unk2_null; 77 | } KERB_ECRYPT, * PKERB_ECRYPT; 78 | 79 | 80 | typedef NTSTATUS(WINAPI* pCDLocateCSystem)(ULONG Type, PKERB_ECRYPT* ppCSystem); 81 | pCDLocateCSystem CDLocateCSystem; 82 | 83 | void char2unicode(char* source, UNICODE_STRING* result); 84 | 85 | void loadCryptoFunctions(); 86 | void get_key_rc4(char* password, PBYTE* hash, size_t* size); 87 | void get_key_aes256(char* domain, char* username, char* password, PBYTE* hash, size_t* size); 88 | void get_enc_timestamp(PBYTE key, DWORD eType, PBYTE* result, size_t* size); 89 | 90 | void decrypt(PBYTE key, DWORD eType, DWORD keyUsage, PBYTE data, size_t dataSize, PBYTE* result, size_t* size); -------------------------------------------------------------------------------- /Cerbere/network.c: -------------------------------------------------------------------------------- 1 | #include "network.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma comment (lib, "Ws2_32.lib") 8 | #pragma comment (lib, "Mswsock.lib") 9 | #pragma comment (lib, "AdvApi32.lib") 10 | 11 | #define DEFAULT_BUFLEN 512 12 | #define DEFAULT_PORT "27015" 13 | 14 | void sendBytes(char *server, char* port, PBYTE content, int contentSize, PBYTE *response, int *size) { 15 | WSADATA wsaData; 16 | SOCKET ConnectSocket = INVALID_SOCKET; 17 | struct addrinfo* result = NULL; 18 | struct addrinfo* ptr = NULL; 19 | struct addrinfo hints; 20 | int iResult; 21 | 22 | 23 | // Initialize Winsock 24 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 25 | if (iResult != 0) { 26 | printf("[x] Failed to start WSA Winsocks: %d\n", iResult); 27 | return 1; 28 | } 29 | 30 | ZeroMemory(&hints, sizeof(hints)); 31 | hints.ai_family = AF_INET; 32 | hints.ai_socktype = SOCK_STREAM; 33 | hints.ai_protocol = IPPROTO_TCP; 34 | 35 | // Resolve the server address and port 36 | iResult = getaddrinfo(server, port, &hints, &result); 37 | if (iResult != 0) { 38 | printf("[x] Failed to get KDC IP info: %d\n", iResult); 39 | WSACleanup(); 40 | return 1; 41 | } 42 | 43 | // Attempt to connect to an address until one succeeds 44 | for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { 45 | 46 | // Create a SOCKET for connecting to server 47 | ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 48 | ptr->ai_protocol); 49 | if (ConnectSocket == INVALID_SOCKET) { 50 | printf("[x] Failed to connect to the KDC: %ld\n", WSAGetLastError()); 51 | WSACleanup(); 52 | return 1; 53 | } 54 | 55 | // Connect to server. 56 | iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 57 | if (iResult == SOCKET_ERROR) { 58 | closesocket(ConnectSocket); 59 | ConnectSocket = INVALID_SOCKET; 60 | continue; 61 | } 62 | break; 63 | } 64 | 65 | freeaddrinfo(result); 66 | 67 | if (ConnectSocket == INVALID_SOCKET) { 68 | printf("[x] Failed to connect to server!\n"); 69 | WSACleanup(); 70 | return 1; 71 | } 72 | 73 | // Send an initial buffer 74 | int networkContentSize = htonl(contentSize); 75 | char test[4] = ""; 76 | CopyMemory(test, &networkContentSize, sizeof(int)); 77 | iResult = send(ConnectSocket, test, 4, 0); 78 | iResult = send(ConnectSocket, content, contentSize, 0); 79 | if (iResult == SOCKET_ERROR) { 80 | printf("[x] Failed to write data: %d\n", WSAGetLastError()); 81 | closesocket(ConnectSocket); 82 | WSACleanup(); 83 | return 1; 84 | } 85 | 86 | char sizeBuff[4] = ""; 87 | iResult = recv(ConnectSocket, sizeBuff, 4, 0); 88 | if (iResult < 0) { 89 | printf("[x] Failed to receive data size from KDC: %d\n", WSAGetLastError()); 90 | exit(-1); 91 | } 92 | 93 | CopyMemory(size, sizeBuff, sizeof(int)); 94 | *size = ntohl(*size) & 0x7fffffff; 95 | 96 | *response = calloc(*size, sizeof(char)); 97 | if (!*response) { 98 | printf("[x] Failed to allocate KDC response buffer\n"); 99 | exit(-1); 100 | } 101 | PBYTE buff = *response; 102 | int bufferSize = 0; 103 | do { 104 | iResult = recv(ConnectSocket, buff, *size, 0); 105 | if (iResult < 0) { 106 | printf("[x] Failed to receive data size from KDC: %d\n", WSAGetLastError()); 107 | exit(-1); 108 | } 109 | buff += iResult; 110 | bufferSize += iResult; 111 | } while (bufferSize != *size); 112 | 113 | // cleanup 114 | closesocket(ConnectSocket); 115 | WSACleanup(); 116 | 117 | } -------------------------------------------------------------------------------- /Cerbere/crypto.c: -------------------------------------------------------------------------------- 1 | #include "crypto.h" 2 | #include "time.h" 3 | #include "asn1.h" 4 | 5 | void loadCryptoFunctions() { 6 | HMODULE crypt = LoadLibraryA("CRYPTDLL"); 7 | if (!crypt) { 8 | printf("[x] Failed to load CRYPTDLL module\n"); 9 | exit(-1); 10 | } 11 | 12 | CDLocateCSystem = GetProcAddress(crypt, "CDLocateCSystem"); 13 | if (!CDLocateCSystem) { 14 | printf("[x] Failed to load CDLocateCSystem\n"); 15 | exit(-1); 16 | } 17 | 18 | HMODULE ntdll = GetModuleHandleA("NTDLL"); 19 | if (!ntdll) { 20 | printf("[x] Failed to load NTDLL module\n"); 21 | exit(-1); 22 | } 23 | 24 | RtlInitUnicodeString = GetProcAddress(ntdll, "RtlInitUnicodeString"); 25 | if (!RtlInitUnicodeString) { 26 | printf("[x] Failed to load RtlInitUnicodeString\n"); 27 | exit(-1); 28 | } 29 | 30 | RtlInitAnsiString = GetProcAddress(ntdll, "RtlInitAnsiString"); 31 | if (!RtlInitAnsiString) { 32 | printf("[x] Failed to load RtlInitAnsiString\n"); 33 | exit(-1); 34 | } 35 | 36 | RtlAnsiStringToUnicodeString = GetProcAddress(ntdll, "RtlAnsiStringToUnicodeString"); 37 | if (!RtlAnsiStringToUnicodeString) { 38 | printf("[x] Failed to load RtlAnsiStringToUnicodeString\n"); 39 | exit(-1); 40 | } 41 | } 42 | 43 | void char2unicode(char* source, UNICODE_STRING* result) { 44 | STRING ansiPassword; 45 | UNICODE_STRING unicodePassword; 46 | 47 | RtlInitAnsiString(&ansiPassword, source); 48 | RtlAnsiStringToUnicodeString(result, &ansiPassword, 1); 49 | } 50 | 51 | void get_key_rc4(char* password, PBYTE* hash, size_t* size) { 52 | NTSTATUS status; 53 | PKERB_ECRYPT pCSystem; 54 | PVOID pContext; 55 | 56 | status = CDLocateCSystem(RC4_HMAC, &pCSystem); 57 | if (!NT_SUCCESS(status)) { 58 | printf("[x] Failed to call CDLocateCSystem\n"); 59 | exit(-1); 60 | } 61 | *size = pCSystem->KeySize; 62 | 63 | STRING ansiPassword; 64 | UNICODE_STRING unicodePassword; 65 | UNICODE_STRING Salt; 66 | 67 | char2unicode(password, &unicodePassword); 68 | //RtlInitAnsiString(&ansiPassword, password); 69 | //RtlAnsiStringToUnicodeString(&unicodePassword, &ansiPassword, 1); 70 | RtlInitUnicodeString(&Salt, L""); 71 | 72 | *hash = calloc(pCSystem->KeySize, sizeof(char)); 73 | pCSystem->HashPassword_NT6(&unicodePassword, &Salt, 4096, *hash); 74 | pCSystem->Finish(&pContext); 75 | } 76 | 77 | void get_key_aes256(char* domain, char* username, char* password, PBYTE* hash, size_t* size) { 78 | NTSTATUS status; 79 | PKERB_ECRYPT pCSystem; 80 | PVOID pContext; 81 | 82 | status = CDLocateCSystem(AES256_CTS_HMAC_SHA1, &pCSystem); 83 | if (!NT_SUCCESS(status)) { 84 | printf("[x] Failed to call CDLocateCSystem\n"); 85 | exit(-1); 86 | } 87 | *size = pCSystem->KeySize; 88 | 89 | char* salt = calloc(strlen(domain) + strlen(username), sizeof(char)); 90 | if (!salt) { 91 | printf("[x] Failed to allocate salt buffer\n"); 92 | exit(-1); 93 | } 94 | for (int i = 0; i < strlen(domain); i++) { 95 | salt[i] = toupper(domain[i]); 96 | } 97 | strcpy(&salt[strlen(domain)], username); 98 | 99 | STRING ansiPassword; 100 | STRING ansiSalt; 101 | UNICODE_STRING unicodePassword; 102 | UNICODE_STRING unicodeSalt; 103 | 104 | //RtlInitAnsiString(&ansiPassword, password); 105 | //RtlAnsiStringToUnicodeString(&unicodePassword, &ansiPassword, 1); 106 | char2unicode(password, &unicodePassword); 107 | 108 | //RtlInitAnsiString(&ansiSalt, salt); 109 | //RtlAnsiStringToUnicodeString(&unicodeSalt, &ansiSalt, 1); 110 | char2unicode(salt, &unicodeSalt); 111 | 112 | *hash = calloc(pCSystem->KeySize, sizeof(char)); 113 | pCSystem->HashPassword_NT6(&unicodePassword, &unicodeSalt, 4096, *hash); 114 | 115 | } 116 | 117 | void decrypt(PBYTE key, DWORD eType, DWORD keyUsage, PBYTE data, size_t dataSize, PBYTE* result, size_t* size) { 118 | PKERB_ECRYPT pCSystem; 119 | PVOID pContext; 120 | NTSTATUS status; 121 | 122 | status = CDLocateCSystem(eType, &pCSystem); 123 | if (!NT_SUCCESS(status)) { 124 | printf("[x] Failed to call CDLocateCSystem\n"); 125 | exit(-1); 126 | } 127 | 128 | status = pCSystem->Initialize(key, pCSystem->KeySize, keyUsage, &pContext); 129 | if (!NT_SUCCESS(status)) { 130 | printf("[x] Failed to initialize crypto system\n"); 131 | exit(-1); 132 | } 133 | *result = calloc(dataSize, sizeof(unsigned char)); 134 | *size = dataSize; 135 | status = pCSystem->Decrypt(pContext, data, dataSize, *result, size); 136 | } 137 | 138 | void get_enc_timestamp(PBYTE key, DWORD eType, PBYTE* result, size_t* size) { 139 | PKERB_ECRYPT pCSystem; 140 | PVOID pContext; 141 | NTSTATUS status; 142 | 143 | status = CDLocateCSystem(eType, &pCSystem); 144 | if (!NT_SUCCESS(status)) { 145 | printf("[x] Failed to call CDLocateCSystem\n"); 146 | exit(-1); 147 | } 148 | 149 | status = pCSystem->Initialize(key, pCSystem->KeySize, KRB_KEY_USAGE_AS_REQ_PA_ENC_TIMESTAMP, &pContext); 150 | if (!NT_SUCCESS(status)) { 151 | printf("[x] Failed to initialize crypto system\n"); 152 | exit(-1); 153 | } 154 | 155 | char data[16]; 156 | time_t timestamp = time(NULL); 157 | struct tm* pTime = gmtime(×tamp); 158 | strftime(data, 16, "%Y%m%d%H%M%SZ", pTime); 159 | 160 | ASN encTimeSequence = { 161 | .tag = SEQUENCE, 162 | .isAsnContent = 1, 163 | .asnContent = calloc(2, sizeof(ASN)) 164 | }; 165 | 166 | ASN encTimeElement = { 167 | .tag = LIST | 0, 168 | .isAsnContent = 1, 169 | .asnContent = calloc(2, sizeof(ASN)) 170 | }; 171 | 172 | encTimeSequence.asnContent[0] = encTimeElement; 173 | 174 | ASN encTime = { 175 | .tag = GENERALIZED_TIME, 176 | .isAsnContent = 0, 177 | .content = data, 178 | .contentSize = strlen(data) 179 | }; 180 | 181 | encTimeElement.asnContent[0] = encTime; 182 | 183 | size_t nil = 0; 184 | PBYTE plainData = NULL; 185 | asn2byte(&encTimeSequence, &plainData, size, &nil); 186 | 187 | DWORD dataSize = *size; 188 | DWORD modulo = *size % pCSystem->BlockSize; 189 | if (modulo) { 190 | *size += pCSystem->BlockSize - modulo; 191 | } 192 | *size += pCSystem->HeaderSize; 193 | *result = calloc(*size, sizeof(char)); 194 | status = pCSystem->Encrypt(pContext, plainData, dataSize, *result, size); 195 | 196 | 197 | if (!NT_SUCCESS(status)) { 198 | printf("[x] Failed to encrypt data\n"); 199 | exit(-1); 200 | } 201 | 202 | pCSystem->Finish(&pContext); 203 | return 0; 204 | } -------------------------------------------------------------------------------- /Cerbere/asn1.c: -------------------------------------------------------------------------------- 1 | #include "asn1.h" 2 | #include 3 | #include "math.h" 4 | 5 | size_t getAsnSize(ASN* asn, int includeLengthByte) { 6 | size_t result = 0; 7 | if (!asn->isAsnContent) { 8 | result += asn->contentSize; 9 | } 10 | else { 11 | ASN* currentAsn = asn->asnContent; 12 | while (currentAsn->tag != 0) { 13 | result += getAsnSize(currentAsn, 1); 14 | currentAsn += 1; 15 | } 16 | } 17 | 18 | if (includeLengthByte) { 19 | if (result > 127) { 20 | result += (((int)log2(result) + 1) / 8 + (((int)log2(result) + 1) % 8 != 0)) & 0b01111111; 21 | } 22 | result += 2; 23 | } 24 | 25 | return result; 26 | 27 | } 28 | 29 | void asn2byte(ASN* asn, unsigned char** result, size_t* size, size_t* pointer) { 30 | if (!asn || asn->tag == 0) { return; } 31 | if (!(*result)) { 32 | *pointer = 0; 33 | size_t asn_size = getAsnSize(asn, 1); 34 | *result = calloc(asn_size, sizeof(unsigned char)); 35 | if (!(*result)) { 36 | printf("[x] Failed to allocate ASN byte array\n"); 37 | exit(-1); 38 | } 39 | 40 | if (size) { 41 | *size = asn_size; 42 | } 43 | } 44 | 45 | (*result)[*pointer] = asn->tag; 46 | *pointer += 1; 47 | size_t asn_size = getAsnSize(asn, 0); 48 | 49 | if (asn_size < 128) { 50 | (*result)[*pointer] = asn_size; 51 | *pointer += 1; 52 | } 53 | else { 54 | int overflow = (((int)log2(asn_size) + 1) / 8 + (((int)log2(asn_size) + 1) % 8 != 0)) & 0b01111111; 55 | (*result)[*pointer] = 0b10000000 | overflow; 56 | *pointer += 1; 57 | int size = htonl(asn_size); 58 | int i = 0; 59 | while (i < 4 && *((char*)(&size) + i) == 0) { i += 1; } 60 | for (int j = 0; j < 4 - i; j++) { 61 | CopyMemory(&(*result)[*pointer+j], (char*)(&size) + i + j, sizeof(char)); 62 | } 63 | //CopyMemory(&(*result)[*pointer], &asn_size, overflow * sizeof(unsigned char)); 64 | *pointer += overflow; 65 | } 66 | if (!asn->isAsnContent) { 67 | CopyMemory(&(*result)[*pointer], asn->content, asn->contentSize * sizeof(unsigned char)); 68 | *pointer += asn->contentSize; 69 | asn = NULL; 70 | } 71 | else { 72 | ASN* currentAsn = asn->asnContent; 73 | while (currentAsn->tag) { 74 | asn2byte(currentAsn, result, NULL, pointer); 75 | currentAsn += 1; 76 | } 77 | 78 | } 79 | 80 | // add a recursive call on asn->next here if multiple Application needed 81 | } 82 | 83 | void printAsn(ASN* asn) { 84 | unsigned char* asnByte = NULL; 85 | size_t size = 0; 86 | size_t pointer = 0; 87 | asn2byte(asn, &asnByte, &size, &pointer); 88 | for (int i = 0; i < size; i++) { 89 | printf("%02x", asnByte[i]); 90 | } 91 | printf("\n"); 92 | } 93 | 94 | void addChild(ASN* parent, ASN* child) { 95 | ASN* currentAsn = parent->asnContent; 96 | int i = 0; 97 | while (currentAsn->tag) { 98 | currentAsn += 1; 99 | i += 1; 100 | } 101 | *currentAsn = *child; 102 | } 103 | 104 | void newInteger(ASN* asn, int value) { 105 | 106 | int networkValue = htonl(value); 107 | int i = 0; 108 | while (i < 4 && *((char*)(&networkValue) + i) == 0) { i += 1; } 109 | 110 | asn->tag = INTEGER; 111 | asn->isAsnContent = 0; 112 | if (value == 0) { 113 | asn->content = calloc(1, sizeof(char)); 114 | asn->contentSize = 1; 115 | return; 116 | } 117 | asn->content = calloc(4 - i, sizeof(char)); 118 | if (!asn->content) { 119 | printf("[x] Failed to allocate new integer ASN buffer\n"); 120 | exit(-1); 121 | } 122 | asn->contentSize = 4 - i; 123 | 124 | for (int j = 0; j < 4 - i; j++) { 125 | CopyMemory(asn->content + j, (char*)(&networkValue) + i + j, sizeof(char)); 126 | } 127 | } 128 | 129 | int getInteger(ASN* asn) { 130 | int result = 0; 131 | for (int i = 0; i < asn->contentSize; i++) { 132 | result = (result >> 8) + asn->content[i]; 133 | } 134 | return result; 135 | } 136 | 137 | int isAsnContent(PBYTE asnByte, int parentSize) { 138 | PBYTE pointer = asnByte; 139 | pointer++; 140 | int length = *pointer; 141 | pointer++; 142 | int headerSize = 2; 143 | 144 | if (length > 0x80) { 145 | int additionalLengthByte = length - 0x80; 146 | headerSize += additionalLengthByte; 147 | if (additionalLengthByte + 2 >= parentSize) { 148 | return 0; 149 | } 150 | 151 | length = 0; 152 | for (int i = 0; i < additionalLengthByte; i++) { 153 | length = length << 8; 154 | length += *pointer; 155 | pointer++; 156 | } 157 | } 158 | 159 | if (length + headerSize > parentSize || length <= 0) { 160 | return 0; 161 | } 162 | if (length + headerSize == parentSize) { 163 | return 1; 164 | } 165 | 166 | int childSize = 0; 167 | 168 | while (childSize < length) { 169 | headerSize = 2; 170 | pointer++; 171 | int lengthChild = *pointer; 172 | pointer++; 173 | 174 | if (length > 0x80) { 175 | int additionalLengthByte = lengthChild - 0x80; 176 | headerSize += additionalLengthByte; 177 | if (additionalLengthByte + 2 >= length) { 178 | return 0; 179 | } 180 | 181 | lengthChild = 0; 182 | for (int i = 0; i < additionalLengthByte; i++) { 183 | lengthChild = lengthChild << 8; 184 | lengthChild += *pointer; 185 | pointer++; 186 | } 187 | } 188 | childSize += lengthChild + headerSize; 189 | pointer += lengthChild; 190 | } 191 | 192 | if (childSize != length) { 193 | return 0; 194 | } 195 | 196 | return 1; 197 | } 198 | 199 | PBYTE byte2asn(PBYTE asnByte, ASN* asn, int parentSize) { 200 | PBYTE pointer = asnByte; 201 | 202 | int tag = *pointer; 203 | pointer++; 204 | int length = *pointer; 205 | pointer++; 206 | 207 | if (length > 0x80) { 208 | int additionalLengthByte = length - 0x80; 209 | length = 0; 210 | for (int i = 0; i < additionalLengthByte; i++) { 211 | length = length << 8; 212 | length += *pointer; 213 | pointer++; 214 | } 215 | } 216 | 217 | asn->tag = tag; 218 | asn->isAsnContent = isAsnContent(pointer, length); 219 | //printf("Tag : %02x - isAsnContent : %d\n", asn->tag, asn->isAsnContent); 220 | 221 | if (asn->isAsnContent) { 222 | asn->asnContent = calloc(1, sizeof(ASN)); 223 | if (!asn->asnContent) { 224 | printf("[x] Cannot allocate ASN ASN content element\n"); 225 | exit(-1); 226 | } 227 | 228 | int i = 2; 229 | PBYTE endAddress = pointer + length; 230 | while (pointer != endAddress) { 231 | ASN* tmp = calloc(i, sizeof(ASN)); 232 | if (!tmp) { 233 | printf("[x] Failed to reallocate ASN ASN content buffer"); 234 | exit(-1); 235 | } 236 | for (int j = 0; j < i-1; j++) { 237 | tmp[j] = asn->asnContent[j]; 238 | } 239 | free(asn->asnContent); 240 | asn->asnContent = tmp; 241 | 242 | ZeroMemory(asn->asnContent + i - 1, sizeof(ASN)); 243 | PBYTE childPointer = pointer; 244 | pointer = byte2asn(childPointer, &asn->asnContent[i-2], length); 245 | i++; 246 | } 247 | } 248 | else { 249 | asn->content = calloc(length, sizeof(unsigned char)); 250 | if (!asn->content) { 251 | printf("[x] Failed to allocate ASN content element\n"); 252 | exit(-1); 253 | } 254 | CopyMemory(asn->content, pointer, length * sizeof(unsigned char)); 255 | asn->contentSize = length; 256 | pointer += length; 257 | } 258 | 259 | return pointer; 260 | } 261 | 262 | int getListElementByIndex(ASN* asn, int element, ASN* result) { 263 | ASN* asnContent = asn->asnContent; 264 | while (asnContent->tag != 0) { 265 | if (asnContent->tag == (LIST | element)) { 266 | *result = *asnContent; 267 | return 1; 268 | } 269 | asnContent++; 270 | } 271 | result = NULL; 272 | return 0; 273 | } 274 | 275 | 276 | -------------------------------------------------------------------------------- /Asktgt/Asktgt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {0174f7ca-57e0-4c17-9612-e08d1e5dc4e6} 30 | 31 | 32 | 33 | 16.0 34 | Win32Proj 35 | {702d109a-42c5-4e98-bd8c-81d4cba10830} 36 | Asktgt 37 | 10.0 38 | 39 | 40 | 41 | Application 42 | true 43 | v143 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v143 50 | true 51 | Unicode 52 | 53 | 54 | Application 55 | true 56 | v143 57 | Unicode 58 | 59 | 60 | Application 61 | false 62 | v143 63 | true 64 | Unicode 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | true 86 | 87 | 88 | false 89 | 90 | 91 | true 92 | 93 | 94 | false 95 | 96 | 97 | 98 | Level3 99 | true 100 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 101 | true 102 | 103 | 104 | Console 105 | true 106 | 107 | 108 | 109 | 110 | Level3 111 | true 112 | true 113 | true 114 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 115 | true 116 | 117 | 118 | Console 119 | true 120 | true 121 | true 122 | 123 | 124 | 125 | 126 | Level3 127 | true 128 | _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 129 | true 130 | ..\Cerbere 131 | 132 | 133 | Console 134 | true 135 | 136 | 137 | 138 | 139 | Level3 140 | true 141 | true 142 | true 143 | _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 144 | true 145 | ..\Cerbere 146 | 147 | 148 | Console 149 | true 150 | true 151 | true 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /Ptt/Ptt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {7fcca2ca-938a-41b1-a04d-86d8606e917d} 25 | Ptt 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | ..\Cerbere 120 | 121 | 122 | Console 123 | true 124 | 125 | 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 135 | true 136 | ..\Cerbere 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | {0174f7ca-57e0-4c17-9612-e08d1e5dc4e6} 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /Cerbere/Cerbere.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {0174f7ca-57e0-4c17-9612-e08d1e5dc4e6} 25 | Cerbere 26 | 10.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | StaticLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 90 | true 91 | Use 92 | pch.h 93 | 94 | 95 | 96 | 97 | true 98 | 99 | 100 | 101 | 102 | Level3 103 | true 104 | true 105 | true 106 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 107 | true 108 | Use 109 | pch.h 110 | 111 | 112 | 113 | 114 | true 115 | true 116 | true 117 | 118 | 119 | 120 | 121 | Level3 122 | true 123 | _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;%(PreprocessorDefinitions) 124 | true 125 | NotUsing 126 | pch.h 127 | 128 | 129 | 130 | 131 | true 132 | 133 | 134 | 135 | 136 | Level3 137 | true 138 | true 139 | true 140 | _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions) 141 | true 142 | NotUsing 143 | pch.h 144 | 145 | 146 | 147 | 148 | true 149 | true 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | --------------------------------------------------------------------------------