FridaTrace++ – quick & dirty API monitor

In my two previous posts I described:

I’ve been experimenting with improving Frida Trace tool to enrich its output. Since the tool allows for rapid prototyping I decided to incorproate that SDK into it. After few weeks of endless coding that took barely 2-3h I came up with a first version of auto-generated handlers.

How does it work?

  • Install Python 3.7
  • Install Frida
  • Run automation (perl script) and build handlers for 16K APIs automagically
  • Place them in c:\python\__handlers__\
  • Run frida-tools

This is how it looks in practice:

  • c:\python\Scripts\frida-trace.exe c:\windows\notepad.exe -i *CreateFile*

You will notice that:

  • Instead of just an API name, we can now see a DLL name, actual API name, and all the arguments and their names as per SDK, and their values as well:
    • KernelBase.dll!CreateFileW (lpFileName=”C:\Windows\Fonts\staticcache.dat” (0x6483f8b310), dwDesiredAccess=GENERIC_READ (0x80000000), dwShareMode=0x5, lpSecurityAttributes=0x0, dwCreationDisposition=0xb6f000000003, dwFlagsAndAttributes=0x6400000000, hTemplateFile=0x0)
  • Return values are shown
    • RET = 0x<hex> /Kernel32.dll!CreateFileW/
  • For some arguments I added additional data enrichment
    • Extraction of file names passed to CreateFile* functions (also see below comment on all generic string arguments)
    • dwDesiredAccess is converted to a more readable flag dwDesiredAccess=GENERIC_READ (0x80000000) – this was a test of an idea, and it seem to work so can probably pretty quickly expand other attributes as well

If you look at the prototype files you will notice that they include a snapshot of SDK information which can help to manually develop code of a given API further:

The flag expansion idea I mention above can be best explained using the actual code – we build an array of masks, and walk through all of them, adding relevant strings as we walk through it (this code is not finished; and for some cases it will be just a direct comparison, not bit testing):

onEnter: function (log, args, state) {
GENERIC_READ      = 0x80000000
GENERIC_WRITE     = 0x40000000
GENERIC_EXECUTE   = 0x20000000
GENERIC_ALL       = 0x10000000

FILE_SHARE_READ   = 0x000000001
FILE_SHARE_WRITE  = 0x000000002
FILE_SHARE_DELETE = 0x000000004

masks =

dwDesiredAccess = ''

for (i = 0; i < masks.length/2; i++)
    res = args[1] & masks[i*2]
    if ((res == masks[i*2]) || (res==-masks[i*2]))
       if (dwDesiredAccess != '') { dwDesiredAccess = dwDesiredAccess + ' | ' }
       dwDesiredAccess = dwDesiredAccess + masks[i*2+1]
    log('Kernel32.dll!CreateFileW ('+
  'lpFileName='+'"' + args[0].readUtf16String() + '" (' + args[0] + ')'+', '+
  'dwDesiredAccess='+'' + dwDesiredAccess + '(' + args[1] + ')'+', '+
  'dwShareMode='+args[2]+', '+
  'lpSecurityAttributes='+args[3]+', '+
  'dwCreationDisposition='+args[4]+', '+
  'dwFlagsAndAttributes='+args[5]+', '+

Quick and dirty stats on argument names across the whole SDK gave me this nice list:

  • dwFlags 1053
  • hdc 566
  • Flags 422
  • hWnd 352
  • hProcess 331
  • pszPath 227
  • hwnd 217
  • hKey 202
  • lpBuffer 201
  • error 187
  • lParam 175
  • engineHandle 174
  • riid 162
  • lpName 161
  • hFile 158
  • ServerIpAddress 157
  • lpFileName 156
  • Buffer 152

With that list I was able to identify a couple of arguments that are obvious strings – as a result I added argument expansion for them as well. We can see this in action here:

c:\python\Scripts\frida-trace.exe c:\windows\notepad.exe -i *strcmp*

When I ran the above command the first time I noticed that my handlers were missing msvcrt.dll prototypes for strcmp & _strcmpi so I added them manually copypasta-ing the prototypes for lstrcmp. This is obviously something that needs work as this particular library (and its versions) are very popular. Then we can think of VB programs, etc. – this just needs more time.

And speaking of time… time for a little bonus.

If you run this:

  • c:\python\Scripts\frida-trace.exe c:\windows\system32\cmd.exe -i *CreateFile* -i FindFirstFile*

you will run cmd.exe in a window of your current Frida Trace session.

So, as you type commands you can literally inspect which API calls are made to deliver given functionality. On the attached screen you can see how FindFirstFileExW API is executed to find files as per the wildcard ‘foo*’. After creating a file ‘foobar’, we can see how it is being accessed by CreateFileW.

This is literally the fastest API monitoring ever. I will be spending more time improving the handlers & when I am happy with the outcome I will post my automation script here.