首页
论坛
课程
招聘
[原创]带加密字符串的.NET样本分析的一些技巧
2022-8-9 14:37 6512

[原创]带加密字符串的.NET样本分析的一些技巧

2022-8-9 14:37
6512

日常遇到的样本,前两层主要就是解密dll文件,加载,不做分析,从第三层开始

 

由于程序本身被混淆,尝试使用de4dot效果不明显,字符串全部被加密,所以想试着解一下字符串看看效果

 

动态调试发现所有字符串调用都在Gn6.O3i()函数内,通过不同的数字来生成字符串

思路一:自己写
看一下解密函数


从360行到3317行,放弃……
思路二:直接调用
既然它是一个dll,那我们就可以写一个程序来调用这个函数不就行了吗
上代码,然后...

失败,找不到该方法

查找原因,是由于该方法被internal修饰,不能够被从外部调用

 

思路三:
直接从外部调用行不通,那如果在内部加一个类似的调用呢,这就可以用到dnspy的编译功能了,由于Gn6这个类太大,而且被混淆了,直接在它内部加方法很大可能编译失败,所以还是最好自己加一个新的类

 

编译后,可以看到已经出现刚刚编译进去的文件

随后保存模块

修改一下文件名

 

因为混淆的原因,会报错

修改以下选项

修改完成后,继续上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.IO;
 
namespace dessttrrr
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = @"C:\Users\admin1\Desktop\新建文件夹\newDll"//调用dll路径
 
 
            Assembly assem = Assembly.LoadFile(path);
 
 
            Type[] tys;
            try
            {
                tys = assem.GetTypes();
                int i = 0;
                string []mystr=new string[10000];
                int j = 0;
                foreach (Type ty in tys)//遍历查找类名
                {
                    if (ty.Name == "Program")
                    {
                        for (; i < 10000; ++i)
                        {
                            ConstructorInfo magicConstructor = ty.GetConstructor(Type.EmptyTypes);
                            object magicClassObject = magicConstructor.Invoke(new object[] { });//获取一个类实例
                            object[] paramertors = new object[] { i };  //需要传入的参数
 
                            MethodInfo[] methods = ty.GetMethods();
                            MethodInfo mi = ty.GetMethod("getStr");  //获取方法
                            object aa = mi.Invoke(magicClassObject, paramertors);
                            int flag = String.Compare("", aa.ToString());
 
                            if (flag != 0)
                            {
                                int flag2 = aa.ToString()[0];//去除乱码
                                if (flag2 < 255)
                                {
                                    mystr[j] = i.ToString() + ": " + aa.ToString() + "\n";
                                    ++j;
                                }
 
                            }
                        }
                        File.WriteAllLines("str.txt", mystr, Encoding.Default);
                    }
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                // now look at ex.LoaderExceptions - this is an Exception[], so:
                foreach (Exception inner in ex.LoaderExceptions)
                {
                    // write details of"inner", in particular inner.Message
                }
            }
 
        }
    }
}

解密效果如下,可以看到,该模块主要功能为反沙箱,反虚拟机,还有注入


下一层
提取到下一层文件如下,是一个可执行文件了,并且所有字符串同样被加密了

解密函数如下:
经分析知,函数调用的参数(字符串数组下标,字符串所在位置偏移量,字符串长度)

 

它将所有需要的字符串放在一起并做了异或加密,解密为 字符 xor 下标 xor 170,随后通过偏移位置与字符串长度将其取出

 

由于它的字符串没有隔断,需要自行控制截断,而字符串数量过大,所有就想直接提取该部分解密函数使用

 

思路:
在提取前,因为混淆过于严重,先使用de4dot做一下处理,处理后要好看很多,并且一些可能在编译的时候有问题的地方也帮忙做了处理

选择”文件->导出到工程”得到工程文件,然后找到解密函数所在的文件,直接添加现有项到自己要写的代码中,随后修改下报错的地方,同时由于程序需要解密的字符串数组太大,导致在dnspy中显示不全

这段数组可以通过查看文件的16进制直接找到这一段,根据dnspy的提示长度将该段复制出来,替换掉自己工程文件中的这一段

 

替换

 

由于每个字符串都是一个函数,函数过多,可以通过遍历该类中所有函数方法的方式来调用每一个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PrivateImplementationDetails;
using System.Reflection;
using System.IO;
 
namespace getstr
{
    class Program
    {
 
        static void Main(string[] args)
        {
            try
            {
                string[] mystr = new string[10000];
                Type type = typeof(Class0);
                object obj = Activator.CreateInstance(type);
                ConstructorInfo magicConstructor = type.GetConstructor(Type.EmptyTypes);
                // 获取所有方法。
                MethodInfo[] methods = type.GetMethods();
                object magicClassObject = magicConstructor.Invoke(new object[] { });
                int i = 0;
 
                foreach (MethodInfo method in methods)//遍历方法
                {
                    MethodInfo mi = type.GetMethod(method.Name);
                    if (method.Name.Length < 3)//解密的方法名称长度都不大于,以此来过滤掉其他函数
                    {
                        object aa = mi.Invoke(magicClassObject, new object[] { });
 
 
 
                        mystr[i] = "_" + method.Name+"__: "+aa.ToString() + "\n";
                        ++i;
 
 
                    }
                }
                File.WriteAllLines("newstr.txt", mystr, Encoding.Default);
            }
            catch (ReflectionTypeLoadException ex)
            {
                // now look at ex.LoaderExceptions - this is an Exception[], so:
                foreach (Exception inner in ex.LoaderExceptions)
                {
                    // write details of"inner", in particular inner.Message
                }
            }
        }
    }
}

解密效果如下:
通过解密出来的字符串与动态调试的一些行为,发现其实该样本为Agent Tesla 木马的变种


恭喜ID[飞翔的猫咪]获看雪安卓应用安全能力认证高级安全工程师!!

收藏
点赞8
打赏
分享
打赏 + 50.00雪花
打赏次数 1 雪花 + 50.00
 
赞赏  Editor   +50.00 2022/08/23 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (5)
雪    币: 3356
活跃值: 活跃值 (1357)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
pxhb 活跃值 2 2022-8-9 14:42
2
0
不错的思路,感谢分享
雪    币: 1931
活跃值: 活跃值 (1205)
能力值: ( LV8,RANK:126 )
在线值:
发帖
回帖
粉丝
binlmmhc 活跃值 2022-8-10 11:41
3
0
可以的
雪    币: 1192
活跃值: 活跃值 (787)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
goldli 活跃值 2022-8-10 14:51
4
0
收藏 备用。
雪    币: 442
活跃值: 活跃值 (800)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
codemaker 活跃值 2022-8-10 14:55
5
2

这种知道解密函数位置的可以在de4dot使用参数``--strtyp delegate --strtok xxx``(xxx即该解密函数的Token,通过ILSpy或dnSpy都能看到),然后就会解密字符串了

雪    币: 1790
活跃值: 活跃值 (1374)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
LexSafe 活跃值 2022-8-19 10:38
6
0
codemaker 这种知道解密函数位置的可以在de4dot使用参数``--strtyp delegate --strtok xxx``(xxx即该解密函数的Token,通过ILSpy或dnSpy都能看到),然后就会解密 ...
感谢
游客
登录 | 注册 方可回帖
返回