# Object Oriented Programming
writeup by [haskal](https://awoo.systems) for [BLÅHAJ](https://blahaj.awoo.systems)
**Pwn/Rev****413 points****88 solves**
>There's this small up and coming language called java I want to tell you about
provided file: <src.zip>
## writeup
we are given a zip file with java source. there's a Main.java and a bunch of 2-character sourcefiles, with classes that contain a bunch of 2-character methods that return 2-character strings.examining Main, we see it uses reflection to call into these classes and methods to map the inputstring to the output.
```java		String userInput = getUserInputMethodFromScannerAndInvokeAndReturnOutput(scanner);		if (userInput.length() != SIXTEEN)			System.exit(0); 		if (executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(userInput).equals(scanner.getClass().getPackageName().replace(".", ""))) {			invokePrintLineMethodForOutputPrintStream(outputPrintStream, printLineMethod, "Nice. Flag: rgbCTF{" + userInput + "}");		} else {			invokePrintLineMethodForOutputPrintStream(outputPrintStream, printLineMethod, "Try again.");		}```
this code shows us the user input must be 16 chars exactly, and then a transformation function iscalled (with the parameter `javautil`, the package of Scanner without periods).
```java	public static String executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(String stringToExecuteAforementionedCodeOn) throws Exception {		String encryptedString = reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(stringToExecuteAforementionedCodeOn);		String returnValueOfThisFunction = new String();		String[] chunksOfEncryptedStringOfLengthFour = splitStringIntoChunksOfLength(encryptedString, FOUR);		for (String chunkOfEncryptedStringOfLengthFour : chunksOfEncryptedStringOfLengthFour) {			String[] chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = splitStringIntoChunksOfLength(chunkOfEncryptedStringOfLengthFour, TWO);			String firstChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo[0];			String secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo[1];			Class classAndExtraCharactersSoItsNotAKeyword = Class.forName(firstChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);			Object object = classAndExtraCharactersSoItsNotAKeyword.getConstructors()[ZERO].newInstance();			for (int loopArbitraryCounterIterator = 0; loopArbitraryCounterIterator < THREE; loopArbitraryCounterIterator++) {				Method method = classAndExtraCharactersSoItsNotAKeyword.getMethod(secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);				secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = (String)method.invoke(object);			}			returnValueOfThisFunction = new String(returnValueOfThisFunction + secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);		}		return returnValueOfThisFunction;	}```
looking at the transformation function, we find it calls a method that XORs all the characters inthe input with a key, which turns out to be `2` (found by modifying the code to print it out). then,it splits the input into chunks of 4, uses the first 2 chars as a class name, and iterates 3 timesto transform the second 2 chars by calling the method in the class. the result is concatenatedtogether. this can be solved with a simple script to parse the java files to map thetransformations, then reversing the transformation by doing the opposite of this operation.
first, parse the java. it's very regular so this isn't too hard
```pythonmapping = {}
for file in pathlib.Path("src").iterdir():    if "Main" in file.name:        continue    name = file.name.replace(".java", "")    with file.open("r") as f:        data = f.read()    thisfile = {}    mname = None    for line in data.split("\n"):        if mname is None:            if "public String" in line:                mname = line.strip().split(" ")[2].replace("()", "")        else:            val = line.strip().split(" ")[1].replace('"', "").replace(";", "")            thisfile[mname] = val            mname = None    mapping[name] = thisfile
```
next, go through backwards to find which class has 3 methods that can be chained to produce therequired output. (implemented this with horrible CTF spaghetti code, please don't tell my fundiesprofessor :)
```pythonstart = "javautil"
def rfind(what):    for file,data in mapping.items():        for k,v in data.items():            if v == what and k in data.values():                for k2, v2 in data.items():                    if v2 == k and k2 in data.values():                        for k3, v3 in data.items():                            if v3 == k2:                                return file + k3
data = rfind("ja") + rfind("va") + rfind("ut") + rfind("il")```
finally compute XOR for the flag
```pythondata = bytearray(data.encode())for i in range(len(data)):    data[i] ^= 2
print(data)```
see original writeup for full source