【问题标题】:How to Understand Code如何理解代码
【发布时间】:2016-07-06 21:36:45
【问题描述】:

我最近收到了这段代码,我很难理解。我对整体编程非常陌生,并且仍在学习。任何有关此的信息将不胜感激。这是出现的代码:

void enc(char* plaintxt, unsigned char key) 
{ 
    while(*plaintxt)
    { 
        *plaintxt^ = (key=(key*13)+37);
        *(plaintxt++) +=3;
    }
}

输出:

0F A8 9F FE 7A D6 E2 08 AE 2B 5F 53 25 9A

【问题讨论】:

  • 为什么用pythonC++标记?它看起来像标准 C 而不是 Python。
  • 在尝试理解任何代码之前,请尝试使用美化器,只需谷歌搜索“c 代码美化器”即可。
  • 我的错误。我将标签更改为 c
  • 这段代码没有输出任何东西。
  • 如何理解代码:学习编写代码所使用的语言。

标签: c


【解决方案1】:

了解您的具体问题会有所帮助。

简而言之,此代码采用一个字符串并使用键值对其进行加密/编码。线

*plaintxt^ = (key=(key*13)+37);

是一种非常密集的书写方式

*plaintxt = *plaintxt ^ (key * 13 + 37);
key = key * 13 + 37;

需要注意的是,未指定更新 key*plaintxt 的确切顺序(IOW,在原始代码中 key 可能在 *plaintxt 更新之前或之后更新)。

^ 运算符是按位异或运算符; *plaintext 中的每一位都与 key 中的每一位进行异或运算。

线

 *(plaintxt++) +=3;

是一种密集的书写方式

 *plaintxt = *plaintxt + 3;
 plaintxt = plaintxt + 1;

同样需要注意的是,未指定更新 *plaintxtplaintxt 的确切顺序。此行将3 添加到*plaintext,然后将指针推进以指向字符串中的下一个字符。

在 C 中,字符串是由0 终止的字符值序列。 plaintext 是指向字符串第一个字符的指针。 while 循环通过测试*plaintxt 的值来检查我们是否还没有到达字符串的末尾; while ( *plaintext )while ( *plaintext != 0 ) 相同。

所以,假设plaintext 指向字符串"test"1

           +---+              +----+
plaintext: |   | ----> "test" | 74 |    Assumes ASCII, all values in hex
           +---+              +----+
                              | 65 |
           +----+             +----+
      key: |  1 |             | 75 |
           +----+             +----+
                              | 74 |
                              +----+
                              |  0 |
                              +----+

key 最初是 1。

在循环的开始,plaintext 指向"test" 中的第一个t(ASCII 0x74)。我们将其与key * 13 + 37 的结果进行异或,即十进制的 50 或十六进制的 0x32:

  0x74 ^ 0x32 == 0x46

我们把这个值写回*plaintext,然后加上3,得到0x49。我们将 0x32 保存到 key。然后我们推进plaintext 指向字符串中的下一个字符,给我们:

           +---+              +----+
plaintext: |   | --+   "Iest" | 49 |    
           +---+   |          +----+
                   +------->  | 65 |
           +----+             +----+
      key: | 32 |             | 75 |
           +----+             +----+
                              | 74 |
                              +----+
                              |  0 |
                              +----+

现在我们对 e 做同样的事情:

key = 50 * 13 + 37 == 687 % 255 == 177 == 0xb1

unsigned char 只能存储从 0 到 2CHAR_BIT-1 的值,在大多数现代系统上是 255; 687 太大而无法存储在 key 中,因此它“环绕”回 177 或 0xb12

0x65 ^ 0xb1 == 0xd4
0xd4 + 3    == 0xd7

所有这些都完成后,我们有

           +---+              +----+
plaintext: |   | --+   "I?st" | 49 |    
           +---+   |          +----+
                   |          | d7 |  
           +----+  |          +----+
      key: | b1 |  +--------> | 75 |
           +----+             +----+
                              | 74 |
                              +----+
                              |  0 |
                              +----+

起泡、冲洗、重复。这将一直持续到plaintext 指向包含 0 的内存单元。


  1. 从技术上讲,它指向一个包含字符串 `"test"` 的 array,而不是 字符串文字 `"test"`。字符串文字可能不会修改其内容;试图这样做会调用未定义的行为。
  2. 这仅适用于 unsigned 整数类型;有符号整数类型的溢出没有明确定义,并且可能无法按预期运行。

【讨论】:

    【解决方案2】:

    我知道这有点晚了,无论你从哪个安全会议上得到那张卡都早已结束(Raytheon Game Of Pwns)......但让我为你省点挫折。 您不会找到比上面显示的更好的代码正在做什么的描述,但是您根本不需要重新创建此代码来解决密码。 你甚至不需要知道 C. 无论您选择哪种语言,您都可以生成轻松破解此代码的密钥。 鉴于初始键 (0-255) 只有 256 个可能的值,您可以暴力破解它,但您可以通过有根据的猜测来解决这个问题,以获得键的第一个值。

    Game Of Pwns 卡片包含密钥,您可能在解决解析为 Key=2EZ01 的二进制编码 ASCII 消息时注意到了这一点。你可以猜到第一个字符可能是一个大写的 K (0x4B)。 关于 XOR 操作的有趣事实是它可以用来反转自身。 让我们假设第一个字符确实是K,并且我们已经知道第一个输出元素是0x0F(实际上是0x0C)。这告诉我们 标志 ^ key = (output-3) 诀窍是 (输出 3)^ 标志 = 键! 基于这个假设,我们可以得到((key*13)+37)的第一个结果,即0x0C ^ 0x4B = 0x47。

    两个重要说明,代码中的 13 和 37 确实是十进制值,而不是十六进制值,并且标志在索引到数组中的下一个字符之前增加 3。

    使用第一个键,您可以使用您选择的任何语言生成其余键,方法是创建一个循环来为您提供接下来的 13 个键 ((key*13)+37)%256) %256 模仿 C 中 unsigned char 的环绕行为。 当您拥有 14 个键时,只需将列表中的每个键与其对应的原始输出 (-3) 进行异或运算即可获得编码消息,这很清楚......它开始 Key= 如果您还从 Raytheon 获得了另一张具有相似代码的卡,则该卡上的所有密码都以 Flag= 开头,因此您可以简单地应用您在此处了解的 XOR 来轻松破解该卡。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 2016-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      相关资源
      最近更新 更多