India - Reverse Me & Extract Flag from Packets (rev/network)

Inspecting the wireshark PCAP, there only seems to be one TCP stream. Right click any packet and follow TCP Stream to see the following:
type c:\tmp\flag.txt
1KeGOcMvvKpPbxrNRdyqJmSGh3j+ZCvIT5RKk6lTBkSGBYSYrX7dy3Q/E8wVuQAXNFMs978T1A4qyx7EeX9fvg==We can guess that this is probably some ciphertext we need to decrypt.
Let's look at the DMP we are given:
elijah@soyabean:/mnt/c/Users/chiae/Downloads/cyberseagames/csg_reversing_network_forensic_challenge/csg_reversing_network_forensic_challenge$ file ./csg_reversing_network_forensic_challenge.DMP
./csg_reversing_network_forensic_challenge.DMP: Mini DuMP crash report, 16 streams, Sun Sep 7 06:03:02 2025, 0x421826 typeI found that volatility was unable to work with this file, but WinDbg worked fine. On loading it into WinDbg we can list all modules using lm:
0:000> lm
start end module name
0000015c`f4e80000 0000015c`f4e88000 Microsoft_Win32_Primitives (pdb symbols) C:\ProgramData\Dbg\sym\Microsoft.Win32.Primitives.pdb\CE3B39E6FAD8F5EC8C3AA743CDF400641\Microsoft.Win32.Primitives.pdb
0000015c`f67b0000 0000015c`f67b8000 ajccbc_reversing_challenge (deferred)
0000015c`f67c0000 0000015c`f67ce000 System_Runtime (deferred)
0000015c`f67d0000 0000015c`f67d8000 System_Runtime_Intrinsics (deferred)
0000015c`f67e0000 0000015c`f67e8000 System_Diagnostics_Tracing (deferred)
00007ff7`97ce0000 00007ff7`98638000 csg_reversing_network_forensic_challenge (deferred)
00007ffc`893e0000 00007ffc`8a06d000 System_Private_CoreLib (deferred)
00007ffc`93a40000 00007ffc`93c6e000 icu (deferred)
00007ffc`a82f0000 00007ffc`a8373000 System_Net_Sockets (deferred)
00007ffc`a8500000 00007ffc`a8524000 System_Memory (deferred)
00007ffc`a8580000 00007ffc`a85a8000 System_Console (deferred)
00007ffc`a8660000 00007ffc`a8696000 System_Net_Primitives (deferred)
00007ffc`af430000 00007ffc`af445000 System_Runtime_InteropServices (deferred)
00007ffc`b2180000 00007ffc`b2214000 apphelp (deferred)
00007ffc`b2420000 00007ffc`b2427000 wshunix (deferred)
00007ffc`b2ca0000 00007ffc`b2cb2000 kernel_appcore (deferred)
00007ffc`b44b0000 00007ffc`b451a000 mswsock (pdb symbols) C:\ProgramData\Dbg\sym\mswsock.pdb\E366E96F199A74D8B7651617AF8408431\mswsock.pdb
00007ffc`b4e00000 00007ffc`b4e27000 bcrypt (deferred)
00007ffc`b4f90000 00007ffc`b528d000 KERNELBASE (deferred)
00007ffc`b5290000 00007ffc`b53a7000 gdi32full (deferred)
00007ffc`b53b0000 00007ffc`b53d2000 win32u (deferred)
00007ffc`b5500000 00007ffc`b5582000 bcryptPrimitives (deferred)
00007ffc`b55e0000 00007ffc`b56e0000 ucrtbase (deferred)
00007ffc`b56e0000 00007ffc`b577d000 msvcp_win (deferred)
00007ffc`b5780000 00007ffc`b58a3000 rpcrt4 (deferred)
00007ffc`b58b0000 00007ffc`b601f000 shell32 (deferred)
00007ffc`b6600000 00007ffc`b6953000 combase (deferred)
00007ffc`b6a70000 00007ffc`b6b10000 sechost (deferred)
00007ffc`b6bc0000 00007ffc`b6d5d000 user32 (deferred)
00007ffc`b6d60000 00007ffc`b6e21000 kernel32 (deferred)
00007ffc`b6f30000 00007ffc`b6f9b000 ws2_32 (pdb symbols) C:\ProgramData\Dbg\sym\ws2_32.pdb\C4AF2923BB8706346F027C3A7631E89F1\ws2_32.pdb
00007ffc`b6fa0000 00007ffc`b706d000 oleaut32 (deferred)
00007ffc`b7070000 00007ffc`b709b000 gdi32 (deferred)
00007ffc`b7100000 00007ffc`b719e000 msvcrt (deferred)
00007ffc`b71a0000 00007ffc`b72cb000 ole32 (deferred)
00007ffc`b72d0000 00007ffc`b72ff000 imm32 (deferred)
00007ffc`b7300000 00007ffc`b73b0000 advapi32 (deferred)
00007ffc`b7750000 00007ffc`b7948000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\4C328D42D0B9A2B218FB85860DECF27C1\ntdll.pdb
We can guess that the module of interest is probably csg_reversing_network_forensic_challenge or ajccbc_reversing_challenge. Unfortunately the WinDbg .writemem command didn't work successfully. This is because ajccbc_reversing_challenge.dll was not stored contiguously in memory, as we can see using !address -f:MEM_COMMIT to filter by committed virtual memory:
15c`f67b0000 15c`f67b1000 0`00001000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image [ajccbc_reversing_challenge; "C:\Users\tsshimizu\Desktop\share\win-x64\ajccbc_reversing_challenge.dll"]
15c`f67b2000 15c`f67b5000 0`00003000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image [ajccbc_reversing_challenge; "C:\Users\tsshimizu\Desktop\share\win-x64\ajccbc_reversing_challenge.dll"]
15c`f67b6000 15c`f67b7000 0`00001000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image [ajccbc_reversing_challenge; "C:\Users\tsshimizu\Desktop\share\win-x64\ajccbc_reversing_challenge.dll"]What worked was using the MEX Debugging Extension for WinDbg, and using it to write modules. You can use the following command to dump all DLLs/EXEs:
!mex.writemodule -a -p "C:\Users\chiae\Downloads\cyberseagames\csg_reversing_network_forensic_challenge\csg_reversing_network_forensic_challenge"Apparently the exe was generated as a result of JIT compilation when the dll is run.
Let's analyse the dll using dnspy:
Let's look at the important C# functions:
private static void <Main>$(string[] args)
{
arc_server.RemoteShell();
}
internal class arc_server
{
// Token: 0x06000008 RID: 8 RVA: 0x00002160 File Offset: 0x00000360
public static void RemoteShell()
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 8553);
tcpListener.Start();
bool flag = true;
arc_crypto arc_crypto = new arc_crypto();
while (flag)
{
using (TcpClient tcpClient = tcpListener.AcceptTcpClient())
{
using (NetworkStream stream = tcpClient.GetStream())
{
using (StreamReader streamReader = new StreamReader(stream))
{
using (StreamWriter streamWriter = new StreamWriter(stream)
{
AutoFlush = true
})
{
string text;
while ((text = streamReader.ReadLine()) != null)
{
string text2 = text.ToLower().Trim();
if (text2 == "quit" || text2 == "q" || (text2 != null && text2.Length == 0))
{
flag = false;
}
else
{
Console.WriteLine("Received command: " + text);
string text3 = arc_server.ExecuteCommand(text);
arc_communicator.postBlog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ": " + arc_crypto.obfuscate(text), arc_crypto.obfuscate(text3));
streamWriter.WriteLine(arc_crypto.obfuscate(text3));
}
}
}
}
}
}
}
}As we can see from this snippet:
string text;
while ((text = streamReader.ReadLine()) != null)
{
string text2 = text.ToLower().Trim();
if (text2 == "quit" || text2 == "q" || (text2 != null && text2.Length == 0))
{
flag = false;
}
else
{
Console.WriteLine("Received command: " + text);
string text3 = arc_server.ExecuteCommand(text);
arc_communicator.postBlog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ": " + arc_crypto.obfuscate(text), arc_crypto.obfuscate(text3));
streamWriter.WriteLine(arc_crypto.obfuscate(text3));
}
}What wireshark captured was the command executed, and the following line was the obfuscated result of executing that command.
Let's look at all the obfuscation:
public class arc_crypto
{
// Token: 0x0600000B RID: 11 RVA: 0x000023B4 File Offset: 0x000005B4
public arc_crypto()
{
string text = "2a5b05310e08081f2b3405031134372a073c1f1c371a2e1c09303b4308393219";
string text2 = "252e0a0a3a1f291c1b343b39212b3c11013d312f08315158";
this.key = Encoding.UTF8.GetBytes(arc_crypto.AdvancedDecode(text));
this.iv = Encoding.UTF8.GetBytes(arc_crypto.AdvancedDecode(text2));
}
// Token: 0x0600000C RID: 12 RVA: 0x00002400 File Offset: 0x00000600
public string obfuscate(string plainText)
{
string text;
using (Aes aes = Aes.Create())
{
aes.Key = this.key;
aes.IV = this.iv;
ICryptoTransform cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, 1))
{
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(plainText);
}
text = Convert.ToBase64String(memoryStream.ToArray());
}
}
}
return text;
}
// Token: 0x0600000D RID: 13 RVA: 0x000024D0 File Offset: 0x000006D0
public static string AdvancedEncode(string input)
{
string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
stringBuilder.Append(text[i] ^ arc_crypto.xorKey[i % arc_crypto.xorKey.Length]);
}
string text2 = stringBuilder.ToString();
StringBuilder stringBuilder2 = new StringBuilder();
foreach (char c in text2)
{
StringBuilder stringBuilder3 = stringBuilder2;
int num = (int)c;
stringBuilder3.Append(num.ToString("x2"));
}
return stringBuilder2.ToString();
}
// Token: 0x0600000E RID: 14 RVA: 0x00002578 File Offset: 0x00000778
public static string AdvancedDecode(string input)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < input.Length; i += 2)
{
stringBuilder.Append((char)Convert.ToInt32(input.Substring(i, 2), 16));
}
string text = stringBuilder.ToString();
StringBuilder stringBuilder2 = new StringBuilder();
for (int j = 0; j < text.Length; j++)
{
stringBuilder2.Append(text[j] ^ arc_crypto.xorKey[j % arc_crypto.xorKey.Length]);
}
string text2 = stringBuilder2.ToString();
string text3;
try
{
byte[] array = Convert.FromBase64String(text2);
text3 = Encoding.UTF8.GetString(array);
}
catch (Exception)
{
text3 = null;
}
return text3;
}
// Token: 0x04000001 RID: 1
private readonly byte[] key;
// Token: 0x04000002 RID: 2
private readonly byte[] iv;
// Token: 0x04000003 RID: 3
private static readonly string xorKey = "simplekey";
// Token: 0x04000004 RID: 4
private static readonly string orKeyx = "complekey";
}
}key: AdvancedDecode("2a5b05310e08081f2b3405031134372a073c1f1c371a2e1c09303b4308393219")
iv: AdvancedDecode("252e0a0a3a1f291c1b343b39212b3c11013d312f08315158")
Upon decoding the key and iv using the xorKey which is simplekey, we can use AES CBC to decrypt the flag:
from base64 import b64decode
from pwn import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
key = "2a5b05310e08081f2b3405031134372a073c1f1c371a2e1c09303b4308393219"
iv = "252e0a0a3a1f291c1b343b39212b3c11013d312f08315158"
ct = "1KeGOcMvvKpPbxrNRdyqJmSGh3j+ZCvIT5RKk6lTBkSGBYSYrX7dy3Q/E8wVuQAXNFMs978T1A4qyx7EeX9fvg=="
xorKey = b'simplekey'
key = bytes.fromhex(key)
iv = bytes.fromhex(iv)
key = xor(key, xorKey)
iv = xor(iv, xorKey)
key = b64decode(key.decode())
iv = b64decode(iv.decode())
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
ct = b64decode(ct)
pt = cipher.decrypt(ct)
pt = unpad(pt, AES.block_size).decode()
print(f"plaintext: {pt}")
# plaintext: R3v3rsing_@nd_N3tw0rk_F0r3nsic_Ch@ll3ng3_S0lv3d!!Last updated