admin 发表于 2020-3-10 15:38:57

使用ILAsm与ILDasm修改.Net exe(dll)文件

内容预览:
[*]下面将会用示例代码讲解如何修改已经的.exe文件~
[*]二、ILAsm与ILDasm 我们知道,.net是一个跨平台的的开发平台,其跨平台...~
[*]通过这个例子,大家应该对代码被篡改的风险也有一定的认识了,所以如果...~


一、背景
最近项目组新上项目,交付的时间比较急迫,原本好的分支管理习惯没有遵守好,于是出现下面状况:

[*]多个小伙伴在不同的分支上开发。

[*]原本QA环境也存在一个阻碍性的bug A

[*]一位同事在QA环境发布了新的代码,引入了新bug B

[*]回滚QA能修改bug B,但是对于bugA却无能为力

[*]同时,混乱的代码管理已经导致无法确定原始发布包对应的代码版本。


最终陷入了两难的地步,既不能发布新包,回滚也无法解决问题。好在之前了解到如何使用微软官方工具ILAsm与ILDasm对dll文件进行修改,于是开始动手实现。下面将会用示例代码讲解如何修改已经的.exe文件。
二、ILAsm与ILDasm
我们知道,.net是一个跨平台的的开发平台,其跨平台则是由其编译的中间语言(Intermediate Language, 简称IL或MSIL)实现,无论我们使用的是C#、VB.Net、还是F#或者C++, 最终都会被编译成IL,由JIT(Just In Time)编译成目标机器语言,在CLR(Commen Language Runtime, 公用语言运行时)上运行。
因此,理论上,我们可以跳过过平时使用的C#代码,直接修改IL,然后生成相应的dll或者exe文件。
那么如何查看与修改IL呢,这就是ILAsm与ILDasm的工作了。ILAsm (MSIL Assembler),用来从IL语言生成PE(Portable Executable),也就是.net中我们使用的.exe、.dll文件。ILDasm (MSIL Disassembler),则与ILAsm相反,从PE文件,生成.IL文件。那么我们可以猜到,要修改dll,我们需要先用ILDasm反编译.dll生成.il文件,再用ILAsm编译修改后的.il文件生成.dll,最终替换.dll文件。
三、使用ILDasm生成IL
先看下示例代码:
```
class Program
{
    static void Main(string[] args)
    {
      var loginResult = Login("foo", "111111");
      if (loginResult)
      {
            Console.WriteLine("登录成功");
      }
      else
      {
            Console.WriteLine("登录失败,请重试");
      }
      Console.ReadLine();
    }
    private static bool Login(string userName, string password)
    {
      if (userName.Equals("johnny") && password.Equals("123456"))
      {
            return false;
      }
      return false;
    }
}
```
显示上述代码针对Login(string userName, string password)的调用会返回false,导致最后Console中会输出“登录失败,请重试”, 我们的目的是通过直接修改.exe文件,让它返回true, Console里面输出“登录成功”。ILDasm与ILAsm已经包含在Visual Studio发行包中中,无需另外下载安装。按如下步骤执行即可:1. 开Developer Command Prompt for VS 2017,在里面输入命令ILDasm。2. 在打开的IL Dasm窗口中找到需要修改的.exe文件。3. 选择菜单 File > Dump,弹出的新窗口中点击确认,保存生成的.il文件。
整个过程如下面gif所示:https://www.01hai.com/wp-content/uploads/2018/04/5ac2445abb981.gif
最后会生成相应的.il与.res文件。https://www.01hai.com/wp-content/uploads/2018/04/5ac2445ae8f2f.png
四、修改IL
打开.il文件,会看到如下代码(节选)
.method private hidebysig static boolLogin(string userName,
                                             string password) cil managed
{
    // Code size       43 (0x2b)
    .maxstack2
    .locals init ( bool V_0,
             bool V_1)
    IL_0000:nop
    IL_0001:ldarg.0
    IL_0002:ldstr      "johnny"
    IL_0007:callvirt   instance bool System.String::Equals(string)
    IL_000c:brfalse.sIL_001b

    IL_000e:ldarg.1
    IL_000f:ldstr      "123456"
    IL_0014:callvirt   instance bool System.String::Equals(string)
    IL_0019:br.s       IL_001c

    IL_001b:ldc.i4.0
    IL_001c:stloc.0
    IL_001d:ldloc.0
    IL_001e:brfalse.sIL_0025

    IL_0020:nop
    IL_0021:ldc.i4.0
    IL_0022:stloc.1
    IL_0023:br.s       IL_0029

    IL_0025:ldc.i4.0
    IL_0026:stloc.1
    IL_0027:br.s       IL_0029

    IL_0029:ldloc.1
    IL_002a:ret
} // end of method Program::Login
这个就是Login(string userName, string password)所对应的IL代码了。如果你了解IL语言,可以直接对其修改。如果不想直接修改IL,我们可以重写一个小的示例方法,直接return true,如下:
private static bool Login()
{
    return true;
}
然后使用ILDasm生成相应的IL代码,替换我们想修改的方法。最终的IL如下:
.method private hidebysig static boolLogin(string userName,
                                             string password) cil managed
{
    .maxstack 8

    IL_0000: ldc.i4.1   
    IL_0001: ret         

} // end of method Program::Login
五、使用ILAsm生成
修改保存完.il文件以后,接下来的工作就是利用 ILAsm 让.il文件生成重新生成.exe可执行文件了,在Console中执行如下命令
ilasm ILAsmAndILDasmDemo.il /output:ILAsmAndILDasmDemo_1.exe
// 如果修改的是dll文件,需要加上参数 /dll

https://www.01hai.com/wp-content/uploads/2018/04/5ac2445b123d7.png
成功以后会生成一个ILAsmAndILDasmDemo_1.exe文件,执行这个文件,我们可以看到,现在已经显示“登录成功”了。https://www.01hai.com/wp-content/uploads/2018/04/5ac2445b3fea1.pnghttps://www.01hai.com/wp-content/uploads/2018/04/5ac2445b65ce5.png
使用反编译工具 dotPeekI查看新生成的ILAsmAndILDasmDemo_1.exe文件,我们能够看到,Login(string userName, string password)已经直接return true了。如下图,https://www.01hai.com/wp-content/uploads/2018/04/5ac2445b9a69d.png
六、总结
其它,上面所做的事情其实也是《CLR via C#》中提到强名能够 防止代码被不怀好意的人篡改 的一个反面教材了。通过这个例子,大家应该对代码被篡改的风险也有一定的认识了,所以如果大家需要将自己的.dll(.exe)文件露给别人,最好还是打上强名,防止别人恶意篡改你的代码,导致不必要的损失。
经过这次事件,也证明了多了解下底层还是很有必要的,说不定哪天就用上了。平时再忙,也不能只限于只业务和编程语言层面,还需要对底层有一定的了解,这样才能知其然与知其所以然。
虽然修改dll在不修改c#代码的情况下完美解决QA的环境问题,但是这种方法也只限于小范围的改懂,只能用来救急。所以给我的教训是分支管理规范才是王道,要能做到随时可发布,随时可回滚才行,这样才能完全避免再次出现这样尴尬的情况了。
页: [1]
查看完整版本: 使用ILAsm与ILDasm修改.Net exe(dll)文件