如何在 .net 中混淆后调查问题?

3

我正在尝试使用ConfuserEx混淆一个库,但之后我的应用程序出现了MissingMethodException崩溃,并且堆栈跟踪指向了第一次使用被混淆的类和方法,被重命名的方法是问题所在。我不知道它的调用或其他用法在哪里找到,因此不清楚我应该检查什么。 我猜想异常发生在JIT过程中。

只有重命名混淆被应用,并且我有映射来还原它。

我查看了混淆模块和重命名版本的方法,确实存在。

在混淆的模块上运行PEVerify.exe会出现一些错误(下面只提供了一小部分):

[IL]: Error: [d:\1\Confused\my.dll : _YGbNngBKpRxvvy7NkSKSrcvDmJG_::_17w1GiROq6y1aWRw9wWSUGOde1C_][mdToken=0x60003cd] Method does not exist.
Method does not exist.
Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : _cdMM5QrQwL2ksRGa1UJRmJUkVTd_::.ctor][mdToken=0x60006c8][offset 0x00000002] Unable to resolve token.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_tGtv2dtaIMIA6LoHXu7DwMxfvlS_][mdToken=0x6000732] Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_tk0zK3VXciZeRsH2nVWBZ6jNVdE_][mdToken=0x6000733] Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_tGtv2dtaIMIA6LoHXu7DwMxfvlS_][mdToken=0x6000732] Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_tk0zK3VXciZeRsH2nVWBZ6jNVdE_][mdToken=0x6000733] Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_PkJlSB6sykBdsQ8OXX3CBVEXudk_][mdToken=0x6000735] Method does not exist.
[IL]: Error: [d:\1\Confused\my.dll : ClassXyz::_AYy29oWv1vnvKJP5Q1lcxUcQZRd_][mdToken=0x6000757] Method does not exist.

我准备调试混淆过程以查找出错的原因…但我不知道该查找什么。我如何找出哪部分代码尝试使用旧方法名?

如何处理PEVerify的输出,例如如何利用mdTokens帮助我?


作为观察或考虑的另一件事,您可能正在使用反射(通过字符串文字)来访问类型或成员,因此代码可能不会“知道”重命名。 - MaLio
不存在的成员的反射通常会返回 null,或者至少会抛出其他异常类型。这个特殊的异常来自于无效的程序集。在混淆期间发生了一些错误,程序集内部的某些链接已经断开了。 - ygoe
3个回答

1
这些标记可以在使用/tokens开关运行时,在ildasm结果中看到。例如:ildasm.exe asm.dll /out=asm.il /tokens。在这种情况下,ildasm在每个定义和引用附近生成MD标记。因此,可以通过PEVerify报告的标记进行简单的文本搜索。
以下是使用/tokens运行时,ildasm生成的IL示例:
  .method /*060035D5*/ private hidebysig newslot virtual final 
          instance void  b() cil managed
  {
    .override [mscorlib/*23000001*/]System.IDisposable/*01000051*/::Dispose /*01000051::0A000069*/ 

注意,ildasm不会在标记前加入0x(可能是为了简洁起见),因此您应该执行不区分大小写的搜索060006c8而不是0x060006c8

1
它只需要耐心。首先,使用WinDbg启动该应用程序并让应用程序崩溃。然后,您可以看到详细的异常信息,例如调用堆栈和寄存器。借助诸如ILSpy之类的工具,您可以准确地查看缺失的方法。最后,分析混淆日志文件以找到原始方法。
典型的解决方法是尝试从混淆中排除该方法,以查看是否解决了问题。但可能会有其他解决方法,或者只能修复混淆器。
我是Obfuscar的当前维护者,上述是我在调试Obfuscar问题时的个人经验。希望对您有所帮助。

我想我得学习一下WinDbg...目前,我有一个巨大的堆栈跟踪来自于相关线程在clr.dll中的深层结束(!EEStack的输出,因为相对于VS调试器,!CLRStack没有显示任何新信息),而我不知道接下来该怎么做... - Ivan Danilov
@IvanDanilov !pe -nested - Lex Li
https://www.dropbox.com/s/dq4bqh3z8gl0vv7/windbg.log?dl=0(我已经重命名了一些类型名称,否则它是不变的) - Ivan Danilov

0

根据我在开发SeeUnsharp .NET混淆器时的经验,运行时出现MissingMethodException表示您想要执行一个程序集,该程序集对IL代码中的成员具有无效或缺失的引用。 IL代码(.NET CLI编译器生成的内容)可能包含不需要存在的方法引用。如果您在C#中这样做,C#编译器会告诉您。

PEVerify会在编译器(在本例中为混淆器)未能捕获错误时捕捉此错误,并告诉您缺少哪个方法,或者至少告诉您缺陷方法调用位于哪个方法的哪个IL偏移处。您可以使用ILSpy,启用元数据令牌显示并切换到IL模式,以查找相关指令。来自PEVerify的剩余错误可能会在运行时导致麻烦,这就是为什么SeeUnsharp总是通过PEVerify运行混淆后的程序集以确保输出有效性的原因。

我认为这是ConfuserEx的问题。当我在IL处理过程中将事情搞错时,我也遇到了这些异常。当您找到缺失方法的原始位置后,可以检查它是否有特殊之处。它是虚拟的吗?它是接口方法吗?是否涉及动态类型?最终,从重命名中排除该方法可能是一个解决方案。

MSDN博客中还有关于此错误的更多信息。


是的,这绝对是ConfuserEx的问题。我试图找到并修复那里的问题。但是PEVerify的消息没有说明它在哪里找到了方法的引用 - 只是找不到哪个方法。可能是引用错误(未正确重命名),而不是方法本身丢失。问题是如何找出缺少的细节。PEVerify报告目标程序集中的不一致性,并且有些问题...显然是有问题的。 - Ivan Danilov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接