正常先下载附件,解压后,先拖到 JADX-gui 中去反编译一下,然后保存到文件夹里去,后用 IDEA 打开,方便我们编辑。
打开之后,先观察一下 AndroidManifest.xml 里面都有什么。
值得注意的东西:
js
js复制代码包名:com.a.easyjava
Main Activity:com.a.easyjava.MainActivity
看看 MainActivity 怎么写的
java
public void onCreate(Bundle bundle) {
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (MainActivity.b(((EditText) ((MainActivity) this).findViewById(R.id.edit)).getText().toString()).booleanValue()) {
Toast.makeText(this, "You are right!", 1).show();
return;
}
Toast.makeText(this, "You are wrong! Bye~", 1).show();
new Timer().schedule(new TimerTask() {
public void run() {
System.exit(1);
}
}, 2000L);
}
});
}
MainActivity 里没啥特别的东西,就是 if 判断那里,将输入框里的东西传入 MainActivity.b() 函数里判断一下,如果正确就提示正确。
那么分析一下 b 函数内容吧
java
public static Boolean b(String str) {
if (str.startsWith("flag{") && str.endsWith("}")) {
String substring = str.substring(5, str.length() - 1);
b bVar = new b(2);
a aVar = new a(3);
StringBuilder sb = new StringBuilder();
int i = 0;
for (int i2 = 0; i2 < substring.length(); i2++) {
sb.append(a(substring.charAt(i2) + "", bVar, aVar));
Integer valueOf = Integer.valueOf(bVar.b().intValue() / 25);
if (valueOf.intValue() > i && valueOf.intValue() >= 1) {
i++;
}
}
return Boolean.valueOf(sb.toString().equals("wigwrkaugala"));
}
return false;
}
这里就涉及到 a、b 类了,因为反编译的代码里面爆了好多红色代码错误,那么我们把代码复制到别的文件夹里去重新打开,尝试跑一下代码,我把这几个类都放到一个文件里去了
把爆红的地方改改,在不改变代码逻辑的基础上,修改一下代码的格式,差不多能运行就行
然后在 main 方法里面调用 b 方法,一步一步调试,去看看代码到底需要满足什么条件,这个过程就没法一一展示了,需要你自己去理解代码了。也不需要太仔细看。
仔细调试了一遍发现,这个判断是一位一位判断的,不像是 md5 那样位数是固定的,那么好办了,一种思路直接排列组合所有可能性直接爆破,但是 12 的 26 次方也太大了,内存不够, 咋办呢,再读读代码,猜测一下,能不能一位一位的去试试呢。
需要注意的是,这里的类大量使用了 static 这导致这些类的属性是不会在第二次运行的时候而重置的,所以你必须把 static 关键字给他取掉。(超级坑,如果不是程序会报错,我估计就没有这篇文章了😭)
java
import java.util.ArrayList;
public class CTF {
public static void main(String[] args) {
String b = "abcdefghijklmnopqrstuvwxyz";
char[] flag = {'a','a','a','a','a','a','a','a','a','a','a','a'};
// 遍历 flag 的每一位,然后在 b 函数里输出结果,
int i = 0; // 一步一步从 0 开始尝试,尝试出来一个就把 flag 改一个。
for(int j =0;j<b.length();j++){
flag[i] = b.charAt(j);
String s = "flag{" + new String(flag) + "}";
b(s);
}
}
private static char a(String str, b bVar, a aVar) {
return aVar.a(bVar.a(str));
}
public static Boolean b(String str) {
if (str.startsWith("flag{") && str.endsWith("}")) {
String substring = str.substring(5, str.length() - 1);
b bVar = new b(2);
a aVar = new a(3);
StringBuilder sb = new StringBuilder();
int i = 0;
for (int i2 = 0; i2 < substring.length(); i2++) {
sb.append(a(substring.charAt(i2) + "", bVar, aVar));
Integer valueOf = Integer.valueOf(bVar.b().intValue() / 25);
if (valueOf.intValue() > i && valueOf.intValue() >= 1) {
i++;
}
}
// 这里打印出来看看结果
System.out.println("输入的 falg:" + str + "输出结果: " + sb);
return Boolean.valueOf(sb.toString().equals("wigwrkaugala"));
}
return false;
}
}
class a {
public ArrayList<Integer> a = new ArrayList<>();
String b = "abcdefghijklmnopqrstuvwxyz";
Integer d = 0;
Integer[] c = {7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8};
public a(Integer num) {
for (int intValue = num.intValue(); intValue < this.c.length; intValue++) {
a.add(this.c[intValue]);
}
for (int i = 0; i < num.intValue(); i++) {
a.add(this.c[i]);
}
}
public void a() {
Integer num = d;
d = Integer.valueOf(d.intValue() + 1);
if (d.intValue() == 25) {
int intValue = a.get(0).intValue();
a.remove(0);
a.add(Integer.valueOf(intValue));
d = 0;
}
}
public char a(Integer num) {
Integer num2 = 0;
if (num.intValue() == -10) {
a();
return " ".charAt(0);
}
for (int i = 0; i < a.size() - 1; i++) {
if (a.get(i) == num) {
num2 = Integer.valueOf(i);
}
}
a();
return b.charAt(num2.intValue());
}
}
class b {
public ArrayList<Integer> a = new ArrayList<>();
String b = "abcdefghijklmnopqrstuvwxyz";
Integer d = 0;
Integer[] c = {8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13};
public b(Integer num) {
for (int intValue = num.intValue(); intValue < this.c.length; intValue++) {
a.add(this.c[intValue]);
}
for (int i = 0; i < num.intValue(); i++) {
a.add(this.c[i]);
}
}
public void a() {
int intValue = a.get(0).intValue();
a.remove(0);
a.add(Integer.valueOf(intValue));
b += "" + b.charAt(0);
b = b.substring(1, 27);
Integer num = d;
d = Integer.valueOf(d.intValue() + 1);
}
public Integer a(String str) {
int i = 0;
if (b.contains(str.toLowerCase())) {
Integer valueOf = Integer.valueOf(b.indexOf(str));
for (int i2 = 0; i2 < a.size() - 1; i2++) {
if (a.get(i2) == valueOf) {
i = Integer.valueOf(i2);
}
}
} else {
i = str.contains(" ") ? -10 : -1;
}
a();
return i;
}
public Integer b() {
return d;
}
}
好像确实是我猜想的那样,后面的就算是错误的也不影响我们验证前面的。那就好,直接手动去试试得了。
先修改 i = 0;发现 v 对应的是 w
ok,flag 第一位设置为 v ,然后 i = 1;继续尝试
ok ,可以看到第二位应该是 ve 对应 wi,
.........
以此类推即可找到正确的 flag
最后发现有多个 flag 都是符合的, 一共有 10 个,都能得到结果,这就尴尬了,提交哪一个呢。
发现官方提交 flag 的时候只有一个判断为正确。
java
flag{venividivicr}
flag{venividivici}
flag{venividivkci}
flag{venividivkcr} // 这个是题目要提交的。
flag{venividivkci}
flag{venividivkcr}
flag{veniviaivicr}
flag{veniviaivici}
flag{veniviaivkci}
flag{veniviaivkcr}
这里需要注意一点,app 安装到手机上去之后,因为 static 关键字原因,无法运行两次,会抱错导致闪退。