WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER WE DON’T EVEN KNOW EITHER
US Navy CCT – Deep Six
4 min read
Avatar of jakesss jakesss
Table of Contents

This is my writeup for the Deep Six forensics challenge from the US Navy Cyber Competition Team 2019 assessment.

Challenge Description

Another one with really no story behind it…just find the flag. Flag will be in the format: CCT{flag}

Challenge Summary

This challenge started with a USB packet capture, where a zip file was extracted using tshark. An in-depth inspection of this pcapng file revealed covert communication through the ICMP protocol, decrypted with information from OSINT research related to the movie “The Net.” Next, Cryptcat communications were spotted and decrypted using a password found via OSINT. Lastly, a ROT-13 encoded and reversed string was statically analyzed in a captured x64 ELF binary, leading to the discovery of the flag.

Extract pcapng file From USB Capture

Running a hex dump on the file, I see the magic bytes for a zip file, with a file named pcap_chal.pcap inside:

xxd pcap1_v2.pcapng | head -n 50

image

Opening the packet capture in Wireshark, it appears the file was transferred via the USB protocol: image

Extract the zip file using the following bash script

# Extract hexedecimal usb data from the packet capture
tshark -r pcap1_v2.pcapng -Y 'usb.capdata' -T fields -e usb.capdata > raw
# Convert the hexedecimal output to raw bytes that binwalk can understand
xxd -r -p raw raw.bin
# Carve the zip file from the raw data
binwalk --dd='.*' raw.bin

image

Unzip the file from the directory created by binwalk: image

Discover Covert ICMP Communication Channel

Open pcap_chal.pcap in Wireshark, and view the Protocol Hierarchy Statistics —> Protocol Hierarchy: image

There were an unusually large amount of ICMP packets. Let’s filter by ICMP, and view these packets: image

Every once in a while, there is a ICMP packet sent with no response, and a packet length not equal to 98. It appears the ICMP protocol’s data field is being used as a covert communication channel: image

Lets extract all of their conversations with tshark

tshark -r pcap_chal.pcap -Y 'icmp && frame.len != 98' -T fields -e data

image

Decode the hex in CyberChef to view their communications: image It seems there was a file transferred over the network with cryptcat.

After some quick OSINT, I discover the character and location in the messages are from the movie The Net. In the movie, Angela Bennett finds a password in Delvin’s wallet. It seems we need to decrypt the cryptcat communications using the password BER5348833

Extract Binary from .pcap with cryptcat

First, extract all the cryptcat packets from the .pcap file, and convert it to raw bytes:

# Note, the messages say to use the "metasploit port"; by default, meterpreter sessions listen on port 4444.
tshark -r pcap_chal.pcap -Y 'tcp.dstport==4444' -T fields -e data | tr -d '\n' | xxd -r -p > bytes

Set up the cryptcat listener on your primary machine:

# This machine: 192.168.19.131
sudo apt install cryptcat
cryptcat -l -k BER5348833 -p 4444 > unencrypted_cryptcat

Copy the bytes binary file to another system on the same subnet as your primary box, and send the file to port 4444 with netcat

# This machine: 192.168.19.132
netcat 192.168.19.131 4444 < bytes

It appears we have a x64 ELF binary. Time to open up IDA. image

Discover and Decode the Flag Using Static Analysis

