一、开篇

  首先写在前面,这篇文章源于个人的研究和探索,由于.NET有自己的反射机制,可以清楚的将源码反射出来,这样你的软件就很容易被破解,当然这篇文章不会说怎么样保护你的软件不被破解,相反是借用一个软件来讲述是怎么被攻破的,也会有人说这是一篇破文,我其实这篇文章已经写了很长时间了,不知道以什么形式发出来,因为毕竟是有些破解类的东西。但是我觉得从这篇文章相反的是能够带来一些启发。大家应该都知道Reflector这个反编译软件还有一个插件是专门用来改IL的插件叫Reflexil,这里我们也要用到前面那个工具Reflector,后面的插件我们这里我们不用,接下来分析的东西可以让大家能够更深入.NET的PE,深入内幕来看看,好,闲话少说….直接上分析。

二、详细分析过程

  如果不懂.NET的PE文件结构的帅哥美女,可以看一下上一篇文章http://www.cnblogs.com/dwlsxj/p/4052871.html,这里要用到PE的知识,首先我们来看一下这个程序的限制,这个程序有显示限制也就是显示的列表只能显示三行。如下图所示:

  我们现在要用Reflector工具将我们要破解的程序反编译一下看一下哪里没有跳转到MessagBox弹出对话框了!反编译成C#代码后我们可以看到这个程序就一个主界面,看到了Form名字就说明这个是一个Windows的窗体:

  点开之后,就发现ProgressChanged方法里面有内容,里面包含了弹出消息框的全部代码,好的我们这里就确定了是这个方法让这个消息框弹出来的!的确他就是罪魁祸首,先记录备案。

  现在已经知道是哪个方法弹出消息框来了,那么我们就可以再元数据表中进行查找该方法所在的RVA,这里我要讲一个元数据表中的表这个表就是MethodDef表,这个表很重要也很好玩,这个表里不但指出了该方法的IL代码的位置,还限定了方法的属性。下面来看一下表结构:

偏移

大小

名称

说明

0

4

RVA

该方法体的RVA(方法体包括:方法头、IL代码、异常处理定义)

4

2

ImplFlags

限定了方法的执行方法(如abstract、P/Invoke)

6

2

Flags

先顶了方法的调用属性和其他的一些性质

8

2(4)

Name

指向#String的偏移,表示该方法的名称

2(4)

Signature

指向#Blob的偏移,Signature定义了方法的调用方式(如返回值类型等)

2

ParamList

指向Param表的索引,指出了方法的参数

  看到上面这个表不禁让我开心,因为我能找到这个方法存放的位置,也就是我需要的是这个RVA的地址,那么这个方法的RVA是多少呢?带着疑问思考,我们会想到用到一个工具来帮助我们查找这个方法到底在Method的第几个,这里不讲直接打开CFF也可以看到这个方法。我要曲折的找一下。打开ILDASM,既然.NET里面有元数据这个一号人物,我们就来小窥一下元数据表,该方法的元数据肯定在里面。

  果然不出我们所料,确实在元数据里面有描述,因为元数据是描述数据的数据,那么我们就拿到了这个Token标示:0600001F,可以翻回到上一篇文章找一下这个对应的表是MethodDef正还是我们想要的,在这个表下的第31的位置就是我们要找的内容,怀着疑问打开CFF软件,来证实一下我们找的没有错!!!

  经过证实是我要找的ProgressChanged方法在元数据表中的描述,现在就可以取出关键信息ProgressChanged方法的RVA:0x3184

  通过CFF查看一下区块的内容:

  可以正确的观察到该方法的RVA存放在.text区块中,因为该区块的范围是:2000~14A00,而3184正好落在了这段地址当中,好,接下来就可以算出该代码在物理地址了:3184-2000+200=1384,好的,0x1384就是我们要在文件中查找的的物理地址。这时候打开16进制编辑器,将程序载入到16进制编辑器中。CTRL+G搜索0x1384这个地址,下面是我们搜到的地址:

  你们会疑问我怎么知道这么一段就是这个方法的代码呢?让我来揭晓这个谜底。OK,RVA我们算的肯定没错,也就是开始位置1384这个肯定是没错的,但是代码的长度不是很确定对吧?好,打开ILDASM找到这个方法就知道这个方法的长度,或者是在这个方法的头部我们就可以确定这个方法的长度。

  验证结果的时候到了通过ILDASM来验证下:

  通过上述结论我们可以证实确实是存放的IL的代码,我们可以看到上面有一个开始指令,是我标记的这个开始指令的IL代码是ldarg.2加载方法参数2到堆栈上。这里不看他的个什么东东!我们只要知道他的Opcode是多少就好了这个指令的Opcode是04,那么我们就在上面的16进制编辑器中进行搜索:

  意思就是04这个指令的前面都是在做初始化堆栈和初始化参数的操作,而从04开始才是真正执行代码。好的开始的指令已经找好了,我们就要看一下我们要修改那段代码了,先观察这段比较num--==0这里,注意这里修改代码的时候不能破坏代码的长度和代码的堆栈平衡原理。我们想如何能让这个条件永远不成立,OK,我想到了一个方法就是不让这个参数进行减法操作,让他一直进行加法操作!首先先小窥一下的他的IL代码我们开讲一下整体IL的实现,这里只讲num--==0处的代码:

代码详细讲解如下:

  IL_002f:  ldloc.3           //加载3到堆栈上。

  IL_0030:  dup               //复制栈顶数据

  IL_0031:  ldc.i4.1          //加载1到堆栈上

  IL_0032:  sub               //3-1的操作。

  IL_0033:  stloc.3           //保存到局部变量3中这是由原来的3变成了2

  IL_0034:  ldc.i4.0          //加载变量0到堆栈

  IL_0035:  ceq               //于O比较后的结果放在堆栈上(返回0或1)    IL_0037:  ldc.i4.0           //因为我们比较后的结果为0或1所以在压入一个0后面进行比较false(ceq从堆栈弹出两个参数)

  IL_0038:  ceq

  IL_003a:  brfalse    IL_0113//条件成立跳到消息框

  OK分析到这里,这段指令的sub指令是我们的关键,我们要将这个指令改为Add就可以实现了,对应的Sub的Opcode是59,而对应AddOpcode是58这样我们把59变成58再把16进制另存一份就可以实现所有功能了。

  改好后我们来看一下效果如何吧!!!

  其实我们看似Reflexil简简单单的修改了一个指令的值,其实背后做了大内容,比如要对区块的RVA进行修正,就当前的方法的RVA的修改以及所有方法的修改等操作。这块就不多说了有兴趣的自己研究下!

三、结束语

  这东西虽然看着没有Reflexil来得快但是能让你更深入的了解.NET的PE结构,小弟再次声明本文章只是为了研究技术,没有用做商业用途,为了支持正版我已经将标题遮挡住了,通过上述的文章,我有点小小的想法,就是我们可以讲我们需要加密的方法体抽出来,当jit调用时再进行还原这样就会对程序的安全性有一个提升。这里只是我自己的个人看法,还请各位大牛指点小弟,小弟在此谢过了。

再探.NET的PE文件结构(安全篇)的更多相关文章

  1. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

  2. COFF/PE文件结构

    COFF/PE文件结构 原创 C++应用程序在Windows下的编译.链接(二)COFF/PE文件结构 2.1概述 在windows操作系统下,可执行文件的存储格式是PE格式:在Linux操作系统下, ...

  3. PE文件结构及其加载机制

    一.PE文件结构 PE即Portable Executable,是win32环境自身所带的执行体文件格式,其部分特性继承自Unix的COFF(Common Object File Format)文件格 ...

  4. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  5. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  6. PE文件结构详解(六)重定位

    前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里 ...

  7. PE文件结构详解(五)延迟导入表

    PE文件结构详解(四)PE导入表讲 了一般的PE导入表,这次我们来看一下另外一种导入表:延迟导入(Delay Import).看名字就知道,这种导入机制导入其他DLL的时机比较“迟”,为什么要迟呢?因 ...

  8. PE文件结构详解(四)PE导入表

    PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPO ...

  9. PE文件结构详解(二)可执行文件头

    在PE文件结构详解(一)基本概念里,解释了一些PE文件的一些基本概念,从这篇开始,将详细讲解PE文件中的重要结构. 了解一个文件的格式,最应该首先了解的就是这个文件的文件头的含义,因为几乎所有的文件格 ...

随机推荐

  1. 数据分析(8):Series介绍

    Series Series由一组数据及索引组成 索引 采用默认索引 data = pd.Series([4, 3, 2, 1]) 自定义索引 data = pd.Series([4, 3, 2, 1] ...

  2. Spring MVC重定向和转发及异常处理

    SpringMVC核心技术---转发和重定向 当处理器对请求处理完毕后,向其他资源进行跳转时,有两种跳转方式:请求转发与重定向.而根据要跳转的资源类型,又可分为两类:跳转到页面与跳转到其他处理器.对于 ...

  3. Drools 函数学习

    Drools 函数学习 函数是定义在规则文件当中一代码块,作用是将在规则文件当中若干个规则都会用到的业务操作封装起来,实现业务代码的复用,减少规则编写的工作量.函数的编写位置可以是规则文件当中 pac ...

  4. InnoDB还是MyISAM 再谈MySQL存储引擎的选择

    两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...

  5. 从vue1.0到vue2.0遇到的一些问题的记录

    1.取消v-el的使用方式,改为refs使用 获取指定的dom元素 html:<div ref="div"></div> js: $refs.div 问题: ...

  6. .NET开发人员必看:提高ASP.NET Web应用性能的24种方法和技巧

    那性能问题到底该如何解决?以下是应用系统发布前,作为 .NET 开发人员需要检查的点. 1.debug=「false」 当创建 ASP.NET Web应用程序,默认设置为「true」.开发过程中,设置 ...

  7. $event 获取对象

    用Angular给元素添加事件时获取可以用 $event 传递当前触发的事件的元素对象 页面上可以这样写 <img ng-src="" alt="" ng ...

  8. SQl 2005 For XMl 简单查询(Raw,Auto,Path模式)(1)

    很多人对Xpath可能比较熟悉,但不知道有没有直接操作过数据库,我们都知道 在Sql2005里公支持的几种查询有Raw,Auto模式,页并没有Path和Elements用法等,如果在2000里使用过 ...

  9. Linux系统学习优缺点

    Linux是一套操作系统,按照鸟哥的说法Linux提供了一个完整的操作系统当中最底层的硬件控制与资源管理的完整架构,这个架构是沿袭Unix良好的传统而来的,功能强大而且稳定性卓越.其实Torvalds ...

  10. BZOJ4742 : [Usaco2016 Dec]Team Building

    如果我们将两个人拥有的牛混在一起,并按照战斗力从小到大排序,同时把第一个人选的牛看成$)$,第二个人选的牛看成$($的话,那么我们会发现一个合法的方案对应了一个长度为$2k$的括号序列. 于是DP即可 ...