首页
社区
课程
招聘
[原创]某公司otp生成分析
发表于: 2020-2-15 09:00 5363

[原创]某公司otp生成分析

2020-2-15 09:00
5363

下面跟踪mo10123h() mo10126i() mo10130j() mo10109e()4个函数,分析这4个函数都是数据库查询函数,其中最重要的一句就是数据库查询,以mo10109e()为例,

Cursor query = this.f9841b.query(true, "config", new String[]{"key", "value"}, "key=?", new String[]{this.f9842d.mo10260V()}, null, null, null, null);


从表config中提取key=this.f9842d.mo10260V()的value值,而f9842d为 C3830e的实例

private C3830e f9842d = new C3830e(m13872an());



对应方法分别为mo10123h :mo10268d() mo10126i: mo10266b() mo10130j: mo10267c() mo10109e: mo10260V()

hook com.netease.mkey.core.e类实例的4个方法

找到这4个key,寻找数据库中对应的value


adb pull出数据库 目录/data/data/com.netease.mkey/databases/ekey

很容易找到3个函数产生的key对应的value


这些key和value对应的数据库如何生成呢,以mo10268d 为例,他在mo10107d函数中通过contentvalue 将参数j update进入数据库

ActivationActivity.this.f9569d.mo10107d(bundle.getLong(C3806c.m14238j()));


我们再看mo10260V()在 mo10078a(long j)函数中通过contentvalue 将参数j update进入数据库 ,而参数j为 f9848a,下面我们分析f9848a如何生成

f9848a首先通过mo10109e从数据库中查询生成初始值,然后通过m14035a(long j)函数更新,,在函数onOtpRefreshClick中通过这句代码OtpLib.m14035a(this.f10441j.longValue()),简单观察我们可以猜想,f9848a存储的是上一次的时间戳e,保证当前e>上次运行存储的e,不然时间不就倒回去了嘛,

而我们每次点击刷新触发onOtpRefreshClick,都会将e提前到下一个30s的e,otp也将是下一个,但我们不能无限制刷新,还记得将军令有个冷却吗,就是在这个函数中实现的,刷新时间必须小于f9851d,根据经验大概最多同时出现4个otp,我们就不hook寻找他的值了

str就是你的序列号,他是怎么生成的呢

这里就明白了 bArr是密钥,在函数m13873ao生成,bArr2是查询结果s2用base64decode后的数组

而str在数据库中的keyvalue是通过mo10095b插入的,key的生成在mo10266b是固定的,value需要mo10095b的参数str,查找mo10095b的调用,发现它在ActivationActivity和ChangeMobileNumPreActivity中调用过,猜想是在激活和改变手机号码时将军令初始化调用mo10095b生成了value

str2与str生成类似,也是调用了 m13851E函数,通过m14453c进行aes加密

str2插入数据库是通过mo10101c

ActivationActivity.this.f9569d.mo10101c(bundle.getString(C3806c.m14236h()));

hook得到另一个api:m14236h:https://service.mkey.163.com/WSszq1twyG/api/v3/sms_auth_code_activate

所以app通过f8402a这个handler生成了数据库中的key-value

简单跟一下还可以找到发送信息的函数

hook这个函数重新激活,就可以尝试搞明白他的协议了,这里我们就不深入分析了

我们搞明白了3个参数的生成,回头再看函数

关键函数是一个jin函数,在libmkey.so中,他的3个参数分别为,时间戳e,序列号转化的long类型

我们简单看一下m16044c函数,发现他仅仅具有string转化为byte数组的功能,所以第三个参数str2转化的byte数组。如果只实现otp功能的话,我们直接写一个app调用libmkey.so中的 getOtp就可以了,因为他的第一个参数是时间戳,第二三个参数是激活时通过api获取的,在本地计算后是一个定值,直接hook就可以拿到了

想完整分析参数的生成原理才需要一个一个分析{:1_911:} {:1_911:},下面先放一下本地测试代码,拿到这2个值就可以完全动态生成otp:

https://github.com/conanan/my_mkey 


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2020-2-15 10:24
0
雪    币: 2222
活跃值: (739)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2020-2-17 08:32
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2020-3-6 12:05
0
游客
登录 | 注册 方可回帖
返回
//