本屌是一个苦逼的爬虫,从入行到现在一年多,接触过各种反爬,什么检测自动化之类的都常见了,碰到js加密、app逆向的采集基本都是歇菜了,不过慢慢的还是接触这个,慢慢的学了很多。关于js解密的已经有一篇文章了,如果我说的不明确的话可以留言给我,我会回复的.
首先说一下做app逆向的几个工具,
1. dex2jar 这是个jar包,版本没啥限制选一个合适的版本就好
2.jd-gui这个可以将你反解出来的jar包打开,看里面的代码和结构
3.一台装有xposed框架的root手机,本人用的华为的nexus 6p (市面上都是二手的,最好买的时候换个电池,不然一直重启啥的)
4.android studio 编译你的apk,将你的xposed 插件装到手机上。
5.一定版本的app apk文件
由于工作的需求,破解了某鱼和某夕夕的apk。
首先将你的apk后缀改成 .zip,然后将你的包进行解压,有的解压工具可能是解不了的,换一个工具 或者用 unzip命令去解包,解了包 里面会出现很多文件 ,我们需要的就是 classes.dex 可能会存在多个类似的文件,我们只要这一个就好,将这个文件拷贝到下载好的 dex2jar 文件中,将你这个文件中的 d2j-dex2jar.sh d2j_invoke.sh 修改权限为可执行,然后执行
sh d2j-dex2jar.sh ./classes.dex
他会将你的包改成一个jar包,classes-dex2jar.jar,ok 你拿到这个jar包 就可以放到jd-gui中 了,里面会看到他所有的类和方法(有可能是混淆过的哦),这就该用到了这个工具的搜索功能了,搜你想hook的关键词,除非所有的类和方法都混淆过,不然你一定可以找到你想要的东西。
我想要的就是列表页的数据,搜索一下goods respoinse 等关键词,轻松的找到
com.xunmeng.pinduoduo.ui.fragment.search.entity.SearchResponse 这个类下面是我想要的方法。
既然找到了 接下来就是 在android studio中写hook代码咯
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable{
if (loadPackageParam.packageName.equals("com.taobao.idlefish")){
XposedBridge.log("PackageName====>"+loadPackageParam.packageName);
XposedBridge.log("ProcessName====>"+loadPackageParam.processName);
XposedBridge.log("AppInfo====>"+loadPackageParam.appInfo);
XposedBridge.log("闲鱼");
}else if (loadPackageParam.packageName.equals("com.xunmeng.pinduoduo")){
XposedBridge.log("PackageName====>"+loadPackageParam.packageName);
XposedBridge.log("ProcessName====>"+loadPackageParam.processName);
XposedBridge.log("AppInfo====>"+loadPackageParam.appInfo);
pddhook(loadPackageParam);
}
}
这几行代码可以在xposed中输出你选中的包的一些相关的属性,没什么用 不过用来玩耍 还是不错的
private void pddhook(final XC_LoadPackage.LoadPackageParam lppam) throws JSONException, MalformedURLException {
Class> aClass = XposedHelpers.findClass("com.xunmeng.pinduoduo.constant.HttpConstants",lppam.classLoader);
List listMember = new ArrayList();
for (Method method: aClass.getDeclaredMethods()){
XposedBridge.log("【当前类中的方法】=====>{}"+method);
listMember.add(method);
}
for (final Member member : listMember) {
XposedBridge.hookMethod(member, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String result = param.getResult().toString();
XposedBridge.log("【方法名称】=====>" + member.toString());
XposedBridge.log("【每个方法中的返回值】=====>" + result);
}
});
if (member.toString().contains("buildQuery")) {
XposedBridge.hookMethod(member, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String result = param.getResult().toString();
if (result.length() > 20){
keyUrl = result;
XposedBridge.log("【请求的url】=====>" + result);
}
}
});
}
}
上面第一个hookmethod 是穷举了HttpConstants 这个类下面所有的方法和每个方法执行完毕后的所有结果,第二个methodhook其实就是筛选了一下制定的方法名获取他的结果
Class> bClass = XposedHelpers.findClass("com.xunmeng.pinduoduo.ui.fragment.search.entity.SearchResponse",lppam.classLoader);
List listMemberb = new ArrayList();
for (Method method: bClass.getDeclaredMethods()){
XposedBridge.log("【当前SearchResponse类中的方法】=====>{}"+method);
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("【每个方法的结果】=====>" + param.getResult());
}
});
listMemberb.add(method);
}
for (final Member member1 : listMemberb){
if (member1.toString().contains("getItems")){
XposedBridge.hookMethod(member1, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String result = param.getResult().toString();
goodsList = result;
XposedBridge.log("【result】=====>"+result +"$"+keyUrl);
// URL url = new URL("");
URL url = new URL("");
try{
String str = goodsList + keyUrl;
try {
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setConnectTimeout(2000);
httpURLConnection.setReadTimeout(5000);
httpURLConnection.setDoOutput(true);//设置允许输出
httpURLConnection.setRequestMethod("POST");//设置请求的方式
httpURLConnection.setRequestProperty("ser-Agent", "Fiddler");
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
PrintWriter out = new PrintWriter(httpURLConnection.getOutputStream());
out.print(str);
out.flush();
out.close();
int code = httpURLConnection.getResponseCode();
if (code == 200){
XposedBridge.log("发送成功");
}else{
XposedBridge.log("发送失败");
}
}catch (Exception e2){
XposedBridge.log("pddPost请求异常"+e2);
}
}catch (Exception e1){
XposedBridge.log("urlencode 异常"+e1);
}
}
});
}
}
}
这些代码是hook了他列表页搜索的结果 并且将数据转发到我的服务器,其实你如果只是想hook一些数据没什么难度的。
整个的流程就是这些,其中比较耗时的就是一个包的查找和hook,有许多的方法是hook不到的,需要用别的方法去处理。
hook的强大之处在于 可以在你目标方法之前执行也可以在你目标方法之后执行,可以获取他传入的参数也可以获取他返回的参数。
听说阿里下面的app都是有反hook机制,所以需要先破解这个,这个就比较高深了需要大神去解决。
这个逆向就说到这,需要了解的同学,留言~本博客纯属技术交流~