字符串反混淆实战 Dotfuscator 4.9 字符串加密技术应对策略

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

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

internal class Program
{
    // Methods
    private static void Main(string[] args)
    {
        int num2 = 4;
        try
        {
            List<string> expressionStack_51_0;
            string expressionStack_51_1;
            List<string> expressionStack_3C_0;
            string expressionStack_3C_1;
            int expressionStack_12_0 = 1;
            if (expressionStack_12_0 == 0)
            {
            }
            string exePath = args[0];
            List<string> 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<string> 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<string, string>(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));
 }

套用一下这个方法,没有解密成功,得到的仍然是乱码。如果你有读过我昨天发布的文章”字符串混淆技术在.NET程序保护中的应用及如何解密被混淆的字符串“,就相当于我已经解决了这个问题。但是,我想把这个思路解释一下,以至不忘。

第一个知识点是关于多模块。现在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论坛中有一个关于如何调用模块中的方法的,地址是的http://social.msdn.microsoft.com/Forums/vstudio/en-US/8a48f5bb-08c3-4d80-b5fc-56cb359fca94/call-a-global-function-using-c-emit

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

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加载程序集,可以看到,模块下面有一个静态方法

image

 

于是,要借助于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本身却不用字符串混淆技术加密,原因可能是性能。经过混淆的字符串在被调用时,要解密,性能上有损失。如果有几百个,

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

image

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

 

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

源代码下载: http://files.cnblogs.com/JamesLi2015/ExtractExeNetStrings.zip

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

image

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

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。

 

源代码下载: http://files.cnblogs.com/JamesLi2015/ExtractExeNetStrings.zip

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Net 脱壳 混淆神器De4dot-3.1.41592最新版,De4Dot是一个开源的脱壳/混淆工具,这款工具可以奉为神器级工具。因为它的脱壳能力的确很强,使用它可以成功地脱掉了Dotfuscator、MaxToCode处理过的程序,至于其它的加壳/混淆工具比如说Xenocode、ThemIDA等我还没有进行过实验,之后我将计划研究各类加壳/混淆工具的脱壳方法,我深信De4Dot能够给我带来巨大帮助。(由于De4Dot是开源的,我相信即便De4Dot暂时处理不了的壳通过扩展其功能必将能解决) 支持以下几种混淆: CliSecure Crypto Obfuscator Dotfuscator .NET Reactor 4.x Eazfuscator.NET SmartAssembly 4.x-6.x Xenocode 用法说明: 开始-运行-cmd 输入以下命令: de4dot工具解压路径\de4dot --dont-rename -f 你要混淆的程序集dll 例如: C:\Users\Administrator\Desktop\de4dot\de4dot --dont-rename -f C:\Users\Administrator\Desktop\zkcms.dll 特点: 伪随机列表会做的事情,它取决于什么混淆混淆组装: 内联方法。有些混淆器移动到另一个静态方法的方法,并调用它的一小部分。 解密字符串的静态或动态 解密等常量。有些混淆器也可以加密其他常数,如整数,双打等 解密方法静态或动态 删除代理方法。许多混淆器取代大多数/所有调用指令调用委托。此委托依次调用真正的方法。 重命名符号。尽管大多数符号不能恢复,将它们重命名为人类可读的字符串。有时,一些原来的名称可以被恢复,虽然。 Devirtualize虚拟化代码 解密资源。许多混淆器有一个选项来加密.NET资源。 解密嵌入的文件。许多混淆器有一个嵌入,可能加密/压缩其他组件的选项。 删除篡改检测代码 删除调试代码 控制流混淆。许多混淆器修改IL代码,所以它看起来像意大利面条式的代码很难理解代码。 还原类字段。有些混淆器可以移动领域从一个类来创建类其他一些混淆。 PE EXE转换.NET exe文件。有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和字段

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值