dewuApp逆向

第一步就是抓包

根据抓到的包,可以看出需要破解的参数 newSign 、password、uuid 还有 headers 中的参数 shumeiid/x-auth-token/duuid/duimei/shumengid 。也就是有这么多的参数是不知道的,需要去 app 中找的。
dewuApp逆向

第二步 使用 jadx 打开 app

直接搜索 api,
dewuApp逆向

点进去后直接查找用例,就会跳转到下图。

dewuApp逆向

走到这再去点的时候,发现一些参数而且调用了 newParams, 参数 userName、type、sourcePage、countryCode 都是没有加密的,所以重点就是看看这个 password。hook 这个方法发现里面密码是已经加密过的,直接查找用例
dewuApp逆向

点进去就找到 password 的加密位置。

dewuApp逆向

从这个方法中可以看到密码是 MD5Util 的加密。为了验证我的判断,直接 Hook MD5Util.a方法

md5_js_code = """

Java.perform(function () {
var MainActivity = Java.use('com.shizhuang.duapp.framework.util.encrypt.MD5Util');
MainActivity.a.overload('java.lang.String').implementation = function () {
console.log("password: #################" + arguments[0]);
var str2 = "12345678du";
Java.openClassFile("/data/local/tmp/r0gson.dex").load();
const gson = Java.use("com.r0ysue.gson.Gson");
console.log("11111111111111111111111111111111111111111+++++++++++++++++++++")
console.log(gson.$new().toJson(this.a(str2)));
console("------------------------------");
};
});
"""

打印的结果

dewuApp逆向
dewuApp逆向

然后点击 LoginFacade.c ,发现到了最开始的发起请求,拼接参数的地方。到这里 password 的就完事了。

然后又重新搜索参数 newSign

这里看看 OkHttp https://blog.****.net/qq_38851536/article/details/100146115

dewuApp逆向

点进去后,发现基本参数,以及请求头这些东西都可以找到。剩下的就是这些具体的实现以及加密。

继续找到 RequestUtils.b 方法,这个方法最后就是该参数的加密位置以及加密方法。从名字看就是个 AES 加密。加密的内容就是请求参数转为字符串,然后拼接后加密。

dewuApp逆向

继续进入这个 b 方法, 可以看到返回的是一个执行encodeByte 方法后的返回值。而这个方法是 native, 加载的 so 文件为 JNIEncrypt

dewuApp逆向

剩下的就是关于这个加密参数的 Hook.

第三步直接 HOOK 这个方法,查看具体都加密了哪些东西

dewuApp逆向

可以看到 java 层加密的就是这么多的东西,剩下的就是 native 层

参考文章

爬虫工程师的unidbg入门教程

通过 unidbg 直接调用 so 文件

直接去 github上下载 https://github.com/zhkl0228/unidbg

参考上面大佬文章中的代码,进行简单的修改。我逆向的版本中 encodeByte 方法有更新,简单修改一下,就可以了

public class du extends AbstractJni {
//ARM模拟器
private final AndroidEmulator emulator;
//vm
private final VM vm;
//载入的模块
private final Module module;

private final DvmClass TTEncryptUtils;

//初始化
public du() throws IOException {
//创建毒进程,这里其实可以不用写的,我这里是随便写的,使用app本身的进程就可以绕过进程检测
emulator = new AndroidARMEmulator("com.shizhuang.duapp");
final Memory memory = emulator.getMemory();
//作者支持19和23两个sdk
memory.setLibraryResolver(new AndroidResolver(23));
// memory.setCallInitFunction();
//创建DalvikVM,利用apk本身,可以为null
//如果用apk文件加载so的话,会自动处理签名方面的jni,具体可看AbstractJni,这就是利用apk加载的好处
vm = emulator.createDalvikVM(null);
vm.setVerbose(true);
vm.setJni(this);
// vm = emulator.createDalvikVM(null);
//加载so,使用armv8-64速度会快很多
DalvikModule dm = vm.loadLibrary(new File("src/test/resources/xiaohongshu/libJNIEncrypt.so"), false);
//调用jni
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
//Jni调用的类,加载so
TTEncryptUtils = vm.resolveClass("com/duapp/aesjni/AESEncrypt");
}


//关闭模拟器
private void destroy() throws IOException {
emulator.close();
System.out.println("destroy");
}

public static void main(String[] args) throws IOException {
du t = new du();
t.encodeByte("123456");
t.destroy();

}

private String encodeByte(String strs) {
//调试
// 这里还支持gdb调试,
//emulator.attach(DebuggerType.GDB_SERVER);
//附加调试器
// emulator.attach(DebuggerType.SIMPLE);
// emulator.traceCode();
//这里是打断点,原地址0x00005028->新地址0x40005028 新地址需要改成0x4
// emulator.attach().addBreakPoint(null, 0x40001188);//encode地址
// emulator.attach().addBreakPoint(null, 0x40000D10);
Number ret = TTEncryptUtils.callStaticJniMethod(emulator, "getByteValues()Ljava/lang/String;");
System.out.println(ret);
System.out.println("-----------------------");
long hash = ret.intValue() & 0xffffffffL;
StringObject st1 = vm.getObject(hash);
//*这里要处理下字符串
String byteString = st1.getValue();
StringBuilder builder = new StringBuilder(byteString.length());
for (int i = 0; i < byteString.length(); i++) {
if (byteString.charAt(i) == '0') {
builder.append('1');
} else {
builder.append('0');
}
}
byte[] strs_byte = strs.getBytes();
//获取encodeByte地址
ret = TTEncryptUtils.callStaticJniMethod(emulator, "encodeByte([BLjava/lang/String;)Ljava/lang/String;", vm.addLocalObject(new ByteArray(strs_byte)),

//传参,这里需要两个字符串,所以就传入两个参数
// vm.addLocalObject(new StringObject(vm, strs)),
vm.addLocalObject(new StringObject(vm, builder.toString()))

);
//ret 返回的是地址,
hash = ret.intValue() & 0xffffffffL;
//获得其值
StringObject str = vm.getObject(hash);
System.out.println(str);
System.out.println("----------------------");
System.out.println(str.getValue());
return str.getValue();
}
}

dewuApp逆向

这个执行完之后在进行 md5 . 就 OK 了

第四步:使用 python 调用 jar