# Introduction
WiiWii was a challenge from the 2024 edition of the Midnight Flag CTF. This particular challenge was about reversing a Dolphin file.
I started by loading this file on a Dolphin Emulator in Debug mode by doing dolphin-emu -d
. I then set up my View
to have the register
, memory
and instruction
tabs.
We can see this starts a server on a local IP address. I patched the port so it would be on port 4095 instead of 80 since the emulator didn’t have permissions for that port. Let’s try and curl
it.
curl 10.96.0.16:4095/flag
This printed /STTO
to the output, meaning it probably did some encoding/encrypting on our /flag
endpoint.
# Disassembly
We can look at the file on the disassembler, for this I used the GameCube DOL Binary Ninja plugin. Looking for the Default response sent
string, we find this function :
If you’ve ever followed Beej’s networking programming guide this function should look very similar to the C implementation of a TCP server. We see that we should strive to get the check_endpoint
function to return something different than to get the Initialization response
.
Some clarification on how I found the strcmp_int32
Well I could reconstruct the string by hand, and although I suspect that var_d0
is the key for the Vigenere-like rotation, I’m not quite sure.
Here we go into disassembly view, and look for the instructions which will contain our wanted values.
# Debugging with dolphin-emu
Using this as an excuse to learn a bit about the Dolphin Emulator debugger, I placed a few breakpoints, one at 80005928
and one at 8000595c
. This would allow me to look in memory for the value and confirm the rotation hypothesis.
Let’s curl 10.96.0.16:4095/AAAAAAAAAAAA
.
We break at the expected functions.
And sure enough, in memory at around 801c8cc0
.
If we step through the operations around r9
, we can confirm some Vigenere
like encryption with the INIT
variable, where each character from the alphabet is subtracted by one of the letters according to the index.
This could also be deducted by sending some request like /ABCDEF123456abcdefghi
and looking at the offsets from the results.
From all this information, we can assume that the wanted input is one that results in the :.{01L_5PP001_64Z3_K0V5013}
string. We write a small solution script :
key = [0x13, 0x18, 0xD, 0x18]
def find(string, key):
rev = []
for i in range(len(string)):
c = string[i]
if 'a' <= c <= 'z':
rev.append(chr(ord(c) + key[i % 4]))
elif 'A' <= c <= 'Z':
rev.append(chr(ord(c) + key[i % 4]))
else:
rev.append(c)
return rev
transformed_str = ":.{01L_5PP001_64Z3_K0V5013}"
original_str = find(transformed_str, key)
print("Original string:", ''.join(original_str))
And we get the flag: :.{01d_5ch001_64m3_c0n5013}