Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Detecting hooks

14 views
Skip to first unread message

EliCZ

unread,
Sep 5, 2000, 3:58:14 AM9/5/00
to

>Try to walk virtual address space (using VirtualQuery in a lopp) to see if
>there are any unknown non-system DLLs being added, especially after the
>program is running.

Yes, then you can hook VirtualQuery and return what you want ;)

EliCZ

(Hi Dejan, btw)


Dejan Maksimovic

unread,
Sep 5, 2000, 9:00:40 AM9/5/00
to
> (Hi Dejan, btw)

Nice to see You again!
Any ideas?

--
Regards, Dejan M. CEO Alfa Co. http://www.alfaunits.co.yu
E-mail : de...@alfaunits.co.yu ICQ# : 56570367
Professional file&system related components and libraries for Win32 developers.

Alfa Units - #1 file and system handling units for Delphi.
Alfa File Monitor - #1 file monitoring system for Win32 developers.
Alfa Interceptor - #1 file protection and hiding system for Win32 developers.


Feng Yuan

unread,
Sep 5, 2000, 2:21:22 PM9/5/00
to
> Yes, then you can hook VirtualQuery and return what you want ;)

Read every byte of virtual memory in plain C/C++ code, under the protection
of an exception handler.

Actually, you only need to read the first block in every 4KB page, and check
for PE header signature.

Feng Yuan


EliCZ

unread,
Sep 6, 2000, 6:22:25 AM9/6/00
to

>Read every byte of virtual memory in plain C/C++ code, under the protection
>of an exception handler.
>
>Actually, you only need to read the first block in every 4KB page, and
check
>for PE header signature.

What is it good for?
You will analyze every module? How?
What about speed?
What about loading/unloading (indicdll, imm32,...)


EliCZ


Slava M. Usov

unread,
Sep 5, 2000, 10:30:38 PM9/5/00
to

"Dejan Maksimovic" <alfa...@ptt.yu> wrote in message
news:39B38B0F...@ptt.yu...
>
> Hi,
>
> Is there a way to detect whether an application is being hooked,
> i.e. whether the API functions are real, or are filter functions from an
> API hook library or program?

That depends on how one hooks Win32 APIs. A well-known method is to patch
the executable's import thunks to point to the interceptor's code.
GetProcAddress() is hooked, as well. The imports arte normally patched on
the first breakpoint. To detect this sort of hooking, you need to check if
import thunks and pointers returned by GetProcAddress() actually point to
the DLL that should contain the code. Normally, you'll only need to inspect
the address of GetProcAddress("GetProcAddress") and see if it belongs to
kernel32.dll. There is the trick... to get the base address of kernel32.dll,
you need to call, say, LoadLibrary(), which may be hooked, or walk the
address space and call GetModuleFile(), which again may be hooked. You may
want to open the file of kernel32.dll and read the optional header and then
maybe the exports directory to be sure... both CreateFile() and ReadFile()
may be hooked, though...

Another way of hooking, more elaborate, the DLLs' routines one is interested
in are patched, i.e., the first few bytes are replaced with a call to a hook
routine, which then restores the original code, and calls the routine, then
patches the routine again [these operations, BTW, must be serialized]. Or a
breakpoint is planted and the debugger does that externally. In this case,
the only way to detect if an API is hooked is to load its DLL, parse PE
format, locate the address of the routine, and compare a few first bytes to
the image in memory. Notice that in this case GetProcAddress() may be itself
*not* hooked, so you'll have to do that on per-routine basis. And, as usual,
CreateFile() and ReadFile() may be hooked. You might also disassemble the
first bytes of the routines you're interested in and see if they start with
a near JMP. This is not 100% reliable because some routines may be indeed
coded that way; and the interceptor might easily replace the JMP with a few
innocently looking instructions, like

push eax
mov eax, hook_address
push eax
ret

Finally, there is a "stealth" way. IA debug registers may contain up to 4
breakpoints, and no code modifications are necessary. The only way to detect
that is to look at the registers. And that is per-thread.

