一、APP常用抓包技术
二、APP脱壳
public class PackageHook {
Class Dex;
Method Dex_getBytes;
Method getDex;
String packagename;
public PackageHook(XC_LoadPackage.LoadPackageParam sharePkgParam) {
packageHook(sharePkgParam);
}
private void packageHook(final XC_LoadPackage.LoadPackageParam lpparam) {
Log.i("jyy", lpparam.packageName);
final String packagename = "你要脱壳的app包名";
//添加程序包名
initRefect();
XposedBridge.log("目标包名:" + lpparam.packageName);
String str = "java.lang.ClassLoader";
String str2 = "loadClass";
XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class cls = (Class) param.getResult();
if (cls == null) {
//XposedBridge.log("cls == null");
return;
}
String name = cls.getName();
XposedBridge.log("当前类名:" + name);
byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
if (bArr == null) {
XposedBridge.log("数据为空:返回");
return;
}
XposedBridge.log("开始写数据");
String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
XposedBridge.log(dex_path);
File file = new File(dex_path);
if (file.exists()) return;
writeByte(bArr, file.getAbsolutePath());
}
} );
}
public void initRefect() {
try {
Dex = Class.forName("com.android.dex.Dex");
Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void writeByte(byte[] bArr, String str) {
try {
OutputStream outputStream = new FileOutputStream(str);
outputStream.write(bArr);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
XposedBridge.log("文件写出失败");
}
}
通过代码可以发现就是反射拿到Android中com.android.dex.Dex对象然后调用getDex方法然后把字节写到文件,其实就是脱壳后dex文件。Fdex2脱壳工具的核心原理就是上述代码。
三、App逆向分析
private void cgvHook(final XC_LoadPackage.LoadPackageParam lpp) {
Log.i("jyy", lpp.packageName);
if (!lpp.packageName.contains("com.cgv.cn.movie")) {
return;
}
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
ClassLoader cl = ((Context) param.args[0]).getClassLoader();
Class> hookclass = null;
try {
hookclass = cl.loadClass("com.cgv.cn.movie.b.ar");
} catch (Exception e) {
Log.e("jyy", "寻找xxx.xxx.xxx报错", e);
return;
}
//cn.ikicker.moviefans.ui.activity.b
//a(String str, String str2, String str3)
Log.e("jyy", "寻找xxx.xxx.xxx成功");
//com.loopj.android.http
Class hookclasss = cl.loadClass("com.loopj.android.http.RequestParams");
XposedHelpers.findAndHookMethod(hookclass, "a",hookclasss,String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Object params = param.args[0];
String param1 = (String) param.args[1];
XposedBridge.log("a params:"+params.toString());
XposedBridge.log("a param1:"+param1);
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String result = (String) param.getResult();
XposedBridge.log("a result:"+result);
super.afterHookedMethod(param);
}
});
XposedHelpers.findAndHookMethod(hookclass, "a",hookclasss,String.class, String.class,new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Object params = param.args[0];
String param1 = (String) param.args[1];
String param2 = (String) param.args[2];
XposedBridge.log("aa params:"+params.toString());
XposedBridge.log("aa param1:"+param1);
XposedBridge.log("aa param2:"+param2);
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String result = (String) param.getResult();
XposedBridge.log("aa result:"+result);
super.afterHookedMethod(param);
}
});
XposedHelpers.findAndHookMethod(hookclass, "g",String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
String params = (String) param.args[0];
XposedBridge.log("g param1:"+params);
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String result = (String) param.getResult();
XposedBridge.log("g result:"+result);
super.afterHookedMethod(param);
}
});
XposedHelpers.findAndHookMethod(hookclass, "h",String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
String params = (String) param.args[0];
XposedBridge.log("h param1:"+params);
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String result = (String) param.getResult();
XposedBridge.log("h result:"+result);
super.afterHookedMethod(param);
}
});
}
});
}
打开ddms就可以查看aa params打印出来的就是我们a方法的第一个参数,aa param1打印出的就是第二参数,其实就是请求URL,换句话如果抓不到包也就可以使用这种办法把请求URL打出,也就是上面描述抓包方法中的第四种。aa result打印出的就是a方法的返回值,发现和抓包的的值是完全一样的,h方法的参数和返回值也打印出来了。其他的参数都可以按照这种思路去操作,图片中打码部分为手机号,你换成你们注册发送短信的手机号码即可。
加密算法和加密参数已经知道了,CLIENT_KEY基本搞定了,这些都是一些初级的操作,还有很多app算法套路更深需要不断提升自己的实力才能击破他。其实这种Java基础加密完全可以写一套常用算法hook也就是可以直接打印出加密参数和加密结果,本人写了一个Java基本算法自吐插件,常规算法可以不需要脱壳和逆向app,直接打印加密算法和加密参数,但也有缺陷仅仅是Java层的算法而且是常规算法,如果算法有做修改则还是需要逆向代码,但是可以给我做一些前期的准备,过滤掉一些参数算法逆向操作。