小Pwn手杂谈(1.0.0)之不同输入函数之间的区别

news/2024/12/25 2:10:39/文章来源:https://www.cnblogs.com/XiDP0/p/18554028

前言

本文涉及 read函数 fgets函数 scanf函数 以及 gets函数 获取字符串后内存的区别,以及在pwntools中使用 sendlinesend 的区别。实验过程有些冗长,嫌麻烦的师傅可以直接查看下面的总结

实验目标

  1. read fgets scanf 这种可以限定大小的输入,如果输入量小于/等于/大于它们的输入量分别会出现什么情况
  2. scanf("%s",&buf)这种情况是否存在溢出
  3. gets 输入是怎么处理\n符号的

下面是我实验用的代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int init()
{setvbuf(stdin, NULL, _IONBF, 0);setvbuf(stdout, NULL, _IONBF, 0);setvbuf(stderr, NULL, _IONBF, 0);return 0;
}
char bss[8];
int main() {init();char *ptr[13];// 初始化bss数组memset(bss, 0x22, sizeof(bss)*3);// 利用循环申请12个0x30大小的堆块,并将对应地址存储在ptr这个指针数组里面// 如果申请失败则直接退出程序for (int i = 0; i < 13; i++) {ptr[i] = (char *)malloc(0x30);if (!ptr[i]) {return 1;}}// 不用在意,只是gdb调试时方便跳转的标记sleep(0.1);// 使用memset将堆块的内容设置为\x22,为了方便我们区分哪些是我们输入的东西for (int i = 0; i < 13; i++) {memset(ptr[i], 0x22, 0x30);}sleep(0.1);// 这里free是因为free之后的堆块在pwndbg里面显示绿绿的,方便进行区分不同函数输入free(ptr[3]);free(ptr[7]);free(ptr[11]);sleep(0.1);// step 1 测试read函数,限定输入大小为8字节,查看分别输入 a*6 a*8 a*10 后内存的样子printf("read a*6\n");read(0, ptr[0], 8);while (getchar() != '\n' && getchar() != EOF); // 为了防止残留的\x0a影响后续的输入,这里采用了getchar来把多余的\x0a吃掉printf("read a*8\n");read(0, ptr[1], 8);while (getchar() != '\n' && getchar() != EOF);printf("read a*10\n");read(0, ptr[2], 8);while (getchar() != '\n' && getchar() != EOF);sleep(0.1);// step 2 测试fgets函数,限定输入大小为8字节,查看分别输入 a*6 a*8 a*10 后内存的样子printf("fgets a*6\n");fgets(ptr[4], 8, stdin);while (getchar() != '\n' && getchar() != EOF);printf("fgets a*8\n");fgets(ptr[5], 8, stdin);    while (getchar() != '\n' && getchar() != EOF);printf("fgets a*10\n");fgets(ptr[6], 8, stdin);while (getchar() != '\n' && getchar() != EOF);sleep(0.1);// step 3 测试scanf函数,限定输入的字符串大小为8字节,查看分别输入 a*6 a*8 a*10 后内存的样子printf("scanf a*6\n");scanf("%8s", ptr[8]);while (getchar() != '\n' && getchar() != EOF);printf("scanf a*8\n");scanf("%8s", ptr[9]);while (getchar() != '\n' && getchar() != EOF);printf("scanf a*10\n");scanf("%8s", ptr[10]);while (getchar() != '\n' && getchar() != EOF);sleep(0.1);// step 4 测试gets函数输入之后是什么样子的,仅输入一次,输入6个字节的aprintf("gets a*6\n");gets(ptr[12]);while (getchar() != '\n' && getchar() != EOF);sleep(0.1);// 测试scanf("%s",bss)是否存在溢出scanf("%s",bss);printf("%s",bss);while (getchar() != '\n' && getchar() != EOF);sleep(0.1);return 0;
}

下面我们开始测试:

start

在这里插入图片描述

开头在sleep上打断点,方便我们后续使用c快速跟进,查看到bss全局变量在 0x555555558050 这个位置上

