Tags: reversing java 

Rating:

The file `file.jar` is given. When executed with `java -jar file.jar` it promts the user for input "Enter the password:". Upon wrong input the program prints "Try again".
So, obviously we need the correct input (= the flag) to get the correct answer.

Besides the main() function there are the static functions a, b, c, d, e, f withing the Main class.
Basically, the input string gets passed into the functions a to f. Each function checks if a portion of the input string is correct and returns a boolean accordingly.
Only if all functions a - f return true (this means that the input string is completely correct) the user gets the "correct answer".
There is one catch to this:
The substring which each functions checks is obfuscated and not available in clear when statically analyzed. The strings are generated via the function `private static String a(int arg7, int arg8)`. So it expects two integer and returns the unofuscated string.
In order to get the strings, we could
1. Use a static analyzer with built in emulation function to resolve the calls.
2. Execute the jar and use a debugger or tracer to extract the strings via runtime
3. Re-implement the function which unobfuscated the strings.

We chose the second method. With `java -Xdebug -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y -jar file.jar` we start the execution in suspended mode until a debugger is attached at port 8000.
To attach we enter `jdb -connect com.sun.jdi.SocketAttach:port=8000`. The interface is similar to gdb. With the command `trace` we can collect all function entries and exits with the return values. This way we can extract the unobfuscated strings one-by-one.

The following mapping show what checks each function will do:
| function | check |
|----------|-------|
| a | checks if length of input string equals 39 |
| d | (arg4.substring(0, 6).equals("dvCTF{")) && arg4.charAt(arg4.length() - 1) == 0x7D |
| c | arg4.substring(19, 30).equals("c1d284e27ff"); |
| f | ((String)v1.invoke(v8, ((int)30), ((int)v8.length()))).equals("97bd0987");|
| e | checks if substring(12, 19) == "3cbf488" |
| b | (arg2.contains("327f7e")) && arg2.indexOf("327f7e") == 6 |

The resulting input (= flag) is thus:
`dvCTF{327f7e3cbf488c1d284e27ff97bd0987}`

Original writeup (https://github.com/jlp1701/davinci-ctf-2022/blob/main/obfuscated/readme.md).