专栏首页鸿鹄实验室VanillaRat功能代码分析

VanillaRat功能代码分析

前言

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 + @"\root\SecurityCenter2";
                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";
            }
        }

我们可以清楚的看到

@"\root\SecurityCenter2"
SELECT * FROM AntivirusProduct

等字样,是很明显的WMI得到利用方法,而在C#中一般用来获取硬件等信息的类为ManagementObjectSearcher。效果如下

信息获取--系统版本

先来上代码吧:

        [DllImport("kernel32.dll")]
        private static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetCurrentProcess();

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string moduleName);

        [DllImport("kernel32")]
        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(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName");
            string csdVersion = HKLM_GetString(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CSDVersion");
            string currentBuild = HKLM_GetString(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "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中调用:

就先分析到这里吧,还有很多功能,下次一定。

本文分享自微信公众号 - 鸿鹄实验室(gh_a2210090ba3f),作者:鸿鹄实验室a

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-04-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 分页功能 封装代码

    郭楷丰
  • SpringBoot 源码解析——源码模块功能分析

    可以看见整体的结构目录是比较清晰的,主要源码模块分为 spring-boot-project 和 spring-boot-tests 两个,其中第一个是源码...

    zhisheng
  • XDebug分析php代码性能

    XDebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况。是一个C语言扩展包(Windows下扩展名...

    用户3094376
  • Android 截图功能源码的分析

    一般没有修改rom的android原生系统截图功能的组合键是音量减+开机键;今天我们从源码角度来分析截图功能是如何在源码中实现的。

    砸漏
  • Python代码性能分析之cProfile

    cProfile(语言编写的测试模块)是一个标准库内建的性能分析工具,可以在标准输出中看到每一个函数被调用的次数和运行的时间,从而找到程序的性能瓶颈,从而有针对...

    吾非同
  • Android6.0源码分析之录音功能(一)

    Android源码录音功能说起来似乎也很简单,只不过就是一个录音的功能然后进行了一个保存的操作。为什么要研究这个呢?毕竟现 在语音通话、直播亦或者是语音助手比...

    fanfan
  • 竞品分析 VS 功能分析

    理论上来讲任何一个互联网产品都会有一个生命周期,只不过有些产品没度过探索期就夭折了,有些产品顽强的活了下来,这个以后有机会再聊。

    靠谱先生
  • html+js实现分页功能代码实例

    PHP开发工程师
  • Python中syslog功能代码

    在我们日常工作中,我们需要从Windows系统上发送syslog消息到syslog服务器。下面的代码能够工作的很好。

    py3study
  • 一款功能强大的软件源代码分析与审计工具

    ApplicationInspector是一款功能强大的软件源代码分析与审计工具,它可以帮助研究人员识别和发现目标应用程序中的公众周知的功能以及源代码中有意思的...

    FB客服
  • Android实现截图和分享功能的代码

    以上所述是小编给大家介绍的Android实现截图和分享功能的代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对Z...

    砸漏
  • HBuilder扩展代码块功能

    作为程序员,大家都应该比较烦的事情就是将相同的代码块复制到N多个地方,但是这种情况有不可避免。为了解决这个问题,我希望实现的是直接将对应的模块提前在编辑器中编辑...

    Rattenking
  • PHP10段常用功能代码

    用户7657330
  • 使用Gprof分析代码性能瓶颈

    Gprof是GNU binutils工具之一。可以分析出代码中每个函数的调用次数、每个函数消耗的处理器时间等。

    查利鹏
  • CRF++代码分析

    用户1908973
  • thrift/swift:ThriftMethodProcessor代码分析

    thrift是一种跨语言的RPC框架,为了保证在各种语言下都能正确表述,IDL语言在设计的时候就只能选取各种语言的共性。 比如对于null,虽然在java中...

    用户1148648
  • JavaScript 代码分析

    #div1 {width:100px; height:100px; background:red;  position:absolute; }

    三杯水Plus
  • Ogitor代码分析

    逍遥剑客
  • Android源码分析:手把手带你分析 Glide的缓存功能

    Glide的缓存机制使得 Glide具备非常好的图片缓存效果,从而使得具备较高的图片加载效率。

    Carson.Ho

扫码关注云+社区

领取腾讯云代金券