形成和检查位掩码的方法

时间:2013-07-05 10:49:12

标签: c bit-manipulation bitmask

之前很可能已经被问过并回答过,但我的搜索是徒劳的。

问题是关于位,字节掩码和检查。

假设有两个“触发器”0xC40xC5

196: 1100 0100  0xc4
197: 1100 0101  0xc5

检查var是否为的简单方法是:

if (var == 0xc5 || var == 0xc4) {

}

但有时人们会看到这个(或类似的):

if ( ((var ^ magic) & mask) == 0)  {

}

我的问题是如何找到 magic mask 。使用哪些方法,程序,技巧等来形成这些值并断言是否存在?


修改

澄清。是的,在这个确切的例子中,前者会比后者更好,但我的问题更像是生成和检查这些类型的掩码。总的来说有点蠢蠢欲动。我省略了很多,并试图使问题变得简单。但是......

作为一个例子,我看了一下OllyDbg反编译源的来源,其中一个找到:

if (((code ^ pd->code) & pd->mask) == 0) 
    FOUND

其中code是0-3个字节的命令来自指令。

unsigned long code = 0;
if (size > 0) *(((char *)&code) + 0) = cmd[0];
if (size > 1) *(((char *)&code) + 1) = cmd[1];
if (size > 2) *(((char *)&code) + 2) = cmd[2];

仅屏蔽cmd

的字节部分

pd是其中的一部分:

struct t_cmddata {
    uint32_t mask;          Mask for first 4 bytes of the command
    uint32_t code;          Compare masked bytes with this
        ...
}

持有一个长数组:

const t_cmddata cmddata[] = {
/*      mask      code  */
  { 0x0000FF, 0x000090, 1,00,  NNN,NNN,NNN, C_CMD+0,        "NOP" },
  { 0x0000FE, 0x00008A, 1,WW,  REG,MRG,NNN, C_CMD+0,        "MOV" },
  { 0x0000F8, 0x000050, 1,00,  RCM,NNN,NNN, C_PSH+0,        "PUSH" },
  { 0x0000FE, 0x000088, 1,WW,  MRG,REG,NNN, C_CMD+0,        "MOV" },
  { 0x0000FF, 0x0000E8, 1,00,  JOW,NNN,NNN, C_CAL+0,        "CALL" },
  { 0x0000FD, 0x000068, 1,SS,  IMM,NNN,NNN, C_PSH+0,        "PUSH" },
  { 0x0000FF, 0x00008D, 1,00,  REG,MMA,NNN, C_CMD+0,        "LEA" },
  { 0x0000FF, 0x000074, 1,CC,  JOB,NNN,NNN, C_JMC+0,        "JE,JZ" },
  { 0x0000F8, 0x000058, 1,00,  RCM,NNN,NNN, C_POP+0,        "POP" },
  { 0x0038FC, 0x000080, 1,WS,  MRG,IMM,NNN, C_CMD+1,        "ADD" },
  { 0x0000FF, 0x000075, 1,CC,  JOB,NNN,NNN, C_JMC+0,        "JNZ,JNE" },
  { 0x0000FF, 0x0000EB, 1,00,  JOB,NNN,NNN, C_JMP+0,        "JMP" },
  { 0x0000FF, 0x0000E9, 1,00,  JOW,NNN,NNN, C_JMP+0,        "JMP" },
  { 0x0000FE, 0x000084, 1,WW,  MRG,REG,NNN, C_CMD+0,        "TEST" },
  { 0x0038FE, 0x0000C6, 1,WW,  MRG,IMM,NNN, C_CMD+1,        "MOV" },
  { 0x0000FE, 0x000032, 1,WW,  REG,MRG,NNN, C_CMD+0,        "XOR" },
  ...

这将是典型的 live 使用示例。再说一次:方法。一直在关注Karnaugh map等等 - 但是认为在同一个操作区域还有其他等方法。

2 个答案:

答案 0 :(得分:2)

我假设您的问题是:给定一组“触发器”,我们可以找到一个掩码和魔法,可以通过以下代码检查触发器

if ( ((var ^ magic) & mask) == 0)  {
}

或与

相同
if ((var & mask) == (magic & mask))  {
}

“触发器”的一个例子就像

196: 1100 0100  0xc4
197: 1100 0101  0xc5
204: 1100 1100  0xcc
205: 1100 1101  0xcd

如果可行,“触发器”的位应分为2种类型:“特定位”和“任意位”。与前4位,第6位和第7位一样,每个触发中的特定位相同。如果你改变一个触发器的任意位,它仍然是一个触发器。

因此恰好有2 ^ N个触发器,其中N表示任意位的数量。

这是我在stackoverflow上的第一个答案。我不确定我是否正确理解你的问题。或者你在问其他有点麻烦的方法吗?

答案 1 :(得分:1)

鉴于你的两个价值观,

196: 1100 0100  0xc4
197: 1100 0101  0xc5

你想要掩盖不同的位,在这种情况下是位0.因此掩码值将是0x01的倒数,0xFE。

即。 0xC4& 0xFE == 0xC4,以及0xC5& 0xFE == 0xC4。

这意味着两个值都变为0xC4。然后,您可以通过xor -ing检查0xC4与应保留的确切位模式。

     1100 0100  0xC4

即。 0xC4 ^ 0xC4 == 0。

     1100 0100    1100 0101
   & 1111 1110    1111 1110 
     ---- ----    ---- ----
     1100 0100    1100 0100
   ^ 1100 0100
     ---- ----
     0000 0000

首先掩盖,或冒险完全混淆。


通过实际的source file,我认为他正试图被混淆。许多功能都需要保理。