Let’s view the main function:

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  size_t v3; // rax
  size_t v4; // rax
  char v6; // [rsp+17h] [rbp-A9h]
  int i; // [rsp+18h] [rbp-A8h]
  int j; // [rsp+18h] [rbp-A8h]
  int v9; // [rsp+1Ch] [rbp-A4h]
  int v10; // [rsp+24h] [rbp-9Ch]
  char *ptr; // [rsp+28h] [rbp-98h]
  char *ptra; // [rsp+28h] [rbp-98h]
  char *ptrb; // [rsp+28h] [rbp-98h]
  char *buf; // [rsp+38h] [rbp-88h]
  char *v15; // [rsp+40h] [rbp-80h]
  char *dest; // [rsp+48h] [rbp-78h]
  char s[48]; // [rsp+50h] [rbp-70h] BYREF
  char src[56]; // [rsp+80h] [rbp-40h] BYREF
  unsigned __int64 v19; // [rsp+B8h] [rbp-8h]

  v19 = __readfsqword(0x28u);
  strcpy(s, "gf1j7_n_r6_bg_g0t_f4u_re3ug_qe@m1j_c@pc_n_f'3u");
  buf = (char *)calloc(1uLL, 0x10uLL);
  v15 = (char *)sub_5568F1038279();
  if ( (int)sub_5568F10382A8((__int64)v15, "irc.cct", 0x1A0Bu) < 0 )
  {
    printf("ERROR %s\n", *((const char **)v15 + 4));
    exit(*((_DWORD *)v15 + 6));
  }
  inet_ntop(2, v15 + 8, buf, 0x10u);
  if ( !buf )
  {
    puts("Failed to get ip");
    exit(*((_DWORD *)v15 + 6));
  }
  printf("Found the server at %s\n", buf);
  free(buf);
  if ( (int)sub_5568F10383CC(v15) < 0 )
  {
    printf("ERROR %s\n", *((const char **)v15 + 4));
    exit(*((_DWORD *)v15 + 6));
  }
  puts("Connected to my server!");
  sleep(5u);
  ptr = (char *)sub_5568F10384A2(v15);
  if ( ptr )
    printf("%s", ptr + 8);
  sub_5568F1038437((__int64)v15, "CAP LS 302\r\n", 0xCuLL);
  sub_5568F1038437((__int64)v15, "USER cct2019 cct2019 irc.cct :realname\r\n", 0x28uLL);
  sub_5568F1038437((__int64)v15, "NICK cct\r\n", 0xAuLL);
  if ( ptr )
    free(ptr);
  ptra = (char *)sub_5568F10384A2(v15);
  if ( ptra )
    printf("%s", ptra + 8);
  sub_5568F1038437((__int64)v15, "JOIN #flag\r\n", 0xCuLL);
  if ( ptra )
    free(ptra);
  ptrb = (char *)sub_5568F10384A2(v15);
  if ( ptrb )
    printf("%s", ptrb + 8);
  v10 = strlen(s);
  v9 = v10 - 1;
  for ( i = 0; i < v10; ++i )
  {
    v6 = s[i];
    if ( (v6 <= 64 || v6 > 77) && (v6 <= 96 || v6 > 109) )
    {
      if ( v6 > 77 && v6 <= 90 || v6 > 109 && v6 <= 122 )
        s[i] = v6 - 13;
    }
    else
    {
      s[i] = v6 + 13;
    }
  }
  for ( j = 0; j < v10; ++j )
    src[j] = s[v9--];
  src[j] = 0;
  v3 = strlen(src);
  dest = (char *)calloc(1uLL, v3 + 22);
  strcat(dest, "PRIVMSG #flag :CCT{");
  strcat(dest, src);


  *(_DWORD *)&dest[strlen(dest)] = 658813;
  v4 = strlen(dest);
  sub_5568F1038437((__int64)v15, dest, v4);
  free(dest);
  while ( *((_DWORD *)v15 + 6) != -1 )
  {
    if ( ptrb )
      free(ptrb);
    ptrb = (char *)sub_5568F10384A2(v15);
  }
  puts(*((const char **)v15 + 4));
  if ( ptrb )
    free(ptrb);
  close(*(_DWORD *)v15);
  free(v15);
  return 0LL;
}

On line 22, it appears we have a encoded flag saved to the s variable:

strcpy(s, "gf1j7_n_r6_bg_g0t_f4u_re3ug_qe@m1j_c@pc_n_f'3u");

It looks ROT-13 encoded:

v10 = strlen(s);
v9 = v10 - 1;
for (i = 0; i < v10; ++i) {
  v6 = s[i];
  if ((v6 <= 64 || v6 > 77) && (v6 <= 96 || v6 > 109)) {
    if (v6 > 77 && v6 <= 90 || v6 > 109 && v6 <= 122)
      s[i] = v6 - 13;
  } else {
    s[i] = v6 + 13;
  }
}

Then reversed:

for ( j = 0; j < v10; ++j )
    src[j] = s[v9--];

The following C code decodes and prints the flag:

solve.c

#include <stdio.h>
#include <string.h>

int main() {
    char s[100];
    char src[100];
    int v10, v9, i, v6, j;

    strcpy(s, "gf1j7_n_r6_bg_g0t_f4u_re3ug_qe@m1j_c@pc_n_f'3u");
    
    v10 = strlen(s);
    v9 = v10 - 1;
    for (i = 0; i < v10; ++i) {
        v6 = s[i];
        if ((v6 <= 64 || v6 > 77) && (v6 <= 96 || v6 > 109)) {
            if (v6 > 77 && v6 <= 90 || v6 > 109 && v6 <= 122)
                s[i] = v6 - 13;
        }
        else {
            s[i] = v6 + 13;
        }
    }
    
    for ( j = 0; j < v10; ++j ) {
      src[j] = s[v9--];
      }
    printf("ROT-13 decoded string: %s\n", s);
    printf("Reversed string: %s\n", src);
    return 0;
}

Compile and run the code to reveal the flag:

gcc solve.c -o solve
./solve

image

Flag: CCT{h3's_a_pc@p_w1z@rd_th3re_h4s_g0t_to_6e_a_7w1st}