宝塔更新了数据存储的方式,PanelForensics会尽快支持
最近啊,fic中出现了宝塔,结果PanelForensics居然没有梭哈,这怎么行??
于是我就一通分析,发现这个版本更新了架构,并且对密码的加解密是通过调用二进制依赖进行实现的
我这里就以mysql的密码为例,在新版本中,mysql的密码主要会出现在3个地方,涉及2个sqlite文件(另外,宝塔的主要数据存储数据库default.db
的文件路径也改到了/www/server/panel/data/db/default.db
,但其中很多部分都被摘除,另建数据库保存)
/www/server/panel/data/db/database.db
/www/server/panel/data/db/panel.db
一般用户的账号密码(database.db
)
远程数据库的账号密码(database.db
)
本地数据库root密码(panel.db
)
可以看到很明显的特征BT-0x:
,后面跟了一段密文
通过不断的跟代码,可以找到python中的解密函数
这里导入了一个模块PluginLoader
,可以找到是一个so,也就是说数据的加解密被放到了二进制程序中
可以在db_decrypt
中找到解密代码
很明显可以看到key和iv的获取方式
可以看到key就是一眼顶针,取偶数位的字符,得到key为3P+_lN3+jPW6Kgt#
iv的情况就比较复杂,需要先判断是否存在/www/server/panel/data/div.pl
文件,如果不存在,还需要从数据库中读取div再写入文件(所以div.pl
和db
目录或许是检测这个版本较好的方式)
实际上,如果没有div.pl
,还会有个默认的iv(但是前面无论如何都会保证div.pl
存在,所以这里保留的iv4HpOz4pT^4Hh-Lfl
应该永远用不上)
很明显可以看到div是加密的,仍需要解密,所以跟进_aes_decrypt_module
函数看后续操作
很明显用_get_sgin_key
函数获得了解密div所需要的key和iv
根据逻辑来看,就是把v4劈开,分成了key和iv
char *__fastcall Ploader::_get_sgin_key(Ploader *this, char *a2, char *a3)
{char *result; // raxint v4[35]; // [rsp+18h] [rbp-A0h]int v5; // [rsp+A4h] [rbp-14h]int v6; // [rsp+A8h] [rbp-10h]int v7; // [rsp+ACh] [rbp-Ch]int v8; // [rsp+B0h] [rbp-8h]int i; // [rsp+B4h] [rbp-4h]v4[0] = 90;v4[1] = 87;v4[2] = 50;v4[3] = 119;v4[4] = 66;v4[5] = 97;v4[6] = 56;v4[7] = 100;v4[8] = 55;v4[9] = 72;v4[10] = 78;v4[11] = 54;v4[12] = 69;v4[13] = 54;v4[14] = 65;v4[15] = 69;v4[16] = 83;v4[17] = 71;v4[18] = 50;v4[19] = 87;v4[20] = 66;v4[21] = 112;v4[22] = 107;v4[23] = 101;v4[24] = 120;v4[25] = 101;v4[26] = 84;v4[27] = 84;v4[28] = 114;v4[29] = 84;v4[30] = 104;v4[31] = 54;v8 = 0;v7 = 0;v6 = 0;v5 = 32;for ( i = 0; i < v5; ++i ){if ( v8 ){a3[v6] = v4[i];v8 = 0;++v6;}else{a2[v7] = v4[i];v8 = 1;++v7;}}a2[16] = 0;result = a3 + 16;a3[16] = 0;return result;
}
解一下
v4 = [90,87,50,119,66,97,56,100,55,72,78,54,69,54,65,69,83,71,50,87,66,112,107,101,120,101,84,84,114,84,104,54]
v8 = 0
key = [0]*16
iv = [0]*16
idx_key = 0
idx_iv = 0
for i in range(32):if v8 == 1:iv[idx_iv] = v4[i]v8 = 0idx_iv += 1else:key[idx_key] = v4[i]v8 = 1idx_key += 1
print(key)
for v in key:print(chr(v),end='')
print()
print(iv)
for v in iv:print(chr(v),end='')
# key:Z2B87NEAS2BkxTrh
# iv :WwadH66EGWpeeTT6
此时可以解密div
随后可以用解密后的iv去解密一开始的密文
成功解密