April 17, 2015

How many characters a Windows API name could have?

So yesterday was my birthday, and after having a good company and watching a movie, I thought about doing something special, guess what? .. fixing a weird bug I had for a long time.

In my PE scanning engine there was a weird heap corruption bug, after I spent a while looking for the cause, I found that some files have too long API names .. too longer than I expected.

I did a quick search online to see what is the maximum number of characters an API name could have.  I didn’t find a technically valid answer, no documentations for that. So I asked Peter Ferrie, and he told me that it is just a couple of bytes under 64KiB! .. I really didn’t expect such a big number.  He said that the limitation is set by RtlInitString API. That was extremely helpful!

So I started from there, and checked RtlInitString in ntdll.dll. It takes a string, computes its length and fills a STRING structure.


Length is the number of characters in the API, MaximumLength is always equals Length+1 which will have number of bytes of the buffer, since it terminates with zero. Buffer is the address of the string.

This is RtlInitString:


So the number of bytes an API name can have is exactly 0xFFFE, or 65,534 bytes. The other question that was in my mind, is there any characters that are NOT allowed?

I checked pefile source code and found that it checks only for characters in range a-z, A-Z, _?@$() as you can see here, just because compilers use them when they “mangle” or decorate the API names. But malware don’t adhere to any documentation.

But wait, why not check ntdll.dll itself and see how Windows does it! .. So I followed GetProcAddress, a function to function, until I reached LdrGetProcedureAddressEx in ntdll.dll which parses the import table of a PE file. What I've found was interesting .. it doesn't check or exclude any characters.

So I tried to play with the names. I wrote a small DLL, compiled it and then manually changed the API name in the export table and included some weird characters, even non-printable ones. I wrote another small test executable that imports my DLL and manually changed the imported API name to match the one in the DLL .. the surprise is .. it works!.

When I uploaded the file to VirusTotal, which by the way uses pefile in the backend to do the file structure analysis, it didn’t show my weird API name.

You can see the file scanning report here. This file uses the function bar() as 5F 62 61 72 2F 02 .. which is "_bar/" plus hex 0x02. It doesn't show on VirusTotal, yet it is valid on Windows.

And finally I fixed it in my code, the bug is gone, and my scanner lived happily ever after :)
Here is a snippet of my code:

So in conclusion:
  • API name can have up to 65,534 characters.
  • API name can have any characters terminated by NULL.
  • VirusTotal will not see your weird imported API, until Ero Carrera fix his pefile.



March 16, 2015

Using Windows Native APIs with CL and GCC

error LNK2019: unresolved external symbol _ZwDelayExecution@8 referenced in function "int __cdecl foo(void)" (?foo@@YAHXZ)

fatal error LNK1120: 1 unresolved externals

This will show up whenever you try to compile the following example code with "CL" (Microsoft compiler) in the straight normal way. This article is about why, and how.


As Microsoft keep saying, using internal APIs directly in your programs is absolutely not recommended. Because those are subject to change from a service pack to another, or may be a patch to another. But sometimes you just need to use them in some circumstances.
In order to use an internal API, you have two options:

Method 1 - Dynamic Linking:

Which is I guess is pretty well known. Just use LoadLibrary API to load "ntdll", then use GetProcAddress to get a function pointer to the function you want to use in ntdll. The following example illustrates that.


Method 2 - Importing ntdll.lib:

