buu-java逆向 题解

前置知识点

是什么

前置知识点学习了:

java是一门半解释半执行的语言,.java后缀的java源码可以理解为全解释的解释型代码,而javac编译器可以将.java后缀的代码(也就是日常所说的java代码)编译成java虚拟机可以直接使用的半编译的代码后缀为 .class,因为java虚拟机每次在运行 .java文件的时候都需要经历javac这一步,因此将java代码提前编译成javac文件无疑会提高代码编译执行速度。

  • .java文件:直接写的java原代码
  • .jar文件:将一系列.java文件和一些配置文件集合的一个文件夹封装成文件的形式,提高项目集成度,类似php的.phar文件
  • .class文件:将java原代码使用javac编译产生的字节码(jdk环境中默认安装javac编译器)

    • javac 文件路径.java
    • javap -c -verbose 文件路径.class(javap不自带)

怎么做

回到正题,而作为ctf逆向来说直接阅读字节码显然是不现实,我们可以使用更为方便的官方的一些软件来直接反编译呈现代码。

经过查询,最为方便的要数JD-GUI

项目地址:http://java-decompiler.github.io/

因为没有java项目开发或者学习经验,因此直接采用集成度更高的JD-GUI

如果有相关经验的,可以采用相关的插件来使自己的编辑器支持这些功能也是可以的。

正式解题

得到反编译代码

使用JD-GUI打开这个文件,可以得到如下已经反编译的代码,简单加上注释

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) {
    ArrayList<Integer> Resultlist = new ArrayList<>();
    for (int i = 0; i < arr.length; i++) {
      int result = arr[i] + 64 ^ 0x20;//逐个进行加密后保存到Resultlist数组中
      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<>();
    for (int j = 0; j < KEY.length; j++)
      KEYList.add(Integer.valueOf(KEY[j])); //把KEY的值保存到KEYLIST中
    System.out.println("Result:");
    if (Resultlist.equals(KEYList)) {//比对KEYList和输入值一次加密后的值相等的话输入值就是flag了
      System.out.println("Congratulations");
    } else {
      System.err.println("Error");
    } 
  }
}

解读加密过程

因为已知加密后应该是

    int[] KEY = { 
        180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 
        133, 191, 134, 140, 129, 135, 191, 65 };

并且加密运算是这样的

int result = arr[i] + 64 ^ 0x20;//逐个进行加密后保存到Resultlist数组中

很容易得到求出arr[i]也就是答案的算法

逆向反加密代码

这里为了方便使用python写

# arr[i] = result - 64 ^ 0x20
result = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65 ]
flag = ""
for i in result:
    flag += chr(i - 64 ^ 0x20)
print(flag)

输出的结果就是:This_is_the_flag_!如图也就是flag了

Last modification:January 27, 2021
如果觉得我的文章对你有用,请随意赞赏。咖啡(12RMB)进度+100%,一块巧克力(1RMB)进度+6%。
(赞赏请备注你的名称哦!后台记录中来自理工小菜狗)