获取安卓中加密数据库的密钥

news/2024/11/13 12:39:47/文章来源:https://www.cnblogs.com/WXjzc/p/18335226

带大家过一遍如何分析常见java层的数据库加密密钥

确定数据库是否加密,找到数据库路径,对于有度这个样本,其数据库位于/data/data/im.xinda.youdu/files/youdu/db/路径下,该路径会存在1个或多个文件夹,用于存储不同用户的数据,其格式为buin_用户uin_user_用户gid,其中uingid是解密的关键,请看后续分析

截图

进行逆向分析前,先看一下应用的lib目录里都有些什么东西,可以很明显地看到libwcdb.so这个依赖,显然这个应用大概率是使用了wcdb来完成数据库操作,我们只需要跟一下wcdb的数据库打开操作,即可找到密钥计算方式

截图

使用jadx进行反编译,找到wcdb的com.tencent.wcdb.database.SQLiteOpenHelper类,在这里可以看到封装了一个获取数据库的方法,其中调用了openOrCreateDatabase去打开数据库,第3个参数就是密钥

截图

跟一下就能看到,实际是要调用com.tencent.wcdb.database.SQLiteDatabase.openDatabase这个方法去打开数据库

截图

这个方法中的第二个参数就是密钥

截图

com.tencent.wcdb.database.SQLiteDatabase下又有很多基于openDatabase封装的方法,都是用于接收不同的参数去打开数据库,所以只需要查看这些方法(包括com.tencent.wcdb.database.SQLiteOpenHelper类中的一些方法)的引用即可

截图

这样可以找到疑似的引用

截图

咱们一步步往上跟,这里的第3个参数是密钥

截图

这个方法有2个引用

截图

第一个跟下去是直接拿已经计算好的密钥,可以暂时不去管

截图

截图

第二个跟下去,第4个参数是密钥

截图

继续跟,这边第3个参数是密钥

截图

这个跟一下,第一个实际上就是之前直接获取密钥的那个,不去管他,后面两个跟哪个都能拿到结果

截图

先跟第二个吧,这边直接看密钥计算的方法

截图

跟一层其实就比较清晰了,传入YDAccountInfo,获取其中的两个值,然后和其他内容一起算sha1得到密钥

截图

yDAccountInfo.b()其实就是uinyDAccountInfo.a()其实就是gid

截图

而前面那一段,其实是获取了设备的deviceID,通常返回的是IMEI或者MEID

截图

那么密钥实际上就是SHA1(deviceID的hashcode+uin+601216000547603300+gid)的结果

如果是跟第3个,则是直接传入了uingid,从哪来的呢?

截图

跟一下a2其实就知道了,是将数据库目录名进行拆分,分别获取到uingid,也就是我开头所说的

截图

现在的问题是,deviceID如何获取?实际上应用都会将数据进行保存,这里就是保存的操作

截图

每次获取前,实际都是先从文件读取看看有没有,没有才再次获取

截图

截图

那么从这里往下跟,就能找到数据所在目录是global

截图

截图

这里有account_info和deviceId,可以拿到密钥计算所需要的内容

截图

截图

接下来计算密钥

from hashlib import sha1def java_string_hashcode(s):h = 0for char in s:h = (31 * h + ord(char)) & 0xFFFFFFFFif h > 0x7FFFFFFF:h -= 0x100000000return hhashcode = java_string_hashcode('863640031394918')salt = '601216000547603300'
uin = '14104680'
gid = '100022'
_sha1 = sha1()
_sha1.update((str(hashcode)+uin+salt+gid).encode('utf8'))
print(_sha1.hexdigest())
#6d2ac6f687955b27373cdeb422b4737d1f7b7c92

im.xinda.youdu.lib.xutils.DbUtils中还定义了数据库采用默认的SQLCipher3参数进行加密

截图

成功解密数据库

截图


逆向分析就到此结束,此外还能通过对wcdb的数据库打开方法进行hook,从而达到对该框架的密钥通杀(要想hook已经提取出的应用的密钥,可以使用仿真的方式,即在模拟器中安装目标应用,将提取出的数据覆盖到模拟器中,大多数情况下都可以正常打开(断网状态))

