原文:.Net反编译实战

当你面对一个已经部署好的网站,功能,性能都非常不给力的时候,你会怎么办?

当你尝试去了解这个网站业务逻辑,代码逻辑和数据库逻辑时却发现根本没有任何资料时你会怎么办?

当你准备去修改这个程序却发现根本木有源代码而只有一堆堆的DLL和aspx的时候,你会怎么办?

当你发现这个网站配置及其复杂,只有一个线上环境而且处处是坑的时候,你会怎么办?

当你面对一个要求严格的领导,心怀一切皆有可能的思想时,准备让你对此进行优化和功能修改时,你会怎么办?

重构?罢工?辞职?

不错,是个选择!

要是那样的话,就不会有这篇文章了亲。

所以,只有硬着头皮干下去。。

言归正传,首先介绍几款神器:

1.Reflector ——.Net反编译工具

  我用的是8.0的破解版,支持直接运行和以VS插件形式运行,测试表示以VS插件的形式速度比较慢,容易将VS卡死,所以不推荐。

2.Ilasm和ildasm——微软自带的编译和反编译工具

  这两款工具是Framework自带的,虽然界面不是很华丽,但是功能还是很给力的。

3.Reflexil——一款Reflector插件

  相当给力,可以通过界面的形式对DLL中的类,方法,属性等进行修改和注入

有了几款神器,下面就是如何对一个DLL进行开刀了。

首先,在不清楚DLL作用的情况下,可以先通过aspx页面找一些线索。

<%@ Page Language="C#" MasterPageFile="Template/LogonMasterPage.Master" AutoEventWireup="true" Inherits="Logon" Codebehind="Logon.aspx.cs" %>

如页面顶部Inherits表示的是这个页面 定义供页继承的代码隐藏类,在DLL中搜索这个类可以找到该页面的一些后台代码逻辑。

结合aspx的服务器控件的事件可以找到对应的实现。

找到了对应的C#代码,是时候对其进行大显身手了。

此时的需求可能有如下几个:

  1. 修改某一个变量的值(如某个SQL语句字符串)
  2. 修改某一个方法的具体实现逻辑(如修改某一个按钮点击后做的一些事情)
  3. 在原有的逻辑中,补充插入自己的新方法或程序中已有的方法。
  4. 其他未想到的需求。。

下面挨个解决。

1.修改变量的值。

这类问题应该是最简单的一类问题,在我最初没有发现神器插件的时候,用了这样一种相对复杂的方法去做的。

当时的需求是修改程序中的一个执行较慢的SQL语句,也就是改某个字符串的值。

