Compile the implementation of hook api in ring3

Source: Internet
Author: User
Tags what parameter

Compile ring3 to implement hook api favorites
Guidance:
Question: Compile ring3 to implement hook api [original]
Author: insecure
Time: 2006-07-: 39
Chain: http://bbs.pediy.com/showthread.php? T = 28895
Compile the implementation of hook api in ring3 (secondary modification)
[Article Title] compile the implementation of hook api in ring3
[Author] nohacks (non-secure, hacker0058)
[Author's homepage] hacker0058.ys168.com
[Article Source] xuexue Forum (bbs.pediy.com)
=======================================[ Compile ring3 to implement the hook api] ====== ============================
Author: nohacks
Emil: kker.cn@163.com
Version: 1.1
Date: 7.18.2006
  
===== [1. content] ============================================== ========
1. Content
2. Introduction
2.1 What is hook api?
2.2 Introduction to API hook applications
2.3 API hook principles
3. hook Method
3.1 rewrite the IAT import Table Method
3.2 rewrite the memory address JMP Method
4. Assembly implementation
4.1. Code
4.2. Analysis
5. Conclusion
===== [2. introduction] =================================================== ============
This article describes how to hook up API functions in OS windows. All examples are in the NT-based Windows Version NT4.0
And above (Windows NT 4.0, Windows 2000, Windows XP ). It may also work in other Windows systems.
You should be familiar with Windows processes, compilers, and some API functions to understand the content in this article.
===== [2.1 What is hook api?] ======================================
  
The so-called hook refers to the hook, and the API refers to the programming interface that Windows opens to programmers, so that at the user level
In order to control the operating system, that is, general applications need to call APIs to complete some functions.
That is, these applications can be intercepted before calling the real system API, so as to perform some processing before calling the real API.
Yes.
===== [2.2 API hook application introduction] ============================== =====
  
API hook is widely used in screen buzzwords, network firewalls, virus Trojans, shelling software, serial infrared communication, out-of-game
The Chinese meaning of API hook in Internet communication and other fields is to hook the API, pre-process the API, and first execute our function, for example
For example, we use the API Hook Technology to mount the exitwindowsex API function, so that the shutdown fails and the zwopenprocess function (for example, Lao Wang's
Encryptpe), hide processes, and so on ......
===== [2.3 API hook principles] ============================ ==========
  
The hook api has a principle that the original functions of the hooked API cannot be affected. Just like doctors saving lives,
If the virus in the patient's body is killed and the patient is also dead, it makes no sense to "save. If you hook an API
After that, your goal is achieved, but the original functions of the API are invalid. This is not a hook, but a replace, the normal functions of the operating system.
And even crash.
==== [3. hook method] ============================================ ==========
In general, there are two common hook api methods:
3.1 rewrite the IAT import Table Method
Modify the IAT table of the executable file (that is, the input table) because the table records all the function addresses that call the API, you only need
You can change the address to the address of your function, but there is a limitation, because some programs will shell, this will hide the real IAT table
To make the method invalid.
3.2 rewrite the memory address JMP Method
Directly jump, change the entry or exit several bytes of the API function, so that the program jumps to its own function, this method is not shelled by the program
. This technology is not complicated to say, that is, the technology that changes the program process. In CPU commands, several commands can be changed.
Procedures: JMP, call, Int, RET, retf, iret, and other commands. Theoretically, you only need to change any machine code at the API entry and exit.
You can hook them up. Next I will talk about the common methods to rewrite the API endpoint:
  
Because it works in ring3 mode, we cannot directly modify the physical memory, but can only open the changes one by one, but the specific method is divided
There are several operations:
<1> first, rewrite the first byte of the API. To implement the function of the original API, you must restore the modified byte before calling the original API.
It will be a bit difficult to implement after it is used up, but it is the simplest. In theory, there is a possibility of missing hooks, because we restored the API first. If
Before that, the program calls the API and may escape the hook!
(2) Save the overwritten assembly code, simulate the overwritten function in the substitution function, and then call the original function (original address + overwritten ).
The length of the Assembly command is different (for example, the JMP command we write occupies 5 characters ).
But the five bytes we write do not necessarily occupy one or more complete commands, and seven bytes may need to be saved,
In order to not disrupt the original functions of the program, you need to write a large judgment system to determine the length of the command, such an assembly program already exists on the Internet
(The lde32 written by z0mbie) is very complicated!
(3) back up the hook function and call the backup function in the replacement function when calling it. To avoid the trouble, you can directly back up the entire
The disadvantage of DLL is that it sacrifices too much memory. This method is generally not recommended!
  
===== [4. assembly implementation] ================================================= ==========
This article is based on the 2nd methods! Based on the principle of ease of use and difficulty, let's talk about its 1st operating methods first today.
  
Let's take the API function exitwindowsex as an example. below is the original entry section of exitwindowsex that I blocked in OD.
77d59e2d $ 8bff mov EDI, EDI
77d59e2f. 55 push EBP
77d59e30. 8bec mov EBP, ESP
77d59e32. 83ec 18 sub ESP, 18
......
If we change the entry point of exitwindowsex to the following, what will happen?
77d59e2d B8 00400000 mov eax, 4000
77d59e32 ffe0 JMP eax
......
We can imagine that when the program is executed at 77d59e32, the process will change to 00400000.
If our 00400000 is such a sub-process:
======================================
Myapi proc BS: DWORD, dwreserved: DWORD; like exitwindowsex, there are two parameters
Do what you want
......
Here, the API entry point is used to change the code of the original machine code.
If you are backing up the entire DLL, you can directly call the backup API. You do not need to change it. There is no possibility of missing the API!
Invoke exitwindowsex, BS, dwreserved
  
Hook api code
  
. Endif
MoV eax, true
RET
======================================
Here, myapi is the same as the exitwindowsex parameter, because the program jumps in the API entry part, according
Stdcall Convention (the parameter data is pressed from right to left, and the stack recovery is handed over to the called user). At this time, the stack has not been recovered. We
The parameter data retrieved in the sub-process is still valid. We can execute our own code here, and you can decide whether to continue with the original parameter or change
You can change the parameters before calling the original API, or do nothing. Of course, before calling the API, we need to restore the modified API (you can use it in advance ).
The API function readprocessmemory reads the first several bytes of the original API for backup.) After the call, it is changed back to continue to hook the API.
The method may leak the API (the reason has already been mentioned). If you think this method is inappropriate, because the system DLL is generally not large, you can backup it.
The entire DLL.
Below I will list several steps of the HOOK API under ring3:
1. Get the entry point for the API to be checked
2. Modify the page of the API entry point to ensure read/write mode.
3. Use readprocessmemory to read several bytes of backup at the API entry point
4. Use writeprocessmemory to modify the API entry point in the following format:
  