And most importantly, hooks may be planted *after* you have made the checks,
so even if you have determined there are no hooks, they may appear during
the next quantum. The moral is that of "copy-protection": you can make it
complicated, paranoid, and hard to penetrate, but you cannot make it
absolutely reliable.

Slava

Feng Yuan

unread,
Sep 6, 2000, 4:59:41 PM9/6/00
to
> What is it good for?

Check changes in virtual memory, in case someone hooks your VirtualQuery.

> You will analyze every module? How?

Only analysze when a change is found. PE file format is well-documented.

> What about speed?

2MB/4KB=512. Only 512 blocks to compare, not much.

> What about loading/unloading (indicdll, imm32,...)

If you want to know whether your process is being hooked, you have to
monitor any DLL being loaded into your process.

Feng Yuan www.fengyuan.com

Per Larsen

unread,
Sep 7, 2000, 6:11:30 AM9/7/00
to
I don't personally have the need to detect hooking, but this is an
interesting thread from an academic perspective...

It occurs to me that if you can run an application once knowing that it
isn't hooked at that time - perhaps as part of installation - you can make
use of the fact that KERNEL always loads at the same address and store the
addresses (and possibly the first few bytes of) - at least - the KERNEL API
functions you're concerned about in a (possibly encrypted) table. You can
then check against that table during normal application startup.

> Finally, there is a "stealth" way. IA debug registers may contain up to 4
> breakpoints, and no code modifications are necessary. The only way to
detect
> that is to look at the registers. And that is per-thread.

I've been wondering about that for other reasons (a custom debugger project
I have on the back burner): Is that functionality (and the other hardware
breakpoint options) accessible from ring 3? Can you show an example of how
to set it up?

- Per

J. Wesley Cleveland

unread,
Sep 7, 2000, 12:38:07 PM9/7/00
to

Feng Yuan wrote:
>

[snip]


>
> > What about speed?
>
> 2MB/4KB=512. Only 512 blocks to compare, not much.

^

Don't you mean 2GB and 512K blocks ?

Per Larsen

unread,
Sep 7, 2000, 2:21:10 PM9/7/00
to
Ahmed,

You're not modifying the debug registers here. Did I miss your point?

- Per

"Ahmed Kandeel" <a...@sakhr.com> wrote in message > //
========================================================
> // ModifyThrdCtx ========================================================
> void ModifyThrdCtx (void)
> {
> DWORD dwThreadID = 0;
> CONTEXT ThrdCtx;
> void* pVoid =NULL;
>
> HANDLE hThread = NULL;
> hThread =
CreateThread(NULL,0,GuardThread,0,CREATE_SUSPENDED,&dwThreadID);
>
> // CONTEXT_DEBUG_REGISTERS is not part of the context CONTEXT_FULL
> ThrdCtx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
> if(GetThreadContext(hThread ,&ThrdCtx))
> {
> pVoid = (void*)GlobalAllocPtr(GMEM_FIXED,1024*64);
> ThrdCtx.Esp = ((DWORD) pVoid) + 1024*64;
> if(!SetThreadContext(hThread,&ThrdCtx))
> {
> OutputDebugString("Cant set thread context");
> GlobalFreePtr(pVoid);
> pVoid = NULL;
> }
> }
> ResumeThread(hThread);
> WaitForSingleObject(hThread,INFINITE);
> CloseHandle(hThread);
> if (pVoid)
> {
> GlobalFreePtr(pVoid);
> pVoid = NULL;
> }
>
> return;
> }
>

Slava M. Usov

unread,
Sep 7, 2000, 2:20:41 PM9/7/00
to

"Per Larsen" <pe...@turbopower.com> wrote in message
news:mRJt5.1880$qU2....@news010.worldonline.dk...

> I don't personally have the need to detect hooking, but this is an
> interesting thread from an academic perspective...
>
> It occurs to me that if you can run an application once knowing that it
> isn't hooked at that time - perhaps as part of installation - you can make
> use of the fact that KERNEL always loads at the same address and store the
> addresses (and possibly the first few bytes of) - at least - the KERNEL
API
> functions you're concerned about in a (possibly encrypted) table. You can
> then check against that table during normal application startup.

