【问题标题】:How does this reverse-engineered algorithm work?这种逆向工程算法是如何工作的?
【发布时间】:2023-04-01 02:47:01
【问题描述】:

实际的算法函数是:

output[i] = ( (129 * input[i]) XOR input[i-1]) % 256 //input[-1] = 0

对此有多种解决方案。通常这样做的方式是:

var output = [0, 129, 3, 129, 7, 129, 3, 129, 15, 129, 3, 129, 7, 129, 3, 129];
var outputToInputArray = function(array) {
  var input = [];
  var outputToInput = function(dig, lastInput) {
    var current = dig;

    while(true) {
      if (!((current ^ lastInput) % 129)) {
        return (current ^ lastInput)/129;
      }
      current += 256;
    }
  }

  for(var i = 0; i < output.length; i++) {
    input.push(outputToInput(output[i], i>0 ? input[i-1] : 0));
  }

  return input;
}

console.log(outputToInputArray(output));

但是,我刚刚来了:

output = [0, 129, 3, 129, 7, 129, 3, 129, 15, 129, 3, 129, 7, 129, 3, 129]
var input = [];
for(var i =0; i < output.length; i++) {
    lastInput = input.length < 1 ? 0 : input[i-1];
    input.push(((output[i] ^ lastInput) * 129) % 256);
}
console.log(input);

当被要求反转函数时要遵循的想法是代数反转函数。但是,第二种解决方案似乎以一种在数学上不应该有效的方式简化了反转函数!但它有效!请帮忙!

附:预期输出为 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

【问题讨论】:

  • 您无法反转哈希。它们是单向函数。在适当的散列中完成的特定计算不能被反转以获得产生散列的原始值。例如1+2 =&gt; 3 很好,但 3 -&gt; ???。有无数种可能性:sqrt(9)4-1 等...
  • 我听到你在说什么,但这是哈希函数可以逆向工程的特殊情况。
  • @MarcB 大多数哈希函数是单向的(或关闭;真正的单向函数的存在是 CS 中的一个悬而未决的问题)。可以创建一个哈希函数,对于给定的输入域,它是可逆的。
  • 确实如此,我想我应该开始更一般地思考,而不仅仅是“加密哈希”。
  • 虽然这个“哈希函数”的输出看起来不仅仅是一个固定位数的单个值......它看起来与输入的大小相同。所以它不是真正的哈希

标签: javascript algorithm reverse-engineering algebra simplify


【解决方案1】:

注意:写完这个答案后,我通过qxz重新阅读了答案,并且 意识到这里涵盖的所有内容也都包含在 qxz 的答案中。 但我还是决定发布这个,因为略有不同 格式可能对某些人有帮助。

要了解为什么会这样,您所要做的就是计算

y = (129 * x) % 256;  

对于 0 到 255 之间的每个 x。从偶数开始

for ( x = 0; x < 256; x += 2 ) {
    y = (129 * x) % 256; 
    console.log(y);
}

输出是

  0   0
  2   2
  4   4
  6   6
  8   8
 10  10
 12  12
 14  14
... ...

换句话说,当你以 256 为模乘以 129 时,偶数不会改变。

奇数的输出是

  1 129
  3 131
  5 133
  7 135
  9 137
 11 139
... ...
125 253
127 255
129   1
131   3
133   5
... ...

换句话说,乘以 129 模 256 与将 128 加到模 256 的数字相同。因此,当您执行两次时,您会得到原始数字:(x + 128 + 128) % 256 = x

公式的其余部分确实对此没有任何影响。模 256 丢弃第 7 位以上的所有位,保留低 8 位。 XOR 对第 7 位以上的位没有影响,它只是反转一些低 8 位。因此异或和模256之间没有相互作用。异或只影响低8位,模只影响高位。

这意味着在反转计算时,您可以先进行 XOR 以取回低 8 位。然后乘以 129 模 256 或者什么都不做(如果数字是偶数)或者它添加 128 模 256(如果数字是奇数)。无论哪种方式,您都可以取回原始号码。

【讨论】:

    【解决方案2】:

    首先,您的“散列函数”并不是传统意义上的散列函数。散列函数通常接受一个输入(可以是可变大小,例如字符串)并将其转换为固定位数的单个值。这类函数不能真正反转,因为在转换过程中会丢失很多位数据;你不能从 4 位重构 100 位。

    您的函数将一个字节列表转换为另一个等长的字节列表。看起来它接受当前输入,通过函数 x =&gt; (x*129)%256 运行它,然后 xors 它与之前的输入一起运行。

    函数f(x) = (x*129) % 256 是有趣的部分。如果输入是偶数,则输出是相同的数字。如果输入为奇数,则输出为第 7 位(第 127 位)反转的输入。 (尝试自己插入一些值。)因此,f(x) 是它自己的倒数; f(f(x)) == x.

    因此,整个“哈希函数”可以这样反转:

    • xor 当前哈希值与前一个输入值,或者0 如果是第一个输入值
    • 通过f(x) 函数运行结果以在计算值时反转f(x)
    • 对每个值重复

    ... 这就是你最后一个 sn-p 所做的。我不确定第一个。

    【讨论】:

    • x*129 = x
    • 我的函数不是 x => (x*129)%256 它是 x=> ((129 * x) XOR x[i-1]) % 256。据我所知模数不能在 (129 * x) 和 x[i-1] 之间分布,因为 XOR 没有分布特性。所以你不能挑出 (x*129) % 256
    • @samgak 255*129= (255
    • @googamanga 如果您将 % 256 重写为 & 255 则可以:((129 * x) ^ x[i-1]) & 255 => ((129 * x) & 255) ^ (x[i-1] & 255)
    • 32895 & 255 = 32639 & 255 = 127
    猜你喜欢
    • 2012-07-30
    • 2023-03-13
    • 2011-05-09
    • 2015-02-28
    • 1970-01-01
    • 2017-06-06
    • 2016-11-23
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多