MoV eax, 4000
  
JMP eax
4000 must be replaced by a subprogram address that is the same as the original API parameter.
In this subroutine, we decide what parameter to use to call the original API, but we need to change the first 8 bytes of the backup before calling it.
After the call, it is checked.
===== [4.1. code] ============================================ ==========
As mentioned above, this process is checked. To hook all processes, you can use a global hook. You need a separate DLL. We can
Hook the API in the DLL dll_process_attach event
==================================== Hookdll. DLL ====================================
. 486
. Model flat, stdcall; parameter transfer convention is stdcall (from right to left, stack recovery is handed over to the caller)
Option Casemap: None
Include/masm32/include/Windows. inc
Include/masm32/include/kernel32.inc
Includelib/masm32/lib/kernel32.lib
Include/masm32/include/user32.inc
Includelib/masm32/lib/user32.lib
Hookapi struct
A byte?
Pmyapi DWORD?
D byte?
E byte?
Hookapi ends
Subroutine Declaration
Writeapi proto: DWORD,: DWORD
Myapi proto: DWORD,: DWORD
Getapi proto: DWORD,: DWORD
Initialized data
. Data
Hinstance dd 0
Wprocess dd 0
Hacker hookapi <>
CommandLine lpstr?
Papi1 DWORD?
Myapi1 DWORD?
Apibak1 dB 10 DUP (?)
Dllname1 DB "user32.dll", 0
Apiname1 DB "exitwindowsex", 0
If the program below MDB dB wants to shut down the computer, do you want to stop it? ", 0
Uninitialized data
. Data?
Hhook dd?
Hwnd dd?
Program code segment
. Code
Dllentry proc hinst: hinstance, reason: DWORD, reserved1: DWORD
  
  
. If reason = dll_process_attach; this event is generated when the DLL is loaded.
Push hinst
Pop hinstance
Invoke getcommandline
MoV CommandLine, eax; get program command line
Initialization
MoV hacker. A, 0b8h; MoV eax,
MoV hacker. d pmyapi; 0x000000
MoV hacker. D, 0ffh; JMP
MoV hacker. E, 0e0h; eax
  
Invoke getcurrentprocess; obtain the pseudo Process Handle
MoV wprocess, eax
  
