Basic intro to WMI and WQL queries

WMI is an important component of Windows OS and everyone knows about it so I won’t get into detail about what it is (read the linked wikipedia article if you want to know). I will focus on practical stuff instead which we come across more and more often.

I will begin by saying that nowadays lots of malware is using WMI – either to establish a stealthy persistence mechanism, or query various information from the system. This typically is done using WQL queries which are so popular that even a couple of typical OS commands are implemented as ‘processors’ simply interpreting results of many WQL queries instead of actually using old-school APIs.

A good example is a tasklist.exe. If you ever launched it from a command line and observed a slight delay before it returned the data it is because it has to ‘talk’ to WMI first and sometimes WMI initialization may take a while.

This particular program is actually a good example we can use to show what exactly happens when it ‘talks’ to WMI.

Have a look at the Tasklist.exe log below.

  • First WMI connects to the WMI server – the ‘root\cimv2’ is a namespace used by most WMI classes
  • Then it executes the WQL query
     SELECT 
        __PATH,
        ProcessId, 
        CSName, 
        Caption, 
        SessionId, 
        ThreadCount, 
        WorkingSetSize, 
        KernelModeTime, 
        UserModeTime  
     FROM 
        Win32_Process
  • Then the result returned by the query is processed using the IWbemClassObject::Get method
  • Finally, this obtained data is sent to the the console using a WriteConsoleW function

Apart from tasklist.exe, we can also find WQL in taskkill.exe.

Killing a process requires a different query, one that specifies f.ex. a name of the process:

     SELECT
        __PATH,
        ProcessId,
        CSName,
        Caption,
        SessionId,
        ThreadCount,
        WorkingSetSize,
        KernelModeTime,
        UserModeTime,
        ParentProcessId
     FROM
        Win32_Process
     WHERE
        (  Caption = "notepad.exe")

which is ran when we execute

taskkill.exe /im notepad.exe /f

The WMI is then queried for a method ‘Terminate’ which is supposed to kill the object. All of these queries are ran via COM so it’s a bit of a pain to analyze it, but once you get used to it it’s actually manageable (just a bit mundane).

Refer to a short Taskkill.exe log below.

As I mentioned above, malware often uses WQL queries and the most popular are listed below:

  • select * from antispywareproduct
  • select * from antivirusproduct
  • select * from firewallproduct
  • select * from win32_baseboard
  • select * from win32_bios where manufacturer like ‘%xen%’ or (smbiosbiosversion like ‘%vbox%’) or (smbiosbiosversion like ‘%bochs%’) or (smbiosbiosversion like ‘%qemu%’) or (smbiosbiosversion like ‘%virtualbox%’)
  • select * from win32_bios
  • select * from win32_cdromdrive
  • select * from win32_computersystem
  • select * from win32_computersystemproduct
  • select * from win32_diskdrive
  • select * from win32_networkadapter where (name like ‘%tap%’) and (not pnpdeviceid like ‘%*isatap%’) and (netenabled = true)
  • select * from win32_onboarddevice
  • select * from win32_operatingsystem
  • select * from win32_physicalmedia
  • select * from win32_processor
  • select * from win32_systemenclosure
  • select * from win32_useraccount
  • select * from win32_videocontroller
  • select name, executablepath from win32_process

There are many more which often focus on sandbox detection, but I may cover them in a separate post.

Taskkill.exe log

IWbemLocator::ConnectServer: ‘root\cimv2’
IWbemServices::ExecQuery: (‘SELECT __PATH, ProcessId, CSName, Caption, SessionId, ThreadCount, WorkingSetSize, KernelModeTime, UserModeTime, ParentProcessId FROM Win32_Process WHERE (  Caption = “notepad.exe”)’)
IWbemServices::GetObjectA: Win32_Process
IWbemClassObject::GetMethod: Terminate

Tasklist.exe log

