Ways to interpose on win32 api calls:
++++++++++++++++++++++
(1) using "strace-0.3" - kernel-land hooking via altering SSDT; for NT only
++++++++++++++++++++++
- run via e.g. "strace notepad"
- prints out all win "native api" calls (e.g. calls which trap to the kernel)
and their arguments
- works : hooks System Service Descriptor Table (so works at a kernel level,
i.e. is hooking function calls which trap to the kernel)
-- device driver does the hooking
-- user-space app loads the driver, tells it what to trace,
then pulls data from driver and prints that data
- limitations : current version works for NT, 2k but doesn't work for XP,
nor Win '9x; not sure how much work required to create
support for target platform
-- not sound code either (read: buggy)
- have source code but to edit source code for NT, 2k, XP, requires DDK
for those platforms
+++++++++++++++++++++++++++++
(2) edit import address table
+++++++++++++++++++++++++++++
- given binary : prog.exe
- this is what you want to instrument
- write program which takes as args:
(1) program to be interposed upon (e.g. prog.exe)
(2) API calls of interest (i.e. functions you want to hook)
and the libraries (DLLs) in which each such function lives
(3) for each such function in (2), a replacement function
that you want called
- then program parses the Import Address Table of prog.exe and
for each call to some function in (2), replaces that function
name with the address of your desired replacement function
- then execute that program [whose image has been modified in memory only
(not on disk)]
- general strategy:
(1) create process for target executable with creation flags DEBUG_PROCESS
(2) when debugee starts executing, this creates debug event
(3) at this point, overwrite import address table function addresses for
desired functions with desired addresses then continue
- overwriting these in memory not on disk
(4) as well if get LoadDLL debug event, then if DLL being loaded contains
a function of interest, overwrite the proc address for that fxn
--> a way to capture dynamically-loaded libraries e.g. functions
for which DLL is loaded at runtime via LoadLibrary(...) and
then that function is obtained via GetProcAddress
+ an extension to the general Import Address Table rewriting
continue executing
- e.g. ApiSpy32
limitations : is unclear whether apps which do late-demand binding
for some functions will be able to have such function
calls be caught; plus code is old and needs some major updating
- can't hook kernel fxns (library ntdll.dll doesn't have an FNL file)
-- easy enough to fix?
- can bypass this via (1) map desired dll into memory, (2) call fxn via
creating pointer to somwhere in that mapped region and then calling
that ptr (need POC to prove this)
- CLARIFY : meant by "late-demand binding" and confirm that such would
not be caught by current version of api spy 32
"late-demand binding" == delay-loaded DLLs
- a delay-loaded DLL is implicitly linked but the loader won't
load the dll til code actually calls a fxn w/in that dll
- need to add two linker switches :
/Lib:DelayImp.lib
/DelayLoad:MyDll.dll
- the /Lib switch causes linker to embed _delayLoadHelper fxn into executable
- /DelayLoad switch :
makes sure tht MyDll.dll not loaded at process init time,
creates special table in executable indicating which fxns are in MyDll.dll,
resolves calls to the delay-loaded fxns by having calls jump to _delayLoadHelper fxn
- THEN if one can hook the _delayLoadHelper function in a similar
way to how LoadLibrary(...) and GetProcAddress(...) are hooked
then can remedy this problem
- or maybe just having debugger handle LoadDLL event will already
cover this; anyway seems totally surmountable
- or maybe even by hooking LoadLibrary(...), GetProcAddress(...) have
solved this problem since it appears that's what
__delayLoadHelper does [CONFIRM]
http://www.codeproject.com/dll/Delay_Loading_Dll.asp
- note that current version of apispy32 does catch run-time loaded calls,
e.g. if fxn X is the fxn of interest and you do either:
X(...,...,...);
or
Xmod = LoadLibrary( dll where X lives ); // what I mean by run-time loaded calls
X = GetProcAddress( Xmod, "X name" );
X(...,...,...);
- note older version (for which have source, Matt Pietrek's version) does
not catch run-time loaded calls
- presumably newer version catches functions called via dynamically-loaded
fxn pointers via instrumenting handling of LOAD_DLL debug events
- Check!
==============
REAL QUESTIONS
==============
(a) can bypass using all static-time loading AND run-time loading via
mapping desired dll into memory then calling a function via specifying
some offset into that mapped-into memory?
-- if so, then this idea is sufficiently broken given adversarial nature
-- i.e. can bypass hooking (with albeit a bit of work) so game over...
(b) insurmountable problem ?
-- only able to do win32 api level hooking
-- normal apps don't use ntdll.dll functions ("windows syscalls")
-- so doing IAT overwriting for kernel calls won't work
(since executable isn't likely to make kernel calls)
-- so then have problem of figuring out all semantically-equivalent syscalls
(rather than neater problem (as in easier) of just hooking semantically-
disjoint set of native kernel calls)
++++++++++++++++++++++++++++
(3) in-line function hooking (see especially detours.lib from Hunt/Brubacher)
++++++++++++++++++++++++++++