字符串混淆技术应用 设计一个字符串混淆程序 可混淆.NET程序集中的字符串

原文:字符串混淆技术应用 设计一个字符串混淆程序 可混淆.NET程序集中的字符串

关于字符串的研究,目前已经有两篇。

原理篇:字符串混淆技术在.NET程序保护中的应用及如何解密被混淆的字符串 

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

今天来讲第三篇,如何应用上面所学内容,设计一个字符串混淆程序。

先设计一个控制台程序,它是将要被我混淆的程序集文件:

public static void Main()
{
        try
        {
            RunSnippet();
        }
        catch (Exception e)
        {
            string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
            Console.WriteLine(error);
        }
        finally
        {
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }
}
 

代码是Snippet Compiler 的标准模板,在控制台上打印一段字符串。这里,有二个字符串常量,是我需要对它进行加密的地方。

不能直接改源代码,而且要以程序的方式来操作程序集。要能修改.net程序集,现在能找到的方法是Mono.Cecil,最新的版本是0.9.5.0。

先设计混淆算法,是个很简单的Base64代码转换,这一步可以深入挖掘,做更复杂的混淆算法。

public static string StringDecode(string text1)
{
    return Encoding.UTF8.GetString(Convert.FromBase64String(text1));
}

要把这段代码转化为IL代码,用Mono.Cecil来注入到制定的程序集中,先来看看翻译成IL之后的代码

.method public hidebysig static string StringDecode(string) cil managed
{
    .maxstack 8
    L_0000: call class [mscorlib]System.Text.Encoding [mscorlib]System.Text.Encoding::get_UTF8()
    L_0005: ldarg.0
    L_0006: call uint8[] [mscorlib]System.Convert::FromBase64String(string)
    L_000b: callvirt instance string [mscorlib]System.Text.Encoding::GetString(uint8[])
    L_0010: ret
}

再对比Mono.Cecil的语法例子,把上面的IL代码,翻译成C#代码

MethodDefinition new_method = new MethodDefinition("StringDecode", attr, asm.MainModule.Import(typeof(string)));
ParameterDefinition para = new ParameterDefinition(asm.MainModule.Import(typeof(string)));
new_method.Parameters.Add(para);
tp.Methods.Add(new_method);

new_method.Body.MaxStackSize = 8;
MethodReference mr;
ILProcessor worker = new_method.Body.GetILProcessor ();

mr = asm.MainModule.Import(typeof(Encoding).GetMethod("get_UTF8"));
worker.Append(worker.Create(OpCodes.Call, mr));

worker.Append(worker.Create(OpCodes.Ldarg_0));

mr = asm.MainModule.Import(typeof(Convert).GetMethod("FromBase64String"));
worker.Append(worker.Create(OpCodes.Call, mr));

mr = asm.MainModule.Import(typeof(Encoding).GetMethod("GetString", new Type[] { typeof(Byte[]) }));
worker.Append(worker.Create(OpCodes.Callvirt, mr));
worker.Append(worker.Create(OpCodes.Ret));

 

再次,我样要搜索目标程序集中的所有字符串,把它转化成Base64的字符串编码,于是遍历IL指令,进行转化

List<Instruction>  actionInsert=new List<Instruction> ();
foreach (Instruction ins in entry_point.Body.Instructions)
{
       if (ins.OpCode.Name == "ldstr")
       {
                Console.WriteLine("Find target instruction, start modify..");
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes (Convert.ToString (ins.Operand));
                ins.Operand = Convert.ToBase64String (bytes);

                actionInsert.Add(ins);
      }
}
 
 

最后,我们把原来的指令替换成字符串混淆算法调用

for (int i = 0; i < actionInsert.Count; i++)
{
         mr = asm.MainModule.Import(new_method);
         worker = entry_point.Body.GetILProcessor();
         worker.InsertAfter(actionInsert[i], worker.Create(OpCodes.Call, mr));
}
 
 

