baffle 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +28 -0
- data/README.markdown +52 -0
- data/bin/baffle +5 -0
- data/data/probes.yml +32 -0
- data/lib/baffle.rb +52 -0
- data/lib/baffle/fingerprint_diagram.rb +43 -0
- data/lib/baffle/gtk_queue.rb +29 -0
- data/lib/baffle/gui.glade +138 -0
- data/lib/baffle/gui.rb +169 -0
- data/lib/baffle/options.rb +84 -0
- data/lib/baffle/probe.rb +193 -0
- data/lib/baffle/probes/authreq_flags.rb +45 -0
- data/lib/baffle/probes/probereq_flags.rb +51 -0
- data/lib/baffle/util.rb +36 -0
- metadata +108 -0
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Baffle is distributed under this license:
|
2
|
+
|
3
|
+
Copyright (c) 2007-2008, The Trustees of Dartmouth College.
|
4
|
+
|
5
|
+
All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without
|
8
|
+
modification, are permitted provided that the following conditions
|
9
|
+
are met:
|
10
|
+
|
11
|
+
1. Redistributions of source code must retain the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer.
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
3. The name of the author may not be used to endorse or promote products
|
17
|
+
derived from this software without specific prior written permission.
|
18
|
+
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
20
|
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
21
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
23
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
24
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
28
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.markdown
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
Baffle
|
2
|
+
======
|
3
|
+
|
4
|
+
Baffle is a tool for actively fingerprinting and identifying wireless devices.
|
5
|
+
See ./tool --help for options.
|
6
|
+
|
7
|
+
Compiling
|
8
|
+
---------
|
9
|
+
|
10
|
+
Because we need to be able to sniff and inject arbitrary 802.11 packets, we
|
11
|
+
need help from a few C-libraries (see Depedencies). Before running Baffle,
|
12
|
+
you must compile the Ruby extensions wrapping these libraries. Generally, it
|
13
|
+
it done in the following manner:
|
14
|
+
|
15
|
+
$ ruby extconf
|
16
|
+
$ make
|
17
|
+
|
18
|
+
You will need to run these commands in the following directories:
|
19
|
+
|
20
|
+
- ./lib/capture/
|
21
|
+
- ./lib/ruby-lorcon/
|
22
|
+
|
23
|
+
Linalg depends on LAPACK, a fortran linear algebra package, and on f2c, a
|
24
|
+
fortran to C bridge. These can typically be installed from package management
|
25
|
+
systems or compiled from source.
|
26
|
+
The ruby linalg library itself is compiled with the following commands:
|
27
|
+
|
28
|
+
$ ruby install.rb configure
|
29
|
+
$ ruby install.rb make
|
30
|
+
$ sudo ruby install.rb install
|
31
|
+
|
32
|
+
Once those dependencies are met, everything should work fine.
|
33
|
+
|
34
|
+
Depedencies
|
35
|
+
-----------
|
36
|
+
|
37
|
+
+ C-libraries
|
38
|
+
- lorcon
|
39
|
+
- libpcap
|
40
|
+
|
41
|
+
+ Fortran libraries
|
42
|
+
- LAPACK
|
43
|
+
|
44
|
+
+ Ruby libraries
|
45
|
+
- linalg (depends on the LAPACK fortran library and f2c library)
|
46
|
+
|
47
|
+
License
|
48
|
+
-------
|
49
|
+
|
50
|
+
Copyright (c) 2007-2008, The Trustees of Dartmouth College.
|
51
|
+
|
52
|
+
Baffle is released as open source under a BSD license. See LICENSE for details.
|
data/bin/baffle
ADDED
data/data/probes.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
probereq_flags:
|
2
|
+
Linksys WRT54G:
|
3
|
+
- [5, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 2, 2, 2, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 3, 3, 3, 3, 3, 3, 3, 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 3, 3, 3, 3, 3, 2, 2, 4, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 2, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 2, 2, 2, 2, 3]
|
4
|
+
- [4, 3, 3, 3, 3, 3, 3, 4, 5, 5, 4, 2, 2, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 2, 2, 2, 1, 2, 1, 2, 2, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 2, 4, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 2, 1, 1, 1, 1, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 2, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2]
|
5
|
+
- [7, 6, 6, 7, 7, 7, 6, 7, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 5, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 5, 7, 7, 7, 7, 6, 7, 7, 6, 7, 7, 7, 5, 7, 6, 7, 6, 7, 7, 7, 7, 6, 7, 7, 7, 7, 6, 7, 7, 6, 7, 6, 7, 6, 6, 7, 6, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 5, 7, 6, 5, 7, 7, 7, 7, 5, 7, 7, 7, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 6, 7, 5, 7, 7, 7, 6, 7, 7, 7, 7, 6, 7, 7, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 6, 7, 5, 7, 7, 7, 6, 7, 5, 7, 6, 7, 6, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 7, 7, 7, 6, 7, 5, 6, 6, 6, 7, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 7, 7, 7, 6, 5, 6, 7]
|
6
|
+
- [7, 6, 7, 7, 6, 7, 6, 6, 6, 6, 5, 6, 6, 5, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 6, 7, 6, 7, 6, 7, 7, 6, 7, 4, 6, 7, 7, 7, 6, 6, 6, 6, 7, 6, 6, 6, 6, 7, 4, 6, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 7, 7, 6, 6, 6, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 7, 6, 6, 6, 7, 7, 7, 7, 5, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 7, 7, 7, 6, 7, 5, 7, 6, 7, 6, 6, 5, 6, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 5, 6, 7, 6, 7, 7, 7, 5, 5, 6, 6, 7, 7, 7, 6, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 6, 5, 7, 6, 7, 6, 7, 7, 7, 6, 6, 7, 6, 6, 7, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 5, 6, 7, 7, 7, 7, 5, 6, 7, 6, 7, 7, 7, 7, 7, 6, 7, 7, 5, 7, 6, 6, 6, 7, 7, 4, 7, 7, 7, 6, 7]
|
7
|
+
ExtraSys WAP-257:
|
8
|
+
- [5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0]
|
9
|
+
- [5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0]
|
10
|
+
- [7, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]
|
11
|
+
MadWifi-ng Master Mode:
|
12
|
+
- [5, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
13
|
+
- [5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
14
|
+
- [10, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
15
|
+
HostAP Master Mode:
|
16
|
+
- [5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
17
|
+
- [4, 4, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
18
|
+
|
19
|
+
authreq_flags:
|
20
|
+
Linksys WRT56G:
|
21
|
+
- [5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
22
|
+
- [43, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 70, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 63, 0, 0, 0, 70, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 69, 0, 0, 0, 75, 0, 0, 0, 69, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
23
|
+
- [43, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 70, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 76, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
24
|
+
ExtraSys WAP-257:
|
25
|
+
- [5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0]
|
26
|
+
- [40, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0]
|
27
|
+
MadWifi-ng Master Mode:
|
28
|
+
- [5, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
29
|
+
- [22, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
30
|
+
HostAP master mode:
|
31
|
+
- [5, 5, 5, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
32
|
+
|
data/lib/baffle.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'dot11'
|
4
|
+
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'baffle', 'options'))
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'baffle', 'probe'))
|
7
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'baffle', 'fingerprint_diagram'))
|
8
|
+
|
9
|
+
module Baffle
|
10
|
+
def self.run(args)
|
11
|
+
options = Baffle::Options.parse(args)
|
12
|
+
|
13
|
+
options
|
14
|
+
|
15
|
+
if options.gui?
|
16
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'baffle', 'gui'))
|
17
|
+
|
18
|
+
Gui.run(options)
|
19
|
+
else
|
20
|
+
scan(options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.scan(options)
|
25
|
+
hypotheses = {}
|
26
|
+
|
27
|
+
Baffle::Probes.each do |probe|
|
28
|
+
puts "Running probe #{probe.name}"
|
29
|
+
vector = probe.run(options)
|
30
|
+
|
31
|
+
unless vector
|
32
|
+
warn "Probe was skipped."
|
33
|
+
next
|
34
|
+
end
|
35
|
+
|
36
|
+
if options.fpdiagram
|
37
|
+
File.open("#{options.fpdiagram}#{probe.name}.svg", 'w+') do |f|
|
38
|
+
f << Baffle.fingerprint_diagram(vector).to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "Vector: #{vector.inspect}"
|
43
|
+
|
44
|
+
unless options.train?
|
45
|
+
hypotheses[probe.name] = probe.hypothesize(vector)
|
46
|
+
puts "#{probe.name} hypothesizes: #{hypotheses[probe.name]}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
hypotheses
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
include REXML
|
4
|
+
|
5
|
+
module Baffle
|
6
|
+
WIDTH = 24
|
7
|
+
HEIGHT = 24
|
8
|
+
|
9
|
+
def self.fingerprint_diagram(vector)
|
10
|
+
doc = Document.new '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
|
11
|
+
svg = doc.add_element "svg", "width" => "100%", "viewbox" => "0 0 100 100", "version" => "1.1", "xmlns" => "http://www.w3.org/2000/svg"
|
12
|
+
|
13
|
+
max_count = 0
|
14
|
+
|
15
|
+
x = 0
|
16
|
+
|
17
|
+
max_count = vector.max
|
18
|
+
|
19
|
+
total_width = 32 * WIDTH * 1.05
|
20
|
+
|
21
|
+
vector.each_with_index do |respond_count, flags_value|
|
22
|
+
alpha = (respond_count / max_count.to_f) ** 3 + 0.1
|
23
|
+
width = (WIDTH * alpha + 1) / total_width * 600.0
|
24
|
+
|
25
|
+
alpha = 1 if alpha.nan?
|
26
|
+
width = WIDTH if width.nan?
|
27
|
+
|
28
|
+
alpha = (respond_count > 1 ? 1 : 0.05)
|
29
|
+
width = 3
|
30
|
+
|
31
|
+
("%08d" %flags_value.to_s(2)).split(//).each_with_index do |c, i|
|
32
|
+
y = 1 + i * (HEIGHT + 1)
|
33
|
+
color = (c == "0") ? "black" : "red"
|
34
|
+
|
35
|
+
svg.add_element "rect", "x" => x - (width / 2), "y" => y, "width" => width, "height" => HEIGHT, "style" => "fill:#{color};fill-opacity:#{alpha}"
|
36
|
+
end
|
37
|
+
|
38
|
+
x += total_width / 256
|
39
|
+
end
|
40
|
+
|
41
|
+
svg
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
3
|
+
module Gtk
|
4
|
+
GTK_PENDING_BLOCKS = []
|
5
|
+
GTK_PENDING_BLOCKS_LOCK = Monitor.new
|
6
|
+
|
7
|
+
def Gtk.queue(&block)
|
8
|
+
if Thread.current == Thread.main
|
9
|
+
block.call
|
10
|
+
else
|
11
|
+
GTK_PENDING_BLOCKS_LOCK.synchronize do
|
12
|
+
GTK_PENDING_BLOCKS << block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def Gtk.main_with_queue(timeout=100)
|
18
|
+
Gtk.timeout_add(timeout) do
|
19
|
+
GTK_PENDING_BLOCKS_LOCK.synchronize do
|
20
|
+
GTK_PENDING_BLOCKS.each { |block| block.call }
|
21
|
+
GTK_PENDING_BLOCKS.clear
|
22
|
+
end
|
23
|
+
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
Gtk.main
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
2
|
+
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
3
|
+
|
4
|
+
<glade-interface>
|
5
|
+
|
6
|
+
<widget class="GtkWindow" id="window">
|
7
|
+
<property name="width_request">810</property>
|
8
|
+
<property name="height_request">530</property>
|
9
|
+
<property name="visible">True</property>
|
10
|
+
<property name="title" translatable="yes">Baffle</property>
|
11
|
+
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
12
|
+
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
13
|
+
<property name="modal">False</property>
|
14
|
+
<property name="resizable">False</property>
|
15
|
+
<property name="destroy_with_parent">False</property>
|
16
|
+
<property name="decorated">True</property>
|
17
|
+
<property name="skip_taskbar_hint">False</property>
|
18
|
+
<property name="skip_pager_hint">False</property>
|
19
|
+
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
20
|
+
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
21
|
+
<property name="focus_on_map">True</property>
|
22
|
+
<property name="urgency_hint">False</property>
|
23
|
+
|
24
|
+
<child>
|
25
|
+
<widget class="GtkFixed" id="fixed1">
|
26
|
+
<property name="width_request">820</property>
|
27
|
+
<property name="height_request">500</property>
|
28
|
+
<property name="visible">True</property>
|
29
|
+
|
30
|
+
<child>
|
31
|
+
<widget class="GtkComboBoxEntry" id="mac_addresses">
|
32
|
+
<property name="width_request">304</property>
|
33
|
+
<property name="height_request">32</property>
|
34
|
+
<property name="visible">True</property>
|
35
|
+
<property name="add_tearoffs">False</property>
|
36
|
+
<property name="has_frame">True</property>
|
37
|
+
<property name="focus_on_click">True</property>
|
38
|
+
</widget>
|
39
|
+
<packing>
|
40
|
+
<property name="x">0</property>
|
41
|
+
<property name="y">8</property>
|
42
|
+
</packing>
|
43
|
+
</child>
|
44
|
+
|
45
|
+
<child>
|
46
|
+
<widget class="GtkNotebook" id="results">
|
47
|
+
<property name="width_request">808</property>
|
48
|
+
<property name="height_request">472</property>
|
49
|
+
<property name="visible">True</property>
|
50
|
+
<property name="can_focus">True</property>
|
51
|
+
<property name="show_tabs">True</property>
|
52
|
+
<property name="show_border">True</property>
|
53
|
+
<property name="tab_pos">GTK_POS_TOP</property>
|
54
|
+
<property name="scrollable">True</property>
|
55
|
+
<property name="enable_popup">False</property>
|
56
|
+
</widget>
|
57
|
+
<packing>
|
58
|
+
<property name="x">0</property>
|
59
|
+
<property name="y">56</property>
|
60
|
+
</packing>
|
61
|
+
</child>
|
62
|
+
|
63
|
+
<child>
|
64
|
+
<widget class="GtkButton" id="load">
|
65
|
+
<property name="width_request">100</property>
|
66
|
+
<property name="height_request">32</property>
|
67
|
+
<property name="visible">True</property>
|
68
|
+
<property name="can_focus">True</property>
|
69
|
+
<property name="label" translatable="yes">Load</property>
|
70
|
+
<property name="use_underline">True</property>
|
71
|
+
<property name="relief">GTK_RELIEF_NORMAL</property>
|
72
|
+
<property name="focus_on_click">True</property>
|
73
|
+
<signal name="clicked" handler="on_load_clicked" last_modification_time="Mon, 04 Aug 2008 22:12:14 GMT"/>
|
74
|
+
</widget>
|
75
|
+
<packing>
|
76
|
+
<property name="x">312</property>
|
77
|
+
<property name="y">8</property>
|
78
|
+
</packing>
|
79
|
+
</child>
|
80
|
+
|
81
|
+
<child>
|
82
|
+
<widget class="GtkButton" id="remove">
|
83
|
+
<property name="width_request">100</property>
|
84
|
+
<property name="height_request">32</property>
|
85
|
+
<property name="visible">True</property>
|
86
|
+
<property name="can_focus">True</property>
|
87
|
+
<property name="label" translatable="yes">Remove</property>
|
88
|
+
<property name="use_underline">True</property>
|
89
|
+
<property name="relief">GTK_RELIEF_NORMAL</property>
|
90
|
+
<property name="focus_on_click">True</property>
|
91
|
+
<signal name="clicked" handler="on_remove_clicked" last_modification_time="Mon, 04 Aug 2008 06:20:23 GMT"/>
|
92
|
+
</widget>
|
93
|
+
<packing>
|
94
|
+
<property name="x">416</property>
|
95
|
+
<property name="y">8</property>
|
96
|
+
</packing>
|
97
|
+
</child>
|
98
|
+
|
99
|
+
<child>
|
100
|
+
<widget class="GtkButton" id="scan_all">
|
101
|
+
<property name="width_request">110</property>
|
102
|
+
<property name="height_request">32</property>
|
103
|
+
<property name="visible">True</property>
|
104
|
+
<property name="can_focus">True</property>
|
105
|
+
<property name="label" translatable="yes">Scan All</property>
|
106
|
+
<property name="use_underline">True</property>
|
107
|
+
<property name="relief">GTK_RELIEF_NORMAL</property>
|
108
|
+
<property name="focus_on_click">True</property>
|
109
|
+
<signal name="clicked" handler="on_scan_all_clicked" last_modification_time="Sun, 03 Aug 2008 01:39:04 GMT"/>
|
110
|
+
</widget>
|
111
|
+
<packing>
|
112
|
+
<property name="x">696</property>
|
113
|
+
<property name="y">8</property>
|
114
|
+
</packing>
|
115
|
+
</child>
|
116
|
+
|
117
|
+
<child>
|
118
|
+
<widget class="GtkButton" id="scan_selected">
|
119
|
+
<property name="width_request">110</property>
|
120
|
+
<property name="height_request">32</property>
|
121
|
+
<property name="visible">True</property>
|
122
|
+
<property name="can_focus">True</property>
|
123
|
+
<property name="label" translatable="yes">Scan Selected</property>
|
124
|
+
<property name="use_underline">True</property>
|
125
|
+
<property name="relief">GTK_RELIEF_NORMAL</property>
|
126
|
+
<property name="focus_on_click">True</property>
|
127
|
+
<signal name="clicked" handler="on_scan_selected_clicked" last_modification_time="Sun, 03 Aug 2008 01:39:08 GMT"/>
|
128
|
+
</widget>
|
129
|
+
<packing>
|
130
|
+
<property name="x">584</property>
|
131
|
+
<property name="y">8</property>
|
132
|
+
</packing>
|
133
|
+
</child>
|
134
|
+
</widget>
|
135
|
+
</child>
|
136
|
+
</widget>
|
137
|
+
|
138
|
+
</glade-interface>
|
data/lib/baffle/gui.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'gtk2'
|
4
|
+
require 'libglade2'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'thread'
|
7
|
+
|
8
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'baffle.rb'))
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'gtk_queue.rb'))
|
10
|
+
|
11
|
+
module Baffle
|
12
|
+
class Gui
|
13
|
+
@@glade_path = File.expand_path(File.join(File.dirname(__FILE__), 'gui.glade'))
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
@glade = GladeXML.new(@@glade_path) { |handler| method(handler) }
|
17
|
+
@options = options
|
18
|
+
@scan_lock = Mutex.new
|
19
|
+
|
20
|
+
@window = @glade.get_widget('window')
|
21
|
+
@window.signal_connect("destroy") { Gtk.main_quit }
|
22
|
+
|
23
|
+
@mac_addresses = @glade.get_widget('mac_addresses')
|
24
|
+
@mac_addresses.model = Gtk::ListStore.new(String)
|
25
|
+
@mac_addresses.text_column = 0
|
26
|
+
|
27
|
+
@results = @glade.get_widget('results')
|
28
|
+
|
29
|
+
on_refresh_clicked(@mac_addresses)
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_refresh_clicked(widget)
|
33
|
+
iwlist = `iwlist #{@options.capture} scan`
|
34
|
+
|
35
|
+
essid = nil
|
36
|
+
bssid = nil
|
37
|
+
|
38
|
+
@mac_addresses.model.clear
|
39
|
+
|
40
|
+
iwlist.each_line do |line|
|
41
|
+
bssid = $1 if line =~ /Cell \d+ - Address: (([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2})/
|
42
|
+
essid = $1 if line =~ /ESSID:"([^"]+)"/
|
43
|
+
|
44
|
+
@mac_addresses.append_text("#{bssid} #{essid}") if essid
|
45
|
+
|
46
|
+
essid = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
@mac_addresses.active = 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_scan_selected_clicked(widget)
|
53
|
+
args = parse(@mac_addresses.active_text)
|
54
|
+
scan(*args) if args
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_scan_all_clicked(widget)
|
58
|
+
@mac_addresses.model.each do |model, path, iter|
|
59
|
+
args = parse(iter.get_value(0))
|
60
|
+
scan(*args) if args
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def on_remove_clicked(widget)
|
65
|
+
@mac_addresses.remove_text(@mac_addresses.active)
|
66
|
+
@mac_addresses.active = 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_load_clicked(widget)
|
70
|
+
dialog = Gtk::FileChooserDialog.new("Choose a Kismet CSV file", @window, Gtk::FileChooser::ACTION_OPEN, nil, [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT], [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
|
71
|
+
|
72
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
73
|
+
@mac_addresses.model.clear
|
74
|
+
|
75
|
+
File.open(dialog.filename).each_line do |line|
|
76
|
+
num, type, essid, bssid, rest = line.split(';')
|
77
|
+
|
78
|
+
@mac_addresses.append_text("#{bssid} #{essid}") if type == 'infrastructure' && bssid =~ /^(([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2})$/
|
79
|
+
end
|
80
|
+
|
81
|
+
@mac_addresses.active = 0
|
82
|
+
end
|
83
|
+
|
84
|
+
dialog.destroy
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def parse(text)
|
90
|
+
return $1, $3 if text =~ /^(([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}) (.*)$/
|
91
|
+
end
|
92
|
+
|
93
|
+
def scan(bssid, essid)
|
94
|
+
progress = Gtk::ProgressBar.new
|
95
|
+
progress.pulse_step = 0.05
|
96
|
+
|
97
|
+
page = Gtk::ScrolledWindow.new
|
98
|
+
page.add_with_viewport(Gtk::VBox.new.add(progress))
|
99
|
+
page.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC)
|
100
|
+
|
101
|
+
page_label = Gtk::Label.new("#{bssid} #{essid}")
|
102
|
+
|
103
|
+
@results.append_page(page, page_label)
|
104
|
+
@window.show_all
|
105
|
+
|
106
|
+
cur_page = @results.n_pages - 1
|
107
|
+
updated_page = Gtk::VBox.new
|
108
|
+
|
109
|
+
Thread.new do
|
110
|
+
Gtk.queue { progress.text = 'Waiting to acquire scan lock...' }
|
111
|
+
|
112
|
+
@scan_lock.lock
|
113
|
+
|
114
|
+
@options.essid = essid
|
115
|
+
@options.bssid = bssid
|
116
|
+
|
117
|
+
Gtk.queue { @results.page = cur_page }
|
118
|
+
|
119
|
+
progress_count = 0
|
120
|
+
progress_total = Baffle::Probes.total_injection_values
|
121
|
+
|
122
|
+
Baffle::Probes.each do |probe|
|
123
|
+
Gtk.queue { progress.text = "Running #{probe.name} probe..." }
|
124
|
+
|
125
|
+
vector = probe.run(@options) do
|
126
|
+
progress_count += 1
|
127
|
+
|
128
|
+
Gtk.queue { progress.fraction = progress_count.to_f / progress_total.to_f }
|
129
|
+
end
|
130
|
+
|
131
|
+
unless vector
|
132
|
+
warn "Probe was skipped."
|
133
|
+
next
|
134
|
+
end
|
135
|
+
|
136
|
+
temp = Tempfile.new('baffle.svg')
|
137
|
+
temp_path = temp.path
|
138
|
+
temp.close!
|
139
|
+
|
140
|
+
File.open(temp_path, 'w') do |f|
|
141
|
+
f << Baffle.fingerprint_diagram(vector).to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
hypothesis = probe.hypothesize(vector)
|
145
|
+
|
146
|
+
Gtk.queue do
|
147
|
+
updated_page.add(Gtk::Label.new("#{probe.name} - #{hypothesis}")).add(Gtk::Image.new(temp_path))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
Gtk.queue do
|
152
|
+
page.each do |child|
|
153
|
+
page.remove(child)
|
154
|
+
end
|
155
|
+
page.add_with_viewport(updated_page)
|
156
|
+
page_label.set_markup("<b>#{page_label.text}</b>")
|
157
|
+
@window.show_all
|
158
|
+
end
|
159
|
+
|
160
|
+
@scan_lock.unlock
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.run(options)
|
165
|
+
Gui.new(options)
|
166
|
+
Gtk.main_with_queue
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Baffle
|
4
|
+
class Options
|
5
|
+
attr_accessor :inject
|
6
|
+
attr_accessor :capture
|
7
|
+
attr_accessor :driver
|
8
|
+
attr_accessor :channel
|
9
|
+
attr_accessor :train
|
10
|
+
attr_accessor :verbose
|
11
|
+
attr_accessor :fpdiagram
|
12
|
+
attr_accessor :plot_prefix
|
13
|
+
attr_accessor :bssid, :essid
|
14
|
+
attr_accessor :gui
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@inject = 'ath0'
|
18
|
+
@capture = 'ath0'
|
19
|
+
@driver = 'madwifing'
|
20
|
+
@channel = 11
|
21
|
+
@train = false
|
22
|
+
@verbose = false
|
23
|
+
@gui = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def train?; @train == true; end
|
27
|
+
def verbose?; @verbose == true; end
|
28
|
+
def gui?; @gui == true; end
|
29
|
+
def interface=(value); self.inject = value; self.capture = value; end
|
30
|
+
|
31
|
+
def self.parse(args)
|
32
|
+
options = Options.new
|
33
|
+
|
34
|
+
opts = OptionParser.new do |opts|
|
35
|
+
opts.program_name = "baffle"
|
36
|
+
opts.version = "0.2.0"
|
37
|
+
|
38
|
+
opts.banner = "Usage: #{opts.program_name} [options] bssid essid"
|
39
|
+
|
40
|
+
opts.separator("")
|
41
|
+
opts.separator("Fingerprinting options:")
|
42
|
+
opts.on("-i INTERFACE", "--interface INTERFACE", "The INTERFACE to use for both injection and capture (default: ath0)") { |interface| options.interface = interface }
|
43
|
+
opts.on("-j INTERFACE", "--inject INTERFACE", "The INTERFACE to use for injection (default: ath0)") { |interface| options.inject = interface }
|
44
|
+
opts.on("-c INTERFACE", "--capture INTERFACE", "The INTERFACE to use for capture (default: ath0)") { |interface| options.capture = interface }
|
45
|
+
opts.on("-d DRIVER", "--driver DRIVER", "The driver used for injection (default: madwifing)") { |driver| options.driver = driver }
|
46
|
+
opts.on("-h CHANNEL", "--channel CHANNEL", "The channel to listen on (default: 11)") { |channel| options.channel = channel.to_i }
|
47
|
+
|
48
|
+
opts.separator("")
|
49
|
+
opts.separator("Output options:")
|
50
|
+
opts.on("-f SVGPREFIX", "--fpdiagram SVGPREFIX", "Write a fingerprint diagram for each probe used, using SVGPREFIX") { |svgprefix| options.fpdiagram = svgprefix }
|
51
|
+
opts.on("-p SVGPREFIX", "--plot SVGPREFIX", "Write a plot file for each probe used, using SVGPREFIX") { |svgprefix| options.plot_prefix = svgprefix }
|
52
|
+
|
53
|
+
opts.separator("")
|
54
|
+
opts.separator("Training options:")
|
55
|
+
opts.on("-t", "--train", "Train baffle with a new device fingerprint") { options.train = true }
|
56
|
+
|
57
|
+
opts.separator("")
|
58
|
+
opts.separator("Common options:")
|
59
|
+
opts.on("-v", "--verbose", "More detailed output") { options.verbose = true }
|
60
|
+
opts.on("-?", "--help", "Show this message") { puts opts.help; exit }
|
61
|
+
opts.on("--version", "Print the version") { puts opts.ver; exit }
|
62
|
+
|
63
|
+
opts.separator("")
|
64
|
+
opts.separator("Other options:")
|
65
|
+
opts.on("-g", "--gui", "Show gui") { options.gui = true }
|
66
|
+
end
|
67
|
+
|
68
|
+
bssid, essid = opts.parse!(args)
|
69
|
+
|
70
|
+
if bssid =~ /^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/
|
71
|
+
options.bssid = bssid
|
72
|
+
end
|
73
|
+
|
74
|
+
options.essid = essid
|
75
|
+
|
76
|
+
unless options.gui? || (options.bssid && options.essid)
|
77
|
+
puts opts.help
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
|
81
|
+
options
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/baffle/probe.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dot11'
|
3
|
+
require 'rb-pcap'
|
4
|
+
require 'facets/array/product'
|
5
|
+
require 'linalg'
|
6
|
+
require 'thread'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'util'))
|
10
|
+
|
11
|
+
module Baffle
|
12
|
+
module Probes
|
13
|
+
def self.<<(probe)
|
14
|
+
@probes << probe
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load
|
18
|
+
return if @probes
|
19
|
+
|
20
|
+
@probes = []
|
21
|
+
|
22
|
+
Dir[File.join(File.dirname(__FILE__), "probes", "*.rb")].each do |file|
|
23
|
+
require File.expand_path(file)
|
24
|
+
end
|
25
|
+
|
26
|
+
probe_data = YAML::load(File.open(File.join(File.dirname(__FILE__), '..', '..', 'data', 'probes.yml')))
|
27
|
+
|
28
|
+
@probes.each do |probe|
|
29
|
+
next unless probe_data[probe.name]
|
30
|
+
|
31
|
+
probe_data[probe.name].each do |name, vectors|
|
32
|
+
vectors.each do |vector|
|
33
|
+
probe.training_data[name] << vector
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@probes
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.each
|
42
|
+
self.load
|
43
|
+
|
44
|
+
@probes.each do |probe|
|
45
|
+
yield probe
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.total_injection_values
|
50
|
+
self.load
|
51
|
+
|
52
|
+
@probes.inject(0) { |sum, probe| sum += probe.injection_values.size * probe.repeats }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Probe
|
57
|
+
attr_reader :name, :training_data, :injection_values, :injection_proc, :filter_procs, :capture_procs
|
58
|
+
|
59
|
+
def initialize(name, &block)
|
60
|
+
@name = name
|
61
|
+
@training_data = Hash.new {|hash, key| hash[key] = []}
|
62
|
+
@names = []
|
63
|
+
@injection_values = nil
|
64
|
+
@injection_proc = nil
|
65
|
+
@filter_procs = {}
|
66
|
+
@capture_procs = {}
|
67
|
+
@repeat = 1
|
68
|
+
|
69
|
+
instance_eval(&block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def run(options, &block)
|
73
|
+
unless options.train?
|
74
|
+
return nil unless learn
|
75
|
+
end
|
76
|
+
|
77
|
+
samples = []
|
78
|
+
|
79
|
+
@repeat.times do |i|
|
80
|
+
samples[i] = []
|
81
|
+
|
82
|
+
filters = {}
|
83
|
+
@filter_procs.each do |name, filter_proc|
|
84
|
+
filter = filter_proc.call(options)
|
85
|
+
|
86
|
+
case filter
|
87
|
+
when Dot11::Packet
|
88
|
+
filter = Dot11::PacketSet.new(Dot11::Dot11, :payload => filter) if !filter.kind_of?(Dot11::Dot11)
|
89
|
+
when Dot11::PacketSet
|
90
|
+
puts "filter is Dot11::PacketSet"
|
91
|
+
filter = Dot11::PacketSet.new(Dot11::Dot11, :payload => filter) if filter.packet_class != Dot11::Dot11
|
92
|
+
end
|
93
|
+
|
94
|
+
filters[name] = Capture::Filter.new(filter.to_filter)
|
95
|
+
end
|
96
|
+
|
97
|
+
sniff_thread = Thread.new do
|
98
|
+
filter = filters.values.map { |filter| "(#{filter.expression})" }.join(" || ")
|
99
|
+
|
100
|
+
Baffle::sniff(:device => options.capture, :filter => filter) do |packet|
|
101
|
+
filters.each do |name, filter|
|
102
|
+
samples[i] << @capture_procs[name].call(packet) if filter =~ packet.data
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Baffle::emit(options, @injection_proc, @injection_values, &block)
|
108
|
+
sniff_thread.kill
|
109
|
+
end
|
110
|
+
|
111
|
+
@vector = @compute_vector.call(samples)
|
112
|
+
end
|
113
|
+
|
114
|
+
def inject(car, *cdr, &block)
|
115
|
+
@injection_proc = block
|
116
|
+
@injection_values = car.to_a rescue []
|
117
|
+
@injection_values = @injection_values.product(*cdr.map{ |v| v.to_a rescue []})
|
118
|
+
end
|
119
|
+
|
120
|
+
def compute_vector(&block)
|
121
|
+
@compute_vector = block
|
122
|
+
end
|
123
|
+
|
124
|
+
def filter(name, &block)
|
125
|
+
@filter_procs[name] = block
|
126
|
+
end
|
127
|
+
|
128
|
+
def capture(name, &block)
|
129
|
+
@capture_procs[name] = block
|
130
|
+
end
|
131
|
+
|
132
|
+
def repeat(count)
|
133
|
+
@repeat = count
|
134
|
+
end
|
135
|
+
|
136
|
+
def repeats
|
137
|
+
@repeat
|
138
|
+
end
|
139
|
+
|
140
|
+
# Gets called when all training samples have been loaded
|
141
|
+
def learn
|
142
|
+
# The code below assumes at least two training values, and doing it with any fewer
|
143
|
+
# doesn't make much sense anyway
|
144
|
+
return false if @training_data.size < 2
|
145
|
+
|
146
|
+
# Doing it this way to make sure we have the same row/column order in names as we do in our matrix.
|
147
|
+
# (there are no guarantees that two iterations over the pairs in a hash will have the same order)
|
148
|
+
row_matrix, @names = @training_data.inject([[], []]) do |result, pair|
|
149
|
+
result[0] += pair[1]
|
150
|
+
pair[1].length.times { result[1] << pair[0] }
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
# We need a matrix of column vectors
|
155
|
+
column_matrix = row_matrix.transpose
|
156
|
+
|
157
|
+
m = Linalg::DMatrix[*column_matrix]
|
158
|
+
|
159
|
+
u, s, vt = m.singular_value_decomposition
|
160
|
+
vt = vt.transpose
|
161
|
+
|
162
|
+
# Do we want more than 2 dimensions? TODO: test other numbers of dimensions
|
163
|
+
@u2 = Linalg::DMatrix.join_columns [u.column(0), u.column(1)]
|
164
|
+
@v2 = Linalg::DMatrix.join_columns [vt.column(0), vt.column(1)]
|
165
|
+
@eig2 = Linalg::DMatrix.columns [s.column(0).to_a.flatten[0,2], s.column(1).to_a.flatten[0,2]]
|
166
|
+
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
# Build a hash of hypotheses on the given vector, with confidence ratings on each hypothesis
|
171
|
+
def hypothesize(vector)
|
172
|
+
similarities = []
|
173
|
+
|
174
|
+
vector_embedded = Linalg::DMatrix[vector] * @u2 * @eig2.inv
|
175
|
+
|
176
|
+
@v2.rows.each_with_index do |row, i|
|
177
|
+
similarities << [@names[i], vector_embedded.transpose.dot(row.transpose) / (row.norm * vector_embedded.norm)]
|
178
|
+
end
|
179
|
+
|
180
|
+
sorted_similarities = similarities.delete_if { |name, score| score.nan? }.sort_by { |name, score| -score }
|
181
|
+
name, score = sorted_similarities.first
|
182
|
+
|
183
|
+
name ||= 'Unknown'
|
184
|
+
score ||= 'NaN'
|
185
|
+
|
186
|
+
"#{name} (#{score})"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def probe(name, &block)
|
192
|
+
Baffle::Probes << Baffle::Probe.new(name, &block)
|
193
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
probe "authreq_flags" do
|
2
|
+
inject(0..255) do |options, flags|
|
3
|
+
local_bssid = "ba:ad:"
|
4
|
+
local_bssid << options.bssid.slice(-5..-1)
|
5
|
+
local_bssid << ":00:"
|
6
|
+
local_bssid << "00#{flags.to_s(16)}".slice(-2..-1)
|
7
|
+
|
8
|
+
Dot11::Dot11.new(:subtype => 0xb,
|
9
|
+
:type => 0x0,
|
10
|
+
:version => 0x0,
|
11
|
+
:flags => flags,
|
12
|
+
:duration => 0x0000,
|
13
|
+
:addr1 => options.bssid,
|
14
|
+
:addr2 => local_bssid,
|
15
|
+
:addr3 => options.bssid,
|
16
|
+
:sc => 0x0000, # This is auto-filled in by the driver.
|
17
|
+
:payload => Dot11::Dot11::Dot11Auth.new(:algo => 0x0000,
|
18
|
+
:seqnum => 0x0001,
|
19
|
+
:status => 0x0000))
|
20
|
+
end
|
21
|
+
|
22
|
+
filter :subtype_addr1 do |options|
|
23
|
+
local_bssid = "ba:ad:"
|
24
|
+
local_bssid << options.bssid.slice(-5..-1)
|
25
|
+
local_bssid << ":00:00/32"
|
26
|
+
|
27
|
+
Dot11::Dot11.new(:type => 0, :subtype => 0xb, :addr1 => local_bssid)
|
28
|
+
end
|
29
|
+
|
30
|
+
capture :subtype_addr1 do |packet|
|
31
|
+
packet.addr1.to_i & 0xff
|
32
|
+
end
|
33
|
+
|
34
|
+
compute_vector do |samples|
|
35
|
+
vector = Array.new(256, 0)
|
36
|
+
|
37
|
+
samples.each do |sample|
|
38
|
+
sample.each do |flags|
|
39
|
+
vector[flags] += 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
vector
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
probe "probereq_flags" do
|
2
|
+
inject(0..255) do |options, flags|
|
3
|
+
local_bssid = "f0:0d:"
|
4
|
+
local_bssid << options.bssid.slice(-5..-1)
|
5
|
+
local_bssid << ":00:"
|
6
|
+
local_bssid << "00#{flags.to_s(16)}".slice(-2..-1)
|
7
|
+
|
8
|
+
Dot11::Dot11.new(:subtype => 0x4,
|
9
|
+
:type => 0x0,
|
10
|
+
:version => 0x0,
|
11
|
+
:flags => flags,
|
12
|
+
:duration => 0x0000,
|
13
|
+
:addr1 => options.bssid,
|
14
|
+
:addr2 => local_bssid,
|
15
|
+
:addr3 => options.bssid,
|
16
|
+
:sc => 0x0000, # This is auto-filled in by the driver.
|
17
|
+
:payload => Dot11::Dot11::Dot11ProbeReq.new /
|
18
|
+
Dot11::Dot11::Dot11Elt.new(
|
19
|
+
:id => 0x00,
|
20
|
+
:info_length => options.essid.length,
|
21
|
+
:info => options.essid) /
|
22
|
+
Dot11::Dot11::Dot11Elt.new(
|
23
|
+
:id => 0x01,
|
24
|
+
:info_length => 0x08,
|
25
|
+
:info => [0x82, 0x84, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24].pack("c*")))
|
26
|
+
end
|
27
|
+
|
28
|
+
filter :subtype_addr1 do |options|
|
29
|
+
local_bssid = "f0:0d:"
|
30
|
+
local_bssid << options.bssid.slice(-5..-1)
|
31
|
+
local_bssid << ":00:00/32"
|
32
|
+
|
33
|
+
Dot11::Dot11.new(:type => 0, :subtype => 0x5, :addr1 => local_bssid)
|
34
|
+
end
|
35
|
+
|
36
|
+
capture :subtype_addr1 do |packet|
|
37
|
+
packet.addr1.to_i & 0xff
|
38
|
+
end
|
39
|
+
|
40
|
+
compute_vector do |samples|
|
41
|
+
vector = Array.new(256, 0)
|
42
|
+
|
43
|
+
samples.each do |sample|
|
44
|
+
sample.each do |flags|
|
45
|
+
vector[flags] += 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
vector
|
50
|
+
end
|
51
|
+
end
|
data/lib/baffle/util.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rb-pcap'
|
3
|
+
require 'rb-lorcon'
|
4
|
+
|
5
|
+
module Baffle
|
6
|
+
def self.emit(options, injection_proc, injection_values)
|
7
|
+
@device = Lorcon::Device.new(options.inject, options.driver)
|
8
|
+
@device.fmode = "INJMON"
|
9
|
+
@device.channel = options.channel
|
10
|
+
|
11
|
+
injection_values << [nil] if injection_values.empty?
|
12
|
+
|
13
|
+
injection_values.each do |args|
|
14
|
+
packet = injection_proc.call(options, *args)
|
15
|
+
yield packet if block_given?
|
16
|
+
send_p(packet.data)
|
17
|
+
sleep 0.05
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.send_p(packet)
|
22
|
+
@device.write(packet, 1, 0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.sniff(*params)
|
26
|
+
Capture.open(*params) do |capture|
|
27
|
+
capture.each do |packet|
|
28
|
+
packet = packet[0..-5]
|
29
|
+
packet = Dot11::Radiotap.new(packet)
|
30
|
+
packet = packet.payload
|
31
|
+
|
32
|
+
yield packet
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: baffle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cory T. Cornelius
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-08-02 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rb-lorcon
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.1.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rb-pcap
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: dot11
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.1.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: facets
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.4.1
|
54
|
+
version:
|
55
|
+
description: See README.markdown for more information.
|
56
|
+
email:
|
57
|
+
- cory.t.cornelius@dartmouth.edu
|
58
|
+
executables:
|
59
|
+
- baffle
|
60
|
+
extensions: []
|
61
|
+
|
62
|
+
extra_rdoc_files: []
|
63
|
+
|
64
|
+
files:
|
65
|
+
- README.markdown
|
66
|
+
- LICENSE
|
67
|
+
- bin/baffle
|
68
|
+
- lib/baffle.rb
|
69
|
+
- lib/baffle/fingerprint_diagram.rb
|
70
|
+
- lib/baffle/gtk_queue.rb
|
71
|
+
- lib/baffle/options.rb
|
72
|
+
- lib/baffle/probe.rb
|
73
|
+
- lib/baffle/util.rb
|
74
|
+
- lib/baffle/gui.rb
|
75
|
+
- lib/baffle/gui.glade
|
76
|
+
- lib/baffle/probes/authreq_flags.rb
|
77
|
+
- lib/baffle/probes/probereq_flags.rb
|
78
|
+
- data/probes.yml
|
79
|
+
has_rdoc: true
|
80
|
+
homepage: http://baffle.cs.dartmouth.edu/
|
81
|
+
licenses: []
|
82
|
+
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: "0"
|
93
|
+
version:
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: "0"
|
99
|
+
version:
|
100
|
+
requirements: []
|
101
|
+
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.3.5
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: A Behavioral Active Fingerprinting tool for 802.11 APs, operating entirely within the Link Layer.
|
107
|
+
test_files: []
|
108
|
+
|