coded_conspiracy

by sealldev & finnersio
๐Ÿšฉ CTFs SecEdu CTF 2024 rev
Suggested: #xor #ghidra #cyberchef #gdb
coded_conspiracy / SecEdu CTF 2024
coded_conspiracy

Description

Our team has discovered a series of binaries on a seized web server associated with NO_NO_NO. These binaries seem to communicate extensively. Your task is to find a way to analyse these messages.

nc chals.secedu.site 5018

Original Writeup on finnersioโ€™s blog

As part of the challenge we are provided with a binary and something to netcat to, we also know these programs are communicating with each other.

Running file on the provided binary we see itโ€™s stripped, meaning we wonโ€™t have any debugging symbols like function names to help us analyse the program.

$ file mystery
mystery: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

Running the strings command we can see the file is presumably written in the go programming language.

$ strings mystery | tail
.noptrbss
.go.fuzzcntrs
.go.buildinfo
.elfdata
.rodata
.typelink
.itablink
.gosymtab
.gopclntab
.shstrtab

Running the binary, we get what looks to be gibberish or encoded data:

./mystery
Received: bhOz*
               ;
                *
rt^RGLwOQ~DH~N1iSu^Yu^OSL~oODoToGP tDH~DH6fYuMHs(
                                                   tDR~IHrER!
_wEO~'6_KH~VER7
+
o~Z)/
+	+
{V~1yYi\Yi^ip]
hK_4	(k 1cGP;\YiYUtD9~D_tNUuM9COt#6$6'
                                         xTihBzy;BHvFK~Wc4k(i4nh_
dS~qW
5OX]uYUoCSuKP4y6;
;
;
6^NzDOr^UtD]wXoN% s^Qw*xOncBHvF
DvFRhs^Hk4]KlK(SiM*"Ds^QcGP!F]uM9OR9
;UEH;cQkFYvORoOX'Hr^P~6sO]6^tNE% 5T*	+6
% 5'^tNE% 4BHvFB

For those wondering what this says, youโ€™ll want to investigate the while loop at the end of the main function

We get some more gibberish when we connect via nc:

$ nc chals.secedu.site 5018
DS;LPzM}EN;SSn

After doing a quick google on reversing Go binaries it looks like you can get most of the function names back in debuggers like IDA and Ghidra using some scripts. I decided to use Ghidra and GoReSym to get the function names back.

After running GoReSym we can see a main.main function is identified in the functions window. There is a lot of stuff going on but right near the top of the function is a for loop which is XORโ€™ing some variable.

for (lVar4 = 0; lVar4 < 0x29; lVar4 = lVar4 + 1) {
    uVar2 = lVar4 + (SUB168(SEXT816(-0x5555555555555555) * SEXT816(lVar4),8) + lVar4 >> 1) * -3;
    if (2 < uVar2) goto LAB_004d2ea5;
    *(byte *)(lVar1 + lVar4) = *(byte *)((long)&local_7b + uVar2) ^ *(byte *)(lVar4 + local_18);
  }

Letโ€™s investigate, click on the beginning of the for loop and take a look at the listing window in ghidra and find the memory address for the instruction. Start up gdb and set a breakpoint:

gdb mystery
(gdb) break *0x004d2be4
Breakpoint 1 at 0x4d2be4
(gdb) r
Thread 1 "mystery" hit Breakpoint 1, 0x00000000004d2be4 in ?? ()

After taking a look at the registries, I didnโ€™t find much. Letโ€™s see what they look like after an iteration of the loop.

(gdb) c
Continuing.
Thread 1 "mystery" hit Breakpoint 1, 0x00000000004d2be4 in ?? ()
(gdb) i r
...
(gdb) x/s $rsi
0xc0000b6000:	"Hello, Server! Can I get the flag please?"
(gdb) x/s $rax
0xc00001c0f0:	"b"

After inspecting all the registries I found rsi and rax were storing strings, presumably the data being XORโ€™d in rsi and the result of the XOR in rax. Letโ€™s find out, back in Ghidra find the ^ in the for loopโ€™s body and set another breakpoint in gdb at this memory address.

(gdb) break *0x004d2bcc
Breakpoint 2 at 0x4d2bcc
(gdb) r
(gdb) c
(gdb) c
Continuing.
Thread 1 "mystery" hit Breakpoint 2, 0x00000000004d2bcc in ?? ()

Analysing the instruction pointer we can see edx and edi are being XORโ€™d

(gdb) x/i $rip
=> 0x4d2bcc:	xor    %edx,%edi
(gdb) i r
...
rdx            0x48                72
rdi            0x2a                42
...

We see rdx is storing 0x48 which corresponds to the ASCII value of โ€˜Hโ€™ and rdi is storing 0x2a. 0x48 ^ 0x2a = 0x62 aka โ€˜bโ€™, terrific news weโ€™ll call it a day and skip to the end of the for loopโ€ฆ

(gdb) x/s $rsi
0xc0000b2000:	"Hello, Server! Can I get the flag please?"
(gdb) x/s $rax
0xc0000b2030:	"bYwFS7\no~XJ~X\035;i]u\nu;MYo\nHsO\034}F]|\nLwO]hO\003"

Ah, not so fast rsi ^ 0x2a is not whatโ€™s ended up in rax, maybe the key is different for every characterโ€ฆ

Letโ€™s head back to breakpoint 2 and continue through the loop, examining the contents of the XOR key in rdi each time.

// First iteration
rdi = 0x2a
// Second Iteration
rdi = 0x3c
// Third Iteration
rdi = 0x1b
// Fourth iteration
rdi = 0x2a
// Fifth Iteration
rdi = 0x3c
// Sixth Iteration
rdi = 0x1b
...

From this we can determine the XOR key is 2a3c1b. We can also confirm this by looking at the value of rax which increments a counter to 2 on each iteration of the loop before resetting to 0.

Letโ€™s send the string in rax to the server and see what we get:

$ echo -ne "bYwFS7\no~XJ~X\035;i]u\nu;MYo\nHsO\034}F]|\nLwO]hO\003" | nc chals.secedu.site 5018
bYwFS7
_wCYu^;O~
HsCO;^S;XYj_Yh^oBY;LPzM;DSuERt
                              #ZNZz#(

We get a different response this time, letโ€™s decode this with our new found XOR key:

Hello, client! Use this to request the flag: nonono5783fddfa9383839

Take the nonono5783fddfa9383839 and XOR that with the key and convert the result to hex with delimiter \x using cyberchef. Letโ€™s send that back to the server like it asked:

$ echo -ne "\x44\x53\x75\x45\x52\x74\x1f\x0b\x23\x19\x5a\x7f\x4e\x5a\x7a\x13\x0f\x23\x19\x04\x28\x13" | nc chals.secedu.site 5018 | xxd

We get some non-ascii characters in the response so I will take a hexdump instead and again XOR the result in cyberchef for the flag: SECEDU{X0R_Y0UR_3Y3S_0NLY}

Flag: SECEDU{X0R_Y0UR_3Y3S_0NLY}

Share this writeup

Contribute

Found an issue or want to improve this writeup?

Edit on GitHub