最后保存程序集,用.net Reflector 载入程序集,如下图所示,字符串常量已经变成了方法调用:

这样,增加了代码反编译的难度,字符串的含义完全被替换成一堆无意义的字符串。

Mono.Cecil最新的版本中,API有变化,本篇程序代码中应用到的读取程序集和写入程序集

string path = @"C:\Users\Administrator\Desktop\CPP\Default.exe";
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(path);
MethodDefinition entry_point = asm.EntryPoint;

path = @"C:\Users\Administrator\Desktop\CPP\DefaultSecury.exe";
asm.MainModule.Write(path);

关于字符串混淆算法,下面列举几个我找到的混淆算法,加密强度会高一些:

static string stringEncrypt(string string_0)
{
    char[] chArray;
    char[] chArray1 = chArray = string_0.ToCharArray();
    while (true)
    {
        int num;
        int length = chArray1.Length;
        if (length <= 0)
        {
            break;
        }
        chArray1[num = length + -1] = (char) (chArray[num] - 'ᑩ');
    }
    return string.Intern(new string(chArray));
}
 

下面是Dotfuscator的混淆算法,还加了盐,强度提升不少。

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));
 }
 

经过混淆后的字符串,完全看不出原文的含义。比如下面的代码片段,都有些怀疑它使用的字符集,有点像中东国家的语言

 

再来看一个代码中有中文的例子,这是一段用户登陆代码,它加密后的字符看起来更不可理解。

如果要给字符串混淆加盐,只需要简单的修改上面的代码,添加一个临时变量,再增加到调用的混淆算法中。

全文代码以NUnit测试方法写成,单元测试配合Resharper真是好用,可以节省大量的代码,一个方法即可作为入口程序启动运行。

给开发和测试带多很多方便。

时间: 2024-10-21 21:08:23

字符串混淆技术应用 设计一个字符串混淆程序 可混淆.NET程序集中的字符串的相关文章

设计一个程序设计竞赛的网站在线的程序测试应该怎么实现啊?????

问题描述 感觉一点头绪都没有,有没有建议. 解决方案 解决方案二:答题时间控制好,不是规定时间内不让提交.然后剩下的就是页面表单设计了解决方案三:我主要的问题是,对于提交上来的程序,怎么进行再线的测试,就是说用户可以在网站上直接测试自己的程序,这个我不知道怎么实现.不知道用什么办法实现?解决方案四:简单的方法:1.将提交上来的代码另存为一个java文件2.调用javac编译成class文件3.利用反射执行指定方法.高级的方法:看看javassist这个东东,很犀利的说!解决方案五:引用1楼def

如何设计一个界面来调用C#编制的程序?

问题描述 我是才开始学习C#的,现在已经用C#编写了一个程序,又要再设计一个界面,通过单击界面上的控件来调用程序,此外,还要通过单击界面上另一控件来调用AutoCAD软件,我不知道应该如何来实现这些功能,请高手们帮忙解答一下,不甚感激! 解决方案 解决方案二:界面本身也是C#写的,叫做Form的继续类然后你用VS的可视设计工具进行设计,然后双击比如按钮控件,待自动转到代码空中的时候添加一些你的其它的C#程序,就行了,这就是你要的.解决方案三:谢谢楼上的回复,我试了,确实可行.谢谢!

数据混淆技术能有效地防止数据泄漏吗?

对于企业而言,数据泄露事故的影响可能是灾难性的,并失去客户的信心和信任,面临经济惩罚和其他严重后果.根据Ponemon研究所2016年数据泄漏事故成本研究显示,数据泄露事故的平均总成本是400万美元,这比2013年增加了29%.每条泄露记录的平均成本是158美元,而医疗保健和零售业每条泄露记录的平均成本分别是355美元和129美元.尽管数据泄露威胁有着极高的风险,企业仍然是数据泄露的受害者,对此,企业开始非常重视对企业拥有.处理和存储数据的保护. 虽然外部威胁仍然是高优先处理事项,但对敏感数据的

