【问题标题】:Decompile with Reflector使用反射器反编译
【发布时间】:2011-10-15 11:08:11
【问题描述】:

我已经完成了代码的反编译。但它不是显示字符串,而是显示一个负数。如何找到原始字符串?
我的反编译代码是这样的:

string str = .(-812265445);  

应该是:

string str = "My string"; 

请帮忙
请注意,当我添加对项目和调试的引用时,它可以看到字符串“我的字符串”不是 .(-812265445);
当我使用另一个反汇编程序时,它显示:

string str = ACK. STX(-812265445);  

我客ACK和STX都是二进制字符。

非常感谢

对您的回答的回应是我从 ILSpy 拍摄的两张照片,以便更好地想象:

【问题讨论】:

  • 我怀疑任何反汇编程序都能够为您提供准确的原始源代码。
  • @harold 阙?什么是“你应该”?
  • @OskarKjellin 一个错误,我的意思是“你能不能展示一下”
  • @akari 显然:: 是一个函数,它从该整数中查找一个字符串,您是否使用了混淆器?
  • ACK.STX() 可能是获取解密字符串的静态方法调用。

标签: c# .net reflector


【解决方案1】:

字符串可能是加密的……或者它是 Reflector 中的一个错误。如果它已加密,这将无济于事(调试器是您最好的选择,因为加密器会在您的应用程序使用字符串之前注入解密代码)。

使用 Reflector 和 ILDasm 在已编译的程序集中查找字符串:

  1. 打开 Reflector 并找到您正在调查的成员/方法
  2. 将语言从 C# 更改为 IL(以查看 ILDASM 会显示什么)
  3. 验证字符串仍然没有正确显示
  4. 获取指令旁边的行标签(例如:L_0060: )

  5. 在 ILDasm 中打开您的程序集并找到您正在调查的方法

  6. 从 Relector 找到指令标签(应该与 IL_0060: 相同的行)
  7. 如果此处的字符串仍然不正确,则该字符串已被加密

要验证程序集中存储了什么字符串,您可以执行以下操作:

  1. 在 ILDasm 中,关闭显示该方法的 IL 的对话框
  2. 转到查看菜单并检查显示令牌
  3. 在 ILDASM 中再次打开该方法,这一次当您找到您的代码行时,它后面应该有一个标记,如 /* 70002C92 */(当然您的数字会不同)但这是字符串所在的位置在程序集的用户字符串元数据堆中。
  4. 转到视图 -> 元信息并检查 Raw:Heaps
  5. 转到视图 -> 元信息并显示!
  6. 在这个新对话框中,转到“查找”菜单并将您的令牌放入其中,然后单击“查找”

这将带您进入用户字符串元数据堆中的条目,并准确显示二进制文件中编译的字符串。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      反编译不会返回原始代码。

      您的示例看起来像一个简单的“使用字符串地址加载寄存器,用它做一些事情......”。

      编译器不会将字符串(或任何数据)与指令内联,数据、字符串、数字都被移动到适当的部分。由于这是一个字符串常量,它很可能被移到了 .data 或 .rodata 部分。

      将您的 -812265445 数字转换为十六进制会更清楚一些,因为它变成了 0xCF95D01B,这是一个存储内容的有效地址。如果您的输出基数是带符号的十进制(看起来很常见),那么地址通常会以巨大的负值告终。将它们转换为十六进制或更改您的默认值以让您看到(或更容易理解)它们指向的位置。

      L_0012: ldc.i4 -812265440  (0xCF95D020)
      L_0017: call string ::(int32)
      L_001c: stloc.0
      L_001d: ldc.i4 -812265445  (0xCF95D01B)
      L_0022: call string ::(int32)
      L_0027: stloc.s str5
      

      从此(您在上面的评论),很明显在第 0x12 行(L_0012)上有一个“带有字符串地址的加载寄存器”,调用 'string::...' 来转换它(我想)然后存储将生成的“字符串”指针放在某处。

      然后在第 0x1D-0x27 行再次执行此操作。也许那里有一个 4 字节长的 const char 字符串(因为第一个和第二个加载 (ldc.i4) 地址相隔 5 个单位。(4 个字符 + 0 个终止符)。

      使用您的调试器或任何您必须在显示的地址处显示内存的东西(尽管使用当前程序反汇编中实际存在的任何内容)并查看那里有什么。探索!

      【讨论】:

      • 我怀疑它们是地址,我猜有可能但是这段代码会在 64 位上中断,而且它们太高了。这也不是常规 C# 编译器会做的事情,它总是使用ldstr。调用也不完全是string::string 部分只是那里的返回类型。所以总而言之,我会说它们是将索引混淆到可能加密的字符串池中,这是混淆器会做的事情。
      • 你在开玩笑吧? 'string::(int32)' 只是一个链接函数调用的占位符,它没有描述它的返回值甚至是所需的值,尽管我可以推测它对'variable'(i4 ),并返回一个存储的值。必须查找“IL”……这是微软的字节码 .NET 东西。讨厌。但这肯定是一个加载/调用/存储序列,并且作为 MS 的 .NET,它在执行之前就已处理,因此该程序很可能是 IL 解释器的数据,这可能会将其推高到 ram 中。尤其是在大型 RAM 64 位机器上。
      • 在开玩笑吗?您甚至知道 MSIL 的工作原理吗? C# 编译器和任何其他健全的编译器将始终使用ldstr 来加载字符串,因为这就是ldstr 的用途。避免它的唯一原因是混淆。地址必须是nativeint,而不是int32。是的,它确实描述了它的返回值和它的参数,因为这就是 MSIL 的工作原理。
      • 不,我不知道细节,暂时不关心。我怀疑它们与任何其他编译器有什么不同,我会优雅地承认你的智慧。我的迟钝冒犯了你,我深表歉意。 :) 谢谢你教我。
      • 没问题,我猜 MSIL 没有你想象的那么低级
      猜你喜欢
      • 2023-03-11
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      • 1970-01-01
      相关资源
      最近更新 更多