Looking at kismet's source code in packet_ieee80211.h is the section
enum crypt_type {
crypt_none = 0,
crypt_unknown = 1,
crypt_wep = (1 << 1),
crypt_layer3 = (1 << 2),
// Derived from WPA headers
crypt_wep40 = (1 << 3),
crypt_wep104 = (1 << 4),
crypt_tkip = (1 << 5),
crypt_wpa = (1 << 6),
crypt_psk = (1 << 7),
crypt_aes_ocb = (1 << 8),
crypt_aes_ccm = (1 << 9),
//WPA Migration Mode
crypt_wpa_migmode = (1 << 19),
// Derived from data traffic
crypt_leap = (1 << 10),
crypt_ttls = (1 << 11),
crypt_tls = (1 << 12),
crypt_peap = (1 << 13),
crypt_isakmp = (1 << 14),
crypt_pptp = (1 << 15),
crypt_fortress = (1 << 16),
crypt_keyguard = (1 << 17),
crypt_unknown_nonwep = (1 << 18),
};
I understand this as shifting bits but that's about it. Suppose I have the int 706, how do I break this number up into the cryptset as defined above i.e. how can I extract which crypts are used give 706 especially ported to python
Thanks
So, what you have to understand here is that this enum is defining a series of bitmasks. In this case, each one of these enum values, in binary, contains one and only one 1
. For example,
crypt_wep = (1 << 1) = 0b10
crypt_wpa = (1 << 6) = 0b1000000
And so on. Using the bitshift operator is just an easy way of representing 'I want the nth+1 binary digit to be the flag'
This lets us bitwise or
a bunch of these values together and get a magic number that describes a combination of these crypt values uniquely as bit flags. To test if a magic number contains a value, we can simply bitwise and
it with the value we wish to test
magic_number = crypt_wep | crypt_wpa
has_wep = (magic_number & crypt_wep) == crypt_wep
has_wpa = (magic_number & crypt_wpa) == crypt_wpa
has_wep
and has_wpa
will be true
if and only if magic_number
contained those bit flags.
So lets look at the number 706
, which in binary is 0b1011000010
. We can look at this and immediately see that it must have been built with crypt_wep
, crypt_wpa
, crypt_psk
and crypt_aes_ccm
, because the correct bits are set for those values.
So how to port to python? Well, python has enums just like C/C++ does if you're in python 3.4 or later. So you can simply create the same enum table in python, and apply the same bitwise tests to determine what your magic number represents. If you're on a version of python that doesn't have enums, you can simply define a class with some static constants in it to get the same effect (and build in a method to test for the set of crypts a magic number contains). Such a class could look like this:
class CryptKeys(object):
crypt_masks = {
'crypt_unknown':1,
....
'crypt_unknown_nonwep': (1 << 18)
}
@classmethod
def find_crypts(cls, magic_number):
if magic_number == 0:
return ['crypt_none']
else:
return [name for name, mask in cls.crypt_masks.items() if magic_number & mask == mask]
Aruisdante's answer is very good, I just wanted to expand on the answer if you have to use a Python previous to 3.4, as there does exist a backport on PyPI:
from enum import IntEnum
class Crypt(IntEnum):
none = 0
unknown = 1
wep = (1 << 1)
layer3 = (1 << 2)
# Derived from WPA headers
wep40 = (1 << 3)
wep104 = (1 << 4)
tkip = (1 << 5)
wpa = (1 << 6)
psk = (1 << 7)
aes_ocb = (1 << 8)
aes_ccm = (1 << 9)
# WPA Migration Mode
wpa_migmode = (1 << 19)
# Derived from data traffic
leap = (1 << 10)
ttls = (1 << 11)
tls = (1 << 12)
peap = (1 << 13)
isakmp = (1 << 14)
pptp = (1 << 15)
fortress = (1 << 16)
keyguard = (1 << 17)
unknown_nonwep = (1 << 18)
@classmethod
def find_crypts(cls, magic_number):
crypts = []
for mask in cls:
if magic_number & mask == mask:
crypts.append(mask)
if len(crypts) > 1:
# remove false positive of none
crypts = crypts[1:]
return crypts
print Crypt.find_crypts(0)
[<Crypt.none: 0>]
print Crypt.find_crypts(706)
[<Crypt.wep: 2>, <Crypt.wpa: 64>, <Crypt.psk: 128>, <Crypt.aes_ccm: 512>]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With