Little aware of the Hook function Ibreathe (Favorites)

zhaozj2021-02-16  47

One,

Preamble is most

Windows developer, how to

Win32 system

The call of the API function interception has been a challenging topic, because this will be a comprehensive test for computer knowledge you have, especially some in today's use.

The knowledge is not commonly used in software development, which includes operating system principles, assembly language or even about machine instruction code (it is a bit horror, but this is the fact).

Currently used

WINDOWS operating system, like

Win 9X and

WIN NT / 2K provides a more robust mechanism to make the memory address space of each process are independent, that is, a valid memory address in a process is meaningless to another process. This memory protection measures greatly increase the stability of the system. However, this also makes system-level

The difficulty of the API interception work is also greatly increased.

Of course, I refer to it here is a relatively elegant interception method, and you will implement the code in memory in memory by modifying executables.

Dynamic interception of API calls; rather than using comparative violence, rewrite the machine code directly on the disk storage of executable files.

two,

API hook system general framework usually, we intercept

This process of the call of the API is called an installation

API hook (

API HOOK. One

The API hook has at least two modules: one is a hook server (

Hook Server) module, generally

EXE form; one is a hook drive (

Hook driver) module, generally

DLL form.

The server is primarily responsible for injecting the drive to the target process, making the drive in the address space of the target process, which is a key first. The driver is responsible for actual

API intercepts work in order to care

API function calls can do some work we need.

One more common

The example of the API hook is some of the high-time translation software (like Jinshan Words): screen scratches, it is mainly for some

The GDI function has intercepted and gets the strings in their input parameters and then displayed in your own window. In response to the two parts described above, we have the following two points. We need to focus on:

What kind of use

DLL injection technology

What kind of

API interception mechanism

three,

Injection technology

The address of each process in the Win32 system is independent of each other, so we cannot make effective modifications to the code of another process in a process. And you have to complete

This operation must be carried out in the work of the API hook. Therefore, we must take some unique means to make

The API hook (accurately the hook drive) can become part of the target process, with a larger possible modification of the target process data and code.

There is usually the following ways:

1. Use the registry if we prepare interception processes connected

User32.dll, that is, use

User32

API (general graphical interface apps in line with this condition), then you can simply put your hook drive

The name of the DLL is added as the value of the following registry:

HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / WindowsNT / CURRENTVERSION / Windows / Appinit_dlls value forms can be single

DLL file name, or a group

DLL file name, with a comma or space between adjacent names. All identified by this value

The DLL will be loaded when the eligible application is started. This is an operating system built-in mechanism, which is less dangerous relative to other ways, but it has some obvious shortcomings: this method is only available

NT / 2K operating system. Look at the name of the key, you should understand

In order to activate or stop the injection of the hook, you must restart

WINDOWS. This seems too inconvenient.

Can't use this method

User32 application injection

DLL, such as console applications

No matter whether it is needed, hooks

DLL will inject every one

GUI app, which will result in a decline in the performance of the entire system

2.

Establish system range

Windows hook wants to inject a process

DLL, a very common method is to build in standard

On the basis of Windows hooks.

Windows hooks are generally

DLL is implemented, this is a global

The basic requirements of the Windows hook, which is also in line with our needs. When we successfully call

After the SETWINDOWSHOKEX function, a type of message hook is installed in the system, which can be a process or all processes in the system. Once this type of message is generated in a process, the operating system will automatically put the hook.

The DLL image is in the address space of the process, so that the message callback function (in

Specified in the parameter of SETWINDOWSHOKEX, can be properly processed, here, of course, is of course not to process the message, so just put the message hook backwards in the message callback function, but we needed

The DLL has successfully injected the address space of the target process, so that follow-up work can be completed.

We know that in different processes

DLLs cannot be shared directly because they are active in different address spaces. In

Windows hook

In the DLL, there are some data, such as

Windows hook handle

Hhook, this is

Setwindowshookex function returns worth it, and as a parameter

CallNexthooKex function and

Used in the UnHookWindoShooKex function, obviously

SETWINDOWSHOKEX function process and use

The process of the CallNexthookex function is generally not the same process, so we must be able to make the handle in all address spaces, that is, its value must be in these hooks

The process hooks the process hooks is shared. In order to achieve this, we should store it in a shared data area.

in

We can use the pre-compilation instruction in VC

#pragma data_seg

Create a new segment in the DLL file, and

The properties of this paragraph are set to "in the DEF file"

", this has established a shared data segment. For use

Delphi people are not so lucky: there is no similar relatively simple method (maybe there, but I have not found). However, we can also use memory image technology to apply for the memory area that can be shared using a process, mainly using

CreateFilemapping and

MapViewOffile These two functions. This is a universal method that is suitable for all development languages, as long as it can use

Windows

API.

in

Borland

There is an instruction in the BCB

#pragma codeseg and

VC

#pragma data_seg is a bit similar, it should also play the same role, but I tried it, there is no effect, and

BCB's online help is also mentioned there, I don't know how to use it correctly. Once hook

After the DLL loads the address space that goes into the target process, it is not possible to stop working before we call UNHOOKWINDOWSHOKEX functions unless the target process is turned off.

This

There are two advantages in the DLL injection method:

This mechanism is

Win 9X / ME and

Win NT / 2K is supported, and it is expected to be supported in future versions.

hook

The DLL can be called by our initiative when it is not required.

UnHookWindowsHookex is uninstalled, which is convenient than the mechanism to use the registry, which is a fairly simple method, but it also has some obvious shortcomings:

First of all, we pay attention to it.

Windows hooks will reduce the performance of the entire system because it adds an additional time of the system in message processing.

Second, only when the target process is ready to accept some kind of message, the hook is

The DLL will be mapped to the address space of the process, and the hook can really start playing. So if we want to have a whole life cycle of some processes

The API call situation is monitored, and this method will obviously miss some

API call

3.

use

CreateremoteThread function In my opinion, this is a quite a good way, but unfortunately,

CreateRemoteThread This function can only be

Support in the Win NT / 2K system, although in

Win 9x this

The API can also be invoked by safe calls, but it does not do anything else to return an empty value. entire

The DLL injection process is very simple. We know that any process can be used

LoadLibrary is dynamically loaded

DLL. But the question is, how do we make the target process loading our hooks under our control

DLL (That is a hook drive)? Here there is one

API function

CreateRemoteThread, which can build and run a remote thread in a process.

Call the

The API needs to specify a thread function pointer as a parameter, the prototype of the thread function is as follows:

Function ThreadProc (LPPARAM: POINTER): DWORD; Let's take a look

LoadLibrary function prototype:

Function LoadLibrary (LPFileName: Pchar): hmodule; It can be seen that these two function prototypes are essentially identical (in fact, whether the return value is not the same, because we can't get the return value of the remote thread function), just The name is different, this same makes we can put it directly

LoadLibrary uses the thread function to use to load hooks in the target process

DLL.

Similar, when we need to unload hooks

DLL can also

Freelibrary is used as a thread function, shifting the hook in the target process.

DLL. Everything seems to be very simple and convenient. Call

GetProcAddress function, we can get

The address of the LoadLibrary function. due to

LoadLibrary is

The function in kernel32, and this system

The DLL mapping address is the same for each process, so

The same is true for the address of the LoadLibrary function. This will make sure we can pass the address of the function as a valid parameter to

CreateremoteThread is used.

AddrofloadLibrary: = getProcadDress (getModuleHandle ('

Kernel32.dll '

), '

LoadLibrary '

);

HREMOTETHREAD: = CreateremoteThread (HtargetProcess, NIL, 0, AddrofloadLibrary, Hookdllname, 0, NIL);

CreateRemoteThread, we need the handle of the target process as a parameter. When we use

When the OpenProcess function is to get the handle of the process, it is usually desirable to have a full access to this process, that is

Process_all_access is a logo opens a process. But for some system-level processes, it is obviously not possible, and only one empty handle (zero) can be returned. To do this, we must set itself to the privilege of the trial level, which will have the largest access rights, so that we can make some necessary operations for these system-level processes.

4.

by

Bho to inject

DLL Sometimes we want to inject

The object of the DLL is just

Internet Explorer. Fortunately,

The Windows operating system provides us with a simple archiving method (this guarantees its reliability) -

use

Browser Helper Objects

BHO). One

Bho is one

Dedicated in DLL

COM object, it mainly implements a

IObjectWithsite interface, and whenever

When I is running, it will automatically load all the interface.

COM object.

four,

Intercepting mechanism has two types in the system level of hook applications

The mechanism of API interception - the interception of the kernel and the user-level interception. The kernel hook is mainly implemented by a driver of a kernel mode. It is clear that its function should be stronger, can capture any details of the system activity, but the difficulty is also large, not within the scope of our exploration (especially for me This use

Delphi's person, has not been involved in this area, so it is impossible to discuss);

And user-level hooks are usually in ordinary

All in DLL

The API intercepted work, this is what we are now focusing on. Interception

The call of the API function, generally can have the following methods:

1.

proxy

DLL (Trojan Horse) an easy way to think is the same name

DLL replaces the original output we are ready to intercept

API

DLL. Of course agency

The DLL also outputs all functions as the original. If you think

Hundreds of functions may be output in the DLL, and we should understand that this method is not high. In addition, we have to consider

DLL version problem.

2. The method of rewriting execution code has many interception is based on the rewriting of executable code. One of them is changing

The function address used in the CALL instruction is a bit difficult, which is more prone to errors. Its basic idea is to retrieve all you have to intercept in memory.

API

Call instruction, then change the original address into the address of the function you provide.

Another method of rewriting another code is more complicated, and its main implementation step is to find the original

The address of the API function, then uses a few bytes starting with the function

JMP instructions (sometimes have to be used

INT instructions, make it

The call to the API function can turn to our own function call. This method is to involve a series of stacks and outstanding operations out of the bottom-up operation, clearly the knowledge of our assembly language and operating system. This method is similar to the infection mechanism of many viruses.

3. Intercepting another optional method as a debugger is to place a tested breakpoint in the target function, so that the process runs to the debug state. However, such some problems have also come, and more important is that the production of debugging will hang all the threads in the process. It also requires an additional debug module to process all exceptions, the entire process will run in debug state until it runs. 4. This method of rewriting the input address table is mainly due to now

Executable files used in the Windows system (including

EXE file and

Good structure of a DLL file -

PE file format (

Portable Executable file format, so it is quite robust and easy to travel. To understand how this method works, first of all you have

The PE file format has an understanding.

One

The structure of the PE file is roughly shown below:

general

The PE file is one beginning.

DOS program, when your program is not supported

When you run in Windows, it will display "

This Program Cannot Be Run in dos mode ", this warning statement, then this

The DOS file header begins to real

The PE file is content. The first is a period of saying "

Image_nt_header "data, which is much about

The message of the PE file, the end of this data is a

Data Directory's data sheet, can quickly locate some

Middle section of PE file (

Section) 's address. After this data, it is a ""

Image_section_Header "list, each of which describes information about a segment of the following sections. Next it is

The most important segment data in the PE file is stored in these segments, respectively.

In all these paragraphs, there is a known "

.idata segment (input data segment) is worthy of us to pay attention, including some input address tables (

IAT,

IMPORT Address Table) Data list. Each implicitly loaded

API

DLL has one

IAT and correspondence, one

The address of the API is also

One corresponds to IAT. When an application is loaded into the memory, for each

The API function call, the corresponding assembly instruction is generated:

JMP DWORD PTR [xxxxxxxx]

If

VC is used

_Delcspec (import), then the corresponding instructions become

Call DWORD PTR [xxxxxxx].

In any case, the above square bracket is always an address, pointing to an entry in the input address table, is a

DWORD, but it is this

DWORD is

The real address of the API function in memory. So we want to intercept one

The call of API, as long as it is simple

DWORD changed to our own function, then all about this

The API call will go to our own function, and the intercepting work will be successful. It should be noted here that the form of calling the custom function should be

The way the API calls, that is

STDCALL method, and

Delf in Delphi is

Pascal call mode, that is

Register mode, there is a big difference in the way of delivery of parameters.

In addition, the parameters of custom functions can be and originally

The API function is the same, but this is not necessary, and this will have some problems at some time, I will mention it later. So to intercept

The call of the API, first we have to get the address of the corresponding IAT. The system loads a process module into memory, actually

The PE file is almost unmounted to the address space of the process, and the module handle

HMODULE is actually the address of the module image in memory,

The address of some data items in the PE file is the offset relative to this address, so it is called a relative virtual address.

RVA,

Relative Virtual Address.

So we can

HMODULE starts, after a series of address offsets

IAT's address. But I have a simple way here, it uses an existing

API function

ImageDirectoryEntryTodata, it helps us in positioning

When IAT can take a few steps, save the offset address wrong, and go to the detour. But pure use

RVA from

HModule starts to position

The address of the IAT is actually not bother, and this is more helpful to

The structure of the PE file is understood. Above mentioned

The API function is

DBGHELP.DLL output (this is from

Win 2K has only begun, before this

ImageHLP.DLL is provided), detailed introduction to this function can be found

MSDN.

Find

After IAT, we only need to traverse it, find what we need.

API address, then use our own function address to overwrite it. A corresponding source code is given below:

Procedure redirectapicall; var importdesc: pimage_import_descriptor; firstthunk: pimage_thunk_data32; s: dword;

Begin

// Get an input to describe the first address of the structure list, each

DLL corresponds to one such structure

Importdesc: = ImageDirectoryEntryTodata (Pointer (HtargetModule), True, Image_Directory_ENTRY_IMPORT, SZ);

While Pointer (importdesc.name) <> nil do

Begin // Judgment is the required

DLL input description

IF stricomp (Pchar (Dllname), Pchar (HtargetModule ImportDesc.name) = 0 THEN BEGIN

//get

IAT's first address

Firstthunk: = pimage_thunk_data32 (HtargetModule ImportDesc.firstthunk);

While firstthunk.func <> NIL DO

Begin

if firstthunk.func = Olddressofapi Then

Begin

// Find a match

API address

......

//rewrite

API address

Break;

END;

Inc (firstthunk);

END;

END;

INC; ImportDesc

END;

END;

In the end, it is necessary to point out if we handle the hook.

DLL's exit target process, then call the function to call the function before exiting the original address, that is

The real address of the API, because once you

DLL exits, rewritten new address will point to a meaningless memory area, and then use it clearly an illegal operation.

Fives,

Replacement function writing

The front key is finished, one

The API hook is basically completed. However, there are some related things that need us to study, including how to do an alternative function.

Below is the step of doing an alternative function:

First of all, we don't lose general, we first assume that such an API function, its prototype is as follows:

Function SomeApi (Param1: Pchar; Param2: Integer): DWORD;

Then establish a function type with the same parameters and return values:

TYPE FUNCTYPE = Function (param1: pchar; param2: integer): DWORD;

Then we put

SomeApi function's address is stored

OldDress pointers. Then we can use the code for writing the function:

Function DummyFunc (param1: pchar; param2: integer): DWORD; begin ...

/ / Do some before calling

Result: = Functype (OldDress) (PARAM1, PARAM2);

// call the original

API function

......

/ / Do some of the calls after calling

END;

We will save the address of this function to

In Newaddress, then cover it with this address.

The address of the API. This time when the target process calls

When the API is actually called our own functions, we can do some operations, then call the original

The API function, the result is like anything. Of course, we can also change the input parameters, even shielded this

Call of API functions.

Although the above method is feasible, there is a significant shortcoming: the method of making this replacement function does not have versatility, only for a small number of functions. If only a few

The API wants to intercept, then it is only necessary to repeat it several times. But if you have a variety of

The API has to handle, their number of parameters and types, and the type of return value are different, or it is too efficient to use this method.

Indeed, the above given is just a simple and easier way to think, just a basic architecture of a replacement function. As I mentioned earlier, the replacement function is originally

The parameter type of the API function does not have to be the same. Generally, we can design a function that does not have a call parameter and has no return value, through certain skills, make it adapt to a variety of

The API function calls, but this requires you to have a certain understanding of the assembly language.

Let me talk about this in detail below.

First, let's take a look at the stack situation before being inside a function (here the function is called

STDCALL).

As can be seen from the example, the call parameters of the function are pressed into the stack in the order from the right to left (the stack is developed by the high-end to low-end), and it is also pressed into a function returned address. Before entering the function,

ESP is pointing to the return address. Therefore, we only need to

ESP 4 can get the call parameters of this function, and increase each parameter

4. In addition, when returning from the function, it is generally

The return value of the payment function is stored in EAX.

Understand the above knowledge, we can design a relatively universal replacement function, which uses it.

Delphi's inline assembly language features.

PROCEDURE DUMMYFUNC;

ASM Add ESP, 4 MOV EAX, ESP // Get the first parameter

MOV EAX, ESP 4 // Get the second parameters

......

/ / Do some processing, here to guarantee

ESP is restored after this

Call Olddress // Calling original

API function

......

/ / Do some other things

END;

Of course, this replacement function is still relatively simple, you can call some pure use

OP language write function or procedure to complete some more complex operations (if you use assembly to complete, then you can die), but you should be unified to stdcall how to call you, which makes them only Use the stack to deliver parameters, so you only need to master the changes in the stack. If you store the machine instructions corresponding to the above assembly code in a byte array, then use the address of the array as a function address, the effect is the same.

The above code is

Implementation in WIN 2K / XP & Delphi 6.0.

Six, postscript

Do one

The API hook is indeed not easy, especially for me.

Delphi people say, in order to solve a problem, often

OP,

C and assembly language information in Middle East Chase, find some unexpected things in the process of procedure, and yourself is a hand. However, I have finally made one.

The prototype of the API hook is still very happy, and the knowledge of computer systems has also mastered a lot, and it is not shallow. I just wanted to translate an article before writing this article.

Down's English information (URL is

Www.codeproject.com, the article name "

API Hook Revealed, the sample source code is used

VC is written, and there is a level of foreigners to admire foreigners, and the article is very depth, and each detail is very detailed).

However, if you turn over, I feel that I am a limited level. Although I understand it yourself, I don't know how to use Chinese to express it. So I have to think that I have used it. I can use some of them. In practice, the experience is experienced with the experience, but it has a little or not, but it is also a lot of time, and I have a lot of time (embarrassing, embarrassing!), I hope that the master should not laugh, please advise.

转载请注明原文地址:https://www.9cbs.com/read-24633.html

New Post(0)