WbemLocator::ConnectServer): 'root\cimv2'
IWbemServices::ExecQuery ('SELECT __PATH, ProcessId, CSName, Caption, SessionId, ThreadCount, WorkingSetSize, KernelModeTime, UserModeTime  FROM Win32_Process')
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="0"
IWbemClassObject::Get: ProcessId=0
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=System Idle Process
IWbemClassObject::Get: ThreadCount=1
IWbemClassObject::Get: KernelModeTime=649121406250
IWbemClassObject::Get: UserModeTime=0
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=28672
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="4"
IWbemClassObject::Get: ProcessId=4
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=System
IWbemClassObject::Get: ThreadCount=48
IWbemClassObject::Get: KernelModeTime=103437500
IWbemClassObject::Get: UserModeTime=0
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=241664
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="412"
IWbemClassObject::Get: ProcessId=412
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=smss.exe
IWbemClassObject::Get: ThreadCount=3
IWbemClassObject::Get: KernelModeTime=156250
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=442368
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="628"
IWbemClassObject::Get: ProcessId=628
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=csrss.exe
IWbemClassObject::Get: ThreadCount=11
IWbemClassObject::Get: KernelModeTime=12343750
IWbemClassObject::Get: UserModeTime=5312500
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=4444160
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="720"
IWbemClassObject::Get: ProcessId=720
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=winlogon.exe
IWbemClassObject::Get: ThreadCount=17
IWbemClassObject::Get: KernelModeTime=15156250
IWbemClassObject::Get: UserModeTime=2343750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=5029888
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="764"
IWbemClassObject::Get: ProcessId=764
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=services.exe
IWbemClassObject::Get: ThreadCount=15
IWbemClassObject::Get: KernelModeTime=8927500000
IWbemClassObject::Get: UserModeTime=901250000
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=3727360
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="776"
IWbemClassObject::Get: ProcessId=776
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=lsass.exe
IWbemClassObject::Get: ThreadCount=20
IWbemClassObject::Get: KernelModeTime=143437500
IWbemClassObject::Get: UserModeTime=28906250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=1490944
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="932"
IWbemClassObject::Get: ProcessId=932
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=vmacthlp.exe
IWbemClassObject::Get: ThreadCount=1
IWbemClassObject::Get: KernelModeTime=0
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=2768896
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="948"
IWbemClassObject::Get: ProcessId=948
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=svchost.exe
IWbemClassObject::Get: ThreadCount=17
IWbemClassObject::Get: KernelModeTime=781250
IWbemClassObject::Get: UserModeTime=468750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=5214208
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1032"
IWbemClassObject::Get: ProcessId=1032
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=svchost.exe
IWbemClassObject::Get: ThreadCount=9
IWbemClassObject::Get: KernelModeTime=625000
IWbemClassObject::Get: UserModeTime=781250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=4546560
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1152"
IWbemClassObject::Get: ProcessId=1152
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=svchost.exe
IWbemClassObject::Get: ThreadCount=49
IWbemClassObject::Get: KernelModeTime=125937500
IWbemClassObject::Get: UserModeTime=50781250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=17682432
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1188"
IWbemClassObject::Get: ProcessId=1188
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=svchost.exe
IWbemClassObject::Get: ThreadCount=5
IWbemClassObject::Get: KernelModeTime=781250
IWbemClassObject::Get: UserModeTime=312500
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=3985408
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1224"
IWbemClassObject::Get: ProcessId=1224
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=svchost.exe
IWbemClassObject::Get: ThreadCount=4
IWbemClassObject::Get: KernelModeTime=0
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=3346432
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1396"
IWbemClassObject::Get: ProcessId=1396
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=spoolsv.exe
IWbemClassObject::Get: ThreadCount=11
IWbemClassObject::Get: KernelModeTime=625000
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=6545408
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1776"
IWbemClassObject::Get: ProcessId=1776
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=explorer.exe
IWbemClassObject::Get: ThreadCount=10
IWbemClassObject::Get: KernelModeTime=21718750
IWbemClassObject::Get: UserModeTime=6093750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=19316736
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="2008"
IWbemClassObject::Get: ProcessId=2008
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=vmtoolsd.exe
IWbemClassObject::Get: ThreadCount=5
IWbemClassObject::Get: KernelModeTime=17031250
IWbemClassObject::Get: UserModeTime=8593750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=12140544
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="2024"
IWbemClassObject::Get: ProcessId=2024
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=ctfmon.exe
IWbemClassObject::Get: ThreadCount=1
IWbemClassObject::Get: KernelModeTime=156250
IWbemClassObject::Get: UserModeTime=312500
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=3600384
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="476"
IWbemClassObject::Get: ProcessId=476
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=PERSFW.exe
IWbemClassObject::Get: ThreadCount=6
IWbemClassObject::Get: KernelModeTime=2187500
IWbemClassObject::Get: UserModeTime=1093750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=6897664
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="516"
IWbemClassObject::Get: ProcessId=516
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=vmtoolsd.exe
IWbemClassObject::Get: ThreadCount=7
IWbemClassObject::Get: KernelModeTime=124531250
IWbemClassObject::Get: UserModeTime=63281250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=13619200
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1472"
IWbemClassObject::Get: ProcessId=1472
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=TPAutoConnSvc.exe
IWbemClassObject::Get: ThreadCount=5
IWbemClassObject::Get: KernelModeTime=1093750
IWbemClassObject::Get: UserModeTime=468750
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=4669440
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1796"
IWbemClassObject::Get: ProcessId=1796
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=TPAutoConnect.exe
IWbemClassObject::Get: ThreadCount=1
IWbemClassObject::Get: KernelModeTime=5312500
IWbemClassObject::Get: UserModeTime=2500000
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=5267456
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="2040"
IWbemClassObject::Get: ProcessId=2040
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=cmd.exe
IWbemClassObject::Get: ThreadCount=1
IWbemClassObject::Get: KernelModeTime=156250
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=2961408
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="588"
IWbemClassObject::Get: ProcessId=588
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=wmiprvse.exe
IWbemClassObject::Get: ThreadCount=7
IWbemClassObject::Get: KernelModeTime=0
IWbemClassObject::Get: UserModeTime=156250
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=6332416
IWbemClassObject::Get: __PATH=\\<hostname>\root\cimv2:Win32_Process.Handle="1592"
IWbemClassObject::Get: ProcessId=1592
IWbemClassObject::Get: CSName=<hostname>
IWbemClassObject::Get: Caption=tasklist.exe
IWbemClassObject::Get: ThreadCount=4
IWbemClassObject::Get: KernelModeTime=2031250
IWbemClassObject::Get: UserModeTime=2187500
IWbemClassObject::Get: SessionId=0
IWbemClassObject::Get: WorkingSetSize=5816320

 

