2014-04-27 15 views
5

Guardando il codice sorgente di Kismet nel packet_ieee80211.h è la sezioneconvert c enum bitfield a Python

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

ho capito questo come lo spostamento bit, ma che su di esso. Supponiamo che io ho l'int 706, come faccio a rompere questo numero fino in cryptset come sopra definito vale a dire come posso estrarre cui cripte sono utilizzati dare 706 specie porting a Python

Grazie

risposta

3

risposta di Aruisdante è molto buona, volevo solo ampliare la risposta, se si deve utilizzare un Python precedente alla 3.4, in quanto non vi does exist a backport su 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

Allora, che cosa si deve capire qui è che questo enum sta definendo una serie di bitmasks. In questo caso, ognuno di questi valori enum, in binario, contiene uno e uno solo 1. Ad esempio,

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

E così via. Utilizzando l'operatore Bitshift è solo un modo semplice di rappresentare 'Voglio l'ennesima + 1 cifra binaria per essere il flag'

Questo ci permette di bit per bit or un mucchio di questi valori insieme e ottenere un numero magico che descrive una combinazione di questi valori di crittografia in modo univoco come bit di bit. Per verificare se un certo numero di magia contiene un valore, possiamo semplicemente bit a bit and con il valore che vogliamo testare

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

has_wep e has_wpa sarà true se e solo se magic_number contenevano quelle bandiere bit.

Quindi guardiamo il numero 706, che in binario è 0b1011000010. Possiamo osservare questo e vedere immediatamente che deve essere stato creato con crypt_wep, crypt_wpa, crypt_psk e crypt_aes_ccm, perché i bit corretti sono impostati per tali valori.

Quindi, come eseguire il porting su Python? Bene, python ha enums proprio come C/C++ se sei in Python 3.4 o successivo. Quindi puoi semplicemente creare la stessa tabella enum in python e applicare gli stessi test bit a bit per determinare cosa rappresenta il numero magico . Se sei su una versione di Python che non ha enumerazione, puoi semplicemente definire una classe con alcune costanti statiche per ottenere lo stesso effetto (e costruire in un metodo per testare l'insieme di cripte che contiene un numero magico). Tale classe potrebbe assomigliare a questo:

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

fantastico che funziona benissimo – WraithWireless