首先我用Reflector查看到相应的方法代码(C#代码),也就是我要修改的那个字符串所在的方法。然后在Reflector工具的上方有个下拉菜单

该菜单可以查看对应该方法C#代码的IL代码,这就给我们这些看不太懂IL代码的童鞋们一些希望了。通过IL视图,我们能够查看到这个方法的IL代码是类似这样的:

由于微软提供的工具可以支持DLL与IL代码的相互转化,那么我们就可以通过修改原始IL代码来重新生成DLL实现修改DLL的目的!那么该如何去做呢?

首先打开ildasm工具,该工具所在的位置大致是:

C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin

打开后将DLL文件拖进去,即可查看该DLL的一些结构:

其中展开可以看到某一个方法的IL代码。

通过该工具可以将DLL转储为IL代码文件,操作是:文件->转储

接下来通过文本编辑器可以查看il文件,由于刚才我们已经通过Reflector定位到了某个方法的IL代码,通过搜索il代码,可以比较容易的找到。(后来又发现了一个更好的方法,由于Reflector工具和微软的工具是两款工具,生成的IL有一些细微的差别,更好的做法是通过ildasm查看到需要修改的方法的原始IL代码,再在文本编辑器里搜索)

接下来就是修改具体的代码了,字符串啊,想改成什么就改成什么,即使我们看不太懂IL命令。

修改后需要重新编译回DLL文件,这就需要请出我们的又一个神器ilasm了,这是一个需要用命令行运行的工具。运行方法是:

//先要找到.net具体版本下的这个目录。

cd C:\Windows\Microsoft.NET\Framework\v2.0.50727

//执行转换操作

ilasm c:\test.il /output=c:\test.dll /dll

意思是将C盘下的test.il文件输出成test.dll文件,没有错误的话就可以成功生成。

PS:有时候还需要将转储后的其他相关文件一起拷贝过来才能成功生成DLL。

2.修改某一个方法的具体实现逻辑

这个就相对有点复杂了,不同情况有不同的处理方式,需要用到一些小技巧。

  1. 修改方法体相对简单的方法。

这种情况只需要Reflector插件就可以搞定了,因为该插件有一个给力的功能就是能以C#视图去修改某个方法的IL代码。有图有真相:

在IL代码中右键 Replace all…可以打开一个C#代码编辑器:

该编辑器中左侧是C#代码,右侧是如果编译成功会显示的IL代码。

这个编译器有几点使用心得:

  1. 需要修改的方法,打开后默认变成空的了。所有如果是小改动,需要提前复制好代码。
  2. 代码中使用的对象除了C#基本的数据类型外,一般都需要写全限定名称。如DataTable dt就应该写成:System.Data.DataTable dt,否则不会编译通过。
  3. 对于引用了外部程序集中的对象,需要自己手工在#region " Imports "中自行添加using了哪个程序集。
  4. 基本修改后尝试点击左下角的编译按钮,如果报错的话,定位到下面的字段说明中,可以把报错的那行注释掉。
  5. 编译通过后,记得把这段代码保存起来,因为下次一旦再修改这段代码,就不用重新改了,省去了一些时间。

修改后点击左侧树形目录的那个程序集,右键,save as,如果不报错,OK,搞定!

  2.修改方法体相对复杂的方法。

对于这种修改,上述方法很可能不容易编译通过,因为牵连的东西比较多,所以……

需要将原程序段中的方法调用,改为一个新的方法调用。(新方法如果和旧方法差异不大的话可以把旧方法进行一个“克隆”)新的方法可以是自己新建DLL中的一个方法(最好是静态方法),而且保险起见,新方法的参数类型和名称尽量和旧方法一致,便于直接修改IL。

调用自己的方法,需要先将自己的DLL拖入Reflector中关联起来。然后在IL视图里找到调用旧方法的那一段(IL表格中的那一行),右键编辑,进行修改。修改时对于调用静态方法使用call指令,具体的方法可以在不同DLL中进行选择。

如图:

之后进行保存就可以了。

如果是对原有方法进行的简单修改,可以采用“克隆”的方法进行操作。

所谓克隆,就是用工具像原有dll中注入一个新的方法。

注入方法时,输入方法名即可,确定后不会立刻看到该方法,需要将DLL保存后,重新加载才能看到。

重新加载后,看到的新方法默认是Void的,而且不带任何参数,这和我们克隆的目标方法可能不太一样,所以,还需要改一下参数和返回值类型以及其他相关属性,修改的方法是比较修改法。即在克隆方法的选项卡中依次比较每一个选项,修改成和目标方法一模一样的新方法。

修改新方法的各个属性。

再次保存。即可克隆出一个方法签名类似的新方法。

接下来就是克隆方法体了,这里还有个技巧,如果方法简单,直接通过C#视图就可以将原方法体粘贴进去,编译。

如果方法体复杂,则需要通过之前提到的微软工具进行IL代码的移植。即,复制原方法的IL代码实现,粘贴到克隆方法的方法体中。

这些操作中可能会遇到的一些注意事项:

添加方法时的参数可参考已有方法的参数界面进行选择,其中System下的对象在microlib.dll里。

il编译不通过可以增加Using,下面字段里不要添加自己的对象,否则无法生成dll(可以把属性用私有成员替代!)

使用C#视图无法调用新注入的函数时,可以先克隆一个原有函数(函数头一样的),然后再使用IL视图的Edit功能把旧方法换成克隆后的方法。最后再修改克隆后的实现。

每次增加新方法,需要更新关联的DLL

Clone方法头可以使用reflecxil工具,克隆复杂的方法体,可以使用微软IL工具,查看到具体的方法的IL代码,复制。然后用文本编辑器找到Clone的方法体,粘贴。重新编译。

此外还可以尝试修改类成员的访问权限,如改成public,注入其他成员等。

除了在DLL中下手调用新的方法,还可以直接通过aspx页面进行修改。

步骤大概是:

  1. 准备一个需要调用的方法(自己的DLL中)
  2. 在aspx页面头添加对自己dll的引用
  3. 实例化自己dll的类的一个对象
  4. 调用自己的方法(页面级调用)
  5. 页面级输出一些结果(如表格数据之类)

具体的操作是:

.Net反编译实战的更多相关文章

  1. 设计模式课程 设计模式精讲 8-8 单例设计模式-Enum枚举单例、原理源码解析以及反编译实战

    1 课堂解析 2 代码演练 2.1 枚举类单例解决序列化破坏demo 2.2 枚举类单例解决序列化破坏原理 2.3 枚举类单例解决反射攻击demo 2.4 枚举类单例解决反射攻击原理 3 jad的使用 ...

  2. java7(1)——反编译深入理解增强的switch(读字节命令实战)

    [本文介绍] 本文主要讲java_7 的改进switch的底层实现.反编译一个使用带String的switch的demo并一步步解析反编译出来的字节命令,从编译的角度解读switch的底层实现. [正 ...

  3. 一次.NET项目反编译的实战经验(WinForm)

    最近由于业务需求,需要对一个老项目进行功能调整.但是项目的源代码已经找不到了.所以只能尝试对项目行进反编译. 一.反编译工具的选择 提到.NET的反编译,第一个想到的就是大名鼎鼎的Reflector. ...

  4. Android 应用程序的反编译

    1.ApkTool工具 安装ApkTool工具,该工具可以解码得到资源文件,但不能得到Java源文件.安装环境:需要安装JRE1.61> 到http://code.google.com/p/an ...

  5. 【转】反编译获取任何微信小程序源码(完)

    一.前言最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了一个阿里妈妈淘宝客小程序的前端实现,过程一言难尽,差不多两周时间过去了,发现小程序的坑远比想象的要多的多!!在实际练手 ...

  6. class-dump 反编译私有的库和应用

    一.下载并安装class-dump 下载class-dump-3.5.dmg  点击下载 下载完成以后双击.dmg的文件,将里面的class-dump拷贝到/usr/local/bin 设置权限chm ...

  7. 反编译.NET工程

    工具:       1.  .Net Reflector       2.   远程桌面 步骤: 1. 远程桌面连接到服务器 IP,port,user,pwd 2. 打开 IIS 这里面就是所部属的网 ...

  8. 将JAR包反编译,修改后重新打包(转)

     将JAR包反编译,修改后重新打包(转)   在学习和开发JAVA项目中,我们经常会用到第三方提供的一些jar.使用这些第三方工具包,可以提高我们开发的效率,缩短开发的时间.有的第三方工具,提供具体的 ...

  9. 反编译apk

    一.反编译Apk得到Java源代码 首先要下载两个工具:dex2jar和JD-GUI 前者是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工具,可以直接查看Jar包的源 ...

随机推荐

  1. python学习笔记--for循环

    推荐一个学习语言的网站:http://www.codecademy.com 有教程,可以边学边写,蛮不错的. for循环: 1.for loops allow us to iterate throug ...

  2. docker 现实---中小企业docker环境结构(五)

    docker对于中小企业,设定paas他没有足够的能量,没有必要为,个人二手sandbox实用性和小点.我个人觉得,中小企业可以使用docker要规范发展.测试.生产环境. 他画了一个简单的图表: d ...

  3. android选择和裁剪图像拍摄的图像

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/39994913 近期从曾经的项目中扒下来一个经常使用的模块.在这里有必要记录一下的. ...

  4. ES6箭头函数和它的作用域

    原文来自我的前端博客: http://www.hacke2.cn/arrow-functions-and-their-scope/ http://es6rocks.com/2014/10/arrow- ...

  5. MySQL在大数据Limit使用

    它已被用于Oracle一世.但今天,很惊讶,MySQL在对数量级的性能,甚至差距如此之大不同的顺序相同的功能. 看看表ibmng(id,title,info)  只要  id key 指数title ...

  6. Portal.MVC

    Portal.MVC Portal.MVC 简介 项目是基于MVC4+EF,带有角色,权限,用户中心及账户相关(登录,注册,修改密码,找回密码等)等基本功能.参考的开源项目nopcommerce,这是 ...

  7. 怎样配置nginx同一时候执行不同版本号的php-fpm

    在/usr/local/php/etc/php-fpm.conf里找到 listen = 127.0.0.1:9000 将port9000改动为9001 在对应的nginx配置里也做相同的port改动

  8. Android实战技术:IPC方式简介教程

    非实时,通知性的方式 第一种方式就是Intent,Intent可以非常方便的通讯,但是它是非实时的,无法进行实时的像函数调用那样的实时的通讯. 实时的函数调用 但是IPC的根本目的还是为了实现函数的调 ...

  9. easyui LinkButton

    http://www.zi-han.net/case/easyui/menu&button.html

  10. 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)

    写在前面: Java SE5 提供了一种新的类型 Java的枚举类型,关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能 ...