CallSite <>p__site 同时反编译大型代码库

CallSite <>p__site while decompiling large code base

我有一个客户的大型代码库,其开发人员拒绝提供代码。

我已经反编译了它的主要部分,尽管我在遵循

时遇到了问题

我正在使用 dnSpy、Just Decompile、dotPeek 来反编译代码。我尝试 google 并查看了 Whosebug,但找不到任何可以回答我的问题。如果有人能指出我正确的方向,我将不胜感激。

更新:我已经粘贴了完整的功能

public virtual string ParseDealerInventoryLink(string toParseLinkData)
        {
            string pattern = "{([^}]+)}";
            string text = toParseLinkData;
            RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
            if (this != null && !string.IsNullOrWhiteSpace(text))
            {
                object dyn = new PropertyBag(this);
                Regex regex = new Regex(pattern, options);
                Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = DealerInventoryFeedUrlParser.GetLinkPatternParamValueMap();
                text = regex.Replace(text, delegate(Match mat)
                {
                    if (mat.Success && mat.Groups.Count > 0)
                    {
                        Group group = mat.Groups[mat.Groups.Count - 1];
                        if (group.Success)
                        {
                            string value = group.Value;
                            if (linkPatternMap.ContainsKey(value))
                            {
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
                                }
                                Func<CallSite, object, string> target = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1.Target;
                                CallSite <>p__Site = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1;
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, Type, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(CSharpBinderFlags.None, "ToString", null, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[]
                                    {
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                                    }));
                                }
                                Func<CallSite, Type, object, object> target2 = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2.Target;
                                CallSite <>p__Site2 = DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site2;
                                Type typeFromHandle = typeof(Convert);
                                if (DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3 == null)
                                {
                                    DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3 = CallSite<Func<CallSite, object, string, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetIndex(CSharpBinderFlags.None, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[]
                                    {
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                                    }));
                                }
                                return target(<>p__Site, target2(<>p__Site2, typeFromHandle, DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3.Target(DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site3, dyn, linkPatternMap[value].ColumnName)));
                            }
                        }
                    }
                    return mat.Value;
                });
            }
            return text;
        }
class DealerInventoryFeedUrlParser
{
    void ParseDealerInventoryLink()
    {
        dynamic input = new object();
        string link = input;
    }
}

编译时生成以下内容,然后在 ILSpy 中反编译:

class DealerInventoryFeedUrlParser
{
    private void ParseDealerInventoryLink()
    {
        object input = new object();
        if (<>o__0.<>p__0 == null)
        {
            <>o__0.<>p__0 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
        }
        string link = <>o__0.<>p__0.Target(<>o__0.<>p__0, input);
    }
  }

...我会归类为 "close enough".

我选择 new object() 作为分配给 dynamic 的值并没有特别的原因。这可能是一个整数、字符串——任何东西。 CallSite 初始化代码看起来是一样的。 CallSite<Func<T1, T2, TResult>> 中的 T2always 对象,因此除非您查看反编译源中 DealerInventoryFeedUrlParser.<ParseDealerInventoryLink>o__SiteContainer0.<>p__Site1实际使用。

编辑

现在已经发布了完整的源代码,让我们尝试将各个部分放在一起:

class DealerInventoryFeedUrlParser
{
    static Dictionary<string, DealerInventoryLinkPatternParam> GetLinkPatternParamValueMap() => throw new NotImplementedException();

    public virtual string ParseDealerInventoryLink(string toParseLinkData)
    {
        string pattern = "{([^}]+)}";
        string text = toParseLinkData;
        RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
        if (/*this != null &&*/ !string.IsNullOrWhiteSpace(text))
        {
            dynamic dyn = new PropertyBag(this);
            Regex regex = new Regex(pattern, options);
            Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = GetLinkPatternParamValueMap();
            text = regex.Replace(text, delegate (Match mat)
            {
                if (mat.Success && mat.Groups.Count > 0)
                {
                    Group group = mat.Groups[mat.Groups.Count - 1];
                    if (group.Success)
                    {
                        string value = group.Value;
                        if (linkPatternMap.ContainsKey(value))
                        {
                            return Convert.ToString(dyn[linkPatternMap[value].ColumnName]);
                        }
                    }
                }
                return mat.Value;
            });
        }
        return text;
    }
}

class PropertyBag
{
    private readonly object Owner;

    public PropertyBag(object obj)
    {
        Owner = obj;
    }
}

class DealerInventoryLinkPatternParam
{
    public string ColumnName { get; set; }
}

ParseDealerInventoryLink compiled/decompiled:

public virtual string ParseDealerInventoryLink(string toParseLinkData)
{
    string pattern = "{([^}]+)}";
    string text = toParseLinkData;
    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;
    if (!string.IsNullOrWhiteSpace(text))
    {
        dynamic dyn = new PropertyBag(this);
        Regex regex = new Regex(pattern, options);
        Dictionary<string, DealerInventoryLinkPatternParam> linkPatternMap = DealerInventoryFeedUrlParser.GetLinkPatternParamValueMap();
        text = regex.Replace(text, delegate(Match mat)
        {
            if (mat.Success && mat.Groups.Count > 0)
            {
                Group group = mat.Groups[mat.Groups.Count - 1];
                if (group.Success)
                {
                    string value = group.Value;
                    if (linkPatternMap.ContainsKey(value))
                    {
                        if (<>o__1.<>p__2 == null)
                        {
                            <>o__1.<>p__2 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(DealerInventoryFeedUrlParser)));
                        }
                        Func<CallSite, object, string> target = <>o__1.<>p__2.Target;
                        CallSite<Func<CallSite, object, string>> <>p__ = <>o__1.<>p__2;
                        if (<>o__1.<>p__1 == null)
                        {
                            <>o__1.<>p__1 = CallSite<Func<CallSite, Type, object, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "ToString", null, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[2]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));
                        }
                        Func<CallSite, Type, object, object> target2 = <>o__1.<>p__1.Target;
                        CallSite<Func<CallSite, Type, object, object>> <>p__2 = <>o__1.<>p__1;
                        Type typeFromHandle = typeof(Convert);
                        if (<>o__1.<>p__0 == null)
                        {
                            <>o__1.<>p__0 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.GetIndex(CSharpBinderFlags.None, typeof(DealerInventoryFeedUrlParser), new CSharpArgumentInfo[2]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                            }));
                        }
                        return target(<>p__, target2(<>p__2, typeFromHandle, <>o__1.<>p__0.Target(<>o__1.<>p__0, dyn, linkPatternMap[value].ColumnName)));
                    }
                }
            }
            return mat.Value;
        });
    }
    return text;
}

您可以替换 compiler-generated 名称来检查我是否一切正确。我所做的是基于我对 dynamic 有限的理解,非常、非常快速地猜测我在看什么的尝试。现在由您来检查所有内容,验证正确性并在必要时进行修复。

P.S。 this != null 检查位让我有点困惑。一定是反编译器的怪癖。我已经把它注释掉了,因为它看起来并不重要。

P.P.S。反编译和重新编译二进制文件是一个非常肮脏且 error-prone 的过程。如果您需要进行的更改很小,请考虑研究 .NET 二进制补丁(Google),即使用 ILSpy + Reflexil。

祝你好运。