在一些安全的项目中,有时候需要对目标进行取证,而浏览器中包含的信息往往对我们来说帮助很大,同样也想学习更多的逆向知识,所以就有了这次的文章,初学逆向,多多指教!
首先需要知道的,Sqlite3库中常用的函数有如下:
1、sqlite3_open:
2、sqlite3_key:如果数据库已加密必须先执行此函数并输入正确密钥才能进行操作,如果数据库没有加密,执行此函数后进行数据库操作反而会出现“此数据库已加密或不是一个数据库文件”的错误
接着通过在所有模块中进行字符串搜索,会发现在chrome.dll中存在”sqlite3_open/assis2.db”字符串以及一系列相关SQL语句的执行,这里是从"sqlite3_open"入手的
在sqlite3数据库中,如果数据库事先是被加密的,那么想要进行SQL操作的话要先进行sqlite3_key函数的解密,所以sqlite3_open函数之后就会对sqlite3_key对该数据库进行解密
这里为什么sub_105C03A3判断为是sqlite3_open的原因是你跟进去会发现某些特征会跟sqlite3库源文件中的一些特征”main” “temp”字符串特征,一般打开的数据库都是main名称的数据库,因为默认的数据库名为”main”,特征如下:
然后sqlite3库中提供的函数sqlite3_open定义有相关特征:
接着就是sub_105C03BA函数进行sqlite3的解密操作,参数为数据库的句柄,同时出现了guid和guid_length
这里同样动态调试也会看到,参数是传入数据库句柄和一些某序列号字符串(machineguid),字符串的长度来进行解密的
通过监视工具API monitor也可以发现该字符串是注册表中的某项的序列号值
到目前第一层解密到现在就结束了,接着就是第二层解密,也就是Base64编码和AES128-ECB的加密的处理
我这里是通过定位关键的sqlite3的insert语句来进行寻找,因为想法是在插入的时候程序肯定会对相关的密码进行先进行加密处理,然后最后进行整合再执行SQL语句,所以这个时候肯定是会有加密函数的调用
接着就在SQL语句这里下断点,然后慢慢跟后跟,下面的内容先会域名长度格式校验,然后对用户名长度格式校验,接着密码校验 一个一个进行校验操作和一些自带的sqlite事务回滚操作,大家可以跟一下看
接着来到下面的地方才开始对密码进行加密操作
跟进去在加密之前的操作的时候会压入一个固定的字符串,这个字符串在后面会与另一串字符串进行拼接然后用来加密
然后进去继续动态调试跟,接着会寻找如下的CALL
这里的与运算的结果导致的最低位0/1来决定两种取值情况
最终[ebp-0x28]的值来影响下面的跳转决定混淆字节如何生成,这里会经过了奇数偶数的校验,最终导致的结果就是[ebp-0x28]中的值如果是\x02的话,那么就偶数位读取,如果为\x01就奇数位读取
接着就是密钥的生成,这里会看到又压入了一串类似序列号的东西,上面一开始加密的时候也会压入一串序列号的东西,这两串最后会进行拼接字符串用于aes密钥的生成
这个call跟进去就会看到两串字符串开始进行拼接
接着就是开始进行密钥的生成
这里主要是两个call,一个call是通过上面拼接的字符串来生成了一段密码字节数组,另一个则是通过该字节数组的十六进制的值转成字符串
这个算法来进行生成一段字节数组的,它会获取了上面拼接的两组固定的序列号取最后的八个字节进行加密生成的一段字节数组
然后这个call是用来对这个字节数组中的十六进制转换为字符串
接着就是AES的加密CALL,压入了混淆后的密码和AES128 ecb加密的密钥
AES加密完之后,接着就是生成Base64编码,因为最终是要存储到数据库中所以需要经过编码操作
Base64编码的特征如下,并且就是默认的码表
此时已经完成了AES128 ECB加密和Base64的加密,最后拼接"(4B01F200ED01)"固定字符串和Base64编码的结果
本机的Machineguid:
这时候会发现看起来是乱码的,其实就是这样的,360自己会混淆一层,这个混淆在上面已经提到过了,这时候你隔一个字节读取,就是222222了
需要注意的就是第一个字节是\x01 \x02的情况处理:
解密总过程:
这是一个一键辅助抓取360安全浏览器密码的CobaltStrike脚本以及解密小工具,用于节省红队工作量,通过下载浏览器数据库、记录密钥来离线解密浏览器密码。360SafeBrowsergetpass.cna主要用与记录解密所需要的信息用于离线解密,3Bpass主要用于解密浏览器密码,支持本机自动导出以及离线解密。
github地址:https://github.com/hayasec/360SafeBrowsergetpass
相关逆向sqlite的文章
sqlite3的函数详解
int
sqlite3_open(const char
*
filename,sqlite3
*
*
ppDb);
int
sqlite3_open(const char
*
filename,sqlite3
*
*
ppDb);
int
sqlite3_key( sqlite3
*
db, const void
*
pKey,
int
nKey)
int
sqlite3_key( sqlite3
*
db, const void
*
pKey,
int
nKey)
sub_105C03BA(
*
*
sqlite3_obj, guid, guid_length);
sub_105C03BA(
*
*
sqlite3_obj, guid, guid_length);
798497D7
|.
68
AEA1A77B push chrome.
7BA7A1AE
;
Insert into [tb_account (domain,username,password,last_modify_time)values(?,?,passencode(?, ?), ?);
798497D7
|.
68
AEA1A77B push chrome.
7BA7A1AE
;
Insert into [tb_account (domain,username,password,last_modify_time)values(?,?,passencode(?, ?), ?);
553A98CA
E8
0D1E1EFF
call chrome.
5458B6DC
; 开始对密码进行加密
553A98CA
E8
0D1E1EFF
call chrome.
5458B6DC
; 开始对密码进行加密
553A47B3
E8 AA020000 call chrome.
553A4A62
; 密码混淆CALL
553A47B3
E8 AA020000 call chrome.
553A4A62
; 密码混淆CALL
082D4E40
81E1
FE000000
and
ecx,
0xFE
; 取低
2
位
082D4E40
81E1
FE000000
and
ecx,
0xFE
; 取低
2
位
080B4E34
E8 A7A20302 call chrome.
0A0EF0E0
; eax的结果计算
080B4E39
89C1
mov ecx,eax ; ecx
=
eax
080B4E3B
C1E9
1F
shr ecx,
0x1F
; ecx
=
ecx >>
0x1f
080B4E3E
01C1
add ecx,eax ; ecx
=
ecx
+
eax
080B4E40
81E1
FE000000
and
ecx,
0xFE
; ecx
=
ecx &
0xFE
080B4E46
29C8
sub eax,ecx ; eax
=
ah
080B4E48
89C3
mov ebx,eax ; ebx
=
ah
080B4E4A
8945
D8 mov dword ptr ss:[ebp
-
0x28
],eax
080B4E4D
8D443F
02
lea eax,dword ptr ds:[edi
+
edi
+
0x2
] ; 密码的长度
*
2
+
2
080B4E51
FEC3 inc bl ; ebx
=
ebx
+
1
080B4E53
8945
DC mov dword ptr ss:[ebp
-
0x24
],eax ; 压入密码的长度
080B4E56
50
push eax ; 压入密码的长度
080B4E57
E8 E0740002 call chrome.
0A0BC33C
080B4E5C
83C4
04
add esp,
0x4
080B4E5F
89C1
mov ecx,eax
080B4E61
8945
E0 mov dword ptr ss:[ebp
-
0x20
],eax
080B4E64
FF75 DC push dword ptr ss:[ebp
-
0x24
] ; 压入密码的长度
080B4E67
31C0
xor eax,eax
080B4E69
50
push eax
080B4E6A
51
push ecx
080B4E6B
E8
80940102
call chrome.
0A0CE2F0
080B4E70
83C4
0C
add esp,
0xC
080B4E73
8B45
E0 mov eax,dword ptr ss:[ebp
-
0x20
]
080B4E76
85FF
test edi,edi ; 判断密码的长度是否存在
080B4E78
885D
DC mov byte ptr ss:[ebp
-
0x24
],bl
080B4E7B
8818
mov byte ptr ds:[eax],bl
080B4E7D
7E
65
jle short chrome.
080B4EE4
080B4E7F
8B5D
E0 mov ebx,dword ptr ss:[ebp
-
0x20
] ; 存储加密完的密码的地方 每次都会先在ebx放个\x01 或 \x02
080B4E34
E8 A7A20302 call chrome.
0A0EF0E0
; eax的结果计算
080B4E39
89C1
mov ecx,eax ; ecx
=
eax
080B4E3B
C1E9
1F
shr ecx,
0x1F
; ecx
=
ecx >>
0x1f
080B4E3E
01C1
add ecx,eax ; ecx
=
ecx
+
eax
080B4E40
81E1
FE000000
and
ecx,
0xFE
; ecx
=
ecx &
0xFE
080B4E46
29C8
sub eax,ecx ; eax
=
ah
080B4E48
89C3
mov ebx,eax ; ebx
=
ah
080B4E4A
8945
D8 mov dword ptr ss:[ebp
-
0x28
],eax
080B4E4D
8D443F
02
lea eax,dword ptr ds:[edi
+
edi
+
0x2
] ; 密码的长度
*
2
+
2
080B4E51
FEC3 inc bl ; ebx
=
ebx
+
1
080B4E53
8945
DC mov dword ptr ss:[ebp
-
0x24
],eax ; 压入密码的长度
080B4E56
50
push eax ; 压入密码的长度
080B4E57
E8 E0740002 call chrome.
0A0BC33C
080B4E5C
83C4
04
add esp,
0x4
080B4E5F
89C1
mov ecx,eax
080B4E61
8945
E0 mov dword ptr ss:[ebp
-
0x20
],eax
080B4E64
FF75 DC push dword ptr ss:[ebp
-
0x24
] ; 压入密码的长度
080B4E67
31C0
xor eax,eax
080B4E69
50
push eax
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-12-2 18:18
被初学逆向编辑
,原因: