【问题标题】:CallSite <>p__site while decompiling large code base反编译大型代码库时调用Site <>p__site
【发布时间】:2019-05-30 12:01:38
【问题描述】:

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

我已经反编译了其中的大部分,尽管我在关注时遇到了问题

我正在使用 dnSpy, Just Decompile, dotPeek 来反编译代码。我也尝试用谷歌搜索并查看了 Stackoverflow,但找不到任何可以回答我的东西。如果有人能指出我正确的方向,我将不胜感激。

更新:我已经粘贴了完整的函数

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;
        }

【问题讨论】:

  • dynamic ParseDealerInventoryLink(string input) { return null; } string link = ParseDealerInventoryLink(""); 生成类似的代码。向我们展示稍后在您的代码中调用 &lt;&gt;p__Site1 会发生什么。

标签: c# decompiler


【解决方案1】:
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);
    }
  }

...我将其归类为“足够接近”。

我选择new object() 作为分配给dynamic 的值并没有什么特别的原因。这可能是一个 int、string - 任何东西。 CallSite 初始化代码看起来是一样的。 T2 in CallSite&lt;Func&lt;T1, T2, TResult&gt;&gt;always 对象,因此除非您查看反编译源中实际使用 DealerInventoryFeedUrlParser.&lt;ParseDealerInventoryLink&gt;o__SiteContainer0.&lt;&gt;p__Site1 的位置,否则您不会知道您的实际输入值是多少。 p>

编辑

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

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 编译/反编译:

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;
}

您可以替换编译器生成的名称来检查我是否一切正确。根据我对dynamic 的有限理解,我所做的是诚实但非常非常快速地尝试猜测我在看什么。现在由您来检查所有内容、验证正确性并在必要时进行修复。

附: this != null 检查位让我有点困惑。一定是反编译器的怪癖。我已将其注释掉,因为它似乎并不重要。

附言反编译和重新编译二进制文件是一个非常肮脏且容易出错的过程。如果您需要进行的更改很小,请考虑查看 .NET 二进制补丁(Google 搜索),即使用 ILSpy + Reflexil。

祝你好运。

【讨论】:

  • 感谢基里尔,这实际上是很大的帮助。我还粘贴了整个功能,以防您进一步指导我。
  • 非常感谢您的帮助,现在我对如何去做有了更好的了解。
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多