Bank of America Infosecurity Challenge

CTF held on-site and online during the 2018 DerbyCon on behalf of Bank of America

October 5 - October 8 2018

Bank of America/DerbyCon

This was my first CTF, and unfortunately I wasn’t taking notes, yet. Plus the website is no longer accessible, so here are my best recollections of how these were presented and solved. It was a fantastic introduction to CTF, and on my first attempt I was able to complete 12 of the challenges. I’m sure I tried most or all of the other challenges but have even less recollection of their details. One of these days I’ll come back and look over the incomplete solutions I’ve written up here and see if I can resolve them – but it’s going to take some more experience to do so without the original clues.

TeamLudite (Web)

My first CTF challenge, and a nice easy one, too. I think a website was provided (or perhaps it was just the main CTF website), and there was a clue about robots. So, I checked the site’s robots.txt file, and sure enough there was the key.

Poetic Password (Password Cracking)

The challenge required cracking a password given the MD5 hash of that password "74ec1e2a9077201372be36d1d2391f93" and the clue that the password was three words from the Edgar Allen Poe poem Annabel Lee. I think the required flag was simply the three words password.

I downloaded a text copy of the poem online and processed it on the UNIX command line to split it into individual words, sorted and reduced that to only the unique words, and created a CSV that I copy/pasted into my Python script as an array. Elegant, no. Effective, yes. My Python was a little rusty, and the CLI text manipulation seemed easy enough at the time.

The following code iterates through every combination of three unique words from the word list “anna”, and checks to see if that combination of words results in the provided MD5 hash. In retrospect, this certainly could have been done with three for loops, removing the counters, but as I said, my Python was a little rusty at the time.

import hashlib

anna = ["A","And","Annabel","But","By","Can","Chilling","Coveted","For","Heaven","I","In","It","Lee","My","Nor","Of","So","Than","That","The","To",...
..."who","whom","wind","winged","wiser","with","without","year","you"]

length = len(anna)

count1 = 0
count2 = 0
count3 = 0
target = "74ec1e2a9077201372be36d1d2391f93"

while count1 < (length - 1):
 string = anna[count1] + anna[count2] + anna[count3]
 if (hashlib.md5(string.encode('utf-8')).hexdigest()) == target:
  check = string
 while count2 < (length - 1):
  string = anna[count1] + anna[count2] + anna[count3]
  if (hashlib.md5(string.encode('utf-8')).hexdigest()) == target:
   check = string
  while count3 < (length - 1):
   string = anna[count1] + anna[count2] + anna[count3]
   if (hashlib.md5(string.encode('utf-8')).hexdigest()) == target:
    check = string
   count3 += 1
  count2 += 1
  count3 = 0
 count1 += 1
 count2 = 0

print (check)

The code returns the password “kingdombeautifulchilling”.

Layers (Password Cracking)

This challenge required cracking the password to a ZIP file given the clue that the password was a four-digit number.

The code below (again some inelegant Python) tests every 4-digit password:

from zipfile import ZipFile

zip_file = 'file.zip'

count1 = 0
count2 = 0
count3 = 0
count4 = 0

while count1 <= 9:
 password = str(count1) + str(count2) + str(count3) + str(count4)
 try:
 # block raising an exception
  with ZipFile(zip_file) as zf:
   zf.extractall(pwd=bytes(password,'utf-8'))
  print (password)
 except:
  pass # doing nothing on exception
 while count2 <= 9:
  password = str(count1) + str(count2) + str(count3) + str(count4)
  try:
  # block raising an exception
   with ZipFile(zip_file) as zf:
    zf.extractall(pwd=bytes(password,'utf-8'))
   print (password)
  except:
   pass # doing nothing on exception
  while count3 <= 9:
   password = str(count1) + str(count2) + str(count3) + str(count4)
   try:
   # block raising an exception
    with ZipFile(zip_file) as zf:
     zf.extractall(pwd=bytes(password,'utf-8'))
    print (password)
   except:
    pass # doing nothing on exception
   while count4 <= 9:
    password = str(count1) + str(count2) + str(count3) + str(count4)
    try:
    # block raising an exception
     with ZipFile(zip_file) as zf:
      zf.extractall(pwd=bytes(password,'utf-8'))
     print (password)
    except:
     pass # doing nothing on exception
    count4 += 1
   count3 += 1
   count4 = 0
  count2 += 1
  count3 = 0
 count1 += 1
 count2 = 0

The code returns the password ‘8412’, which allows the ZIP file to be decompressed to an EXIF image file called “file”. Within the image is a QR code that I checked with a my phone’s QR code reader. The content of the QR code is the flag: ‘L!f3L!k3Ac0mput3r’.

