准备工作
一台已root过的手机
安装Xposed Installe
下载XposedBridge.jar(https://jcenter.bintray.com/de/robv/android/xposed/api/)
下载apktool,dex2jar-2.0,jdgui等反编译工具
下载 铂涛旅行app(我们将对该app进行反编译,你也可下载其它app)
下载dumpDex(用于脱壳)
脱壳(由于铂涛旅行app使用360加壳了,所以我们需要先脱壳)&查看源码
安装dumpDex.apk
在Xposed Installe启用dumpDex模块,重启手机
打开需要脱壳的apk
使用shell命令把/data/data/{package_name}/dump目录下的.dex文件拷贝出来
使用dex2jar将dex文件转成jar文件
使用jdgui查看jar文件,找到需要hook的代码
创建项目
Step 1: 修改AndroidManifest.xml,在application标签下增加如下代码
image.png
Step 2: gradle添加依赖
compileOnly files('libs/api-82.jar')
Step 3: 编写代码
image.png
从源码我们能看到只要我们Hook了LoginForm构造方法便可以获取到未加密的登录账号和密码
class XposedHook : IXposedHookLoadPackage{
override fun handleLoadPackage(loadPackageParam: XC_LoadPackage.LoadPackageParam?) {
if(loadPackageParam!!.packageName.equals("com.plateno.botaoota")){ //找到需要hook的包名
hookBotao(loadPackageParam)
}
}
fun hookBotao(loadPackageParam: XC_LoadPackage.LoadPackageParam?){
XposedHelpers.findAndHookMethod("com.stub.StubApp",loadPackageParam!!.classLoader,"attachBaseContext",Context::class.java,object :XC_MethodHook(){
override fun afterHookedMethod(param: MethodHookParam?) { //由于被360加固过,所以需要hook attachBaseContext来获取类加载器
XposedBridge.log("afterHookedMethod")
val context: Context = param!!.args[0] as Context
val classLoader: ClassLoader = context.classLoader
hookUserNameAndPwd(classLoader)
hookReq(classLoader)
hookReqParam(classLoader)
hookRsp(classLoader)
}
})
}
fun hookUserNameAndPwd(classLoader: ClassLoader){
XposedHelpers.findAndHookConstructor("com.bestwehotel.app.whlogin.model.LoginForm",classLoader, String::class.java,String::class.java,object :XC_MethodHook(){
override fun afterHookedMethod(param: MethodHookParam?) { //hook 构造方法获取登录账号和密码
XposedBridge.log("botao username=========>"+param!!.args[0])
XposedBridge.log("botao password=========>"+param.args[1])
}
})
}
fun hookReq(classLoader: ClassLoader){ //hook okhttp 请求地址等信息
XposedHelpers.findAndHookMethod("okhttp3.RealCall",classLoader,"getResponseWithInterceptorChain",object :XC_MethodHook(){
override fun afterHookedMethod(param: MethodHookParam?) {
val requestField = param!!.result::class.java.getDeclaredField("request")
requestField.isAccessible = true
val requestObj = requestField.get(param.result)
val reqStrMethod = requestObj::class.java.getMethod("toString")
val reqStr = reqStrMethod.invoke(requestObj)
XposedBridge.log("req base info =========>" + reqStr)
}
})
}
fun hookReqParam(classLoader: ClassLoader){ //hook okhttp 请求参数
XposedHelpers.findAndHookConstructor("okhttp3.FormBody",classLoader, List::class.java,List::class.java,object :XC_MethodHook(){
override fun afterHookedMethod(param: MethodHookParam?) {
val names: ArrayList<*> = param!!.args[0] as ArrayList<*>
val values: ArrayList<*> = param.args[1] as ArrayList<*>
XposedBridge.log("============ req param ==========")
for (i in names.indices){
XposedBridge.log(names[i] as String + "=" + values[i] as String)
}
}
})
}
fun hookRsp(classLoader: ClassLoader){ //hook okhttp 响应
XposedHelpers.findAndHookMethod("okhttp3.ResponseBody",classLoader,"string",object :XC_MethodHook(){
override fun afterHookedMethod(param: MethodHookParam?) {
XposedBridge.log("rsp info ==========>" + param!!.result)
}
})
}
}