BUUCTF-PWN-ciscn_2019_c_1
这道题又是新的题型,研究了以下,要好好记录下来。
首先是看程序开启了哪些保护:
发现没开启栈溢出保护,我们继续往下看程序的逻辑:
一个简洁的页面,到此为止我们并不能看出可以利用哪些攻击方式,我们跟踪一下函数encrypt
和begin
发现begin只是一个简单的显示程序,而重点在于encrypt
函数,我们观察其程序内容:
int encrypt()
{
size_t v0; // rbx
char s[48]; // [rsp+0h] [rbp-50h] BYREF
__int16 v3; // [rsp+30h] [rbp-20h]
memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
v0 = (unsigned int)x;
if ( v0 >= strlen(s) )
break;
if ( s[x] <= '`' || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}
我们查看字符串,发现并没有看到想要的system
和\bin\sh\
,也就是说我们要自己构造一个ROP链来实现攻击。但是这里有一个问题,这个程序会对输入的s字符串进行加密,也就是说会破坏我们的ROP链,同时我们也可以看到加密的位数是根据字符串的长度进行判断的strlen(s)
,这里有个小技巧:strlen(s)
是通过'\0'的位置来进行对字符长度的判断的。也就是说,我们只要将字符串的首位设置为\0
,那么程序逻辑就会判断要加密的程序长度为0,这样就不会对我们构造的ROP链进行破坏,接下来我们就可以利用栈溢出来构造我们的攻击方式了。
那么我们需要思考一下这类题的做法是什么呢?他什么后门函数也没给,即使栈溢出也不知道咋整啊?我们整理步骤如下:
- 利用一个程序已经执行过的函数去泄露它在程序中的地址,然后取这个地址的末三位,然后取查找他使用的libc版本
- 程序里的函数地址和它所使用的libc库中的函数地址是不一样的,他们之间存在一个偏移地址。我们通过
offset = 函数中的地址 - libc中的函数地址
取到这个偏移量 - 得到偏移量之后之后我们可以通过
程序中函数地址 = 函数地址 + offset
的方式来找到其他函数在程序中的地址,然后我们就可以去构造rop链了
现在我们首先需要通过已经被执行的puts
函数,利用他的plt和got地址来泄露我们的libc版本,我们构造以下程序:
我们得到了puts在程序中的地址的末九位9c0
接下来我们需要拿到它的libc版本,有两种方法:
- 使用它libc检查的在线网站
- 使用LibcSearcher库实现
我们完成下面的libc定位使用,然后构造我们自己的ROP
这里我们需要注意几个地方: - 一是我们获取我们的地址时我们并不知道会收到几条内容,一开始可以全部打印出来,然后收集你需要的信息
- 二是关于libc的库要多进行几次尝试,如果都不正确就需要考虑是不是哪里出了问题
- 三是关于构造ROP链时,我们需要在其前面添加一个
ret
实现栈对齐,关于这个我暂时还没有搞清楚,之后可能会继续加以记载吧
执行攻击脚本,我们最终可以得到我们想要的构造程序,执行得到:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现