一、目标
李老板: 奋飞呀,我最近从Apk里面跟踪到一个算法,代码清晰,但是我不会java,把他翻译成python貌似挺费劲的,有没有轻松省力的方法呀?
奋飞: 有的呀,给我加工资,我来翻译。
某电商App v10.4.5, 升级之后老有小伙伴说他的sign算法变了,其实他就是做了点小动作。sign参数没有动,uuid是明文去做签名,但是抓包请求里面找不到明文uuid,而是藏在ep参数里面,做了一次加密。
今天我们就来手把手教大家扣出这个加密算法。
java老艺术家就不用往下看了,你们都会。
二、步骤
编辑加编译
大家也跟了这么多期了,如何找到ep,如何定位uuid的加密算法这个步骤,可以自行完成,需要提醒一下的就是,这个uuid加密还有缓存,同样的数据被加密一次之后就会记入一个map里面。下次优先找这个map,所以很多时候都不会触发你hook的加密函数。
但是不要怀疑,你找的就是对的。
今天的大boss就是它,从名称上看貌似是个魔改的Base64算法。
有理想的同学可以试着翻译成别的语言,当然我们今天要做的不是翻译,而是把他扣出来,直接利用。
首先创建一个 ModifiedBase64.java文件,把jadx反编译的结果拷贝进去。
把文件第一行的 包名 删掉,就是那个 package xxx;
然后在 ModifiedBase64 类里面增加一个Main函数
public static void main(String[] args) throws Exception{
ModifiedBase64 zObj = new ModifiedBase64();
String strIn = "DwO4EJPrDJCmY2G2EJq5EG==";
String strOut = new String(zObj.m23209eC(strIn));
System.out.println(strOut);
}
这就ok了,然后开始编译
javac ModifiedBase64.java
ModifiedBase64.java:1: 错误: 程序包com.google.common.primitives不存在
import com.google.common.primitives.SignedBytes;
^
ModifiedBase64.java:63: 错误: 找不到符号
b = SignedBytes.MAX_POWER_OF_TWO;
^
符号: 变量 SignedBytes
位置: 类 ModifiedBase64
2 个错误
报错了,有个包名找不到,常规做法是引入这个包名。
不过我们仔细观察下,发现这个包就干了一件事。
导入了 SignedBytes.MAX_POWER_OF_TWO; 常量。
光吃饭,不干活,那就别怪我们不客气了,问问谷哥。
哥说了
public static final byte MAX_POWER_OF_TWO = 1 << 6;
掐指一算,这不就是 0x40 嘛 ,毫不犹豫删掉这个包,然后把 b的赋值直接改成 0x40
重新编译
javac ModifiedBase64.java
ModifiedBase64.java:41: 错误: 无法访问的语句
while (true) {
^
1 个错误
还有错, 这不科学呀。
仔细看看这个 pf 函数 ,确实不科学
public static void m23208pf() throws Exception {
int i = 0;
int i2 = 0;
while (true) {
byte[] bArr = aaf;
if (i2 <= bArr.length - 1) {
bArr[i2] = -1;
i2++;
}
}
while (true) {
char[] cArr = aae;
if (i <= cArr.length - 1) {
aaf[cArr[i]] = (byte) i;
i++;
} else {
return;
}
}
}
第一个while成死循环了,根本不会往下跑。
应该是jadx不乖了, 结合下 jeb的翻译结果,我们给他加上个退出机制
public static void m23208pf() throws Exception {
int i = 0;
int i2 = 0;
while (true) {
byte[] bArr = aaf;
if (i2 <= bArr.length - 1) {
bArr[i2] = -1;
i2++;
}else{
break;
}
}
while (true) {
char[] cArr = aae;
if (i <= cArr.length - 1) {
aaf[cArr[i]] = (byte) i;
i++;
} else {
return;
}
}
}
完美,这下编译成功,跑一下
javac ModifiedBase64.java
java ModifiedBase64
6a891a530cd69899
可以解密出来了。
打包jar
这还没完,我们总不能每次都去改代码,最好可以传个参数进去调用。
先改改代码
public static void main(String[] args) throws Exception{
ModifiedBase64 zObj = new ModifiedBase64();
String strIn = args[0];
String strOut = new String(zObj.m23209eC(strIn));
System.out.println(strOut);
}
密文不再写死,而是传参进去。
// 编译
javac ModifiedBase64.java
// 打包jar
jar cvfe ModifiedBase64.jar ModifiedBase64 ModifiedBase64.class
打包要注意两点:
1、 e参数,来指定Main类
2、 打包文件是编译之后的 .class 而不是 .java
成功之后生成 ModifiedBase64.jar ,就可以命令行调用了
java -jar ModifiedBase64.jar DwO4EJPrDJCmY2G2EJq5EG==
6a891a530cd69899
完美收工。
三、总结
要练就火眼金睛,hook是不会骗人的,参数没变,算法没变,只是多套了一层做了加密而已。
手工编译java和打包,了解原理即可,简单的算法这么搞,复杂一点的还是上 IDEA吧。
年轻人,学点java吧。
人们曾经不只是为了某个具体的目的去研究一个个具体的问题,而是追求深层次的真理,又怎样由此而造出美好的世界,这就是创造。
关注微信公众号,最新技术干货实时推送