pwnable.kr第五题 passcode 第六题random

文章探讨了如何利用scanf的漏洞和全局OffsetTable(GOT)进行任意内存写入,从而执行system函数。此外,还提到了fflush函数的用途和段错误的原因。在第六题中,文章解释了异或运算在解决固定伪随机数问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在这里插入图片描述

第五题 passcode

参考链接
这个链接写的应该算比较详细了,但是它讲小端序那存在一点问题
学习知识点:
看了上面的链接还是有一些地方不明白,再加上这个链接就完全懂了,点击查看链接

代码如下:
在这里插入图片描述

本文漏洞利用的点在于在红框标记的地方:

对于scanf函数,在读取单个字符或者int类型的数据时,应该传的是地址指针,而这个题目则缺少&,就会直接修改passcode1和passcode2指向的地址。
scanf读取字符串时才不需要&符号。

因此这里无法通过直接输入passcode1和passcode2的值满足比较条件。
passcode1和name的地址如下图所示,通过观察可以发现,name的地址结尾为:ebp-0x70+100=ebp-0xc
而passcode1的初始地址为ebp-0x10,passcode1有4个字节覆盖了name的值,而scanf缺少指针输入导致在进行读取时实际上修改的是passcode1这个地址存放的值的地址,如下所示:

在这里插入图片描述

scanf读取passcode1时是将输入的passcode1写入xxx所在的位置,而非写入passcode1这个位置,因此在这里就实现了一个任意写操作。

因此可以通过name的最后四个字节来修改地址指向。

在这里插入图片描述
在这里插入图片描述

由于got表为了避免重复,对于一些常用函数都指定一个地址来直接存储该函数的调用,如下所示:
查看got表

objdump -R passcode

得到如下查询结果
在这里插入图片描述
由于printf函数被多次调用,因此这里可以直接使用printf函数的地址,在输入name时将存放printf的地址写入name的最后四个字节,当进行passcode输入时将该地址的内容修改为system的函数调用,则在接下来函数的执行中再次调用printf实际执行过程如下:
调用printf函数-》找到printf函数地址(该地址修改后实际存放的是system的函数调用)-》调用该地址所在的函数
此时就可以直接执行system函数。

注意:这里还可以替换成其他后面会调用的函数的地址,如fflush等

使用disas login查看system指令所在地址如下:
在这里插入图片描述
因此passcode1的值可以确定为0x080485e3,由于scanf读passcode1读入的是十进制数据,因此这里需要转换成十进制数据来读:
0x080485e3=134514147
在这里插入图片描述
构造答案例如:

python -c "print('b'*96 + '\x00\xa0\x04\x08'+'\n'+'134514147'+'\n')" | ./passcode 

这里的’\x00\xa0\x04\x08’是printf函数入口地址的小端序0x0804a000。

fflush()函数

该函数有两个参数,
fflush(stdin):该函数功能是清空输入缓冲区,通常是为了确保不影响后面的数据读取(例如在读完一个字符串后紧接着又要读取一个字符,此时应该先执行fflush(stdin)。
fflush(stdout):刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
同时还需要注意此函数仅适用于部分编译器(如VC6),但是并非所有编译器都要支持这个功能(如gcc3.2)。这是一个对C标准的扩充。
接下来直接运行passcode,然而却直接报错:

Segmentation fault (core dumped)
在这里插入图片描述
这里百度说这个错误是内存读入的问题,也就是实际上如果想要通过scanf读取int类型的数据应该是使用以下语句,而它少了一个&

scanf("%d",&passcode1)

而当前passcode1在读取前存放的数据所在的地址可能无法放入数据导致的。

方法2

这里在passcode1实现了任意写以后实际上还有一个方法:
这里可以看到fflush存在一个跳转函数,这里可以直接把跳转地址的内容修改为system所在的位置即可:
在这里插入图片描述
构造答案如下:

python -c “print(‘b’*96 + ‘\x04\xa0\x04\x08’+‘\n’+‘134514147’+‘\n’)” | ./passcode

答案

在这里插入图片描述
可以看到两种方法都可以得到答案。

第六题 random

代码如下:
在这里插入图片描述

这道题突然一下又变得很简单了呀,只需要两个知识点:

  1. a ^ b ^ a=a ^ a ^ b=b (关于异或的运算)
  2. random=rand(),其中rand函数如果没有种子的赋值,那么它产生的随机数是固定不变的。也就是这里产生的是一个固定不变的伪随机数。
  3. 利用以上两点答案就很简单了,key=伪随机数 ^ 0xdeadbeef

使用gdb调试查看伪随机数的值:
在这里插入图片描述
可以看到rax中存放的就是产生的伪随机数的值:1804289383
在这里插入图片描述
答案也就是:3039230856
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值