【问题标题】:Can't decrypt these strings无法解密这些字符串
【发布时间】:2012-08-08 07:24:31
【问题描述】:

序言

我正在尝试反汇编和反向工程一个作者早已不复存在的程序。该程序提供了一些我在其他地方还没有找到的独特功能,而且……我对程序的逆向工程感到好奇和好奇。如果你只是想尝试帮我找到另一个程序...不要打扰。

问题

我正在使用带有 Hex-Rays Decompiler 的 IDA Pro 来获得一些不错的伪代码,以尝试加速逆向工程。我认为有助于加快速度的一件大事是弄清楚字符串的含义。到目前为止,这就是我发现的长度超过 4 个字符的字符串:

dword_131894E = 54264588;
dword_131894A = 51381002;
dword_1318946 = 51380998;
dword_1318942 = 52429571;
dword_131893E = 52298503;
runtimeVersion[0] = 836;
szIndex = 0;
do
{
  runtimeVersion[szIndex] = (runtimeVersion[szIndex] - 1) ^ (szIndex + 882) ^ 0x47;
  ++szIndex;
}
while ( szIndex < 11 );

通过查看三个字符的字符串的类似伪代码,并使用 Hex-Rays 悬停在类型信息上,我是这样理解的:

  • runtimeVersion 是一个 const wchar
  • 这意味着它具有 Unicode 字符 (UTF-16)
  • 字符串嵌入到内存中,但在本例中是弱加密(XOR?)

上面的伪代码对于所有大字符串都是相同的,除了常量“882”对于每个字符串都不同。我假设这是某种编译时加密或宏,它一个一个地找到字符串并唯一地“加密”它们。但是,问题是,我似乎无法通过复制伪代码来获得正确的字符串。这是我在 C# 中的内容:

ushort[] newCharArray = new ushort[rawCharacters.Length];

// Go through and decode all of the characters.
ushort i = 0;
do {
    newCharArray[i] = (ushort)((i + 882) ^ (rawCharacters[i] - 1) ^ 0x47);
    ++i;
}
while (i < 11);

'rawCharacters' 是一个超短数组。我将每个 dword 条目分成两半,并将每个条目视为 ushort。我将它们从底部到顶部放在数组中...因此分配给 runtimeVersion[0] 的值首先添加到我的数组中,然后是来自 dword_131893E 的值,然后是 dword_1318942 等。

我不确定我在这里缺少什么。这似乎很简单,以至于反转和恢复字符串应该是小菜一碟,但我对从伪代码到实际代码的转换感到困惑。

想法?

【问题讨论】:

  • 它与“解密”完全无关。你的意思可能是解码而不是解密。
  • 随心所欲地调用它。很明显,大字符串从其原始形式转换为旨在使它们更难从可执行文件中拉出的东西。对我来说,这就是加密......但也许对你来说 SSL 只是一个“编码”:P
  • 您是否尝试过不同的变体,例如不同的异或或使用不同的编码(utf8、utf16 等)?
  • 我的第一个猜测是您错误地加载了rawCharacters。您能否包括显示 C# 中数据加载的源代码以及 RuntimeVersion 声明的 Hex-Rays 输出?
  • 你确定你找到的代码是加密的吗?我的想法是字符串以加密方式存储在可执行映像中,软件将其展开为可理解的内容。

标签: c# c++ reverse-engineering ida


【解决方案1】:

好的,在一张纸上工作,这就是我得到的:

54264588 = 0x033c030c
51381002 = 0x0310030a
51380998 = 0x03100306
52429571 = 0x03200303
52298503 = 0x031E0307
836 = 0x0344
882 = 0x0372

v = 0x0076 = 0x47 ^ 0x0372 ^ (0x0344 - 1)
2 = 0x0032 = 0x47 ^ 0x0373 ^ (0x0307 - 1)
. = 0x002E = 0x47 ^ 0x0374 ^ (0x031E - 1)
0 = 0x0030 = 0x47 ^ 0x0375 ^ (0x0303 - 1)
. = 0x0076 = 0x47 ^ 0x0376 ^ (0x0320 - 1)
5 = 0x0035 = 0x47 ^ 0x0377 ^ (0x0306 - 1)
0 = 0x0030 = 0x47 ^ 0x0378 ^ (0x0310 - 1)
7 = 0x0037 = 0x47 ^ 0x0379 ^ (0x030a - 1)
2 = 0x0032 = 0x47 ^ 0x037a ^ (0x0310 - 1)
7 = 0x0037 = 0x47 ^ 0x037b ^ (0x030c - 1)
\0 = 0x0000 = 0x47 ^ 0x037c ^ (0x033c - 1)

因此字符串是“v2.0.50727”我还检查了另一个字节序选项,但这个看起来好多了。所以我知道这并没有指出你的代码哪里错了,但它应该可以帮助你用调试器/printf 解决它。

编辑:将最后 7 个添加到字符串中。

【讨论】:

  • 我认为您错过了字符串上的最后一个“7”,这将使它成为“v2.0.50727” - 当前的 .NET 2 版本号。
  • 我刚刚复制了你的数学点。让我回顾一下我的代码,找出我搞砸的地方。
  • 所以问题是我如何解释双字中字节的顺序。在我给出的示例中,我将数据读取为:0x344、0x31e、0x307、0x320 等。看起来您的顺序(每个 dword 右侧的两个字节首先,然后是前两个字节)是诀窍。感谢您帮助我解决这个问题。它变得如此令人沮丧。 :) 另外,对于所有看到这个问题并且没有足够的信息从一个人那里得到关于我正在做什么来提供适当答案的人,我深表歉意。
猜你喜欢
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多