mirror of
https://github.com/GhostPack/SharpDPAPI
synced 2026-06-08 11:11:23 +00:00
Version 1.11.3
-Added ability to use "/password" with "/target" for masterkey command -Small update to README
This commit is contained in:
@@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [1.11.3] - 2022-06-06
|
||||
|
||||
### Fixed
|
||||
* **SharpDPAPI** project
|
||||
* `masterkeys` command now accepts a `/password:X` argument with `/target:X`
|
||||
|
||||
|
||||
## [1.11.2] - 2022-01-12
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -223,6 +223,8 @@ Specific cookies/logins/statekey files can be specified with `/target:X`, and a
|
||||
|
||||
The **masterkeys** command will search for any readable user masterkey files and decrypt them using a supplied domain DPAPI backup key. It will return a set of masterkey {GUID}:SHA1 mappings.
|
||||
|
||||
`/password:X` can be used to decrypt a user's current masterkeys. If `/target` is also supplied with `/password`, the `/sid:X` full domain SID of the user also needs to be specified.
|
||||
|
||||
The domain backup key can be in base64 form (`/pvk:BASE64...`) or file form (`/pvk:key.pvk`).
|
||||
|
||||
C:\Temp>SharpDPAPI.exe masterkeys /pvk:key.pvk
|
||||
@@ -1255,7 +1257,7 @@ The **logins** command will search for Chrome 'Login Data' files and decrypt the
|
||||
|
||||
Login Data files can also be decrypted with a) any "{GUID}:SHA1 {GUID}:SHA1 ..." masterkeys passed, b) a `/mkfile:FILE` of one or more {GUID}:SHA1 masterkey mappings, c) a supplied DPAPI domain backup key (`/pvk:BASE64...` or `/pvk:key.pvk`) to first decrypt any user masterkeys, or d) a `/password:X` to decrypt any user masterkeys, which are then used as a lookup decryption table. DPAPI GUID mappings can be recovered with Mimikatz' `sekurlsa::dpapi` command.
|
||||
|
||||
A specific Login Data file can be specified with `/target:FILE`. A remote `/server:SERVER` can be specified if a `/pvk` is also supplied. If triaging newer Chrome/Edge instances, a `/statekey:X` AES state key can be specified.
|
||||
A specific Login Data file can be specified with `/target:FILE`. A remote `/server:SERVER` can be specified if a `/pvk` or `/password` is also supplied. If triaging newer Chrome/Edge instances, a `/statekey:X` AES state key can be specified.
|
||||
|
||||
By default, logins are displayed in a csv format. This can be modified with `/format:table` for table output. Also, by default only non-null password value entries are displayed, but all values can be displayed with `/showall`.
|
||||
|
||||
|
||||
@@ -51,6 +51,18 @@ namespace SharpDPAPI.Commands
|
||||
{
|
||||
mappings = Triage.TriageUserMasterKeys(null, true, arguments["/server"], password);
|
||||
}
|
||||
else if (arguments.ContainsKey("/target"))
|
||||
{
|
||||
if (!arguments.ContainsKey("/sid"))
|
||||
{
|
||||
Console.WriteLine("[X] When using /password:X with /target:X, a /sid:X (domain user SID) is required!");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("[*] Triaging masterkey target: {0}\r\n", arguments["/target"]);
|
||||
mappings = Triage.TriageUserMasterKeys(null, true, "", password, arguments["/target"], arguments["/sid"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mappings = Triage.TriageUserMasterKeys(null, true, "", password);
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace SharpDPAPI
|
||||
{
|
||||
public static class Version
|
||||
{
|
||||
public static string version = "1.11.2";
|
||||
public static string version = "1.11.3";
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -1725,9 +1725,18 @@ namespace SharpDPAPI
|
||||
return masterKeySubBytes;
|
||||
}
|
||||
|
||||
public static byte[] CalculateKeys(string password, string directory, bool domain)
|
||||
public static byte[] CalculateKeys(string password, string directory, bool domain, string userSID = "")
|
||||
{
|
||||
var usersid = Path.GetFileName(directory).TrimEnd(Path.DirectorySeparatorChar);
|
||||
var usersid = "";
|
||||
|
||||
if (String.IsNullOrEmpty(directory))
|
||||
{
|
||||
usersid = Path.GetFileName(directory).TrimEnd(Path.DirectorySeparatorChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
usersid = userSID;
|
||||
}
|
||||
|
||||
var utf16pass = Encoding.Unicode.GetBytes(password);
|
||||
var utf16sid = Encoding.Unicode.GetBytes(usersid);
|
||||
|
||||
@@ -10,21 +10,20 @@ namespace SharpDPAPI
|
||||
{
|
||||
public class Triage
|
||||
{
|
||||
public static Dictionary<string, string> TriageUserMasterKeys(byte[] backupKeyBytes, bool show = false, string computerName = "", string password = "", string target = "")
|
||||
public static Dictionary<string, string> TriageUserMasterKeys(byte[] backupKeyBytes, bool show = false, string computerName = "", string password = "", string target = "", string userSID = "")
|
||||
{
|
||||
// triage all *user* masterkeys we can find, decrypting if the backupkey is supplied
|
||||
|
||||
|
||||
var mappings = new Dictionary<string, string>();
|
||||
var canAccess = false;
|
||||
|
||||
if (!String.IsNullOrEmpty(target))
|
||||
{
|
||||
// if we're targeting specific masterkey files
|
||||
|
||||
if (backupKeyBytes.Length == 0)
|
||||
if (((backupKeyBytes == null) || (backupKeyBytes.Length == 0)) && String.IsNullOrEmpty(userSID))
|
||||
{
|
||||
// currently only backupkey is supported
|
||||
Console.WriteLine("[X] The masterkey '/target:X' option currently requires '/pvk:BASE64...'");
|
||||
Console.WriteLine("[X] The masterkey '/target:X' option currently requires '/pvk:BASE64...' or '/password:X'");
|
||||
return mappings;
|
||||
}
|
||||
|
||||
@@ -49,7 +48,16 @@ namespace SharpDPAPI
|
||||
if (Helpers.IsGuid(f.Name))
|
||||
{
|
||||
var masterKeyBytes = File.ReadAllBytes(file);
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes);
|
||||
if ((backupKeyBytes != null) && (backupKeyBytes.Length != 0))
|
||||
{
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] hmacBytes = Dpapi.CalculateKeys(password, "", true, userSID);
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKeyWithSha(masterKeyBytes, hmacBytes);
|
||||
}
|
||||
|
||||
mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +73,15 @@ namespace SharpDPAPI
|
||||
try
|
||||
{
|
||||
var masterKeyBytes = File.ReadAllBytes(target);
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes);
|
||||
if ((backupKeyBytes != null) && (backupKeyBytes.Length != 0))
|
||||
{
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] hmacBytes = Dpapi.CalculateKeys(password, "", true, userSID);
|
||||
plaintextMasterKey = Dpapi.DecryptMasterKeyWithSha(masterKeyBytes, hmacBytes);
|
||||
}
|
||||
mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
Reference in New Issue
Block a user