Da Li’L World of DLL Exports and Entry Points, Part 5

The previous parts of this series were done ‘manually’. I would come across some new type of DLL and would jot down its properties so I would have a point of reference if I came across these in the future. The ‘manual’ part involved reading MSDN as well as many types of DLLs I covered are nicely described there.

There is another way to enhance the list by doing it a bit more automatically – such list could f.ex. be incorporated into your yara set, or become a part of tools like DiE.

Over 8 years ago I tried to collect a corpora of signed DLLs dropped by NullSoft installers – my list included over 2200 different DLLs. I will use this list today to show how we can create a table of interesting file properties that in turn could be converted into a detection ruleset.

Using sigcheck we can extract version info from these signed DLLs, and then enhance it by a list of exported APIs (f.ex. using pefile), and also internal DLL names. This is pretty much enough to create a decent detection data set.

Of course, these files are very old so to make the best use of this idea one would need to process a larger data set and newer files.

What is the benefit of using such ruleset? As long as files are signed and show the listed properties you may classify many clean files in an automatic fashion w/o relying on exact hashes, fuzzy hashes, or antivirus scans. And yes, as I mentioned in the past, such list of properties can be abused by malware authors, but then again — these files are actually signed, so it’s a good way to sift through the real and fake ones.

Da Li’L World of DLL Exports and Entry Points, Part 4

Looong time ago I wrote a couple of posts about DLLs and their exports. I decided to return to this series as I have some new notes jotted down about the subject…

The extraordinary way we can run Rundll32 with ordinals gave me an idea to check if commonly exported functions are following some sort of… export order. That is, if we look at e.g. COM DLLs, I tried to check if we always see the same export ordinal mapping of DllCanUnloadNow, DllGetClassObject, DllRegisterServer, etc. .

It turns out that this is usually the case:

 237607 DllCanUnloadNow	1
  19736 DllCanUnloadNow	2
   8665 DllCanUnloadNow	3
   2763 DllCanUnloadNow	5
   2411 DllCanUnloadNow	4

 234844 DllGetClassObject	2
  16700 DllGetClassObject	3
   9188 DllGetClassObject	4
   5669 DllGetClassObject	1
   3402 DllGetClassObject	6

 167356 DllRegisterServer	3
  67396 DllRegisterServer	4
   6308 DllRegisterServer	5
   3427 DllRegisterServer	7
   2026 DllRegisterServer	2

 164710 DllUnregisterServer	4
  66457 DllUnregisterServer	5
   6327 DllUnregisterServer	6
   3304 DllUnregisterServer	8
   1909 DllUnregisterServer	7

  30159 DllMain	3
  24334 DllMain	1
   5503 DllMain	20
   5299 DllMain	2
   2387 DllMain	4

  29805 DllInstall	3
   3014 DllInstall	4
    239 DllInstall	18
    188 DllInstall	5
    169 DllInstall	30

These are pretty consistent:

  • DllCanUnloadNow 1
  • DllGetClassObject 2
  • DllRegisterServer 3
  • DllUnregisterServer 4

As such, one could use them instead of actual API names. Not a biggie, but could confuse some naive detection rules…