首先看看需要研究的包:
这个APP有壳,经脱壳后有四个dex文件,我们在四个dex文件里搜索一下url中的关键字,看看能不能搜索到有用的信息,此处我搜索sendcode,然后再通过右键查找用例的办法找到了这个类:
但是这个类下面有很多方法,我要挨个hook的话工作量较大,这里我们可以采用这样的办法先打印出这个类下面所有的方法看看:
Java.perform(
function(){
console.log('enter Frida!')
var netcontent = Java.use('com.xbiao.utils.net.NetContent')
var methods = netcontent.class.getDeclaredMethods()
methods.forEach(function(method){
var method_name = method.getName()
console.log(method_name)
})
}
)
打印结果如下:
我们可以顺着这个思路hook这个类下面的所有方法:
Java.perform(
function(){
console.log('enter Frida!')
hookclass('com.xbiao.utils.net.NetContent')
}
)
function hookclass(className){
console.log('enter hookclass!')
var myclass = Java.use(className)
//得到类下面的所有方法
var methods = myclass.class.getDeclaredMethods()
//遍历所有方法
methods.forEach(function(method){
console.log('-----------------------------------------------')
//获得方法名
var methodName = method.getName()
console.log('当前方法:',methodName)
//获得该方法的所有重载
var overloads = myclass[methodName].overloads
//遍历重载
overloads.forEach(
function(overload){
//hook重载
var prot = '('
for (var i=0;i<overload.argumentTypes.length;i++){
//console.log(JSON.stringify(overload.argumentTypes))
//console.log(overload.argumentTypes[i])
prot += overload.argumentTypes[i].className + ','
}
prot += ')'
var wMethodName = className + '.' + methodName + prot
console.log('该方法下的重载:',wMethodName)
overload.implementation = function(){
for (var i=0;i<arguments.length;i++){
console.log('arument:' + JSON.stringify(arguments[i]))
}
var ret = this[methodName].apply(this,arguments)
console.log(wMethodName + '===return:' + JSON.stringify(ret))
return ret
}
}
)}
)
}
打印结果如下:
可以和charles里的响应数据对比一下,发现一致
所以可以确定我们需要研究的函数:
单独hook一下这个函数:
Java.perform(
function(){
console.log('enter Frida!')
var netcontent = Java.use('com.xbiao.utils.net.NetContent')
netcontent.decryptResponse.implementation = function(s1,s2){
console.log('enter netcontent.decryptResponse!')
console.log('传入的第一个参数为',s1)
console.log('传入的第二个参数为',s2)
var ret = this.decryptResponse(s1,s2)
console.log('返回值为',ret)
return this.decryptResponse(s1,s2)
}
}
)
再运行程序,可以看到如下的结果:
此时再看看jadx中decryptResponse的代码,就找到了接下来要研究的代码:
尝试一下hook这个方法:
Java.perform(
function(){
console.log('enter Frida!')
var aesedeutil = Java.use('com.xbiao.utils.AESedeUtil')
aesedeutil.decrypt.implementation = function(s1,s2){
console.log('enter aesedeutil.decrypt!')
console.log('传入的第一个参数为',s1)
console.log('传入的第二个参数为',s2)
var ret = this.decrypt(s1,s2)
console.log('返回值为',ret)
return this.decrypt(s1,s2)
}
}
)
打印结果:
可以使用Python代码还原一下:
def decrypt():
key = 'u9J7AkrJixf1qv4='.encode('utf8')
print(key)
text = base64.b64decode('qCT/Tok8WtDq74DkAGemDHQz/dpVkG9dsOiIvEHOyNRnDyOCWf+RjXXjfuwuZaY/rqgb8QplQsIzLcf69jx2y89RQFgVOgl2LVTXL5qDRng=')
iv = b"6di50aH901duea7d"
mode = AES.MODE_CBC
cryptos = AES.new(key, mode, iv)
plain_text = cryptos.decrypt(text)
print(plain_text.decode('unicode_escape'))
打印结果:
至此还原便成功了。
拓展:
当jadx中有代码,但Hook不到类时,可能是动态加载dex,类可能在另外的classloader中,需要切换classloader再hook,如:
Java.enumerateClassLoaders({
onMatch: function(loader){
Java.classFactory.loader = loader;
var TestClass;
// Hook the class if found, else try next classloader.
try{
TestClass = Java.use("com.xbiao.utils.AESedeUtil");
TestClass.decrypt.implementation = function(p1,p2){
console.log('decrypt p1:'+p1)
console.log('decrypt p2:'+p2)
printstack()
return this.decrypt(p1,p2)
}
TestClass.encrypt.implementation = function(p1,p2){
console.log('encrypt p2:'+p2)
console.log('encrypt p2:'+p2)
printstack()
return this.encrypt(p1,p2)
}
}catch(error){
if(error.message.includes("ClassNotFoundException")){
console.log(" You are trying to load encrypted class, trying next loader");
}
else{
console.log(error.message);
}
}
},
onComplete: function(){
}
})
classloader概念普及:
https://www.jianshu.com/p/96a72d1a7974