Motu – yet another string extractor

String extraction is a daily bread for many of us and there are many tools we can use. In the past I wrote a couple of them myself including:

Today I am posting a simple proof of concept string extractor which I called motu. I came up with the name by looking for some fancy names for ‘an island’. According to wikipedia, motu is a reef islet formed by broken coral and sand, surrounding an atoll. If you google for motu you will find a lot of very picturesque photos.

motusSo it’s a short name, and has some pretty pictures 😉

Anyway, back to the idea.

Algorithms extracting strings often work in a streaming FIFO fashion – data in, data out (if data meets criteria). I thought it would be interesting to extract strings first, do some internal crunching and output them as clusters.

The simple idea I came up with is to look at strings inside a file not as separate chunks, but parts of clusters which are a bit like islands (hence the motu :)) separated from each other. We read data from the file, if it looks like a printable string, we assign it to the current island. If the distance between the area where the string was taken from, and the place where we took the previous string from is significant (distance!), we treat the string as belonging to a new island. In other words, if we see a number of strings close to each other, we will output them. If the strings are sparse, or far away we don’t output them. In the end we only print islands that have at least N strings, and at least one string that contains [a-z]{length_of_the_string}. The latter is just to improve the output quality.

The pros are that you see much less junk strings [printable, but not really meaningful], the cons are that you will miss some strings. Still, it may be quicker to review the file outputted by motu than typical strings. In my tests I was getting various results – some very encouraging, some absolute rubbish.

In any case, I hope the idea can be taken further f.ex. having a list of seeds (known good strings taken either from histograms, or even from a dictionary) we could look for islands that contain these seeds only and output only ‘good’ islands instead of everything. The other idea could be to take all islands (including ones with just one string) and sort them by number of strings / island and output everything. This would ensure all strings are visible and the quality of what would be at the top of the output would be the highest (so one could eyeball the top of the resulting file carefully and pay less attention as we progress skimming through the rest of the file).

You can download script here. If you find any bugs, or have an idea for improvements, please let me know. Thanks.

Examples:

  • Notepad
    • Strings (length = 4)
      vs
    • motu (length=4, distance=128, number of strings/island=at least 10)
  • Some random Delphi sample
    • Strings (length = 4)
      vs
    • motu (length=4, distance=128, number of strings/island=at least 10)