Yes, but there is no guarantee that the application is not hooked at the
very first run. This is similar to the key distribution problem.

Additionally, addresses and code of Win32 routines may change from SP to SP.

> I've been wondering about that for other reasons (a custom debugger
project
> I have on the back burner): Is that functionality (and the other hardware
> breakpoint options) accessible from ring 3? Can you show an example of how
> to set it up?

I believe it is accessible from ring-3 [I have some recollections of once
doing that]. If nobody finds an example until the weekend, I'll try to make
one. Alternatively, get yourself a copy of IA architecture manuals [free
downloads from Intel] and read the 3rd volume, section on debugging. It
explains the debug registers pretty well.

Slava


EliCZ

unread,
Sep 8, 2000, 4:04:46 AM9/8/00
to

>Check changes in virtual memory, in case someone hooks your VirtualQuery.

every second or every minute?

But there are better things:

1) What about Win9x shared libraries above 2GB? How would you determine
if they belong to your process? ("They are mapped even if they aren't
mapped").

and the best at the end:

2) What about API forwarding?
Where points NT KERNEL32.HeapAlloc? To KERNEL32.dll ????
API forwarding is OS supported API hooking.

EliCZ

unread,
Sep 8, 2000, 4:11:32 AM9/8/00
to

DRx can be accessed via CONTEXT. I played with it in 1998.
Get SEHall.zip from elicz.cjb.net Infos section

But detecting hooks (via DRx) is nonsense.
Every exception (SINGLE_STEP or ACCESS_VIOLATION)
gets to much time.

EliCZ

Per Larsen

unread,
Sep 8, 2000, 6:36:02 AM9/8/00
to
Eli,

> DRx can be accessed via CONTEXT. I played with it in 1998.
> Get SEHall.zip from elicz.cjb.net Infos section

I did, but I don't see it anywhere. Can you point me in the right direction?

Nice site you've got there, though.

- Per

"EliCZ" <el...@chemi.muni.cz> wrote in message
news:G0K6M...@news.muni.cz...

Slava M. Usov

unread,
Sep 8, 2000, 10:04:52 AM9/8/00
to

"EliCZ" <el...@chemi.muni.cz> wrote in message
news:G0K6M...@news.muni.cz...

[...]

> But detecting hooks (via DRx) is nonsense.
> Every exception (SINGLE_STEP or ACCESS_VIOLATION)
> gets to much time.

Reread the original message. I said it was possible to plant hooks using the
debug registers. And nobody actually cares about speed when it comes to
hooking and hook detecting.

Slava


Slava M. Usov

unread,
Sep 8, 2000, 10:08:59 AM9/8/00
to

"EliCZ" <el...@chemi.muni.cz> wrote in message
news:G0K6...@news.muni.cz...

[...]

> 2) What about API forwarding?
> Where points NT KERNEL32.HeapAlloc? To KERNEL32.dll ????
> API forwarding is OS supported API hooking.

No. API hooking is tampering with API *after* the corresponding DLL has been
loaded. Forwarded APIs are handled by the the OS loader. That means you can,
in principle, make a snapshot of the APIs in question and use the snapshop
to check against later.

Slava


Hosam Aly

unread,
Sep 11, 2000, 12:09:45 PM9/11/00
to

Hi,

I've another idea ...

- You shouldn't rely on the loading time to check the hooking as the API
hooker program might hook afterwards.
- You shouldn't rely also on any Win32 API to do this check as they might be
hooked as well.
- Also dumping the memory is very time consuming.

so, what I think is that u have one of two ways.
the first one is to build a device driver which will get the info you want
about the Kernel32, GDI32 ,... and the other system modules.

Another idea which I think is the better and easiest to implement.
you can rely on the fact that Kernel32, is the first module to be loaded in
memory in Win9x.
In WinNT, it's loaded just after the executable in the high area of the
application private 2G memory.
so as a result of this fact.
on Win9x, Kernel32 is in address of 0xBFFxxxxx
on WinNT, the address should be 0x77Fxxxxx , this is the base address in the
image file.

