使用pwntools与远程交互解misc数学题

Wednesday, January 18, 2023
本文共725字
2分钟阅读时长

⚠️本文是作者P3troL1er原创,首发于https://peterliuzhi.top/tricks/%E4%BD%BF%E7%94%A8pwntools%E4%B8%8E%E8%BF%9C%E7%A8%8B%E4%BA%A4%E4%BA%92%E8%A7%A3misc%E6%95%B0%E5%AD%A6%E9%A2%98/。商业转载请联系作者获得授权,非商业转载请注明出处!

The only real failure in life is not to be true to the best one knows. — Buddha

有时候misc题目会出一些连续解几百个简单数学题然后才能get flag的题目,这时候我们可以利用pwntools进行交互并使用eval解题

注意,此脚本只能解普通数学计算式(加减乘除模,以及在python中符合语法的表达式),而一些英文计算式或者中文计算式要自己写一个转换函数将其转化为数学计算式,一般来说可以使用哈希表

Linux中没有pwntools可以使用以下命令安装:

apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools

具体详见Installation — pwntools 4.8.0 documentation

以下是脚本:

# 自动生成头部
from pwn import *
from pwn import p64, p32, u32, u64, p8, p16

website = "www.example.com"
port: str = "666"
if_32: bool = False
if_debug: bool = False
pg = p32 if if_32 else p64
ug = u32 if if_32 else u64
context(log_level="debug", arch="i386" if if_32 else "amd64", os="linux")
p = remote(website, port)

# 下面是自定义的一些工具函数


def send_after_clean(content: bytes = b"", until: bytes = None,
                     timeout: float = 0.05, no_show: bool = True):
    if until is not None:
        p.recvuntil(flat(until))
    else:
        received = p.clean(timeout)
        if not no_show:
            print(f"[$]received:\n{received.decode('UTF-8')}")
    p.send(flat(content))


def sendline_after_clean(content: bytes = b"", until: bytes = None,
                         timeout: float = 0.05, no_show: bool = True):
    send_after_clean([content, p.newline], until, timeout, no_show)


def interactive_after_clean(timeout: int = 0.05, no_show: bool = True):
    received = p.clean(timeout)
    if not no_show:
        print(f"[$]received:\n{received}")
    p.interactive()


def formula_compute(formula: bytes, precise: bool = False):
    if isinstance(formula, bytes):
        formula = formula.decode("UTF-8")
    formula = formula.strip()
    formula = formula.strip("\n")
    formula = formula.replace("x", "*")
    formula = formula.replace("^", "**")
    formula = formula.replace("÷", "/")
    if not precise:
        formula = formula.replace("//", "/")
        formula = formula.replace("/", "//")
    return bytes(str(eval(formula)), encoding="UTF-8")


for i in range(100):
    # 从标准输出流获取题目
    # 会一直读到b"."为止
    question = p.recvuntil(b".")
    # 工具函数自动计算结果
    # 注意,输入的题目必须是有意义的算式,不能有等号
    # 比如可以是1+2, 1÷2
    # 如果需要小数,定义参数precise=True
    answer = formula_compute(question)
    # 在结尾加上回车发送answer
    # 直到读到"answer:"才开始发送
    # 也可以不定义until字符串,脚本会在程序没有输出的时候发送(但如果网络不好,脚本可能判断出错)
    sendline_after_clean(answer, "answer:")

# 进入人机交互模式
interactive_after_clean()

脚本中的注释应该足够了

需要注意的是,只有Linux中才能使用pwntools