来到第一个sleep所在的地方
查看bss段里面是什么,可以看到已经都变成22了,后面输入后改变我们就可以直观的看到
在这里插入图片描述

来到第二个sleep所在的地方
查看堆中内存,可以看到已经都变成22了,后面输入后改变我们就可以直观的看到
在这里插入图片描述

来到第三个sleep所在的地方
查看堆的情况
在这里插入图片描述

read函数

继续跟进程序,让我们看看read,分别输入 aaaaaa aaaaaaaa aaaaaaaaaa
在这里插入图片描述

这里仔细的人会发现,read a*6 后面到 read a*8 中间除了输入还空了一行,这是因为包括 \n
在内我们输入的全部东西都被读入了内存中,getchar 没有读取到\n所以我手动敲了一个回车来结束 getchar

来到第四个sleep所在的地方
我们已经使用read输入了,下面我们来查看一下堆内存里面是什么
在这里插入图片描述

可以看到输入六个a的话内存里面是 六个a和一个回车符号
输入八个a的话内存里面是 八个a,回车符号没有被读入
输入是十个a的话内存里面是 十个a,回车符号没有被读入

虽然实验很简陋但是我们可以简单得出结论,read输入的话会读取指定的字节数,除非遇到\x00,不然输入其他东西都无法阻止read停止,直到读取完后放入指定的内存中,没读取到的部分则保持原样不动

fgets函数

继续跟进程序,让我们看看fgets,再次分别输入 aaaaaa aaaaaaaa aaaaaaaaaa
在这里插入图片描述

查看对应的堆内存
在这里插入图片描述

我们不难简单的得出结论,fgets和read不太一样,虽然我们设定了读取8个字节,他并不会老实读取8个字节,而是只读取7个,然后再主动添加一个\x00来作为输入的字符串的结尾

因此像read这样的输入函数,如果buf为8字节的字符串,用户输入8字节,而read傻傻的读取八字节,那么字符串结尾的\x00就会被省略掉,如果此时有一个 buf2buf 的位置相邻,那么使用puts输出buf的时候就会连同buf2一起输出出来,因为buf失去了\x00,puts这类输出函数就没办法判断这个字符串什么时候结束,只能无脑输出,直到遇见\x00

scanf函数

继续跟进程序,让我们看看scanf,再次分别输入 aaaaaa aaaaaaaa aaaaaaaaaa
在这里插入图片描述

查看对应的堆内存
在这里插入图片描述

可以发现我们的scanf函数非常的聪明,他不像fgets函数偷工减料,让他读取8字节他是真读取
并且同时他读取完八字节后,会再在后面加一个\x00来保持字符串的独立性

继续跟进程序,让我们看看gets,输入 aaaaaa
在这里插入图片描述

查看堆内存
在这里插入图片描述

scanf函数的溢出

最后来看看scanf("%s",bss)的溢出形式
在这里插入图片描述

总结

read函数:第三个参数是几就读取几个,一旦数量超过第三个参数后就直接忽略,就只读取到第三个参数所规定的数量为止,不会自动添加\x00,如果 允许输入长度 = 字符串长度 可能导致字符串失去结尾的\x00

fgets函数:读取的字节数为第二个参数-1,超出的部分会被忽略,会自动在最后添加\x00

scanf("%?s", &buf):读取?个字节,超出的部分会被忽略,然后在最末尾添加\x00scanf("%s", &buf)没有规定读取字节数,存在溢出

gets函数:无脑读取,一直读取,直到用户输入回车才停止,输入的数据全部读取,但是最后会把读取到的回车(\x0a)变成\x00

对于上面函数如何选择 sendsendline

  1. 对于read函数 sendsendline 都可以,但是建议使用send,不然屁股后面多个\x0a,有时候打入/bin/sh字符串的时候使用sendline没发现有个\x0a在屁股上一直打不通也是很痛苦的

  2. 对于 fgets gets scanf 这三个函数只能使用sendline

