破解目标:在登录界面不用输入账号密码进行验证直接进入下一界面。
破解工具:Xposed,frida,jadx-gui / JEB,雷电模拟器。
apk文件:链接:https://pan.baidu.com/s/1ZtvV2NC0M2tJSdtDTRkC4Q
提取码:k9Yp
对于Xposed和frida的安装和使用在此就不多赘述,直接进入正题。
首先将apk文件拖入模拟器中,然后点击登录按钮,发现有Toast语句
然后根据Toast语句将apk拖进jadx中进行搜索,发现该语句在LoginActivity里面,同时查看一下Manifest文件,发现LoginActivity是主Activity。接着观察该Toast语句所在的方法。
看到要对Login界面进行跳转就需要对isSuccessful变量进行一次判断,所以hook一下sendValue()的参数本来就可以了,但是我的Xposed和frida都提示我找不到目标包,没办法,只好曲线救国。
所以接着分析,发现sendValue()方法在doLogin()里面被引用
一波分析后可以发现,如果result变量值为"success"那么就能sendValue(true),而result的值又是由getInputStream() 和 code变量值决定的,所以思路很清楚了——修改HttpURLConnection的getResponseCode() 和 getInputStream() 这两个方法的返回值。
但是在这里又出现了意外,我在hook HttpURLConnection 的时候发现根本hook不到该类所在包,说实在的我当时人都麻了,连续两次hook不到包还不知道为啥,搞得我都想重新把Xposed和frida再装一遍。但是后来经过高人指点,发现实际要hook的包名和反编译出来的包名完全不是同一个东西。jadx反编译的是java.net.HttpURLConnection,但实际用到的却是com.android.okhttp.internal.huc.HttpURLConnectionImpl。
知道了正确的包名后就可以开始写脚本了,但是frida比Xposed稍微要复杂一点。
Xposed:
Class clazz = loadPackageParam.classLoader.loadClass("com.android.okhttp.internal.huc.HttpURLConnectionImpl");
XposedHelpers.findAndHookMethod(clazz, "getResponseCode", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.d(TAG,"开始劫持");
param.setResult(200);
}
});
XposedHelpers.findAndHookMethod(clazz, "getInputStream", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.d(TAG,"第二次劫持开始");
String str = "success";
InputStream input = new ByteArrayInputStream(str.getBytes());
param.setResult(input);
Log.d(TAG,"劫持全部结束");
}
});
这里稍难的地方可能就在getInputStream()的返回值里面,因为这里需要重新构造一个InputStream对象,然后将字符串包装成字节流放进去,最后再返回。
frida:
Java.perform(function(){
var http = Java.use('com.android.okhttp.internal.huc.HttpURLConnectionImpl');
var String = Java.use("java.lang.String");
var ByteArrayInputStream = Java.use("java.io.ByteArrayInputStream");
var str = String.$new('success');
var input = ByteArrayInputStream.$new(str.getBytes());
http.getResponseCode.implementation = function(){
send('Start! Hook!');
return 200;
}
http.getInputStream.implementation = function(){
send('第二次hook开始');
return input;
}
});
因为JavaScript里面是没有我们所需要的上述类的,所以只好使用Java.use去调用Java里面的类与方法。值得一提的是,我最开始是用的Java.type去调用,但是frida提示我有错,修改为use后就可以了,还有就是js想要new一个java对象,需要用到 类名.$new 类似于这样的格式,其它的就很简单了。
hook后的效果图:
到此就hook结束了。
ps:因为这个apk的原主人服务器到期的问题所以没法对它抓包进行协议分析。还有就是我是一个安卓萌新,如果上述有讲的不对的地方请各位大佬多多指正,如果各位大佬还有其它思路还请补充说明一下,不胜感激。