Company Products Services Customers Resources
Products
Python Scripts Tutorial

 
Namespace spyobjects
Install hooks
Function parameters
Stack trace
 
Namespace spyobjects
This namespace lets you access process list, hook functions, print call information in the output window or generate a breakpoint in a hook call.

To start using this objects type the following in the Python console:

import spyobjects


For example, to list the names of all the processes in the system type:

procs = spyobjects.processes().all()
for p in procs:
  print procs[p].name()

 

Install hooks
To install a hook you can use this code:

hook = spyobjects.installHook(process, "kernel32.dll!CreateFileW", None)


Last parameter receives an interface of the handler of the hook, in the example above there is no handler.
To create a handler of the hook you have to create a class derived from HooksEvents implementing the desired events.
The class below handles hooks' events printing calls in the output window in the same way SpyStudio does.
When a hook changes its state, a line is printed with the present and the previous state.

class HookHandler(spyobjects.HooksEvents):

  def __init__(self):
    spyobjects.HooksEvents.__init__(self)

  def onCall(self, hook, proc, callInfo, remoteCall):
    spyobject.printCall(hook, callInfo)

  def onHookChange(self, hook, prevState):
    print "Hook state changed: ", hook.state(), ". Previous state was: ", prevState

 

Function parameters
Using DParamList that comes in DCallInfo you can loop parameters, see the type, name and value.

The following example prints to the Python console the parameters and all the information associated to them. The level argument of the function indicates how deep is the function from the original DParamList object that represents function parameters. For example, if an argument is a structure, the function will call recursively to parseParams with level = 2 to print all it's members.

def parseParams(pms, level):
  ret = "Fields: "
  c = level
  while (c > 0):
    ret = "\t" + ret
    c = c - 1
  ret = "\r\n" + ret
  for p in pms:
    paramVal = repr(p.value())
    ret = ret + " | " + p.typeName() + " " + p.name() + ": " + paramVal
    parseParams(p.fields(), level + 1)
  return ret + ".-"

Casting types
There are some functions that have generic parameters and their type depend on one of the other parameters.

In this situation it is necessary to test the parameter containing the type information and then cast the other parameter to the correct type using the cast function. This example shows how to cast a void* param to a string:

castedParam = param.castTo('LPSTR')


Truncate parameters
Some times, the parameter size is specified in another parameter.
To handle these situations you can use the DParam.setMaxSize function.
In this example the first parameter contains a string which size is in the second parameter:

param0 = params[0].castTo('LPSTR')
  param1 = params[1].value()
param0.setMaxSize(param1);

The httpReport.py example uses this feature.

Stack trace
To install a hook you can use this code:
hook = spyobjects.installHook(process, "kernel32.dll!CreateFileW", None)
In the context of a function call you can get the DStackTrace object from the DCallInfo that comes as an argument of the call. Using this object you are able to navigate previous calls.

This example navigates the stack and prints in the Python console if the call is in the list self.mods.
This example was done to hook functions from the module wininet.dll, that's why it loops the stack trace until it finds a call that comes from a different module.
This is important because there are functions that call another function of the same module (e.g.: kernel32!CreateFileA calls kernel32!CreateFileW) and then the hooked function is called.

Here is the example (taken from httpReport.py):

def onCall(self, hook, proc, callInfo, remoteCall):
  st = callInfo.stackTrace()
  sti = st.currentCall()
  while sti != None:
    mName = sti.module().name().lower()
    if mName != "wininet.dll":
      if mName in self.mods:
        print 'Module ', mName, ' in list ', ' Address: ', hex(sti.address())
        break
      else
        print 'Skip Module: ', mName, ' Address: ', hex(sti.address())
      return
    sti = st.previousCall()
 


 back