[转]强命名的延迟与关联在.net程序集保护中的作用及其逆向方法

来源:互联网 发布:网络中介交易平台 编辑:程序博客网 时间:2024/06/05 08:40
强命名的延迟与关联在.net程序集保护中的作用及其逆向方法
tankaiha@vxer.cn
2006-9-15

一、老调重谈强命名
    强命名的定义这里就不重复了,不妨就把他看作一个文件的hash,而如果文件被修改的话,计算出的hash将与最被程序设计者给定的强命名不一致,程序将拒绝加载。这可怜的一点点安全特性被人用多种方法证实原来靠强命名保护程序集只是纸老虎。
至少有三种方法可以去除单独的可执行文件的强命名:
1、  ildasm反编译,在il源代码中删除该assembly对强命名的引用,再编译回去。在.net初期时,这种方法还是很好用的,codeproject上也介绍过。但是现在的程序对于ildasm的anti越来越强,想完整的反编译再完整地编译回去,有时还不太容易。
 

2、  利用工具,原理是将CLI Header的标志置0
CLI Header的结构如下:

RVA  Field                       Contents
0x2008  Cb(结构的大小)            0x48
0x200C  MajorRuntimeVersion            2
0x200E  MinorRuntimeVersion            0
0x2010  MetaData                       0x2060
0x2014  Size of the Metadata            0x148 =(RVA of Import Table) – (RVA of MetaData)
0x2018  Flags                       1
0x201C  EntryPointToken             0x06000001 (Method #1 in TypeDef table)
0x2020  Resources                        0
0x2028  StrongNameSignature             0
0x2030  CodeManagerTable             0
0x2038  VTableFixups             0
0x2040  ExportAddressTableJumps  0
0x2048  ManagedNativeHeader             0

包括flags标志要减去COMIMAGE_FLAGS_STRONGNAMESIGNED (0x00000008) ,以及StrongNameSignature处表示的强命名的偏移位置和大小要置0。这还没完,还要将Metadata表中AssemblyDef处的强命名标志删除。
来看一下AssemblyDef的定义:

• HashAlgId (a 4-byte constant of type AssemblyHashAlgorithm).
• MajorVersion, MinorVersion, BuildNumber, RevisionNumber
(2-byte constants).
• Flags (a 4-byte bit mask of type AssemblyFlags).
• PublicKey (index into Blob heap).
• Name (index into String heap).
• Culture (index into String heap).

其中Flags项要减去afPublicKey = 0x0001。

3、就是利用Patch系统文件的形式。这种形式不推荐,毕竟强命名还有判别版本差异及文件完整性的作用,整个Patch了不大方便。


二、延迟强命名
    现在的.net程序都被混淆过了。比如你原来写了个计算注册码的程序叫CalRegCode(),但是混淆过的程序名可能是x0ab23ff10(),或者干脆是不可打印的ASCII字符。但如果你在程序中使用了强命名,混淆不会出错吗?这里其实就要用到延迟强命名。
    在VisualStudio中,点击项目的属性的sign选项,选择延迟强命名:
 

如果不想在窗口中设置,可以直接在AssemblyInfo.cs中设置如下:
   [assembly:AssemblyKeyFileAttribute("key.snk")]
    [assembly:AssemblyDelaySignAttribute(true)]
    延迟强命名就是在编译程序时设置好标志,并将存储空间留出,在编译完成后人工加上。比如,我们可以将strings流中的一些敏感名称,比如crypt()、crypcal()改为不可见:



    保存后在命令行用:sn –Ra xxxx.exe key.snk重新给文件签属强命名便OK了。
    修改名称有个注意事项,如果你修改的方法名称,在别的程序集中对此方法有调用的话,必须在调用的文件中也把相应的方法改为相同的名字,应为这种调用是按名称来的,否则会报找不到method的错误。但总的来说,如果仅仅对一个文件使用这种延迟强命名的方法,仍然是非常容易修改的。但如果一个主程序a.exe要调用b.dll和c.dll时(甚至更多,或者b与c间存在调用),而b.dll和c.dll都被加上强命名的话,这样如果修改b.dll(比如网络验证在b.dll中,我们要对其进行patch),整个程序则会报错。下面一节就讲讲这种整个程序中存在多个文件,且每个文件都有强命名的情况,看看他的保护强度和破解。我暂时给它起名叫关联强命名。


三、关联强命名
    我们来建一个C#工程,名叫example,其中存在两个dll(a.dll和b.dll),主程序对这两个程序分别存在调用,dll的代码只是弹出窗口显示被调用了,且每个dll都被加上强命名。并在主项目中添加对a和b的引用。


    a与b中的代码如图所示。主程序中建两个button控件,分别调用这两个Class Library中的方法。

代码如下:
        
代码:
private void button1_Click(object sender, EventArgs e)        {            a.Class1 newa=new a.Class1();            newa.showMsg();        }        private void button2_Click(object sender, EventArgs e)        {            b.Class1 newb=new b.Class1();            newb.showMsg();        }


单击不同的button会显示不同的窗口,提示当前是哪个lib被调用。如,单击checkLib1的窗口如下:
  

    由于a.dll与b.dll中已被加上强命名,我们试着修改一下,看看能否运行。比如将a.dll中窗口的显示字符改为“ClassLibrary A is called”(UserString的存储格式为Unicode):
00001590h: 53 68 6F 77 00 00 00 00 00 31 43 00 6C 00 61 00 ; Show.....1C.l.a.
000015a0h: 73 00 73 00 4C 00 69 00 62 00 72 00 61 00 72 00 ; s.s.L.i.b.r.a.r.
000015b0h: 79 00 20 00 41 00 20 00 69 00 73 00 20 00 63 00 ; y. .A. .i.s. .c.
000015c0h: 61 00 6C 00 6C 00 65 00 64 00 00 00 E5 79 88 40 ; a.l.l.e.d...鍄園

运行后单击checkLib1,会报错无法载入a.dll:
 

    这样看来,如果我们将关键代码分布在多个dll中,且每个dll加上强命名,并且存在一定的相互调用,就可以保护我们的程序集了。是不是这样呢?我们来看看example.exe中对a.dll的引用,看为什么它会认出我们修改了文件。
    Example.exe中的AssemblyRef表中存储了关于a.dll和b.dll的信息,AssemblyRef表的结构如下:
The AssemblyRef table has the following columns:
•  MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)
•  Flags (a 4-byte bitmask of type AssemblyFlags; see Partition II, section 22.1.2)
•  PublicKeyOrToken (index into Blob heap—the public key or token that identifies the author of this assembly)
•  Name (index into String heap)
•  Culture (index into String heap)
•  HashValue (index into Blob heap)

    其中第三项就规定了是否有PublicKeyOrToken,也就是是否有强命名。看看example.exe中的数据:



