6

There's a .NET malware sample I'm trying to analyze, which goes more or less like this:

internal static class Class1
{
    public static byte[] Code = new byte[]
    {
        9,
        249,
        131,
        225,
        ...,
    }

    private static void Main()
    {  
        // AFAIU this copies the marshaled code in Code to freshly allocated memory
        IntPtr ptr = Class1.Alloc((uint)Class1.Code.Length);
        for (int i = 0; i < Class1.Code.Length; i++)
        {
            int num = (int)Marshal.ReadByte(Class1.Code, i);
            Marshal.WriteByte(ptr, i, (byte)num);
        }

        Class1.newObject newObject = (Class1.newObject)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Class1.newObject));

        object.Equals(null, null);
        [...snip...]
        object.Equals(null, null); // probably some timing mechanism

        Marshal.GetFunctionPointerForDelegate(newObject);
        newObject();
    }
}

I'm trying to get to the code behind newObject(), which is apparently instantiated from marshaled code. I'm no .Net expert, but from what I read marshaled code is some kind of serialization that can be applied on objects to transfer functional code over binary channels (such as a TCP connection, for example). From what I understand, I should be able to reverse it to an understandable, or at least bytecode-like format.

I tried software like ILSpy and dotPeek but they don't seem to recognize the code in Code as being managed code, and provide no usable output.

5

I'm trying to get to the code behind newObject(), which is apparently instantiated from marshaled code. I'm no .Net expert, but from what I read marshaled code is some kind of serialization that can be applied on objects to transfer functional code over binary channels (such as a TCP connection, for example).

I'm not sure what "marshaled code" means, but marshaling in .Net generally refers to interoperability with native code.

It's not really serialization, and I believe it's not commonly used for that purpose. (It can be used to convert a single object to an array of bytes, but that's not really relevant here, since your code doesn't do that.)


Now, to your code: The Marshal class contains methods useful for interoperability, including converting between native and managed types.

And that's exactly what GetDelegateForFunctionPointer() does: it converts from an unmanaged function pointer (pointing to some unmanaged code) to a delegate that can be called from .Net.

To verify that this is indeed what your code does, I have created a slightly simplified version of it and put the x86 machine code for a very simple function into the byte array:

class Program
{
    private static readonly byte[] code =
    {
        0xB8, 0x2A, 0x00, 0x00, 0x00, // mov eax, 0x2a
        0xC3 // ret
    };

    private delegate int FuncInt();

    private static void Main()
    {
        IntPtr ptr = AllocExecutableMemory(code.Length);
        for (int i = 0; i < code.Length; i++)
        {
            Marshal.WriteByte(ptr, i, code[i]);
        }
        var del = (FuncInt)Marshal.GetDelegateForFunctionPointer(ptr, typeof(FuncInt));
        Console.WriteLine(del());
    }

    private static IntPtr AllocExecutableMemory(int length)
    {
        // see http://www.pinvoke.net/default.aspx/kernel32.virtualalloc,
        // but change the return type from UIntPtr to IntPtr
        return NativeMethods.VirtualAlloc(
            UIntPtr.Zero, (UIntPtr)length,
            AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE);
    }
}

This code prints 42 (=0x2A), as expected.

This means that to analyze Code, you have to look at it as unmanaged code (most likely x86).

1

You could likely open the file in IDA and force IDA to interpret the IL machine code bytes as code, thus giving you the disassembly for the IL machine code bytes.

But since you asked about decompiling it, you could try "force-feeding" the IL machine code bytes to ILSpy's decompiler functions to see if it can decompile it for you. You'd need to look through the source code for ILSpy to figure out what function(s) to call.

I realize that this isn't an ideal solution, so hopefully someone can post a better answer :)

  • I tried force-feeding the code to ILSpy but no dice. Same with IDA, it wouldn't find the entry point (which I don't have since it's not a PE I'm loading). I'm headed to try with other .Net disassemblers / decompilers. – Thomas Chopitea Oct 10 '14 at 13:23
  • Load the original .NET exe into IDA, navigate to the Code array, and press 'C' to tell IDA to disassemble it. – Jason Geffner Oct 10 '14 at 13:39
  • Also, which functions in ILSpy did you try feeding the code to? – Jason Geffner Oct 11 '14 at 20:22
  • I simply tried opening the dumped Code array in ILSpy, to no avail. I tried looking for other loading functions but didn't find any. – Thomas Chopitea Oct 13 '14 at 14:29
  • Right, using ILSpy's standard "open file" user interface certainly won't work. I was suggesting above that you load ILSpy's codebase into your IDE and call specific functions in order to decompile your machine code. – Jason Geffner Oct 13 '14 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.