为了发新帖子注册的吾爱,大家支持一下
[md]免责声明:该帖子仅用于学习交流,不做其他用途
准备工作:
包:5ZOU5ZOp5ZOU5ZOpXzYuMTguYXBrCnR2LmRhbm1ha3UuYmlsaQ==
该软件涉及hook检测和抓包检测:
hook检测参考:https://bbs.kanxue.com/thread-277034.htm
抓包:用lsp的JustTrustMe
frida:16.1.3
frida-tools :12.2.1
安卓10
python 3.11.4
抓包:
好了下面就可以开心的使用使用frida进行hook抓包了
先抓一个登录包
登录包是这样的,有四个参数需要处理的
sign:
hook newStringUtf 可以找到sign的值
function hook_netString(){
var symbols = Process.getModuleByName("libart.so").enumerateSymbols();
var newStringUtf = null;
for (let i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if(symbol.name.indexOf("CheckJNI") == -1 &&
symbol.name.indexOf("NewStringUTF") != -1){
console.log(symbol.name, symbol.address);
newStringUtf = symbol.address;
}
}
if(newStringUtf){
Interceptor.attach(newStringUtf, {
onEnter: function (args) {
console.log("newStringUtf args: ", args[1].readCString());
console.log(Thread.backtrace(this.context, Backtracer.FUZZY).
map(DebugSymbol.fromAddress).join('\n') + '\n');
}, onLeave: function (retval) {
console.log("newStringUtf retval: ", retval);
}
});
}
打印调用堆栈可以定位到这个so
args: 2d0fd1f3b61fd50921c0f71a3ee2cf0b
0xb2b611a5 libbili.so!0x31a5
定位到了这个地方
分析一下函数的来源,上面几个函数很关键的
下面是挨个进去看一下,这里面都做了啥
很幸运是的第一个函数里面,对MD5的模数进行初始化了
拿下面就是MD5相关的函数了
下面找一个MD5的源码对着函数进行重名了和类型的修改
修改好了就是这样的,代码简洁明了,就是加盐的MD5
下面对MD5的MD5Update和 MD5Final进行hook
let libbili = Module.findBaseAddress("libbili.so");
if(libbili != null){
console.log("so addr:",libbili);
Interceptor.attach(libbili.add(0x2F88 +1),{
onEnter:function(args){
console.log("明文1:",JSON.stringify((args[1])),args[2],args[3]);
}
})
Interceptor.attach(libbili.add(0x22B0 +1),{
onEnter:function(args){
console.log("明文1:",ptr(args[1]).readCString(),hexdump(args[1]))
}
})
Interceptor.attach(libbili.add(0x2AE0 +1),{
onEnter:function(args){
this.args1 = args[0];
},
onLeave:function(args){
console.log("返回:",ptr(this.args1).readCString(),hexdump(this.args1))
}
})
}
打印参数的时候这里调用两个,第一个包后面分析,我们先看这个sign的加密
ok成功抓到sign,看一下是怎么来的
这里第一个MD5Update里面是明文数据
后面三个加盐的数据
最后两个是MD5Final里面调用的可以忽略了
明文就是前面所有参数的总和:太长了就不贴了,后面会分析都是啥
后面加盐的4个参数是这样的:
60698ba2
f68e01ce
44738920
a0ffe768
拼接在后面,使用MD5加密后,和我们上面抓到的数据一模一样的
这四个参数在我的手机上面是固定的,如果对于怎么来的比较感兴趣在分析一下
看一下java层哪里调用了一个函数,使用这个脚本
function hook_RegisterNatives() {
var symbols = Process.getModuleByName("libart.so").enumerateSymbols();
var RegisterNatives_addr = null;
for (let i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if(symbol.name.indexOf("CheckJNI") == -1 &&
symbol.name.indexOf("RegisterNatives") != -1) {
RegisterNatives_addr = symbol.address;
}
}
console.log("RegisterNatives_addr: ", RegisterNatives_addr);
Interceptor.attach(RegisterNatives_addr, {
onEnter: function (args) {
var env = Java.vm.tryGetEnv();
var className = env.getClassName(args[1]);
var methodCount = args[3].toInt32();
for (let i = 0; i < methodCount; i++) {
var methodName = args[2].add(Process.pointerSize * 3 * i).readPointer().readCString();
var signature = args[2].add(Process.pointerSize * 3 * i).add(Process.pointerSize).readPointer().readCString();
var fnPtr = args[2].add(Process.pointerSize * 3 * i).add(Process.pointerSize * 2).readPointer();
var module = Process.findModuleByAddress(fnPtr);
console.log(className, methodName, signature, fnPtr, module.name, fnPtr.sub(module.base));
}
}, onLeave: function (retval) {}
});
}
定位到了这个函数,通过hook发现i2是1,i3是0
static native SignedQuery so(SortedMap<String, String> sortedMap, int i2, int i3);
在so层会对这个值进行判断,根据值不用取不同的数据
因为i1==1,所有这里对应的表格是dword_971C
v19经过分析是0,对比appkey=bca7e84c2d947ac6得来得,这里不在赘述了
剩下三个参数来自于,数组得下标是7,14,28得数据
欧克到这里sign基本上已经分析完毕了,知道明文书加盐得参数都是怎么来得
password
搜索字符串,找到了login,我们需要分析都在这个里面,看一下哪里调用得
找到引用得地方,可以看到密码得加密方式,跟过去看一下
很清楚,进行更一下
RSA非对称加密
hook一下,获取明文和公钥
明文是密码拼接一个数据,那个拼接得是什么呢?
还记得之前说过登录发送两个包吗?
看返回啥得,我们得hash和公钥
哈哈哈,到此密码也搞定了
device_meta 是login得第三个参数,dt 是login得第四个参数
就是这两个参数,java层可以直接往上跟,
ok可以看到一个字符串书随机生成得
随机生成得16位字符串,对device_meta进行AES加密
这里hook一下,看一下device_meta得明文是啥
霍,好家伙,把手机上面得设备信息上传了,我说数据怎么这么大呢
这信息量真得大呀卧槽、卧槽、卧槽
到这里
device_meta分析完了
下面看一下dt,这里就很熟悉
将上面生成得key用公钥加密,然后上传上去,到此这个登录包得,四个参数都已经分析完了
后面有个滑块,因为初学不会滑块,就先到这里了