本文章中所有内容仅供学习交流,不用于其他目的。若有侵权,请联系作者删除。
一、准备
QQ版本:QQ9.7.23(29394)
x64dbg
IDA
Frida
二、分析
如何参照sqlcipher源码分析汇编代码定位关键函数可以参考这篇文章
点击此处
(1)定位打开数据库函数和设置密钥函数
对Msg3.0数据库操作的关键函数是kernelUtil.dll CMultiSQLite3DB::innerOpen
对CppSQLite3DB::open和sub_56DD6EC3进行hook
js脚本如下:
[Java] 纯文本查看 复制代码 CppSQLite3DB_open();
setdbkey();
function CppSQLite3DB_open() {
var baseAddr = Module.findExportByName("KernelUtil.dll","?open@CppSQLite3DB@@QAEHPBD@Z");
var funcAddr = baseAddr;
Interceptor.attach(funcAddr, {
onEnter: function(args)
{
var filename = Memory.readCString(args[0]);
console.log(filename);
},
onLeave:function(retval)
{
}
});
}
function setdbkey(name,funcAddr) {
var baseAddr = Module.findBaseAddress('KernelUtil.dll');
var funcAddr = baseAddr.add(0x56DD6EC3-0x56D50000);
Interceptor.attach(funcAddr, {
onEnter: function(args)
{
var len=args[2].toInt32();
console.log(hexdump(Memory.readByteArray(args[1], len), {offset: 0,length: len,header: true,ansi: false}));
},
onLeave:function(retval)
{
}
});
}
输出如图:
(2)定位数据库解密函数
用IDA FindCrypt插件查找可疑函数
选择有命令行参数的QQ进程
对sub_56DE0F78下断点,断下后F8步过,可以看到已经解密出明文。
按F5得到IDA伪代码 (XXTEA算法)
[C] 纯文本查看 复制代码 int sub_56DE0F78(unsigned int* a1, signed int a2, byte* a3)
{
unsigned int *v3; // ecx@1
unsigned int v4; // esi@1
signed int v5; // edi@1
int v6; // ebx@1
unsigned int v7; // esi@2
int v8; // eax@2
int v9; // edx@3
unsigned int v10; // ST10_4@4
int v11; // eax@4
signed int result; // eax@6
signed int v13; // edi@8
unsigned int v14; // eax@8
int v15; // edx@11
int v16; // eax@12
int v17; // esi@12
bool v18; // zf@14
int v19; // [sp+Ch] [bp-Ch]@3
unsigned int v20; // [sp+10h] [bp-8h]@1
unsigned int v21; // [sp+14h] [bp-4h]@3
int v22; // [sp+14h] [bp-4h]@11
int v23; // [sp+20h] [bp+8h]@3
unsigned int v24; // [sp+20h] [bp+8h]@8
signed int v25; // [sp+24h] [bp+Ch]@8
v3 = a1;
v4 = *a1;
v5 = a2;
v6 = 0;
v20 = *a1;
if ( a2 <= 1 )
{
if ( a2 >= -1 )
{
result = 1;
}
else
{
v13 = -a2;
v25 = v13;
v14 = -1640531527 * (52 / v13 + 6);
v24 = v14;
if ( v14 )
{
while ( 1 )
{
v15 = v13 - 1;
v22 = (v14 >> 2) & 3;
if ( v13 - 1 > 0 )
{
do
{
v16 = (4 * v4 ^ (v3[v15 - 1] >> 5)) + ((v4 >> 3) ^ 16 * v3[v15 - 1]);
v17 = v3[v15 - 1] ^ *(DWORD *)(a3 + 4 * (v22 ^ v15 & 3));
int index=--v15 + 1;
int arg1=v3[index];
int arg2=((v20 ^ v24) + v17) ^ v16;
v3[index] =arg1- arg2;
v4 = v3[v15 + 1];
v20 = v3[v15 + 1];
}
while ( v15 > 0 );
v13 = v25;
}
*v3 -= ((v4 ^ v24) + (v3[v25 - 1] ^ *(DWORD *)(a3 + 4 * (v22 ^ v15 & 3)))) ^ ((4 * v4 ^ (v3[v13 - 1] >> 5))
+ (16 * v3[v13 - 1] ^ (v4 >> 3)));
v4 = *v3;
v18 = v24 == -1640531527;
v14 = v24 + 1640531527;
v20 = *v3;
v24 += 1640531527;
if ( v18 )
break;
v13 = v25;
}
}
result = 0;
}
}
else
{
v7 = a1[a2 - 1];
v8 = 52 / a2 + 6;
if ( v8 > 0 )
{
do
{
v19 = v8 - 1;
v9 = 0;
v23 = v6 - 1640531527;
v21 = ((unsigned int)(v6 - 1640531527) >> 2) & 3;
if ( v5 - 1 > 0 )
{
do
{
v10 = v3[v9 + 1];
v11 = v7 ^ *(DWORD *)(a3 + 4 * (v21 ^ v9++ & 3));
v3[v9 - 1] += ((v10 ^ v23) + v11) ^ ((4 * v10 ^ (v7 >> 5)) + ((v10 >> 3) ^ 16 * v7));
v7 = v3[v9 - 1];
}
while ( v9 < a2 - 1 );
}
v6 -= 1640531527;
v5 = a2;
v3[v5 - 1] += ((*v3 ^ v23) + (v7 ^ *(DWORD *)(a3 + 4 * (v21 ^ v9 & 3)))) ^ ((4 * *v3 ^ (v7 >> 5))
+ ((*v3 >> 3) ^ 16 * v7));
v8 = v19;
v7 = v3[a2 - 1];
}
while ( v19 > 0 );
}
result = 0;
}
return result;
}
(3)算法还原
密钥来源是将数据库头异或解密然后发送给服务器,服务器返回密钥(msgid=0x12c)。
还原流程:
打开msg3.0.db数据库跳过0x400字节,每次读取0x2000字节进行XXTEA算法(sub_56DE0F78)解密,就可以还原出明文数据库,如图所示:
|