攻防世界-Pwn-new-easypwn

题目给了一个附件,我们将附件下载下来并解压,发现有俩文件,显然这个hello程序就是我们需要破解的

在linux环境下执行下该程序,发现这是一个通讯录小程序,可以对通讯者号码,姓名,描述信息进行增删改查操作

攻防世界-Pwn-new-easypwn_第1张图片

使用file命令查看文件类型,发现是64位的elf文件

ok,接下来使用ida对该文件进行逆向,查看具体的代码逻辑。

代码逻辑如下:
  1. 主函数:从代码中可以看出,主函数的逻辑就是接收增删改查指令去调用对应的函数处理,这和我们执行程序过程中感知到的是一致的

攻防世界-Pwn-new-easypwn_第2张图片

  1. 初始化函数sub_B56如下:这里都是一些赋值操作,没有什么问题,这里初始化了三个变量,一个是qword_202F8,一个是unk_2020E0,一个是unk2020EB,这里我们还不知道这三个变量是用来干嘛的,没关系,我们往下看。

攻防世界-Pwn-new-easypwn_第3张图片
  1. 接收指令函数如下:输入一个正数,根据正数的值决定对应的操作,这里也没有什么问题

攻防世界-Pwn-new-easypwn_第4张图片
  1. 增加记录函数sub_E13:这里说明一下,unk_2020E0位存储数据的基地址,可以认为时一个数组,v1是用户输入的数组索引,dword_2020BC为程序维护的数组索引(0, 1, 2 ,3)。因此这里进行的操作是将用户输入存入到数组中;其中电话号码存入到unk_2020E0中,unk_2020E0再偏移11就是unk_2020EB,这个位置存储的是姓名;由于一条记录大小为32,那么描述信息则再偏移13放在name后面,继续存储到qword_2020F8中(注意,这里存储的是描述信息的地址,不然32位存不下)。这里就和初始化中匹配上了。分析到这里,其实会有一个发现,那就是虽然是这么存储的,但是实际上对用户输入的电话号码和姓名的长度并未进行验证这是不是一个可以利用的点呢?是否可以利用长度未作限制覆盖掉其它值呢?这里描述信息的指针是最后赋值的,要覆盖也是指针覆盖掉姓名,影响有限。不过没关系,我们先继续往下看

攻防世界-Pwn-new-easypwn_第5张图片
  1. 删除记录函数:弄清楚了数据存在哪里,那这个函数也很容易就弄懂了,这个函数就是将对应下标的姓名,电话号码,描述信息清除,这里没发现什么问题

攻防世界-Pwn-new-easypwn_第6张图片
  1. 查询记录函数:这个函数的作用就是将所有的通讯记录打印出来,但是这里有个问题,就是打印电话号码的时候,printf的格式参数受到外部的控制,因为unk_2020E0真是我们存储数据的地址,可以判断这里存在格式化字符串漏洞

攻防世界-Pwn-new-easypwn_第7张图片
  1. 修改记录函数,这里和增加记录函数逻辑基本一致,都是接收用户输入并存到对应的位置,这里和增加记录不一样的地方在于,这里没有重新为描述信息分配一个地址,而且用户名未进行长度限制

攻防世界-Pwn-new-easypwn_第8张图片

如何利用我们从代码中发现的漏洞:

结合前面的分析,在修改记录信息的时候,我们可以输入用户名覆盖掉原本指向描述信息的指针(即输入任意以一个地址),然后等到输入描述信息的时候再往这个地址里面写任意数据。这里我们修改通讯录函数,将atoi地址改为system,当再次选择时,输入/bin/sh就可以拿到shell了

  1. 获取到程序执行基址和__libc_start_main函数地址

调试前做如下设置,保证我们使用到的第三方库和远程服务器的一致

patchelf --replace-needed libc.so.6 ./libc-2.23.so hello
patchelf --set-interpreter ./ld-2.23.so hello

给程序设置断点,在显示通讯录信息功能中存在格式化字符串漏洞的地方设置断点,开启ida调试。可以发现程序的断点处相对于程序的偏移量为0x1274。

攻防世界-Pwn-new-easypwn_第9张图片

查看具体的栈内容,找到这两个地址对应的参数位置分别是第9和第13(64位机器中0-5都传递给寄存器,6之后的才入栈),其中第13个参数的位置相对于_libc_start_main的偏移量为0xF0

攻防世界-Pwn-new-easypwn_第10张图片

ok,知道这两个偏移量后,我们利用格式化字符串漏洞将这两个参数泄露出来,添加用户的时候设置电话号码为:%13$p%9$p

攻防世界-Pwn-new-easypwn_第11张图片

然后,_libc_start_main的地址为0x7f3c601ec840 - 0xf0 = 0x7f3c601ec750   程序基址为0x55c7fa75a274 - 0x1274 = 0x55c7fa759000。

  1. 再获取system和atoi中的地址,获取后修改atoi的地址为system的地址,这里后面就不手动计算了,通过如下代码获取

攻防世界-Pwn-new-easypwn_第12张图片

完整代码参考https://www.cnblogs.com/C0ngvv/p/16656671.html

  1. 执行程序,成功进入后台,拿到flag

攻防世界-Pwn-new-easypwn_第13张图片

总结:第一次对程序进行逆向分析,涉及到的知识点非常多。基本上都是看攻略完成的,不过在整个过程中也积累了很多经验,学到了很多东西。
  1. ida逆向分析,之前未完整使用过ida,这两天学如何使用这个软件都花了不少时间,再加上分析和调试逆向出来的代码,堆栈,确实增长了不少知识。

  1. 在漏洞利用方面,发现漏洞和利用漏洞是两回事,替换掉重要函数system也是一种基本思路。学习和掌握如何实现着这种思路也提升了自己的思维能力

参考资料:

https://www.cnblogs.com/C0ngvv/p/16656671.html

https://blog.csdn.net/yongbaoii/article/details/111938821

https://github.com/matrix1001/glibc-all-in-one

你可能感兴趣的:(安全,web安全)