Java逆向

最近我也在刚刚学习Java语言,那就不如趁热烧铁,开启我的Java逆向学习!

准备——工具安装

jadx

jadx是一款开源的DEX到Java的反汇编工具。它支持apk、dex、jar、class、zip、aar等文件。jadx操作方便,反编译后的代码可读性高,同时还拥有较完善的gui界面,除去混淆部分的代码,jadx已经非常接近源代码了。比较方便的是可以搜索。用来做安卓逆向的题也很不错。

官方地址:https://github.com/skylot/jadx/

jd-gui

JD-GUI 是一个用 C++ 开发的 Java 反编译工具,由 Pavel Kouznetsov开发,支持Windows、Linux和苹果Mac Os三个平台。而且提供了Eclipse平台下的插件JD-Eclipse、IntelliJ的插件JD-IntelliJ。JD-GUI不需要安装,直接点击运行,可以反编译jar,class文件

借鉴学习于一位大佬的博客文章,介绍了常见Java反编译工具,很不错 https://hksanduo.github.io/2021/06/22/2021-06-22-java-decompiler-tools/

官方地址:http://java-decompiler.github.io/

解题练习

1.BUU-Java逆向解密

将class文件用jd-gui打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.ArrayList;
import java.util.Scanner;

public class Reverse {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Please input the flag );
String str = s.next();
System.out.println("Your input is );
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr); //一个加密函数
}

public static void Encrypt(char[] arr) { //传入一个数组arr
ArrayList<Integer> Resultlist = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
int result = arr[i] + 64 ^ 0x20;
//进行一个加法操作再赋值给result 里要注意运算符的优先级,Java中加法优先级高于异或,所以实际上是先加64,再与0x20异或。
Resultlist.add(Integer.valueOf(result));
}
int[] KEY = {
180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
133, 191, 134, 140, 129, 135, 191, 65 };
ArrayList<Integer> KEYList = new ArrayList<>(); //KEY是已经加密过的数组new ArrayList
for (int j = 0; j < KEY.length; j++)
KEYList.add(Integer.valueOf(KEY[j])); // 将 KEY 数组的每个元素转换为 Integer 对象并存入列表。
System.out.println("Result:");
if (Resultlist.equals(KEYList)) { //进行比较,如果相同就是对的
System.out.println("Congratulations);
} else {
System.err.println("Error);
}
}
}

经过分析,原加密是(arr[i] +64)^0x20,那么逆向应该是(KEY元素 ^0x20)-64。这样就能得到原来的字符。

1
2
3
4
5
6
KEY = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 
133, 191, 134, 140, 129, 135, 191, 65 ]
flag=''
for i in range(len(KEY)):
flag+=chr((KEY[i]^0x20)-64)
print(flag)

flag{This_is_the_flag_!}

2.[SWPUCTF 2021 新生赛]easyapp

这是一个apk文件,可以使用jadx打开后,在com的目录下,找到MainActivity,进行分析。

这是获取用户在 EditText 中输入的文本然后将其进行编码,编码之后与特定字符串 "棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌"进行比对,如果正确输出yes,那现在就要找出加密方式

可以看到key是123456789,一眼看就是简单的异或,将字符串每个依次与key异或。逆过来,特定字符串 "棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌"依次与key异或可以得到flag。但是发现不正确。

不容忽视的是在目录下找到了一个MainActlvity类,它在尝试通过反射机制修改 Encoder 类的私有字段 key

修改过后的key是987654321

写出exp,但是注意将字符串转为其对应的 ASCII 数值,并进行异或后,其数值不一定都在0-128之间,所以将异或运算的结果取模 128,确保结果在 0 到 127 之间。

1
2
3
4
5
6
7
text = '棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'
key = 987654321
flag =''

for i in range(len(text)):
flag += chr((ord(text[i]) ^ key) % 128)
print(flag)

得出flag : NSSCTF{apkYYDS}

总结

后知后觉,我知道了安卓逆向就是使用的Java语言,按照我现在的理解Java逆向算是属于安卓逆向的。一般是apk文件,放到jadx里面进行反汇编,找到MainActivity源码再进行对其Java源代码分析,简单的就可以得到flag了。

后续打算继续学习安卓逆向