Android逆向:字节某书(Lark)数据库KEY分析思路

399 阅读1分钟
  • 本地数据库:databases/sdk_storage/{UID-MD5}/messages.db

  • 加密方式:SQLCipher

image.png

1. SQLCipher 调用栈

Hook open 系统调用,查看 messages.db 的调用栈:

// int open(const char *pathname, int flags, mode_t mode);
Interceptor.attach(Module.findExportByName(null, "open"), {
    onEnter: function (args) {
        const pathname = args[0].readCString()
        if (pathname.endsWith("messages.db")) {
            console.log("open: " + pathname)
            console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n'));
        }
    }
})

结果如下,来自 liblark.so 的 Native 层调用: image.png

2. Hook 数据库密钥

Hook libsqlcipher.so 导出函数看看密钥,脚本就不贴了: image.png

结果如下: image.png

应用数据中未发现密钥字符串,继续分析密钥来源。

3. 通过 memcpy 切入

如果密钥是运行时生成,再进行字符串操作生成SQL命令,那么这个过程很可能会用到 memcpy 函数。

在合适的时机调用hookMemcpy(),可以Hook到和密钥生成相关的函数地址。

function hookMemcpy() {
    Interceptor.attach(Module.findExportByName("libc.so", "memcpy"), {
        onEnter: function (args) {
            if (args[2].toUInt32() === 32) {
                let hex = arrayBufferToHex(args[1].readByteArray(32));
                if (hex.indexOf("9e144d3f7cd1") >= 0) {
                    console.log("FIND!: \n" + hexdump(args[1], {length: 32}))
                    console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n'));
                    console.log("---------------------")
                }
            }
        }
    });
}

image.png 未完待续。。。