将c enum位域转换为python

Wra*_*ess 5 python enums

在section_ieee80211.h中查看kismet的源代码是本节

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),
};
Run Code Online (Sandbox Code Playgroud)

我理解这是换位,但这就是它.假设我有int 706,如何将这个数字分解为如上定义的cryptset,即如何提取使用哪个隐藏,特别是将其移植到python中

谢谢

aru*_*nte 9

所以,你在这里要理解的是,这个枚举定义了一系列的位掩码.在这种情况下,这些枚举值中的每一个(二进制)都包含一个且仅包含一个1.例如,

crypt_wep = (1 << 1) = 0b10
crypt_wpa = (1 << 6) = 0b1000000
Run Code Online (Sandbox Code Playgroud)

等等.使用bitshift运算符只是表示'我希望第n + 1个二进制数字为标志'的简单方法

这让我们or将一堆这些值按位在一起并得到一个幻数,它将这些crypt值的组合唯一地描述为位标志.为了测试一个幻数是否包含一个值,我们可以简单地将and它与我们想要测试的值一起按位

magic_number = crypt_wep | crypt_wpa
has_wep      = (magic_number & crypt_wep) == crypt_wep
has_wpa      = (magic_number & crypt_wpa) == crypt_wpa
Run Code Online (Sandbox Code Playgroud)

has_wep并且has_wpatrue当且仅当magic_number包含在这些位标志.

那么让我们看一下706二进制的数字0b1011000010.我们可以看看这个,马上看,它必须已建成crypt_wep,crypt_wpa,crypt_pskcrypt_aes_ccm,因为正确的位为这些值设定.

那么如何移植到python?好吧,如果你在python 3.4或更高版本中,python 就像C/C++那样有枚举.因此,您只需在python中创建相同的枚举表,并应用相同的按位测试来确定您的幻数代表什么.如果您使用的是没有枚举的python版本,您可以简单地定义一个带有一些静态常量的类来获得相同的效果(并构建一个方法来测试一个幻数包含的隐藏集合).这样的类看起来像这样:

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]
Run Code Online (Sandbox Code Playgroud)


Eth*_*man 3

Aruisdante 的答案非常好,如果您必须使用 3.4 之前的 Python,我只是想扩展答案,因为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>]
Run Code Online (Sandbox Code Playgroud)