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>>
中的 T2
是 always 对象,因此除非您查看反编译源中 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。
祝你好运。
我有一个客户的大型代码库,其开发人员拒绝提供代码。
我已经反编译了它的主要部分,尽管我在遵循
时遇到了问题我正在使用 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>>
中的 T2
是 always 对象,因此除非您查看反编译源中 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。
祝你好运。