Windows API Hooking in Python with Deviare

July 20th, 2012 | Posted by Sebastian Wain in Deviare | Python

The code below uses Python to intercept the CreateFile function on the kernel32.dll to forbid opening certain files. It hooks the CreateFile function for the notepad.exe application. The Python code is very small and to the point, and you can customize it for your own purposes. For example, it can be used to sandbox an application to restrict it to a certain set of files, registry keys, and network accesses.

Python has a relatively long history of being used in the computer security field. Among IDA Pro plugins, IDAPython is more popular than IDARub. If search results can be used as a measure of success, a search for each major scripting language plus “reverse engineering” returns:

Query# of results
“python” AND “reverse engineering”215K
“perl” AND “reverse engineering”184K
“ruby” AND “reverse engineering”95.2K

 

Why is that? some people wrote specifically about that in Python and Reverse EngineeringPython Arsenal for Reverse Engineering Whitepaper, and a good video of RECON 2008: Reverse Engineering Dynamic Languages a Focus on Python, Aaron Portn.  The bias towards a programming language might be related to a network effect, but even so, a programming language with a vibrant community is fertile ground for trying out new ideas.

Code

Prerequisites

  1. Install Python 2.7.3 for Windows
  2. Download Deviare and Register DeviareCOM.dll and DeviareCOM64.dll if the script should under an x64 platform: open a command prompt with administrator rights, navigate to the folder where the Deviare’s *.dll files are located, execute “regsvr32 DeviareCOM.dll” and “regsvr32 DeviareCOM64.dll”
  3. Download and install Python Win32 Extensions
  4. The code is also available on github

Python Win32 Extensions Notes

Be careful to download the appropriate version for your platform and Python version.
If you get a message stating that you haven’t installed Python in your system yet (but you did and you are completely sure that you downloaded the correct Python Win32 Extensions installer) you can copy the registry folder HKEY_LOCAL_MACHINESOFTWAREWow6432NodePython to HKEY_LOCAL_MACHINESOFTWAREPython (or viceversa). To do this, you should:
  1. Open the registry editor (start -> run… -> “regedit”)
  2. Find the folder you want to copy
  3. Right click on the folder and select “Export”. This will allow you to save a file with the registry folder content
  4. Edit the file you just created and change all the paths in the file accordingly to where you want to move the folder
  5. Save the file and then double-click it. A message box should appear prompting if you want to add information to the registry. Click “yes” and you are done
  6. Once you’ve done this, the Python Win32 Extensions installer should recognize your Python installation
If you still have problems to install this demo, please visit our forum to get further assistance.

DeviarePythonDemo.py

import win32com.client
import ctypes

from EventHandlers import NktSpyMgrEvents
from AuxFunctions import *

spyManager = win32com.client.DispatchWithEvents('DeviareCOM.NktSpyMgr', NktSpyMgrEvents)
spyManager.Initialize()

StartNotepadAndHook(spyManager)

MessageBox = ctypes.windll.user32.MessageBoxA
MessageBox(None, 'Press OK to end the demo.', 'Deviare Python Demo', 0)

EventHandlers.py

import win32com.client

class NktSpyMgrEvents:
	def OnProcessStarted(self, nktProcessAsPyIDispatch):
		nktProcess = win32com.client.Dispatch(nktProcessAsPyIDispatch)
		if (nktProcess.Name == "notepad.exe"):
			print 'Notepad was started.'

	def OnProcessTerminated(self, nktProcessAsPyIDispatch):
		nktProcess = win32com.client.Dispatch(nktProcessAsPyIDispatch)
		if (nktProcess.Name == "notepad.exe"):
			print 'Notepad was terminated.'

	def OnFunctionCalled(self, nktHookAsPyIDispatch, nktProcessAsPyIDispatch, nktHookCallInfoAsPyIDispatch):
		nktHookCallInfo = win32com.client.Dispatch(nktHookCallInfoAsPyIDispatch)
		nktProcess = win32com.client.Dispatch(nktProcessAsPyIDispatch)

		if (nktHookCallInfo.IsPreCall):
			fileName = self.GetFileNameParam(nktHookCallInfo.Params())
			if (fileName.endswith('.txt')):
				self.SkipCall(nktHookCallInfo, nktProcess)

# Aux Functions

	def SkipCall(self, nktHookCallInfo, nktProcess):
		nktHookCallInfo.SkipCall()
		if (nktProcess.PlatformBits == 64):
			nktHookCallInfo.Result().LongLongVal = -1
		else:
			nktHookCallInfo.Result().LongVal = -1
		nktHookCallInfo.LastError = 5

	def GetFileNameParam(self, nktParamsEnum):
		nktParam = nktParamsEnum.First()
		return nktParam.Value

AuxFunctions.py

from subprocess import *

def GetPIDByProcessName(aProcessName):
	for proc in psutil.process_iter():
		if proc.name == aProcessName:
			return proc.pid

def OpenNotepadAndGetPID():
	print 'Starting Notepad...'
	pid = Popen("notepad").pid
	print 'Notepad started successfully'
	return pid

def HookFunctionForProcess(spyManager, functionModuleAndName, notepadPID):
	print 'Hooking function ' + functionModuleAndName + ' for Notepad...'
	hook = spyManager.CreateHook(functionModuleAndName, 0)
	hook.Attach(notepadPID, True)
	hook.Hook(True)
	print 'Notepad successfully hooked'
	return hook

def StartNotepadAndHook(spyManager):

	notepadPID = OpenNotepadAndGetPID()
	hook = HookFunctionForProcess(spyManager, "kernel32.dll!CreateFileW", notepadPID)

Related Services

  1. Reverse Engineering
  2. Interception and Filter Drivers Services
  3. Application Virtualization and Packaging

If you liked this article, you might also like:

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.