繁体   English   中英

逆向工程 - 这段代码中的算法是什么?

[英]Reverse Engineering - What's Kind of Algorithm In This Code?

有人可以帮我发现这是什么类型的算法吗?

public class hf1 {

    public static final String[] f3650a = {"0sFU@W>Ao*BT64?[L5aONSK.'"...};

    public static final String[] f3651b = {" \bB\u0017\u001e)YBN\u001eT/\u001e4V\u0001ZT/6VV"...};

    public static final String[] f3652c = {"\u0000\u0000\u0013\u00006\u0000\\\u0000\u0000¢\u0000¹\u0000¿\u0000"...};

    public static String m5192a(int i) {
        int i2 = i / 4096;
        int i3 = i % 4096;
        int i4 = i + 1;
        int i5 = i4 / 4096;
        int i6 = i4 % 4096;
        String[] strArr = f3652c;
        String str = strArr[i2];
        String str2 = strArr[i5];

        int i7 = i3 * 2;
        int charAt = ((str.charAt(i7 + 1) & 65535) << 16) | (str.charAt(i7) & 65535);
        int i8 = i6 * 2;
        int charAt2 = ((str2.charAt(i8 + 1) << 16) | str2.charAt(i8)) - charAt;
        char[] cArr = new char[charAt2];
        for (int i9 = 0; i9 < charAt2; i9++) {
            int i10 = charAt + i9;
            int charAt3 = f3651b[i10 / 8192].charAt(i10 % 8192) & 65535;
            cArr[i9] = f3650a[charAt3 / 8192].charAt(charAt3 % 8192);
        }
        return new String(cArr);
    }

}

如果我调用 m5192a(1) 传递任何 int 索引作为参数,代码将返回一个字符串。 这就像在源代码上隐藏了某种纯字符串。

有人知道可能的反向代码吗? 将普通字符串转换成这个? 这是一种有名字的已知技术吗?

我不确定“具有名称的已知技术” - 也许像“反函数”或“双向化”这样的关键字可能会有所帮助,例如在纯函数式语言中,是否有一种算法来获得反函数?

对于这个特定的函数,幸运的是,只要f365xx字符串常量遵守某些特定属性,就可以很容易地进行反转。 请注意, cArr是一一填充的,并且每个字符彼此独立。 我们可以尝试使用字符串的字符和长度来尝试解码输入i 具体来说,

  • 单个字符将为我们提供i10候选者,这将为我们提供charAt候选者。 重复所有的字符,希望每个字符只有一个候选者可以工作,如果字符串是“仁慈的”,那个候选者会给我们i7 / i2 -> i2 / i3 -> i
  • 如果字符串不是善意的,那么字符串的长度将为我们提供charAt2的候选者,与charAt的候选者一起,将为我们提供i8 / i6候选者。 希望只有一个候选对i6 / i8 -> i5 / i6 -> -> i4 -> i如果字符串常量是仁慈的。

如果字符串仍然不是仁慈的,那么它是不可解的,因为函数不是一对一的。

我现在将概述 2 个要点的算法,但作为免责声明,我尚未对此进行测试,它只是伪代码。

从一个字符

假设您从第一个字符cArr[0] 如果我们关注 for 循环内的 3 行,

int i10 = charAt + i9;
int charAt3 = f3651b[i10 / 8192].charAt(i10 % 8192) & 65535;
cArr[i9] = f3650a[charAt3 / 8192].charAt(charAt3 % 8192);

然后,我们可以得到charAt3通过找到cArr[0]出现在f3650a 例如,

charAt3candidates = []
for i = 0 to length(f3650a)-1:
  indexCandidates = f3650[i].indexOf(cArr[0])
  for indexCandidate in indexCandidates:
    charAt3candidate = i * 8192 + indexCandidate
    if indexCandidate >= 8192 or charAt3candidate >= 65536:
      continue
    charAt3candidates.append(charAt3candidate)

请注意,我们过滤掉indexCandidate >= 8192charAt3candidate >= 65536因为模数和按位和使更大的值变得不可能( x & 65535 == x % 65536因为 65536 = 2^16)。

执行类似的过程以找到i10的候选者并减去i9以获得charAt候选者。 如果您有多个候选项,请对cArr中的每个字符重复此过程,并仅保留对cArr中的每个字符都有效的charAtcArr 即使在对cArr每个字符重复之后,您可能仍然有很多候选者。

对于charAt每个候选者,使用charAt表达式的右半部分:

charAt % 65536 = (str.charAt(i7) & 65535)

结合str = f3652c[i2]尝试以与我们尝试找到charAt3i10相同的方式找到i2 / i7 请注意,表达式的左半部分((str.charAt(i7 + 1) & 65535) << 16)无关紧要(目前)。 希望并祈祷这只会为您提供i2 / i7一种可能选择。 如果是这样,请使用它来查找i2 / i3 -> i 如果有多个选项,那么我们必须尝试使用​​字符串的长度。

从字符串的长度

字符串的长度为我们提供了charAt2 ,我们可以使用与之前类似的过程来查找i8str2 ( i5 ) 的所有候选对象。 请注意,在此过程中,我们必须尝试使用​​每个可能的charAt候选者。 希望i8 / i5只剩下一对候选。 如果是这样,请使用它来查找i5 / i6 -> i4 -> i 如果有超过 1 个候选,则该函数不是一对一的,并且不可能反转。

祝你好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM