前言
VanillaRat是一款由C#编写的remote administration tool,其github地址如下:https://github.com/dmhai/VanillaRAT
其功能如下:
-
Remote Desktop Viewer (With remote click)
-
File Browser (Including downloading, drag and drop uploading, and file opening)
-
Process Manager
-
Computer Information
-
Hardware Usage Information (CPU usage, disk usage, available ram)
-
Message Box Sender
-
Text To Speech
-
Screen Locker
-
Live Keylogger (Also shows current window)
-
Website Opener
-
Application Permission Raiser (Normal -> Admin)
-
Clipboard Text (Copied text)
-
Chat (Does not allow for client to close form)
-
Audio Recorder (Microphone)
-
Process Killer (Task manager, etc.)
-
Remote Shell
-
Startup
-
Security Blacklist (Drag client into list if you don't want connection. Press del. key on client to remove from list)
本文将从功能实现的角度来简单分析其功能实现的方法,并以此为想要编写C2的小伙伴们提供思路,毕竟很多代码我们都是可以直接拿过来用的。由于RAT不同于C2,所以本文更多的关注功能方面而忽略其通信方法。
信息获取--杀软
首先我们来分析其信息获取功能,在VanillaRat上线之后,会显示基本的目标信息,效果如下:
其默认端口、解析地址均写在了ClientSettings.cs中:
而基础的信息获取的实现,其代码文件如下
我们先来看一下杀软获取的代码:
public static string GetAntivirus()
{
try
{
string Name = string.Empty;
bool WinDefend = false;
string Path = @"\" + Environment.MachineName + @"rootSecurityCenter2";
using (ManagementObjectSearcher MOS =
new ManagementObjectSearcher(Path, "SELECT * FROM AntivirusProduct"))
{
foreach (var Instance in MOS.Get())
{
if (Instance.GetPropertyValue("displayName").ToString() == "Windows Defender")
WinDefend = true;
if (Instance.GetPropertyValue("displayName").ToString() != "Windows Defender")
Name = Instance.GetPropertyValue("displayName").ToString();
}
if (Name == string.Empty && WinDefend)
Name = "Windows Defender";
if (Name == "")
Name = "N/A";
return Name;
}
}
catch
{
return "N/A";
}
}
我们可以清楚的看到
@"rootSecurityCenter2"
SELECT * FROM AntivirusProduct
等字样,是很明显的WMI得到利用方法,而在C#中一般用来获取硬件等信息的类为ManagementObjectSearcher。效果如下
信息获取--系统版本
先来上代码吧:
[ ]
private static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
[ ]
private static extern IntPtr GetCurrentProcess();
[ ]
private static extern IntPtr GetModuleHandle(string moduleName);
[ ]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
public static bool Is64BitOperatingSystem()
{
// Check if this process is natively an x64 process. If it is, it will only run on x64 environments, thus, the environment must be x64.
if (IntPtr.Size == 8)
return true;
// Check if this process is an x86 process running on an x64 environment.
IntPtr moduleHandle = GetModuleHandle("kernel32");
if (moduleHandle != IntPtr.Zero)
{
IntPtr processAddress = GetProcAddress(moduleHandle, "IsWow64Process");
if (processAddress != IntPtr.Zero)
{
bool result;
if (IsWow64Process(GetCurrentProcess(), out result) && result)
return true;
}
}
// The environment must be an x86 environment.
return false;
}
private static string HKLM_GetString(string key, string value)
{
try
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(key);
return registryKey?.GetValue(value).ToString() ?? string.Empty;
}
catch
{
return string.Empty;
}
}
public static string GetWindowsVersion()
{
string osArchitecture;
try
{
osArchitecture = Is64BitOperatingSystem() ? "64-bit" : "32-bit";
}
catch (Exception)
{
osArchitecture = "32/64-bit (Undetermined)";
}
string productName = HKLM_GetString(@"SOFTWAREMicrosoftWindows NTCurrentVersion", "ProductName");
string csdVersion = HKLM_GetString(@"SOFTWAREMicrosoftWindows NTCurrentVersion", "CSDVersion");
string currentBuild = HKLM_GetString(@"SOFTWAREMicrosoftWindows NTCurrentVersion", "CurrentBuild");
if (!string.IsNullOrEmpty(productName))
return
$"{productName}{(!string.IsNullOrEmpty(csdVersion) ? " " + csdVersion : string.Empty)} {osArchitecture} (OS Build {currentBuild})";
return string.Empty;
}
这个是使用的winapi来进行版本的获取,可以参考该文章:https://www.cnblogs.com/fresky/archive/2012/11/27/2791482.html
它这里自己实现了判断的功能,而c#中是自带了如何判断的即:
Environment.Is64BitOperatingSystem
然后就是通过注册表来查询具体信息了,效果如下:
信息获取--地区等
RAT上显示的如下:
即cpu类型、电脑名、内存、国家、省份、城市。
电脑名获取:
public static string GetName()
{
return Environment.MachineName;
}
内存获取:
public static int GetRamAmount()
{
try
{
int RamAmount = 0;
using (ManagementObjectSearcher MOS = new ManagementObjectSearcher("Select * From Win32_ComputerSystem")
)
{
foreach (ManagementObject MO in MOS.Get())
{
double Bytes = Convert.ToDouble(MO["TotalPhysicalMemory"]);
RamAmount = (int) (Bytes / 1048576);
break;
}
}
return RamAmount;
}
catch
{
return -1;
}
}
CPU类型:
public static string GetGPU()
{
try
{
string Name = string.Empty;
using (ManagementObjectSearcher MOS =
new ManagementObjectSearcher("SELECT * FROM Win32_DisplayConfiguration"))
{
foreach (ManagementObject MO in MOS.Get()) Name += MO["Description"] + " ;";
}
Name = RemoveLastChars(Name);
return !string.IsNullOrEmpty(Name) ? Name : "N/A";
}
catch
{
return "N/A";
}
}
地区信息,这个的实现还是比较有意思的,通过请求http://ip-api.com/json/来从返回的json串中得到相关的信息。代码如下:
try
{
DataContractJsonSerializer JS = new DataContractJsonSerializer(typeof(GeoInfo));
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("http://ip-api.com/json/");
Request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; rv:48.0) Gecko/20100101 Firefox/48.0";
Request.Proxy = null;
Request.Timeout = 10000;
using (HttpWebResponse Response = (HttpWebResponse)Request.GetResponse())
{
using (Stream DS = Response.GetResponseStream())
{
using (StreamReader Reader = new StreamReader(DS))
{
string ResponseString = Reader.ReadToEnd();
using (MemoryStream MS = new MemoryStream(Encoding.UTF8.GetBytes(ResponseString)))
{
GeoInfo = (GeoInfo)JS.ReadObject(MS);
}
}
}
}
}
catch { }
GeoInfo.Ip = string.IsNullOrEmpty(GeoInfo.Ip) ? "N/A" : GeoInfo.Ip;
GeoInfo.Country = string.IsNullOrEmpty(GeoInfo.Country) ? "N/A" : GeoInfo.Country;
GeoInfo.CountryCode = string.IsNullOrEmpty(GeoInfo.CountryCode) ? "-" : GeoInfo.CountryCode;
GeoInfo.Region = string.IsNullOrEmpty(GeoInfo.Region) ? "N/A" : GeoInfo.Region;
GeoInfo.City = string.IsNullOrEmpty(GeoInfo.City) ? "N/A" : GeoInfo.City;
GeoInfo.Timezone = string.IsNullOrEmpty(GeoInfo.Timezone) ? "N/A" : GeoInfo.Timezone;
GeoInfo.Isp = string.IsNullOrEmpty(GeoInfo.Isp) ? "N/A" : GeoInfo.Isp;
}
依赖于
using System.Runtime.Serialization.Json;
命令执行--shell
VanillaRat提供了shell来执行命令。显示如下:
核心代码位置在RemoteShellStream:
这边仿写了一个:
键盘记录
主类在:
然后在StreamClasses中调用:
就先分析到这里吧,还有很多功能,下次一定。
本文始发于微信公众号(鸿鹄实验室):VanillaRat功能代码分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论