其中PublicKeyOrToken项清清楚楚地写的0x00be,这就是有强命名的标志,强命名存储在#Blog表中第0x00be项。再来看一下#Blog表,第0x00be项如下:

 

到这一步,我们就应该知道怎么修改了。首先,将example.exe中对a的引用表中的PublicKeyOrToken项的值改为0,然后第二步是去除a.dll中的强命名。修改完成后,我们再运行,果然,系统已经不再报错,并正确显示我们所修改的字符串了:

 

四、小结
    到这里,强命名的几种应用形式基本介绍完。试想,如果一个有数十个文件的程序每个文件都被加个强命名,其保护强度也是很一般的。我们只须编写程序自动去除每个文件的本身强命名定义与AssemblyRef中的强命名定义(注意,不要把系统文件包含在内),就可以很方便地进行修改。因此,用StrongName做为程序的保护手段实在是不可取,还应另寻别路。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 乐视1s玩王者荣耀卡怎么办 京东商城买东西发现地址错了怎么办 京东分期付款买手机额度不够怎么办 亮皮银色高跟鞋时间放久变色怎么办 饿了么商家钱包提现被锁了怎么办 在淘手游买的游戏账号被找回怎么办 交易猫买手游梦幻号被找回了怎么办 绑定着苹果账号的邮箱忘记了怎么办 京东注册账号跟密码都忘记了怎么办 孩子大学一个宿舍宿友不行怎么办 微信手机支付密码忘记了怎么办 微信公众号不能付款了怎么办 头条误点了投放头条广告怎么办 交行网银密码错误6次怎么办 宁波新冮厦关门我们的消费卡怎么办 第一天上班别人教的学不会怎么办 老公出轨已经不想跟你爱爱了怎么办 妻子出轨丈夫为了孩子不离婚怎么办 妻子出轨分居死也不愿意离婚怎么办 拼多多个人卖家登录密码忘了怎么办 微信被限制添加更多订阅号了怎么办 知网复制粘贴的论文有格式怎么办 知网论文查询网站密码忘记了怎么办 开通了超级会员不能克隆好友怎么办 偷了家里好多钱去买手机了怎么办 中行信用卡短信邀请办白金卡怎么办 注册邮箱说邮箱地址已被注册怎么办 便利店开在小区里面没生意怎么办 微信支付密码忘了怎么办没银行卡 中行5月扣很多钱是怎么办 中银淘宝校园卡影响征信问题怎么办 中银E盾快到期了怎么办 京东e卡电子卡卡密泄漏怎么办 买错了京东e卡怎么办 京东购买手机激活后有问题怎么办 优购m9锁屏密码忘记了怎么办视频 中百仓储的购物卡过期了怎么办 武汉中百超市购物卡过期怎么办 已认证抵扣的发票发生退货怎么办 京东白条分期买手机额度不够怎么办 京东白条闪付手机不支持开通怎么办