u can access ur executable's import table easily, where u can check for the
address of every function u call in Kernel.

I made this idea under the assumption that the API hooker program is just a
simple one and won't patch this code which will check for the hooking.
by the way, it will be nice idea if ur program disables the debugger before
doing these checks.

B.R.
Hosam Aly

"Dejan Maksimovic" <alfa...@ptt.yu> wrote in message
news:39B38B0F...@ptt.yu...
>
> Hi,
>
> Is there a way to detect whether an application is being hooked,
> i.e. whether the API functions are real, or are filter functions from an
> API hook library or program?
>

Slava M. Usov

unread,
Sep 12, 2000, 7:36:00 PM9/12/00
to

"Hosam Aly" <hos...@watchfire.com> wrote in message
news:Ogy4MtA...@cppssbbsa02.microsoft.com...

[...]

> by the way, it will be nice idea if ur program disables the debugger
before
> doing these checks.

Disable? How?

Slava


Mike Philben

unread,
Sep 14, 2000, 3:00:00 AM9/14/00
to

"Slava M. Usov" <stripit...@usa.net> wrote in message
news:ueJrdJAGAHA.242@cppssbbsa05...

> "Dejan Maksimovic" <alfa...@ptt.yu> wrote in message
> news:39B38B0F...@ptt.yu...
> >
> > Hi,
> >
> > Is there a way to detect whether an application is being hooked,
> > i.e. whether the API functions are real, or are filter functions from an
> > API hook library or program?
>
> That depends on how one hooks Win32 APIs. A well-known method is to patch
> the executable's import thunks to point to the interceptor's code.
> GetProcAddress() is hooked, as well.

