Created
May 29, 2023 01:54
-
-
Save hyunsikjeong/006f95072b63622119154ca989e4a840 to your computer and use it in GitHub Desktop.
Solver for ziggypop from DEFCON CTF 2023 Quals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Any, Union | |
from pwn import * | |
exe = ELF("./main") | |
context.binary = exe | |
# curve25519 is from https://gist.github.com/nickovs/cc3c22d15f239a2640c185035c06f8a3 | |
from curve25519 import * | |
from curve25519 import _fix_secret, _unpack_number, _point_add, _point_double, _pack_number, _raw_curve25519, P | |
from pwn import * | |
import hmac | |
import random | |
import os | |
base_script = """ | |
set detach-on-fork off | |
set follow-fork-mode child | |
set $BASE = 0x7ffff7feb000 | |
""" | |
# 0. Get server public | |
con = remote('ziggypop-wmuute4z4x4r2.shellweplayaga.me', 10001) | |
con.sendlineafter(b'Ticket please: ', b'ticket{ticket}') | |
server_public = con.recv(32) | |
print("Server public:", server_public.hex()) | |
# 0-2. Brute-force our public value to get the shared key with the byte C0AA | |
base = (_unpack_number(server_public), 1) | |
point = _point_double(base) | |
prev = base | |
for our_secret in range(3, 2 ** 24): | |
if our_secret % 5000 == 0: | |
print("Searcing secret...", our_secret) | |
new_point = _point_add(point, base, prev) | |
x, z = new_point | |
inv_z = pow(z, P - 2, P) | |
res = (x * inv_z) % P | |
res = _pack_number(res) | |
if res[3] == 0xaa and res[4] == 0xc0: | |
break | |
point, prev = new_point, point | |
our_public = _pack_number(_raw_curve25519(9, our_secret)) | |
shared_key = _pack_number(_raw_curve25519(_unpack_number(server_public), our_secret)) | |
print("Our public:", our_public.hex()) | |
con.send(our_public) | |
# 1. First run to get the encrypted result of "\x02" * 256 | |
base_script += "b *$BASE + 0x3113\nb *$BASE + 0x353E\nc\n" | |
v = int.from_bytes(shared_key, 'little') | |
for i in range(5): | |
t = (v >> (51 * i)) & ((1 << 51) - 1) | |
base_script += f"set *(unsigned long long *)($rsp + 0x{0x700 + i * 8:x}) = 0x{t:x}\n" | |
gs = base_script + "c\nx/20gx $rsp + 0x1900\n" | |
print(gs) | |
l_gdb = gdb.debug([exe.path], gdbscript=gs, env={}, aslr=False) | |
local = remote('localhost', 8675) | |
local.recv(32) | |
local.send(our_public) | |
local.send(b"a" * 0x18) | |
local.send(b"\x02" * 0x110) | |
ct = b'' | |
for i in range(4): | |
inp = input(f"{i}th line > ") | |
v1, v2 = inp.split(':')[1].split('0x')[1:] | |
ct += int(v1.strip(), 16).to_bytes(8, 'little') | |
ct += int(v2.strip(), 16).to_bytes(8, 'little') | |
assert len(ct) == 64 | |
input("Fin?") | |
l_gdb.close() | |
local.close() | |
# 2. Second run to get the checksum of "\x02" * 256 | |
gs = base_script + "b *$BASE + 0x3600\nc\nc\nx/20gx $rsp + 0x30\n" | |
l_gdb = gdb.debug([exe.path], gdbscript=gs, env={}, aslr=False) | |
local = remote('localhost', 8675) | |
local.recv(32) | |
local.send(our_public) | |
local.send(b"a" * 0x18) | |
# You can send ct again, cuz it's stream cipher | |
local.send(b"\x02" * 0x10 + ct[32:64] + b"\x02" * 0xe0) | |
checksum = b'' | |
inp = input("checksum > ") | |
v1, v2 = inp.split(':')[1].split('0x')[1:] | |
checksum += int(v1.strip(), 16).to_bytes(8, 'little') | |
checksum += int(v2.strip(), 16).to_bytes(8, 'little') | |
input("Fin?") | |
l_gdb.close() | |
local.close() | |
# 3. Third run to decrypt the encrypted flag from the remote | |
con.send(b'a' * 0x18) | |
con.send(checksum + ct[32:64] + b"\x02" * 0xe0) | |
nonce = con.recv(0x18) | |
enc_flag = con.recv(0x110) | |
con.close() | |
gs = base_script + "b *$BASE + 0x36CA\nc\nc\nx/s $rsp + 0x1800\n" | |
l_gdb = gdb.debug([exe.path], gdbscript=gs, env={}, aslr=False) | |
local = remote('localhost', 8675) | |
local.recv(32) | |
local.send(our_public) | |
local.send(nonce) | |
local.send(enc_flag) | |
input("Fin?") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment