baffle 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|