only the first three challenges :)
Init:
It’s a pretty easy challenge, so I started by loading the file in jd-gui
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
public class Init {
private static final String infoUrl = "https://ipinfo.io/country";
public static String xorDecrypt(byte[] input, int key) { byte[] output = new byte[input.length]; for (int i = 0; i < input.length; i++) { output[i] = (byte) (input[i] ^ key); } return new String(output); }
public static void main(String[] args) { System.out.println("Welcome to CyCTF 2023."); if (args.length < 1 || !"flag".equals(args[0])) { System.out.println("What do you want?"); } else { try { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(new URI(infoUrl)) .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); String countryCode = response.body().trim();
System.out.println("Your IP-based country code is: " + countryCode); System.out.println("Decoding flag...");
int xorKey = (countryCode.charAt(0) + countryCode.charAt(1)) - 80; byte[] encryptedFlag = {34, 56, 34, 53, 39, 58, 50, 113, 44, 114, 30, 45, 117, 15, 120, 20, 117, 120, 114, 18, 30, 2, 117, 47, 30, 121, 114, 30, 12, 113, 19, 114, 30, 34, 113, 15, 39, 52, 18, 112, 15, 120, 30, 118, 41, 117, 47, 30, 34, 113, 37, 114, 30, 113, 121, 7, 52, 18, 2, 117, 118, 112, 113, 15, 60}; System.out.println("Flag is: " + xorDecrypt(encryptedFlag, xorKey));
} catch (Exception e) { e.printStackTrace(); } } }}It’s a simple code. It just gets a country code from ipinfo (and based on the language used, the country code is ‘CN’), and then xors the bytearray with it, which is the flag!
So the solution is to create a simple Java program that computes the xor with “CN” as the country code.
The flag is: cyctf{s0m3_l4N9U493S_C4n_83_M0R3_c0NfuS1N9_7h4n_c0d3_08FuSC4710N}
Spaghetti:
It’s a pattern checker with an obfuscated javascript file.

This is our target function.

That function takes an array, which is the selected points on the pattern; if the selected first row is from left to right, that array will have [0, 1, 2] and when selected from right to left, it’ll be [2, 1, 0]
So after deobfuscating and refactoring, we get this:
function arrayCheck(inputArray) { if (inputArray[6] + inputArray[2] + (inputArray[3] + inputArray[4]) != 15) { return false; } if ((inputArray[5] + inputArray[6] ^ inputArray[2] + inputArray[5]) != 8) { return false; } if ((inputArray[2] + inputArray[7]) * (inputArray[1] + inputArray[2]) != 165) { return false; } if (inputArray[7] + inputArray[4] + (inputArray[0] ^ inputArray[5]) != 20) { return false; } if ((inputArray[3] ^ inputArray[5]) * (inputArray[6] + inputArray[3]) != 4) { return false; } if ((inputArray[1] + inputArray[3] ^ inputArray[7] + inputArray[3]) != 12) { return false; } if (inputArray[0] + inputArray[3] + (inputArray[4] + inputArray[6]) != 9) { return false; } if ((inputArray[3] + inputArray[0]) * (inputArray[5] * inputArray[1]) != 45) { return false; } if ((inputArray[4] ^ inputArray[1]) + (inputArray[3] + inputArray[0]) != 8) { return false; } if (inputArray[5] * inputArray[6] + inputArray[2] * inputArray[5] != 40) { return false; } if (inputArray[2] * inputArray[7] + inputArray[1] * inputArray[2] != 80) { return false; } if (inputArray[7] * inputArray[4] + inputArray[0] * inputArray[5] != 52) { return false; } if (inputArray[3] * inputArray[5] + inputArray[6] * inputArray[3] != 5) { return false; } if (inputArray[1] * inputArray[3] + inputArray[7] * inputArray[3] != 10) { return false; } if (inputArray[0] * inputArray[3] + inputArray[4] * inputArray[6] != 2) { return false; } if (inputArray[3] * inputArray[0] + inputArray[5] * inputArray[1] != 17) { return false; } if (inputArray[4] * inputArray[1] + inputArray[3] * inputArray[0] != 20) { return false; } return true;}It’s just a couple of checks to make sure the pattern selected is correct, and that pattern is used to decrypt the flag
With the help of a friend, I was able to create a checker to bruteforce this
import itertools
arr = list(itertools.permutations([0,1,2,3,4,5,6,7,8]))
def checker(): for i in arr: if (i[6] + i[2] + i[3] + i[4]) != 15: continue if (i[5] + i[6] ^ i[2] + i[5]) != 8: continue if (i[2] + i[7]) * (i[1] + i[2]) != 165: continue if i[7] + i[4] + (i[0] ^ i[5]) != 20: continue if (i[3] ^ i[5]) * (i[6] + i[3]) != 4: continue if (i[1] + i[3] ^ i[7] + i[3]) != 12: continue if i[0] + i[3] + (i[4] + i[6]) != 9: continue if (i[3] + i[0]) * (i[5] * i[1]) != 45: continue if (i[4] ^ i[1]) + (i[3] + i[0]) != 8: continue if i[5] * i[6] + i[2] * i[5] != 40: continue if i[2] * i[7] + i[1] * i[2] != 80: continue if i[7] * i[4] + i[0] * i[5] != 52: continue if i[3] * i[5] + i[6] * i[3] != 5: continue if i[1] * i[3] + i[7] * i[3] != 10: continue if i[0] * i[3] + i[4] * i[6] != 2: continue if i[3] * i[0] + i[5] * i[1] != 17: continue if i[4] * i[1] + i[3] * i[0] != 20: continue print(i)
checker()And it prints the one pattern: (2, 3, 8, 1, 6, 5, 0, 7, 4)
And then we get our flag!

Undercover:
Based on the description and file structure, it looks like it’s JIT Compiled, but that can’t stop us!
Loading the undercover.dll through dnspy, we get this

After renaming functions

To sum it up, it has encrypted resources and double decrypts them, but the AES key is stored in the JIT Compiled code, but with a simple breakpoint solved it.


From that, I got the key and IV and the decrypted text.

And since then, it’s a DLL. I make the executable load it.
The decrypted text with strings and this PowerShell code
$encodedScript = 'ZgB1AG4AYwB0A ... too long';$decodedScript = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encodedScript));Invoke-Expression $decodedScriptSo, just decoding it in PowerShell, we get a script that does SHA256 hash checking of the input flag split into 2-character chunks.

The hashArray contains 37 SHA256 hashes, each corresponding to a 2-character chunk of the flag.
I just got the array and loaded it into a SHA256 reverse lookup site and got the flag:
cyctf{50_y0u_C4N_3X3CU73_p0W3r5h3Ll_W17h0u7_H4v1N9_70_3X3cu73_P0w3r5H3lL!}
I hope that my explanation is clear and I enjoyed this CTF. See you next time.
If this article helped you, please share it with others!
Some information may be outdated