Bypass AVs via Ordinals

Let’s get in, Microsoft says:

You can specify the entry-point name by supplying a string indicating the name of the DLL containing the entry point, or you can identify the entry point by its ordinal.

So, this means that we have two ways to define the DllImport attribute to call a method by entry-point name (method name) or the ordinal number for the method.

Let me explain it practically so that things will be apparent to you. We will go with MessageBoxExW as example

Syntax

int MessageBoxExW(
  [in, optional] HWND    hWnd,
  [in, optional] LPCWSTR lpText,
  [in, optional] LPCWSTR lpCaption,
  [in]           UINT    uType,
  [in]           WORD    wLanguageId
);

Now we want to write C# code to call the MessageBoxExW method from user32.dll via P/Invoke.

using System;
using System.Runtime.InteropServices;

namespace Test
{
    public class Example
    {

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "MessageBoxExW")]
        static extern int MessageBoxEx(IntPtr hWnd, string lpText, string lpCaption, uint uType, ushort wLanguageId);

        public static void Main()
        {
            MessageBoxEx(new IntPtr(0), "Hello World!", "P/Invoke", 0, 0);
        }
    }
}

Compile and run it.

Upload it to Virustotal. Don't focus on whether it was detected as malicious or not. If we go into details, we will see that Virustotal detected our method in the Unmanaged Method List section.

What do you think will happen if some AVs detect methods like VirtualAlloc or MiniDumpWriteDump ? Exactly 😀

So, now let’s use ordinal as an entry-point.

Ordinals

You can get the ordinal number from the Export Address Table of a DLL (user32.dll) can be viewed by using Dependency Walker.

First, we need to use Dependency Walker to get the ordinal number for the MessageBoxExW method.

File → Open C:\Windows\System32\user32.dll.

In the Function section, we are looking for MessageBoxExW. On the left side, you will see the ordinal number.

The ordinal number for MessageBoxExW is 2153. You can use it as EntryPoint Instead of the method name.

Ensure you're using the correct ordinal numbers for your target, since they can differ between Windows versions.

using System;
using System.Runtime.InteropServices;

namespace Test
{
    public class Example
    {

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "#2153")]
        static extern int MessageBoxEx(IntPtr hWnd, string lpText, string lpCaption, uint uType, ushort wLanguageId);

        public static void Main()
        {
            MessageBoxEx(new IntPtr(0), "Hello World!", "P/Invoke", 0, 0);
        }
    }
}

One more time, let’s upload it to Virustotal.

As shown in the picture, there is no method name.

This approach allows you to bypass some AVs that looking for method names.

References

Last updated