My previous couple of posts have all been centred around VBA, AMSI and Macros. This isn’t going to be different!.
This makes for the easiest AMSI and Windows Defender bypass.
Whilst reading through MSDN, which incidentally makes great bedtime reading…., I read that it was possible to use ordinal numbers with VBA when declaring functions and also when using GetProcAddress….
This gave me an idea….
Firstly what are ordinals?
An ordinal number is an identifier for an exported function in a DLL. Each exported function in a DLL has a unique identifier assigned to it – its ordinal number.
One of the quickest ways to see these values is with a GUI PE Viewer.
The link below is for one which I used to create this post.
http://codedebug.com/php/Products/Products_NikPEViewer_12v.php
Dependancy walker is an alternative.
https://www.dependencywalker.com/
We’ll start by finding our values from amsi.dll and then from kernel32.dll
If we open up amsi.dll and look at the export table we can see the ordinal values for AmsiScanString and AmsiScanBuffer.

We can do the same with kernel32.dll
The functions that we’ll be looking up are




Next question is how do we use ordinals to have some fun?
It’s really simple to use ordinals in function declarations, simple replace the Alias value with the ordinal.
A standard call for ShellExecute looks like the image below.

To add the ordinal we change the string value to #then the ordinal number. We can also change the function name to something completely misleading too 🙂

For GetProcAddress, this is simple too.
ByVal lpProcName As String needs to be changed to
ByVal lpProcName As Long
Then simple pass the ordinal as a value.
If we put all this together, we can very quickly end up with a simple POC which bypasses AMSI and Windows Defender detection in x32 Office 365/Windows 10 Pro.
Code can be found on my git as a module to import https://github.com/rmdavy/AMSI_Ordinal_Bypass