Invoke getapi, ADDR dllname1, ADDR apiname1; obtain the API address
  
MoV papi1, eax; save API address
Invoke readprocessmemory, wprocess, papi1, ADDR apibak1, 8, null; back up the first 8 bytes of the original API
MoV hacker. pmyapi, offset myapi; 0x0000. Here, set the function address to replace the API.
Invoke writeapi, wprocess, papi1, ADDR hacker, size hookapi; HOOK API
. Endif
. If reason = dll_process_detach
Invoke writeapi, wprocess, papi1, ADDR apibak1, 8; restore API
. Endif
MoV eax, true
RET
Dllentry endp
Getmsgproc proc ncode: DWORD, wparam: DWORD, lparam: DWORD
Invoke callnexthookex, hhook, ncode, wparam, lparam
MoV eax, true
  
RET
Getmsgproc endp
Installhook proc
  
Invoke setwindowshookex, wh_getmessage, ADDR getmsgproc, hinstance, null
MoV hhook, eax
RET
Installhook endp
Uninstallhook proc
Invoke unhookwindowshookex, hhook
Invoke writeapi, wprocess, papi1, ADDR apibak1, 8
RET
Uninstallhook endp
Getapi proc dllnameaddress: DWORD, apinameaddress: DWORD
Invoke getmodulehandle, dllnameaddress; obtain the DLL module handle
  
. If eax = NULL
  
Invoke loadlibrary, dllnameaddress; load DLL
  
. Endif
  
Invoke getprocaddress, eax, apinameaddress; obtain the API address
  
MoV eax, eax
  
RET
Getapi endp
==================================== Below is the core section ========== ========================
Writeapi proc process: DWORD, papi: DWORD, ptype: DWORD, psize: DWORD
Local MBI: memory_basic_information
Local msize: DWORD
Return page Virtual Information
Invoke virtualqueryex, process, papi, addr mbi, sizeof memory_basic_information
Change to read/write mode
Invoke virtualprotectex, process, MBI. baseaddress, 8 h, page_execute_readwrite, ADDR
MBI. Protect
Start writing memory
Invoke writeprocessmemory, process, papi, ptype, psize, null
Push eax
Change to read-only mode
Invoke virtualprotectex, process, MBI. baseaddress, 8 h, page_execute_read, addr mbi. Protect
Pop eax
RET
Writeapi endp
The parameter of the alternative API must be the same as that of the original API.
Myapi proc BS: DWORD, dwreserved: DWORD
Invoke MessageBox, null, CommandLine, ADDR mdb, mb_yesno; the pop-up information box selects whether to block
. If eax = 7; if no
Invoke writeapi, wprocess, papi1, ADDR apibak1, 8; restore API first
  
Invoke exitwindowsex, BS, dwreserved; then call the API
  
Invoke writeapi, wprocess, papi1, ADDR hacker, sizeof hookapi; change it back after calling
  
. Endif
MoV eax, true
RET
Myapi endp
End dllentry
================================ Hookdll. def ==================================
Library hookdll
Exports installhook
Exports uninstallhook
===== [4.2. analysis] ============================================== ==========
Hookapi struct
A byte?
Pmyapi DWORD?
D byte?
E byte?
Hookapi ends
For ease of understanding and use, I have defined a structure: This structure has four members. The first member, A, is a byte type.
0b8h (mov eax), pmyapi is an integer type, used to put the address of our alternative API function (0x000), 3rd and 4th members respectively.
For JMP and eax (JMP eax), the connection is mov, 0x0000; JMP eax
. If reason = dll_process_attach
Push hinst
Pop hinstance
Invoke getcommandline
MoV CommandLine, eax
Initialization
MoV hacker. A, 0b8h; MoV eax,
MoV hacker. d pmyapi; 0x0000
MoV hacker. D, 0ffh; JMP
MoV hacker. E, 0e0h; eax
Invoke getcurrentprocess
MoV wprocess, eax
When the DLL is loaded, we first save the module handle, read the program command line, initialize the hookapi structure, and write
Command (written after pmyapi) and call getcurrentprocess to retrieve the pseudo handle of the process so that the memory can be written later.
Invoke getapi, ADDR dllname1, ADDR apiname1
  
MoV papi1, eax
Invoke readprocessmemory, wprocess, papi1, ADDR apibak1, 8, null
  