setImmediate(function () {Java.perform(function () {function bytesToString(arr) {var str = '';arr = new Uint8Array(arr);for (var i in arr) {str += String.fromCharCode(arr[i]);}return str;}let SQLiteDatabase = Java.use('com.tencent.wcdb.database.SQLiteDatabase');SQLiteDatabase['openDatabase'].overload('java.lang.String', '[B', 'com.tencent.wcdb.database.SQLiteCipherSpec', 'com.tencent.wcdb.database.SQLiteDatabase$CursorFactory', 'int', 'com.tencent.wcdb.DatabaseErrorHandler', 'int').implementation = function (str, bArr, sQLiteCipherSpec, cursorFactory, i, databaseErrorHandler, i2) {console.log(`SQLiteDatabase.openDatabase is called: str=${ str }, bArr=${ bytesToString(bArr) }, sQLiteCipherSpec=${ sQLiteCipherSpec }, cursorFactory=${ cursorFactory }, i=${ i }, databaseErrorHandler=${ databaseErrorHandler }, i2=${ i2 }`);let result = this['openDatabase'](str, bArr, sQLiteCipherSpec, cursorFactory, i, databaseErrorHandler, i2);console.log(`SQLiteDatabase.openDatabase result=${ result }`);return result;};});
});

easyFrida已经支持wcdb的hook

截图

截图

这种非常用的(内部通讯工具),我就不加到ForensicsTool里了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/775967.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#/.NET/.NET Core优秀项目和框架2024年7月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项…

Linux 端口排查小结

检查网络端口排查思路:首先进行ping测试,如果ping测试不同检查ICMP协议是否开通和防火墙设置。 如果ping测试通的话 3.telnet ip 端口 ,检查是否可以测通,如果测不通,首先进入服务器检查监听端口和对应开放的IP: netstat -tunlp |grep 224、如果还不通 检查防火墙 和 i…

破案了

看来以后发犇犇要小心点了,不然就被学弟翻到了😰

2024.8.1 鲜花

QQQwwwQQQRe:End of a dream鞅的停时定理 感觉学起来还挺简单的,就是有太灵活逆天的式子。 这里不放鞅的定义了,可以看 百度百科 这里指的是连续鞅。 停时定理: 若满足一下三个条件之一: \[P\{ T < \infty \}=1\\ \]\[E[|M_T|]<\infty\\ \]\[\lim_{n\to \infty} E[|M…

Golang语言文件操作快速入门篇

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.文件的读取操作1.什么是文件2.IO流类型概述3.文件的基本操作3.1 打开和关闭文件3.2 带缓冲大小读取文件内容3.3 循环读取4.ioutil包一次性读取小文件4.1 ioutil包概述4.2 ioutil读取整个文件5.bufio包…

GO语言文件操作快速入门篇

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.文件的读取操作1.什么是文件2.IO流类型概述3.文件的基本操作3.1 打开和关闭文件3.2 带缓冲大小读取文件内容3.3 循环读取4.ioutil包一次性读取小文件4.1 ioutil包概述4.2 ioutil读取整个文件5.bufio包…

[SWPUCTF 2021 新生赛]re1

我们一起来看一下这道逆向题吧! 1.检查一下是几位的程序,并查看是否有壳。看图可以知道它是64位的程序,并没有壳,可以放心反汇编啦! 2.让我们来看一下它的伪C代码:这题的代码也是浅显易懂呀,主要就是输入一个Flag,再将这个Flag进行处理,处理后将得到的字符串与程序中已…

通过模型划分进行分布式训练

通过模型划分进行分布式训练 https://siboehm.com/articles/22/pipeline-parallel-training 流水线并行性使得训练不适合单个GPU内存的大型模型成为可能。示例:Hugginface的BLOOM模型是一个175B参数的Transformer模型。将权重存储为bfloat16需要350GB,但他们用来训练BLOOM的G…

[vue3] Vue3 自定义指令及原理探索

这篇文章记录了在Vue3中如何在全局或者组件内部注册自定义事件,并通过阅读源码探索自定义事件的实现原理。Vue3除了内置的v-on、v-bind等指令,还可以自定义指令。 注册自定义指令 全局注册 const app = createApp({})// 使 v-focus 在所有组件中都可用 app.directive(focus, …

关于在windows系统下使用Linux子系统

今天意外刷到一个短视频,介绍了如何在windows下方便的使用系统自带的Linux子系统,本人抱着好奇的心理,也因为最近碰到了只使用windows操作系统解决不了的问题,还有想到以后测试项目大概率也要在Linux系统下进行。除此之外,本人之前也尝试过使用类似于Vmware等大型虚拟机来…

特性

1.特性的定义:特性就是一个类,必须直接或者间接继承Attribute 特性本身也会被修饰可以用在哪个地方: 如果特性本身的修饰为All : [AttributeUsage(AttributeTargets.All,AllowMultiple =true)] ,则都可修饰 2.特性的访问:特性本身是没有用的,不影响程序的运行;我们只能…

【PHP系列】内存马(二)不死马优化

实验环境工具 phpstudy传统的PHP不死马就是一根筋的往一处写文件,这样就会造成不管文件有没有被修改或者文件是否存在,都会重新创建一个文件,这样会比较占用服务器资源,所以就可以通过这点来对不死马进行优化。 优化前: <?phpset_time_limit(0);ignore_user_abort(1);…