字符串混淆技术在.NET程序保护中的应用及如何解密被混淆的字符串

原文:字符串混淆技术在.NET程序保护中的应用及如何解密被混淆的字符串 Visual Studio提供的Dotfuscator保护程序,可以对用户代码中包含的字符串进行加密.比如下面的例子,为了找到这个程序的注册算法,用.NET Reflector加载程序集后,发现代码中的字符串,都变成这种形式的: Assembly executingAssembly = Assembly.GetExecutingAssembly(); ArrayList list = new ArrayList(); str

PHP中一些通用和易混淆技术点的最佳编程实践

最新改进&维护 本文档最后一次于2013年3月8日审核.最后一次修改是在2013年3月8日. 这由我, Alex Cabal维护的.到现在我已经写了很长时间PHP代码了, 目前我运行Scribophile,为严肃作家提供的在线写作小组, Writerfolio, 为自由职业者提供的简单的在线写作文件夹, 和 Standard Ebooks, 有插画的出版物,无数字版权的公共领域电子图书 . 偶尔我会自由的去找那些让我感兴趣的项目和客户. 如果你认为我能够帮你些什么,或者有些关于本文的建议或勘误的

Android代码混淆技术总结(一)

Android代码混淆技术总结(一)       一.前言 最近一直在学习Android加固方面的知识,看了不少论文.技术博客以及一些github上的源代码,下面总结一下混淆方面的技术,也算是给想学习加固的同学做一些科普,在文中讲到的论文.资料以及源码,我都会给出相应的链接,供大家进一步去深入学习.后面我会弄成一个系列的文章,如有一些混淆技术没讲到,还希望大家指点,当做是交流学习. 二.Android混淆技术介绍 2.1 控制流平坦化 2.1.1 概念和思路 控制流平坦化,就是在不改变源代码的功

【字符串处理算法】字符串包含的算法设计及C代码实现

一.需求描述 给定一个长字符串和一个短字符串,编写程序判断短字符串中的所有字符是否都在长字符串中.如果是,则长字符串包含短字符串:反之,不包含. 为了尽量包含大多数情况,字符串中可以包含大小写英文字母.数字和各种标点符号,并且区分大小写字母. 下面举几个例子予以说明: 1.如果长字符串是"ABCDE",短字符串是"ADC",那么短字符串中的所有字符都在长字符串中,即长字符串包含了短字符串. 2.如果长字符串是"ABCDE",短字符串是"

jsp-JSP页面添加一个“查询”按钮,查询条件为“姓名”反正就是字符串就行

问题描述 JSP页面添加一个"查询"按钮,查询条件为"姓名"反正就是字符串就行 JSP页面添加一个"查询"按钮,查询条件为"姓名"反正就是字符串就行,应该怎么写,对应的action和daoa怎么写?求代码~最主要,我是想知道,字符串怎么传值的,数据类型转换吗?所以我想看看代码..我用的是ssh架构,IntelliJ IDEA 10.5工具,拜托各位大神啦 解决方案 就正常的提交请求呀,和增删查改一样的 解决方案二: 很简单,按

代码-JSP页面添加一个“查询”按钮,查询条件为“姓名”反正就是字符串就行,我想知道,字符串怎么传值的

问题描述 JSP页面添加一个"查询"按钮,查询条件为"姓名"反正就是字符串就行,我想知道,字符串怎么传值的 JSP页面添加一个"查询"按钮,查询条件为"姓名"反正就是字符串就行,应该怎么写,对应的action和daoa怎么写?求代码~**最主要,我是想知道,字符串怎么传值的,数据类型转换吗?所以我想看看代码**..我用的是ssh架构,IntelliJ IDEA 10.5工具,拜托各位大神啦 解决方案 最简单的就是通过表单传值h