MoV hacker. pmyapi, offset myapi; 0x0000
Invoke writeapi, wprocess, papi1, ADDR hacker, size hookapi; HOOK API
Next, use the sub-process getapi to retrieve the entry point of the API to be checked, and use readprocessmemory to back up the entry point in 8 bytes and write
Pmyapi calls the Child Program writeapi to rewrite the API entry point. I am not going to elaborate on this child program. It is very simple, just a few
The core of the API is to rewrite the memory through writeprocessmemory.
. If reason = dll_process_detach
Invoke writeapi, wprocess, papi1, ADDR apibak1, 8
. Endif
MoV eax, true
RET
If the DLL is uninstalled, the replacement function (myapi) in the DLL will be invalid. If the program calls this
Api. Therefore, we must restore the API before the DLL is detached.
To sum up, as long as the program loads this DLL, The exitwindowsex of this program will be hooked up by us. What can we do next?
Let all programs load this DLL? In this case, you need to install the global HOOK:
Installhook proc
  
Invoke setwindowshookex, wh_getmessage, ADDR getmsgproc, hinstance, null
  
Invoke writeapi, wprocess, papi1, ADDR hacker, sizeof hookapi
MoV hhook, eax
RET
Installhook endp
Use setwindowshookex to install hooks. The last parameter determines whether the hook is local or system-wide. If this value
If it is null, the hook will be interpreted as within the system range, so that it can monitor all processes and their threads.
If the function is successfully called, the hook handle is returned in eax; otherwise, null is returned. We must save the handle because
We need it to uninstall the hook. We can see that the hook type we created is wh_callwndproc.
When a message is sent to the system, it is loaded to the process space, so that the DLL initialization function is called to complete the real hook. It is worth mentioning that:
To call setwindowshookex to install the hook, the DLL of our GUI program will not be
Unhookwidowhookex uninstalls, so there is only one dll_process_attach event.
Hook api once!
Let's look back at the hook callback function:
Getmsgproc proc ncode: DWORD, wparam: DWORD, lparam: DWORD
Invoke callnexthookex, hhook, ncode, wparam, lparam
MoV eax, true
  
RET
Getmsgproc endp
We can see that callnexthookex is called to send the message to the next link in the hook chain for processing, because here the API Function
The only role of setwindowshookex is to let the process load our DLL.
Uninstallhook proc
Invoke unhookwindowshookex, hhook
Invoke writeapi, wprocess, papi1, ADDR apibak1, 8
RET
Uninstallhook endp
To uninstall a hook, call the unhookwidowhookex function. This function has only one parameter, that is, the handle of the hook to be detached. Hook
After the sub-uninstall, we also need to restore the APIs of our GUI program.
Library hookdll
Exports installhook
Exports uninstallhook
We publish the installhook and uninstallhook functions in the DLL to facilitate program calls, so that we only need to call
With installhook, you can install global hooks to hook up the APIs in all programs: exitwindowsex and execute our customized child programs!
If you do not need it, you can call uninstallhook to uninstall the global hook.
Note: For remote hooks, hook functions must be placed in the DLL, which will be reflected in other process spaces. When
When Windows maps DLL to other process spaces, data segments are not mapped. In short, all processes share only the DLL
As for the data segment, each process will have its own copy. This is a problem that is easily overlooked. You may take it for granted
It is assumed that the values saved in the DLL can be shared among all the processes mapped to the DLL. Normally
Dll processes all have their own data segments, so in most cases, your program runs well. But the hook function is not like
Here. For hook functions, the DLL data segment must be the same for all processes. In this way, you must set the data segment to be shared.
Of:
Generally, the target file has three segments: Text, data, and BSS.
Put the code in the. Text Segment, which is read-only and runable.
Put static data in the. Data segment, which will be placed in the EXE file. This segment can be read and written, but cannot run.
Dynamic Data is placed in the. BSS segment. This data is not put into the EXE file and is allocated only after the EXE file is loaded into the memory.
You can achieve this by specifying the segment attribute in the Link switch:
/Section: name, [E] [r] [W] [s] [d] [k] [l] [p] [x]
S indicates sharing. The initial segment name is. Data, And the uninitialized segment name is. BSS. If you want to write
DLL, and to share its uninitialized data segments among all processes, you must do this:
  
Link/section:. BSS [s]/dll/subsystem: Windows ..........
Otherwise, your global hooks will not work properly!
===== [5. conclusion] ================================================ ============
I welcome anyone to come up with more hook methods that are not mentioned here. I'm sure there will be many. Are you welcome to add me?
Is a very detailed method. You can also complete other methods that I am too lazy to write and send the source code to me. The purpose of this document is to demonstrate the Hook Technology
I hope I have done it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.