Question (if anyone is still following this thread -- What address does
GetProcAddress return? The Import(or Export) or the actual address of the
Proc. For Windows 9x you could inject and hook your own version of
GetProcAddress that gets the real Kernel address and build from there....

Mike p

Hosam Aly

unread,
Sep 15, 2000, 3:00:00 AM9/15/00
to

Debuggers are activated (called) through interrupts so simply if overwrite
these data it won't be called anymore.
The data themselves are written in the IDT table.


"Slava M. Usov" <stripit...@usa.net> wrote in message

news:urJXcLRHAHA.242@cppssbbsa05...

Slava M. Usov

unread,
Sep 15, 2000, 3:00:00 AM9/15/00
to
"Mike Philben" <mi...@turboware.com> wrote in message
news:Oldjb$rHAHA.242@cppssbbsa04...

> Question (if anyone is still following this thread -- What address does
> GetProcAddress return? The Import(or Export) or the actual address of the

typedef HANDLE (*PGetCurrentProcess)();
PGetCurrentProcess pGetCurrentProcess
= (PGetCurrentProcess)
GetProcAddress(kernel32, "GetCurrentProcess");

pGetCurrentProcess is a pointer to function, that is, contains the address
to which execution is passed to when you call the function. That means it
must be the address of real code.

Slava

Slava M. Usov

unread,
Sep 15, 2000, 3:00:00 AM9/15/00
to
"Hosam Aly" <hos...@watchfire.com> wrote in message
news:#TyLO0xHAHA.271@cppssbbsa05...

> Debuggers are activated (called) through interrupts so simply if overwrite
> these data it won't be called anymore.
> The data themselves are written in the IDT table.

And how exactly will your user-mode code overwrite IDT? On NT?

Slava

el...@my-deja.com

unread,
Sep 21, 2000, 3:00:00 AM9/21/00
to
Hello Slava,

> > 2) What about API forwarding?
> > Where points NT KERNEL32.HeapAlloc? To KERNEL32.dll ????
> > API forwarding is OS supported API hooking.
>
> No. API hooking is tampering with API *after* the corresponding DLL
has been
> loaded.

Really? I thought NTDLL "updates" imported forwarded APIs
also after module (DLL) was loaded.

Forwarded APIs are handled by the the OS loader. That means
you can,
> in principle, make a snapshot of the APIs in question and use the
snapshop
> to check against later.

The effect of API hooking and API forwarding is the same.
Your module import will point to other module than you've wanted
(e.g. KERNEL32.HeapAlloc will point to NTDLL.RtlAllocateHeap).
Then I say API forwarding is API hooking provided by NTDLL.


And snapshots?
Many hooking utils create target suspended, then they apply hooks
then tehy resum target. Snapshots will not help here.

EliCZ


Sent via Deja.com http://www.deja.com/
Before you buy.

Slava M. Usov

unread,
Sep 21, 2000, 3:00:00 AM9/21/00
to

<el...@my-deja.com> wrote in message news:8qcn2c$99q$1...@nnrp1.deja.com...

> Really? I thought NTDLL "updates" imported forwarded APIs
> also after module (DLL) was loaded.

What's your definition of "loaded"? Mine is after being loaded by the OS
loader. So when the OS loader modifies a few bytes in a DLL, it's when it is
BEING loaded, according to my definition.

> The effect of API hooking and API forwarding is the same.
> Your module import will point to other module than you've wanted
> (e.g. KERNEL32.HeapAlloc will point to NTDLL.RtlAllocateHeap).
> Then I say API forwarding is API hooking provided by NTDLL.

As you please.

> And snapshots?
> Many hooking utils create target suspended, then they apply hooks
> then tehy resum target. Snapshots will not help here.

Snapshots may and should be created in a guaranteedly safe execution
environment, e.g., at the developers' machine. I know this will work only
for a particular version or, hopefully, versions of system DLLs, but we're
discussing the principle here. I personally would not recommend anybody even
trying to detect hooking/debugging, because it is a lost battle. Given a
debugger and a sufficiently skilled operator, the debuggeee has no chance.

Slava

J. Wesley Cleveland

unread,
Sep 21, 2000, 3:00:00 AM9/21/00
to


"Slava M. Usov" wrote:
>
[snip]


>
> Snapshots may and should be created in a guaranteedly safe execution
> environment, e.g., at the developers' machine. I know this will work only
> for a particular version or, hopefully, versions of system DLLs, but we're
> discussing the principle here. I personally would not recommend anybody even
> trying to detect hooking/debugging, because it is a lost battle. Given a
> debugger and a sufficiently skilled operator, the debuggeee has no chance.
>
> Slava

I agree about debugging, but hooking is somewhat different as there may
not be an operator. One idea is to LoadLibrary on kernel32, check the
return value for reasonableness, (it's hard to get your own dll at the
location kernel32 normally goes at), parse the export table for a few
important functions, e.g. GetProcAddress, check to see that the code
there is what you expect, and compare these addresses to the addresses
in your import table.

Slava M. Usov

unread,
Sep 21, 2000, 3:00:00 AM9/21/00
to

"J. Wesley Cleveland" <jw...@oro.net> wrote in message
news:39CA2CA7...@oro.net...


> I agree about debugging, but hooking is somewhat different as there may
> not be an operator. One idea is to LoadLibrary on kernel32, check the
> return value for reasonableness, (it's hard to get your own dll at the
> location kernel32 normally goes at), parse the export table for a few
> important functions, e.g. GetProcAddress, check to see that the code
> there is what you expect, and compare these addresses to the addresses
> in your import table.

I agree that is reasonable and I even suggested that, weeks ago and in the
beginning of the thread :-) Since then the thread has slightly changed its
focus. On the other hand, what would possibly the reason to detect hooks be?
The only one I can imagine is deliberate programming to make "exploring" the
program harder, and in this case a skilled human debugger will eventually
appear, if the program is worth it. Is there any other reason to detect
hooking? I know a reason to detect debugging, to provide verbose trace
information but it is as simple as calling IsDebuggerPresent(), and this
will likely work in the case of hooking, if the program and the
hooker/debugger are willing to co-operate.

Slava

0 new messages