什么?你问我上面的 sendsendline 是怎么总结出来的?
由于时间关系(懒得再做一遍了),直接看ZikH26师傅的博客来总结了探究pwntools中sendline的回车所造成的影响(什么时候用sendline,什么时候用send) - ZikH26 - 博客园 (cnblogs.com)
(不要喷我啊,求求了我什么都会做的Orz)

最后感谢您的观看

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

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

相关文章

福气满满-冲刺日志(第三天)

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13305团队名称 福气满满团队成员学号-名字 052203132童潇剑,102201226陈潇健,102201235曾炜坤,102201234洪庆杨,102201224 陈博涵,18220031…

开发一个移动App总共需要四步

🎯开发一个移动App总共需要四步🤣 1️⃣注册账号:在平台注册开发者账号。 2️⃣开发应用:使用专业工具开发应用。 3️⃣测试与优化:进行多轮测试和优化。 4️⃣准备发布:整理发布材料,设置发布日期。

单变量微积分学习笔记:函数的导数(3)

单变量微积分学习笔记:函数的导数(3) 前置 导数的定义 \[f(x) = \lim_{\Delta x \to 0} \frac{f(x+\Delta x) - f(x)}{\Delta x} \\ f(x) = \lim_{x \to x_0} \frac{f(x) - f(x_0)}{x - x_0} \] 割线(Secant line):经过函数图像任意两个不重复的点的直线 切线(Tangent l…

福气满满-冲刺日志(第二天)

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13305团队名称 福气满满团队成员学号-名字 052203132童潇剑,102201226陈潇健,102201235曾炜坤,102201234洪庆杨,102201224 陈博涵,18220031…

DQL

1.使用select进行单表的查询 select*from 表名 会查询所有元素 select 列名,列名 from 表名 会查询所在列的元素select distinct 列名 from 表名; 会去除重复元素添加where字句来限定查询目标select*from student where name not in(‘元素’,元素); where 列名 not in(‘…

《Django 5 By Example》阅读笔记:p645-p650

《Django 5 By Example》学习第8天,p645-p650总结,总计6页。 一、技术总结 1.django-rest-framework (1)serializer p648, Serializer: Provides serialization for normal Python class instances。Serializer又细分为Serializer, ModelSerializer, HyperlinkedModelSeriali…

P1314 [NOIP2011 提高组] 聪明的质监员

题目 [NOIP2011 提高组] 聪明的质监员 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1 到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi 。检验矿产的流程是:给定m 个区间 [li,ri]; 选出一个参数 W; 对于一个区间 [li,ri]…

开源 - Ideal库 - 枚举扩展设计思路及实现难点(三)

分享枚举扩展设计思路,包括枚举值、名、描述、项、类型转换。实现难点包括枚举名称、描述转枚举处理,枚举值类型支持,高效返回键值对,识别有效位标志组合等。今天想和大家分享关于枚举扩展设计思路和在实现过程中遇到的难点。01、设计思路 设计思路说起来其实也很简单,就是…

安装新版pycharm 专业版 百分百成功

安装新版pycharm 专业版 百分百成功 创建时间:20241103 1. 下载插件 1.1 打开下面的网站 https://3.jetbra.in/1.2 选择能进去的网站 没使用鸡哥上网使用鸡哥上网1.3 进入的界面1.4 下载插件 查看这里支持的版本号2. 在官网下载对应的版本 2.1 官网的历史版本位置 我这里使用…

vercel无法导入github项目

背景 点击import后,浏览器打开了github的项目链接,而不是有关于项目部署的设置。根据网络上的说法,import后就会出现相关的配置页面,然而没有出现下面是预想的页面然而并没有出现。 解决 使用cli工具。 npm install -g vercel# 登录 vercel login # 部署 vercel回到官网,发…

福气满满-冲刺日志(第一天)

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13305团队名称 福气满满团队成员学号-名字 052203132童潇剑,102201226陈潇健,102201235曾炜坤,102201234洪庆杨,102201224 陈博涵,18220031…

11.8 每日总结(继续学习redis)

今天依旧Redis,学习时长2小时。数据结构: