一、开篇

  首先写在前面,这篇文章源于个人的研究和探索,由于.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. 《UML大战需求分析》阅读随笔(六)

    在我们做的代码设计中分为系统设计和程序设计.程序设计是系统设计中模拟程序的执行逻辑,定义客户机服务器对象合作的框架的那个部分.程序和事务设计中,作者讲述到程序和事务设计将系统设计制品放在一起,并作为系 ...

  2. IDA的脚本IDC的一个简单使用

    目的:主要是想学习一下IDA的IDC的脚本的使用.这里做了一个小的测试. 这里使用的是VS2015Community来生成文件的. 一.编写测试程序: 这里先生成我们的目标数据. 然后编写测试程序.得 ...

  3. C# Current thread must be set to single thread apartment (STA) mode before OLE calls can be made

    将箭头指向部分替换为编译器报错的内容即可. 参考文章:https://www.experts-exchange.com/questions/28238490/C-help-needed-Current ...

  4. Unreal4教程总结

    一些好的教程分享 Ue4大神的博客 http://www.tomlooman.com 关于CustomDepth的文章的翻译 http://gad.qq.com/program/translatevi ...

  5. 添加ssh key

    我现在根据<github入门和实践>来去摸索github 其实,我发现自己在看github时,感觉不适应,是因为自己太久没有碰到英文了.可以联想到以前当看到一个网页,根据汉字的标题或描述, ...

  6. js 逻辑或

    逻辑或操作符由两个竖线来表示||,属于短路操作符,也就是说,如果第一个操作数的求职结果为true,就不会对第二个操作数进行求值 var found = true; var result = found ...

  7. 伪类before和after

     以你添加的元素为基础!在他的里面!也就是他的内容的前面或者后面添加东西!  如果原来的元素没有内容会出现什么情况?(伪类的宽和高和元素的相等)

  8. CODEVS 天梯 代码记录

    所有水题均被折叠 Lv.1 青铜 1201 #include<iostream> #include<cstring> #include<algorithm> #in ...

  9. [基础技能] 安全技术——哈希算法密码破解之彩虹表(Rainbow Table)学习

    1.基础知识 刚刚学习过数字签名的相关知识,以及数字签名的伪造技术,而伪造数字签名归根结底就是密码破解的一个过程,然而直接破解的速度是非常缓慢的,所以有人想出一种办法,直接建立出一个数据文件,里面事先 ...

  10. SPOJ FASTFLOW网络流水题

    Dinic=bfs+dfs  = = 用bfs算出到原点的最短路径(每条残存都算1) 然后每次都跑两端只差1的路径跑dfs,并且一直跑到不能跑 一个优化:如果一个点流出的量已经到流入量了就可以返回上一 ...