Can you hear me now? (Pcaps)

This challenge provided a PCAP file and the clue mentioned something about someone finding a new “secure” way to store passwords.

Opening the PCAP in Wireshark shows that it is a series of SIP and RTP packets, indicating a VOIP connection or call. Using the Telephony RTP Analysis tool in Wireshark, it is possible to play the stream (i.e. play the conversation). The stream is simply someone reading out the flag ‘051057614277’.

What’s in here? (Pcaps) & Group Think (Pcaps)

Sorry, I don’t recall what the clues and requirements were for these (or even which pcap corresponds to which challenge ;) ), but the pcap for one is a TFTP stream of a text document containing RFC1350 (which happens to be the RFC for TFTP 2) and the pcap for the other contains a variety of traffic.

I think the What’s in here? corresponds to the latter pcap, and it includes an SMB2 session that contained an a request for machine policy preferences on the “mylab.local” machine. That XML document contained the Administrator username and a hashed password “DaihpXtHq3D2R/oClfRXQDoELtGEScRT7HGOi+V+0ZY” – I seem to recall passing that through Hashcat, but don’t remember the outcome.

PowerShell (Crypto)

Again, I don’t recall the clue, but the following Powershell code was included in a text file.

sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String('e797v40yL5dLalFSpXN+noKFgnOIGy+Xsh0vV3lRZkmqbkZ+cYmCerR2rEJIRmpRqkJxRn5pTopCUqpCok
JaTmK6QmJRfmleigJYUk9PT52XK7gksahENzgnNbVAQTc4NTk/L6VYwZiXC2QRSEt1SIZDSblJcV5JiYFBhkNRSi12C4GmBefnppaDjAYaCwA='),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()

First, this runs the Set-Alias (aliased itself to sal) to set an alias ‘a’ for the command New-Object.

Next, it runs Invoke-Expression (alias: iex) to execute the command a (now aliased to New-Object) and provides some Base64-encoded parameters for that New-Object command.

In order to see what the encoded payload is going to do, remove the “iex” part and run it in Powershell to get the flag hidden in a comment in the code:

<# DerbyCon 8 CTF #>
write-host '[+] There should be a flag around here ...'
Start-Sleep -Seconds 3
<# flag{Th@tw4sntt00h@rd} #>
write-host '[+] ...Somewhere'

Mystery Box (Stego)

I don’t recall if there was a clue, but the challenge provided a mysterybox.jpg file.

Being new to steganography, I started with all of the obvious colour manipulations in GIMP, but found nothing of interest. On the advice of some web searches I’ve long since forgotten (sorry), I looked closer at the file in a hex editor (Hex Fiend) and searched for the end code for the JPG file format indicated by the hex FF D9. That did not come at the end of the file, however, and immediately after those bytes I saw PK in the ANSI translation, indicating a PKZIP file starting at that position. I cut and pasted the remainder of the file (from the PK onwards) and saved it as a .ZIP file. Sure enough, the ZIP file could be opened and contained another JPG (key.jpg). I repeated the process, searching for the end of the JPG and found another PK. Cutting and pasting that into a new flag.zip file produced a ZIP file that required a password to open. This was both encouraging and frustrating, since I was getting a working ZIP, but I didn’t know the password. After a great deal of screwing about with colours in GIMP on the key.jpg file and repeated failed online and offline attempts to crack the password, I went back to look at the hex for the key.jpg. And there it was “first_to_the_key” in the JPG header. The flag.zip accepted that as the password and contained a file called flag, which contained the key “34f76fd16dd6c284a98d2eeabe4fb828”.

Binary Sea (Binary)

And last but not least, this challenge provided the Wheres_the_flag.dms file and I don’t recall the clue. Looking at the DMS file in a hex editor, I could see an ELF binary header and midway through the file the sentence “Where’s the flag?”, preceeded by “Flag:” and a string of unprintable characters. Somewhere in the process of picking away at the file, I produced an output file that contained clearer text of the Flag string “09589148-1d22-4c78-b48f-d24b0f095c93”. And I can’t recall if that was accepted as the flag or if more processing was required – the dashes and even numbers of characters make me think it’s a series of words encoded in a hex-like format.

Trivia #1, Trivia #2, Trivia #3 (Trivia)

There were three trivia challenges that I do not recall the details of now. They involved the entertainment and mascot at previous cons and I think there was a Hackers reference in there somewhere. As trivia, they were pretty trivial to solve with some Google and Twitter searches.

FINAL RESULTS

Final Score: 260/???
Final Rank: 41 out of ???