目录
题目二.nssctf平台:[SWPUCTF 2021 新生赛]nc签到
题目三.NSSCTF平台:Does your nc work?
题目:nssctf平台:[NISACTF 2022]ReorPwn?编辑
题目二:nssctf平台--[SWPUCTF 2021 新生赛]gift_pwn
(学习内容参见博客CTF-PWN学习-为缺少指导的同学而生_ctf pwn-CSDN博客)
pwn做题基本流程:
1.开启环境:启动靶机
知识点:linux系统下查看文件内容指令:cat+文件名
6.如果没有显示出文件目录,下载附件,在ubuntu里面用checksec指令检查ELF文件保护开启的状态
7.再用IDApro逆向分析程序漏洞+找后门函数及其地址等,逻辑复杂的可以使用动态调试
8.再在虚拟机中打开vim文本编辑器,按i键变为插入模式,随便输入数据,按esc,输入:wq,就创建好了攻击脚本,在文件目录中找到文件,右键用mousepad打开,即可开始编写python的exp脚本进行攻击
补充vim相关:
1)vim的三种模式:
命令模式:主要用于vim非写入式编辑文本的一种模式,可以控制屏幕光标的移动,字符、字或行的删除,剪贴等操作
插入模式:主要是进行写入文本,向当前文件中写入内容.
末行模式:主要是对文本整体的编辑
2)vim常见指令:
vim打开后默认自动进入命令模式
“i”: 从当前光标位置进入插入模式
“:”: 由命令模式进入末行模式.
易错点:
或者下次直接在桌面右键点击,在这里打开终端也行
(若攻击不成功)进行GDB动态调试,查找原因(若攻击成功)获取flag,编写Writeup
补充:
后门函数:后门函数通常指的是一个被恶意插入或修改到软件或系统中的函数,该函数允许攻击者绕过正常的安全机制或权限限制,从而获得对目标系统更高权限或控制权的函数或方法。
题型一:签到题
题目一.nssctf平台:[SWPUCTF 2021 新生赛]nc签到
wp:
题目二.NSSCTF平台:Does your nc work?
wp:
题目三:nssctf平台:[NISACTF 2022]ReorPwn?
wp:
1.没有找到ls指令
2.分析伪码中main函数的逻辑
3.分析附件中的fun函数,点击fun,分析程序,发现核心就是把用户输入的字符串(传入的是char类型)倒置一下,所以才有我输入的是ls指令,但计算机接收的是sl指令的情况
4.汇总一下,可执行文件内代码的逻辑就是用户输入指令,经过fun函数将字符串倒置,再通过system函数返回倒置后的字符串(命令),那我为了得到ls指令,应该输入的是sl指令
继续打开flag文件,同样的将cat flag变为galf tac,得到flag
知识点三:向数组填充数据并简单写一个攻击脚本
题目一:BUUCTF平台:ciscn_2019_n_8
wp:
1.常规操作一下
2.
2.读伪码,发现只要使数组的第14个数为17即可,所以我们此时需要写一个脚本使得输入数据填充数组前13位,并使数组第14个数为17。
1)(_QWORD *)&var[13]:将 char*
类型的指针转换为 _QWORD*
类型的指针,即有一个指向64位无符号整数的指针,该整数从 var
数组的第14个字节开始。
2)*(_QWORD *)&var[13]:通过 _QWORD*
类型的指针解引用操作来获取该64位无符号整数的值。
知识点:
①位bit--字节Byte--字Word--双字Dword--四字Qword
②17LL
表示一个值为17的 long long
整数
3.写脚本,然后...我发现我之前只在Ubuntu上配置了pwn环境,蚌埠住了,那在ubuntu上也这么操作一下吧
(p32:将数字转化为32位字符串)
5.运行脚本拿到flag
tip:如果运行之后输入ls无反应,可能是交互失败没拿到权限,可能是脚本里有问题
知识点四:栈溢出基础题型
知识补充:
1.前置知识:
学习总览:
2.数据结构:如何把程序代码把现实问题信息化
3.数据单位
a.bit(位):表示二进制位,由0,1组成,是计算机内存中最小的单位,也是最基本的单位。
(注意:位习惯上用小写的b表示,字节习惯上用大写的B表示。)
b.Byte(字节):是计算机系统中最小的存储单位
(理解:1个英文字母占一个字节Byte的空间)
c.字(Word):代表计算机处理指令或数据的二进制数位数,是计算机进行数据存储和数据处理的运算的单位。一个字通常由一个或多个(一般是字节的整数位)字节构成。
(注意:32位计算机:1字=32位=4字节,64位计算机:1字=64位=8字节)
d.字长:计算机的每个字所包含的位数,(字长就是字的长度).字长有固定的和可变的两种。
e.单位换算
1字节(Byte)=8位(bit)
1 KB = 1024 B = 2^10 B
1 MB = 1024 KB = 2^20 B
1 GB = 1024 MB = 2^30 B
1 TB = 1024 GB = 2^40 B
4.计算机组成原理--cpu和内存
在计算机中,CPU是通过地址总线、数据总线、控制总线三条线与内存进行数据传输与操作:首先,CPU通过地址总线,在内存中找到数据的地址;然后,通过控制总线知道该操作是读还是写;最后,通过数据总线,把数据传输到CPU中。
①地址总线
CPU是通过地址总线来指定存储器单元的。可见地址总线上能传送多少个不同的信息,CPU就可以对多少个存储单元进行寻址。
一个CPU有n根地址线,则可以说这个CPU的地址总线的宽度为n。这样的CPU最多可以寻找2的n次方个内存单元。
②数据总线
我们平时所说的计算机是16位、32位、64位,指的是计算机CPU中通用寄存器一次性处理、传输、暂时存储的信息的最大长度,或者说是CPU的数据总线宽度。即CPU在单位时间内(同一时间)能一次处理的二进制数的位数。
(数据存储是以“字节”(Byte)为单位,数据传输大多是以“位”(bit,又名“比特”)为单位)
③控制总线
控制总线的宽度决定了对外部器件的控制能力。内存读或写命令是由几根控制线综合发出的。其中有一根称为读信号输出的控制线,负责由CPU向外传送读信号。CPU向该控制线上输出低电平,表示将要读取数据。有一根称为写信号输出的控制线,则负责传送写信号。
指针的本质是一个整数,它存储的是内存地址。通过指针能找到或访问到内存中所有的地方
所以,在32位的计算机中,指针占4个字节。
同理,在64位的计算机中,指针占8个字节。
常见硬件架构下数据总线和地址总线宽度的示例:CPU架构 数据总线宽度 地址总线宽度 最大内存寻址 指针大小
8位 8位 16位 64KB 1字节
16位 16位 20位 1MB 2字节
32位 32位 32 位 4 GB 4字节
64位 64位 64位 16 EB 8字节
5.栈
①what:栈是只能在表尾进行插入和删除操作的线性表(简单理解为一种数据结构就行)。
②基本概念:
a.栈顶(低地址):可以进行插入(push)和删除(pop)的一端。
b.栈底(高地址):固定不变的一端
(箭头从低地址指向高地址)
c.空栈:什么数据都没有的栈。
③特点:是一种后进先出的数据结构,先放入的数据最后取出,最后放入栈的数据,最先取出。即栈是向低地址方向生长的
④操作:PUSH和POP。PUSH操作是在栈顶部压入一个数据。POP操作在栈顶部弹出一个数据,栈内删掉一个数据。
6.函数调用过程分析:
①调用者将参数压入进栈
②调用者函数使用call指令调用被调函数
call指令:
a.调用函数的下一条指令(让被调函数调用后正常返回)压栈
b.控制eip(存储cpu将要执行的指令的地址)为func函数的第一条语句,即跳转到call的目标地址执行。
③被调函数开辟自己的内部运作空间
指令:
a.push ebp:保存调用者的栈基址
b.mov ebp,esp:将调用者的栈顶地址设为被调函数的栈底地址
c.sub esp 28h:开辟40字节的空间
④存放被调函数中的局部变量和临时变量:
在被调函数中,从ebp的位置处开始存放,这些变量的地址是按照栈的延伸方向排列的,先定义的变量先入栈。
(不同的变量在编译之后会被表示为与ebp不同的距离。
局部变量读取方式eg.ebp-8h
参数读取方式eg.ebp+8)
总结:发生函数调用时,入栈的顺序为:参数N--参数N-1.....参数1--函数返回地址--上一层调用函数的EBP/BP--局部变量1--局部变量2--....--局部变量N(箭头的方向是栈生长的方向)
⑤被调函数返回:
a.用公用指令leave清除栈空间
步骤一:mov esp,ebp,被调函数内容全部出栈
步骤二:pop ebq,恢复调用函数的栈基址
b.公用指令ret返回到“调用函数的下一条指令”处
将栈顶弹出到eip寄存器,恢复调用者执行顺序。
总结:
(函数调用栈是一块连续的用来保存函数运行状态的内存区域)
7.缓冲区
程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。
条件:
1.程序必须向栈写入数据
eg1.出现gets函数:会不断读取用户的输入,直到收到回车符\n时停止
2.写入的数据长度大于本身长度
原理:
缓冲区(栈,堆,数据段等)溢出是由于c语言没有内置检查机制来确保复制到缓冲区的数据不大于缓冲区。因此当缓冲区数据大于缓冲区大小时,缓冲区之外的数据就会被多出去的缓冲区数据覆盖改写。
栈溢出是其中一种,指的是向栈中某局部变量写入的字节数超过了局部变量自身所占有的字节数,从而导致与其相邻的栈中变量的值被改变。常见的栈溢出漏洞利用方式是控制执行流程返回到ret2shellcode或ret2libc
核心:填充数据的长度(输入到返回地址的距离)计算
1.直接从IDA中读出长度
演示:
伪代码:在某函数中声明char s; //[esp+0h] [ebp-108h]
解释:此时在该函数中,s作为局部变量保存在栈上(形象理解为下图中两个.的位置)。此时s距离ebp的位置为0x108个字节,所以s到main_next的距离为0x108+4(通常以4个字节为单位移动),我们要控制返回地址,即需要把main_next的值改为target函数
2.由cyclic自动生成字符串
3.gdb调试
题型:一.利用栈溢出漏洞控制返回地址ret2text技术
题目一:BUUCTF平台--rip
题目:
步骤:
1.ubuntu虚拟机
2.下载附件,查看相关信息,找到主函数,分析伪代码
3. 发现了gets()函数,这个函数很危险,它可以无限的接收字符串(直至接受到换行符或EOF时才停止),因此我们可以通过覆盖函数的返回地址来使函数跳转到任意我们想要跳到的地方。
4.在主窗口按shift+F12进入字符串窗口,发现字符串/bin/sh,这是是系统命令执行函数的标准特征。
5.双击/bin/sh,发现在代码中对应的是fun提权函数,双击fun,按f5转换为伪代码,即可见
(或者用ida打开附件后,在function window处也可以发现fun函数,双击也可以查看
)
6.写攻击脚本
7.运行脚本,得到flag
(补充:exp是exploit的简写,表示漏洞利用程序或用于攻击的脚本与方案。在pwn解题或黑客活动中,exp通常包含对目标系统的详细分析、漏洞的发现与利用、攻击载荷(payload)的构造以及获取目标控制权的方法等。通过编写和执行exp,黑客可以实现对目标系统的渗透和攻击,以获取敏感信息、控制系统或实现其他目的。)
题目二:nssctf平台--[SWPUCTF 2021 新生赛]gift_pwn
题目:
步骤:
1.基本操作后,无反应
2.下载附件,继续基本操作
补充:checksec可以查看保护机制是否开启。如下图中开启了栈不可执行保护和部分开启堆栈随机化
tip:发现在ubuntu中,checksec指令可以查看程序是多少位的了
3.用ida打开附件
4.进入vuln函数查看一下,声明了一个buf的字符串变量,其首字节离rbp的距离是0x10。返回的时候,read读入了0x64个字节,远超栈的大小。
补充:
read函数:
作用:从指定的文件中读取数据。
函数原型:ssize_t read(int fd, void *buf, size_t count);
fd 传入一个文件描述符,它是open函数的返回值。可通过open函数得到
buf 传入的是一个数组的名字,是用来暂存已经读取到的数据用的。
count 一次性读取多少个数据到数组中,一般是数组的大小。
返回值:
成功,则返回实际读取到的字节数。(是一个ssize_t类型的一个数)
失败,返回-1,并且将errno设置为合适的错误原因。
5.主窗口按shift+F12进入字符串窗口,发现/bin/sh字符串,双击,发现有system(“/bin/sh”)这个后门,类似于在linux终端直接调用/bin/sh,双击system函数查看地址
补充:或者逆天一点,题目叫gift,在function window窗口可以看到gift函数,点开即可
6.写攻击脚本
题目三:CTF那些事儿/pwn/stack/ret2text
wp:
1.IDA打开文件,F5反编译查看伪码
2.创建了一个局部变量(保存在栈上),用gets函数向其中写入数据,满足栈溢出题型的条件
3.在target函数里或者说shift+F12,发现后门函数,tab+空格查看函数地址
4.写攻击脚本
知识点补充:
a.大端序:字节存储顺序为:高位字节存入低地址,低位字节存入高地址
eg.1从1000h开始的内存中,写入12345678h
eg.2so,在小端序里p32(0x12345678)=“\x78\x56\x34\x12")、
题目四:Bugku CTF:overflow
wp:
1.老规矩nc交互,输入ls指令行不通
2.在ubuntu虚拟机里面用checksec指令查看发现是64位程序
3.用ida64打开附件pwn2,分析代码:初始化数组--输出put...--向数组中存入数据-->明显的栈溢出漏洞
(点击数组名,查看数组的栈结构
)
4.shift+f12查看字符串,点击看看cat flag
5.发现后门函数get_shell_,点击查看函数
6.tab+空格查看函数地址:0x400751
7.写exp:attack.py