场景:自己想一个吧,也许是某公司有一个2002年开发的一个组件,开发人员是谁已无从知晓,而源码也随着这位开发人员的离职而没了踪影,更无奈的是这个组件被混淆了,却没有强名......,现在突然想用在一个规范化的,全部有强名的程序集中,并且程序集之间的引用还有安全验证......
PS:你当然可以想一个比我这个还悲惨的。
需求:能让这个程序集加上强名,并且用起来。
解决办法:
1、最常用的mono.cecil,在有强名文件的情况下,利用AssemblyFactory、AssemblyDefinition类配合API:
[DllImport("mscoree.dll", EntryPoint = "StrongNameKeyDelete", CharSet = CharSet.Auto)]
public static extern bool StrongNameKeyDelete(string wszKeyContainer);
[DllImport("mscoree.dll", EntryPoint = "StrongNameKeyInstall", CharSet = CharSet.Auto)]
public static extern bool StrongNameKeyInstall([MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2, SizeConst = 0)] byte[] pbKeyBlob, int arg0);
[DllImport("mscoree.dll", EntryPoint = "StrongNameSignatureGeneration", CharSet = CharSet.Auto)]
public static extern bool StrongNameSignatureGeneration(string wszFilePath, string wszKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob, int ppbSignatureBlob, int pcbSignatureBlob);
[DllImport("mscoree.dll", EntryPoint = "StrongNameErrorInfo", CharSet = CharSet.Auto)]
public static extern uint StrongNameErrorInfo();
[DllImport("mscoree.dll", EntryPoint = "StrongNameTokenFromPublicKey", CharSet = CharSet.Auto)]
public static extern bool StrongNameTokenFromPublicKey(byte[] pbPublicKeyBlob, int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, out int pcbStrongNameToken);
[DllImport("mscoree.dll", EntryPoint = "StrongNameFreeBuffer", CharSet = CharSet.Auto)]
public static extern void StrongNameFreeBuffer(IntPtr pbMemory);
等一系列方法对其进行重新签名,所有的一切都回规正常。
PS,你也可以通过其他办法来实现重新签名,自己baidu、google吧。
2、如果没有强名文件?有没有什么办法呢,则使用mono.cecil提取具有与需求强名相同程序集中的PublicKey、PublicKeyToken,然后利用AssemblyFactory、AssemblyDefinition类配合保存,当然这个程序集是没有通过强名验证的,只不过空有PublicKey、PublicKeyToken罢了,使用 sn -v 是绝对通不过的,也无法加载。
所以说这事不算完,如何能让Framework正常加载?
A) sn -Vr 应用程序集名
A+)修改注册表,在HKEY-LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\ 加一项:程序集名,PublicKeyToken,好了这样就可以
A++)在Vista或Windows7上发布时有些麻烦了如果有安装包还可以,如果是ClickOnce发布、或把这些功能写在软件中的话,一会需要以管理员身份运行,一会黑屏一下,估计用户还没用系统呢就崩溃了。
看来还需要进一步处理
B)不就是读注册表吗,把读取注册表的API搞定,在Framework验证程序集强名的时候,直接返回*,*是不是就搞定了,查资料WindowsAPI、注册表相关,C#、Hook、API、RegQueryInfoKey()、 RegEnumKey()、RegEnumKeyEx()、RegEnumValue(),N多关键字,结合Google从入门到精通的要点,也没搞定 C# HOOK API,看来只能放弃了......
B+)为什么去搞Windows的API,也许搞定Framework本身的可能效率更高,什么ring0、ring3、驱动一堆看着熟悉又陌生的词汇,尝试着C#示例,无果,最后只能求助于VC++、Delphi了......
B++)需求才是第一生产力,人家都说授之以鱼不如授之以渔,所以程序代码就不公开了。