2014-04-27 15 views
5

Patrząc na kod źródłowy Kismet w packet_ieee80211.h jest sekcjaconvert c enum bitfield do Pythona

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), 
}; 

Rozumiem to jako przesuwanie bitów, ale to wszystko. Załóżmy, że mam int 706, jak mogę złamać tę liczbę w górę do cryptset jak zdefiniowano powyżej czyli jak można wyodrębnić który krypty są wykorzystywane dać 706 szczególnie przeniesiony do Pythona

Dzięki

Odpowiedz

3

odpowiedź Aruisdante jest bardzo dobra, po prostu chciałem, aby rozwinąć na odpowiedź, jeśli trzeba użyć Python poprzedni do 3.4, jak tam does exist a backport na 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>] 
8

Więc, co trzeba Rozumiem, że to wyliczenie definiuje serię bitmasks. W tym przypadku każda z wartości wyliczeniowych, w formacie binarnym, zawiera jeden i tylko jeden 1. Na przykład:

crypt_wep = (1 << 1) = 0b10 
crypt_wpa = (1 << 6) = 0b1000000 

I tak dalej. Korzystanie z operatorem Bitshift jest po prostu łatwym sposobem reprezentowania „Chcę n-ty + 1 cyfra binarna być flagę”

To pozwala nam bitowe or kilka tych wartości razem i dostać magiczna liczba że opisuje kombinację tych wartości cryptów jednoznacznie jako flag bitowych. Aby sprawdzić, czy magiczna liczba zawiera wartość, możemy po prostu logicznie and ją z wartością chcemy przetestować

magic_number = crypt_wep | crypt_wpa 
has_wep  = (magic_number & crypt_wep) == crypt_wep 
has_wpa  = (magic_number & crypt_wpa) == crypt_wpa 

has_wep i has_wpa będzie true wtedy i tylko wtedy magic_number zawierał te bitowe flagi.

Więc spójrzmy na numer 706, który w systemie binarnym to 0b1011000010. Możemy na to spojrzeć i od razu zobaczyć, że musiało być zbudowane z crypt_wep, crypt_wpa, crypt_psk i crypt_aes_ccm, ponieważ dla tych wartości są ustawione poprawne bity.

Jak przesłać do Pythona? Pyton ma numer enums, podobnie jak C/C++, jeśli używasz Pythona 3.4 lub nowszego. Możesz więc po prostu utworzyć tę samą tabelę wyliczania w pythonie i zastosować te same testy bitowe, aby określić, co reprezentuje Twój magiczny numer . Jeśli używasz wersji python, która nie ma wartości wyliczeniowych, możesz po prostu zdefiniować klasę z pewnymi stałymi statycznymi, aby uzyskać ten sam efekt (i zbudować metodę do testowania zestawu krypt, które zawiera magiczna liczba). Taka klasa może wyglądać następująco:

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] 
+0

niesamowite, że działa świetnie – WraithWireless