博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符串反混淆实战 Dotfuscator 4.9 字符串加密技术应对策略
阅读量:4983 次
发布时间:2019-06-12

本文共 5558 字,大约阅读时间需要 18 分钟。

因为手头需要使用一个第三方类库,网络上又找不到它的可用的版本,于是只好自己动手。这个类库使用了Dotfuscator 加密,用.NET Reflector加载程序集,

看到的字符串是乱码,如下面的代码例子所示:

internal class Program{    // Methods    private static void Main(string[] args)    {        int num2 = 4;        try        {            List
expressionStack_51_0; string expressionStack_51_1; List
expressionStack_3C_0; string expressionStack_3C_1; int expressionStack_12_0 = 1; if (expressionStack_12_0 == 0) { } string exePath = args[0]; List
list = ReadAllUserStrings(exePath); if (CS$<>9__CachedAnonymousMethodDelegate1 != null) { expressionStack_51_1 = exePath + b("䱡ၣṥᱧ", num2); expressionStack_51_0 = list; goto Label_0051; } else { expressionStack_3C_1 = exePath + b("䱡ၣṥᱧ", num2); expressionStack_3C_0 = list; } string expressionStack_3E_1 = expressionStack_3C_1; List
expressionStack_3E_0 = expressionStack_3C_0; CS$<>9__CachedAnonymousMethodDelegate1 = str => CSStringConverter.Convert(str); expressionStack_51_1 = expressionStack_3E_1; expressionStack_51_0 = expressionStack_3E_0; Label_0051: File.WriteAllLines(expressionStack_51_1, expressionStack_51_0.Select
(CS$<>9__CachedAnonymousMethodDelegate1)); Console.WriteLine(b("੡ୣብݧᱩͫ䁭幯山味", num2)); } catch (Exception exception) { Console.WriteLine(b("❡ᱣե൧ᩩᡫݭὯᱱ乳噵", num2) + exception.ToString()); Console.WriteLine(b("ቡᙣͥ᭧ᥩ䱫཭偯ᥱᅳཱུ噷呹剻", num2)); Console.ReadKey(); } }

初步判断是应用了字符串混淆技术。网上可以找到的一个反加密的算法,代码如下所示

static string GetString(string source, int salt) {     int index = 0;     char[] data = source.ToCharArray();     salt += 0xe74d6d7; // This const data generated by dotfuscator     while (index < data.Length)     {         char key = data[index];         byte low = (byte)((key & '\x00ff') ^ salt++);         byte high = (byte)((key >> 8) ^ salt++);         data[index] = (char)((low << 8 | high));         index++;     }     return string.Intern(new string(data)); }

套用一下这个方法,没有解密成功,得到的仍然是乱码。如果你有读过我昨天发布的文章”“,就相当于我已经解决了这个问题。但是,我想把这个思路解释一下,以至不忘。

第一个知识点是关于多模块。现在Visual Studio编译生成的程序集,一个程序集只能有一个模块,但是用命令行的CSC可以生成有多个模块的程序集文件。因为C#中不能给模块添加全局方法,也不能添加全局变量,但是MSIL可以做到这一点。MSIL可以添加完全不依赖于任何类型的全局方法。下面的代码演示了如何添加全局方法和全局变量:

.assembly extern mscorlib { auto }.assembly MyApp {}.module MyApp.exe.namespace MyApp{  .class public auto ansi Program extends [mscorlib]System.Object  {    .method private static void Main(string[] args)     {      .entrypoint      call void Test()      ret     }  }}.field assembly static int32 x.method private hidebysig specialname rtspecialname static void .cctor(){  ldc.i4 1234  stsfld int32 x  ret}.method public static void Test(){  ldsfld int32 x  call void [mscorlib]System.Console::WriteLine(int32)  ret}

MSDN论坛中有一个关于如何调用模块中的方法的,地址是的

那么,如何调用这个全局方法呢,请参看下面的代码:

Assembly assembly = Assembly.LoadFile(file);MethodInfo methodInfo = assembly.GetModules()[0].GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)[0];object result = methodInfo.Invoke(null, new object[] {allUserString, key});

 

用.NET Reflector加载程序集,可以看到,模块下面有一个静态方法

 

于是,要借助于MSIL的知识才可以做到生产多模块的程序集,来看一下Dotfuscator的日志文件:

