AgileDotNet 混淆代码调用错误函数

AgileDotNet obfuscated code calls the wrong function

在 c# 项目上 运行 AgileDotNet 之后,我遇到了最不寻常的错误:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'qVQ=.qLQ=' does not contain a definition for 'MyFunctionActualName'
   at CallSite.Target(Closure , CallSite , Type , Object , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   at ohM=.oQM=.<OnCallback>d__21.MoveNext()     Program.cs::OnCallback() #449

C# 试图通过函数的实际名称调用函数,即:MyFunctionActualName。由于代码被混淆了,名称为 MyFunctionActualName 的函数当然不存在了。为什么 AgileDotNet 会尝试调用它?如何调试这样的问题?

出现此异常的原因是代码使用 dynamic 类型,然后在此类实例上调用方法。

举个例子:

void Main()
{
    dynamic t = new Test();
    t.ActuallyNotPresentMethod();
}

public class Test
{
    public void Execute() => "test".Dump();
}

这抛出:

RuntimeBinderException: 'UserQuery.Test' does not contain a definition for 'ActuallyNotPresentMethod'

让我们看看它产生的IL,UserQuery部分来自LINQPad,我用运行上面的例子得到下面的IL:

IL_0000:  newobj      UserQuery+Test..ctor
IL_0005:  stloc.0     
IL_0006:  ldsfld      UserQuery+<>o__4.<>p__0
IL_000B:  brtrue.s    IL_0041
IL_000D:  ldc.i4      00 01 00 00 
IL_0012:  ldstr       "ActuallyNotPresentMethod"
IL_0017:  ldnull      
IL_0018:  ldtoken     UserQuery
IL_001D:  call        System.Type.GetTypeFromHandle
IL_0022:  ldc.i4.1    
IL_0023:  newarr      Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
IL_0028:  dup         
IL_0029:  ldc.i4.0    
IL_002A:  ldc.i4.0    
IL_002B:  ldnull      
IL_002C:  call        Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_0031:  stelem.ref  
IL_0032:  call        Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember
IL_0037:  call        System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Object>>.Create
IL_003C:  stsfld      UserQuery+<>o__4.<>p__0
IL_0041:  ldsfld      UserQuery+<>o__4.<>p__0
IL_0046:  ldfld       System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Object>>.Target
IL_004B:  ldsfld      UserQuery+<>o__4.<>p__0
IL_0050:  ldloc.0     
IL_0051:  callvirt    System.Action<System.Runtime.CompilerServices.CallSite,System.Object>.Invoke
IL_0056:  ret   

如果你看这一行:

IL_0012:  ldstr       "ActuallyNotPresentMethod"

你可以看到要调用的方法的名称实际上是作为字符串文字嵌入到 IL 中的。

如果我们将代码更改为不使用 dynamic,并调用存在的 Execute,我们将得到:

IL_0000:  newobj      UserQuery+Test..ctor
IL_0005:  callvirt    UserQuery+Test.Execute
IL_000A:  ret  

可以看到调用完全不一样了

这解释了异常。该代码使用 dynamic 来调用一个方法,并且这个字符串没有被混淆,因此包含原始的未混淆的方法名称。由于此方法不再以该名称存在,因此 运行time 活页夹在 运行time 抛出异常。

我不知道为什么 AgileDotNet 错过了动态。可能是它根本不处理 dynamic,在这种情况下,您将不得不处理它。您应该联系 Secureteam 寻求帮助,以确定该工具能够提供什么(如果有的话)。