dewuApp逆向

第一步就是抓包

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

第二步 使用 jadx 打开 app

直接搜索 api,

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

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

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

从这个方法中可以看到密码是 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("------------------------------");
};
});
"""

打印的结果


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

然后又重新搜索参数 newSign

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

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

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

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

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

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

可以看到 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();
}
}

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

第四步:使用 python 调用 jar

posted @ 2020-06-29 16:01  莫贞俊晗  阅读(1091)  评论(0编辑  收藏  举报