Which is the main reason I wrote this blog. In this method, you can use the internal APIs directly without a function pointer. They will show up in your executable's import section normally like any other library you use. If you want to go this way and use this method, what will you do depends on the compiler you'll use. I'll cover here GCC (or G++) and CL (Microsoft Compiler).
 Option 1 - Using GCC:

 MinGW comes loaded with many .lib files, luckily, libntdll.a is one of them. So the process is straight forward. To compile the aforementioned example, just use the following command:

 gcc ZwDelayExecution2.cpp -o ZwDelayExecution2.exe -lntdll

 This will automatically use the file "libntdll.a", GCC will strip the preceding "lib" and succeeding ".a". If you have another file with a different name, use can use -l:<name> to write <name> as the exact file name.

 Do we have to include "-lkernel32" when using kernel32.dll APIs? Nope, GCC will link against kernel32 by default for you. GCC links against some default libraries, and if you want to know what they are in your version, you can add -v option when you compile. Mine shows those libraries been linked against by default:

 -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32

 Let's say, MinGW doesn't have libntdll.a file. Well, you can create the file using the following steps:
 First generate a .def file using the tool pexports that comes with MinGW

 pexports ntdll.dll | sed "s/^_//" > ntdll.def

 Then, generate the library file using dlltool (you should find it in bin directory of your MinGW)

 dlltool -U -d ntdll.def -l libntdll.a

 Viola!

 Option 2 - Using CL:

 cl ZwDelayExecution2.cpp kernel32.lib ntdll.lib user32.lib

 CL needs the name of every library you're using any of its APIs. So in our case we need kernel32.lib, user32.lib and ntdll.lib.
 Unlike MinGW's GCC, CL will not load default libraries for you unless you say so. Check out /DEFAULTLIB:library option.

 But wait! .. you cannot find ntdll.lib file, right?! You've got "LINK : fatal error LNK1181: cannot open input file 'ntdll.lib'" .. Well, yes, Microsoft SDK that comes with Visual Studio doesn't have ntdll.lib. That's Microsoft's way to force you to use Method 1 (The dynamic linking). But don't panic, there are several ways to get the ntdll.lib file.

 1st Way, get it from MinGW directory. As I said earlier, MinGW comes with ntdll.lib, in this case the file name is libntdll.a. Just add the name as is in the command like this.

 cl ZwDelayExecution2.cpp kernel32.lib C:\MinGW\mingw\lib\libntdll.a user32.lib

 CL will give you a little warning "cl : Command line warning D9024 : unrecognized source file type 'C:\MinGW\mingw\lib\libntdll.a', object file assumed", but will compile it right.

 2nd Way, if the 1st way didn't work with your version of CL, try to follow these helpful steps here. http://www.mingw.org/wiki/msvc_and_mingw_dlls

 3rd Way, use the Python method explained in this awesome reply.

 4th Way, If you have the DDK/WDK - for Driver Development Kit and Windows Driver Kit respectively - you should find ntdll.lib files for different architectures there, pick yours.

 That should cover linking against the library. Last thing, what about the line #18 in the source code of ZwDelayExecution2.cpp?. Well, as I said, Microsoft doesn't want you to use the internal APIs in the static way, so the header file for ntdll.dll "winternl.h" is very minimal and doesn't contain definitions for every function in the library. That's why in some cases we need to declare the function signature ourselves.

 That should cover all!.


January 24, 2015

PEiD - Access Out of Boundary Memory Vulnerability

This is a vulnerability I discovered in PEiD v0.95, which is the latest version. The vulnerability was tested on Windows 7 and Windows XP. It's triggered when the PointerToRawData of the last section causes integer overflow when subtracted from file size.

Here's a pseudocode to what's going on:



which is implemented here


then later:



which is implemented here


if file is accepted as a valid PE, then when scanning the last section, PEiD will crash:


A PoC file can be downloaded from here

March 25, 2014

Message box 81 bytes shellcode

As it is my first blog post, I thought about what to add and then I was working on writing a small shellcode, so I said why not post it!
Here is a small shellcode of 81 bytes that displays a message box without importing USER32.DLL. It uses FatalAppExitA API which will display a message and terminates the program.

Thanks to Berend-Jan Wever & Peter Ferrie for their compact shellcode that execute the calculator which this shellcode is based on. Thanks to Giuseppe D'Amore for inspiration.

It worth to mention that the shellcode is null free, fscanf/scanf/sscanf safe, i.e. white-space characters free (0x09, 0x0A, 0x0B, 0x0C, 0x0D and 0x20).

 unsigned char shellcode[81] = {  
   0x33, 0xD2, 0x52, 0x68, 0x4D, 0x30, 0x53, 0x41, 0x54, 0x52, 0xB2, 0x30,  
   0x64, 0x8B, 0x32, 0xC1, 0xEA, 0x02, 0x8B, 0x34, 0x32, 0x8B, 0x34, 0x32,  
   0xAD, 0x8B, 0x30, 0x8B, 0x7E, 0x18, 0x8B, 0x5F, 0x3C, 0x8B, 0x5C, 0x3B,  
   0x78, 0x83, 0xC2, 0x14, 0x03, 0xD3, 0x8B, 0x34, 0x3A, 0x03, 0xF7, 0x8B,  
   0x4C, 0x3B, 0x24, 0x03, 0xCF, 0x33, 0xD2, 0x0F, 0xB7, 0x2C, 0x51, 0x42,  
   0xAD, 0x81, 0x3C, 0x38, 0x46, 0x61, 0x74, 0x61, 0x75, 0xF1, 0x8B, 0x74,  
   0x3B, 0x1C, 0x03, 0xF7, 0x03, 0x3C, 0xAE, 0xFF, 0xD7  
 };  

Assembly code can be downloaded from here