Backed up existing renaming map file G:\CLR\Source\ExtractExeNetStrings\bin\Debug\Dotfuscated\Map.xml to G:\CLR\Source\ExtractExeNetStrings\bin\Debug\Dotfuscated\Map.1.xml

Loading Assemblies...

Running C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\x64\ildasm.exe /OUT=C:\Users\Administrator\AppData\Local\Temp\~Extract.0\ExtractExeNetStrings.exe.il /TEXT /NOBAR /RAWEH /QUOTEALLNAMES /UTF8 /FORWARD G:\CLR\Source\ExtractExeNetStrings\bin\Debug\ExtractExeNetStrings.exe

Processing instrumentation attributes...

Analyzing Markup...

Removal is disabled

Linking is disabled
Analyzing Code...

Renaming...

Encrypting Strings...

Updating Markup...

Writing map file to G:\CLR\Source\ExtractExeNetStrings\bin\Debug\Dotfuscated\Map.xml

Writing Assemblies...

Running C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe /OUTPUT=C:\Users\Administrator\Desktop\CPP\ExtractExeNetStrings.exe /nologo /quiet /resource=C:\Users\Administrator\AppData\Local\Temp\~Extract.0\ExtractExeNetStrings.exe.res  C:\Users\Administrator\AppData\Local\Temp\~Extract.0\ExtractExeNetStrings.exe.il

Build Finished.

 

可以看到一点,它先用ildasm把程序集文件反编译成源代码,把得到的IL源代码经过修改后,再编译成执行文件。

Dotfuscator本身也是用.NET语言开发的,要修改程序集文件,目前常见的技术是调用MONO.Cecil开源类库,以面向对象的方法直接修改.NET程序集。

一个有趣的现象是,Dotfuscator本身却不用字符串混淆技术加密,原因可能是性能。经过混淆的字符串在被调用时,要解密,性能上有损失。如果有几百个,

上千个字符串都要被解密,这样要耗费很多资源。

如上图所示,Dotfuscator 4.9本身的程序集没有使用字符串混淆技术。

 

第三个知识点是关于如何搜索一个程序集中的字符串。这要理解PE文件结构,可直接参考源代码对照理解。

源代码下载:

最后,我把它集成到一起,做一个通用的程序界面,用来解密混淆过的程序集。

代码不复杂,点击按钮,打开程序集文件:

private void btnOpen_Click(object sender, EventArgs e){            OpenFileDialog dlg=new OpenFileDialog();            dlg.Filter = "All File (*.*)|*.*|Library File (*.dll)|*.dll|Application File(*.exe)|*.exe";            if (dlg.ShowDialog() != DialogResult.OK)                return;            OpenLibrayFile(dlg.FileName);}
 
 

接着是分解程序集中的字符串,把到提取到一个List<string> ,调用上面的methodIn.Invoke即可解密。

有一个缺陷是对有密匙(key)的字符串,多数时候会有乱码,因为所传入的key不一样,解密时需要的key不同,无法做到自动化解密,需要手工调整key的值。

这篇文章中被加密的代码,我使用的是Dotfuscator 版本号是4.9.6005.29054。

 

源代码下载:

转载于:https://www.cnblogs.com/JamesLi2015/p/3166252.html

你可能感兴趣的文章
[Leetcode] Unique Paths
查看>>
(九)深浅拷贝
查看>>
PL/SQL块结构和组成元素(为山九仞,岂一日之功)(转EricHu)
查看>>
野外工作照
查看>>
[LeetCode] 342. Power of Four 4的次方数
查看>>
with上下文管理器
查看>>
MySQL中 如何查询表名中包含某字段的表 ,查询MySql数据库架构信息:数据库,表,表字段...
查看>>
03-position和anchorPoint
查看>>
windows 下 nginx 的启动 停止 关闭
查看>>
Django 数据表更改
查看>>
java io读写文件
查看>>
【智能算法】粒子群寻优算法
查看>>
生活中一面,网上另一面
查看>>
[TensorFlow]TensorFlow安装方法
查看>>
机器学习实战-----八大分类器识别树叶带源码
查看>>
springMVC国际化配置和使用
查看>>
centos7下SVN服务器如何搭建
查看>>
CSS自学笔记(11):CSS3背景和边框
查看>>
EL表达式 (详解)
查看>>
重载和重写的区别
查看>>