There are many basic apihook knowledge, such as DLL knowledge, hook knowledge, and the relationship between system processes and threads. For details, see my other two articles: "My DLL (Dynamic Link Library) learning notes" and "my hook learning notes ". :) The focus of this article is as follows: Analyze apihook based on the source code of apihook.
1. dll part of apihook
/// // Apihook_dll.cpp /////// /////////////////////////////////
// Rivershan is written in 2002.9.23 //
//////////////////////////////////////// //////////////////////////////////////// /////////
# Include "stdafx. H"
# Include "apihook_dll.h"
# Include <imagehlp. h>
# Include <tlhelp32.h>
# Pragma comment (Lib, "imagehlp") // defines the global shared data segment
# Pragma data_seg ("shared ")
Hmodule hmoddll = NULL;
Hhook = NULL;
# Pragma data_seg ()
# Pragma comment (linker, "/section: shared, RWS") // you can specify the attribute of the global shared data segment.
/// // Dllmain function/ ////////////////////////////////////////
// DLL entry point
Bool apientry dllmain (hmodule,
DWORD ul_reason_for_call,
Lpvoid lpreserved
)
{
Switch (ul_reason_for_call)
{
Case dll_process_attach:
// If (shook)
Case dll_process_detach:
Uninstallhook ();
Break;
}
Hmoddll = hmodule;
Return true;
}
/// // Hookoneapi function/ ////////////////////////////////////////
// Key function for IAT conversion. Its Parameter meaning:
// Pszcalleemodulename: name of the module to be hooked
// Pfnoriginapiaddress: Address of the API function to be replaced
// Pfndummyfuncaddress: Address of the module name to be hooked
// Hmodcallermodule: name of the module to be searched. If it is not assigned a value,
// All called modules of the program that will be assigned an enumerated Value
Void winapi hookoneapi (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule)
{
Ulong size;
// Obtain the pointer to the image_directory_descriptor array in the import file of the PE.
Pimage_import_descriptor pimportdesc = (pimage_import_descriptor)
Imagedirectoryentrytodata (hmodcallermodule, true, image_directory_entry_import, & size );
If (pimportdesc = NULL)
Return;
// Search for the record to see if there is any DLL we want
For (; pimportdesc-> name; pimportdesc ++)
{
Lpstr pszdllname = (lpstr) (pbyte) hmodcallermodule + pimportdesc-> name );
If (lstrcmpia (pszdllname, pszcalleemodulename) = 0)
Break;
}
If (pimportdesc-> name = NULL)
{
Return;
}
// Find the function we want
Pimage_thunk_data pthunk =
(Pimage_thunk_data) (pbyte) hmodcallermodule + pimportdesc-> firstthunk); // IAT
For (; pthunk-> u1.function; pthunk ++)
{
// PPFN records the address of the function corresponding to the IAT table item
Proc * PPFN = (Proc *) & pthunk-> u1.function;
If (* PPFN = pfnoriginapiaddress)
{
// If the address is the same, find the function we want and rewrite it to point it to the function we define.
Writeprocessmemory (getcurrentprocess (), PPFN, & (pfndummyfuncaddress ),
Sizeof (pfndummyfuncaddress), null );
Return;
}
}
}
// Find the DLL module applied by the linked Process
Bool winapi hookallapi (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule)
{
If (pszcalleemodulename = NULL)
{
Return false;
}
If (pfnoriginapiaddress = NULL)
{
Return false;
}
// If the name of the module to be linked is not passed in, enumerate all referenced modules of the linked process,
// Search for the corresponding function names passed in to these modules
If (hmodcallermodule = NULL)
{
Memory_basic_information minfo;
Hmodule hmodhookdll;
Handle hsnapshot;
Moduleentry32 me = {sizeof (moduleentry32 )};
// Moduleentry32: Describes the struct of a module applied by a specified process.
Virtualquery (hookoneapi, & minfo, sizeof (minfo ));
Hmodhookdll = (hmodule) minfo. allocationbase;
Hsnapshot = createconlhelp32snapshot (th32cs_snapmodule, 0 );
Bool Bok = module32first (hsnapshot, & Me );
While (Bok)
{
If (Me. hmodule! = Hmodhookdll)
{
Hmodcallermodule = me. hmodule; // value assignment
// Me. hmodule: Point to each module of the currently linked Process
Hookoneapi (pszcalleemodulename, pfnoriginapiaddress,
Pfndummyfuncaddress, hmodcallermodule );
}
Bok = module32next (hsnapshot, & Me );
}
Return true;
}
// If it is uploaded, search
Else
{
Hookoneapi (pszcalleemodulename, pfnoriginapiaddress,
Pfndummyfuncaddress, hmodcallermodule );
Return true;
}
Return false;
}
/// // Unhookallapihooks function // ///////////////////////////////////
// Cancel IAT modification by making the pfndummyfuncaddress and pfnoriginapiaddress equal
Bool winapi unhookallapihooks (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule)
{
Proc temp;
Temp = pfnoriginapiaddress;
Pfnoriginapiaddress = pfndummyfuncaddress;
Pfndummyfuncaddress = temp;
Return hookallapi (pszcalleemodulename, pfnoriginapiaddress,
Pfndummyfuncaddress, hmodcallermodule );
}
/// // Getmsgproc function //// ////////////////////////////////////
// Hook procedure. It is not the same as other hooks and does not make any sense. Continue to call the next hook to form a loop.
Lresult callback getmsgproc (INT code, wparam, lparam)
{
Return callnexthookex (hhook, code, wparam, lparam );
}
/// // Installhook function // ///////////////////////////////////
// Install or uninstall the hook. The bool ishook parameter is a flag
// Initialize the API Function
// The hook type we have installed here is wh_getmessage
Void _ declspec (dllexport) winapi installhook (bool ishook, DWORD dwthreadid)
{
If (ishook)
{
Hhook = setwindowshookex (wh_getmessage, (hookproc) getmsgproc, hmoddll, dwthreadid );
// Getprocaddress (getmodulehandle ("gdi32.dll"), "exttextouta"): Get the address of the function to be hooked in the DLL
Hookallapi ("gdi32.dll", getprocaddress (getmodulehandle ("gdi32.dll "),
"Textoutw"), (Proc) & h_textoutw, null );
Hookallapi ("gdi32.dll", getprocaddress (getmodulehandle ("gdi32.dll "),
"Textouta"), (Proc) & h_textouta, null );
}
Else
{
Uninstallhook ();
Unhookallapihooks ("gdi32.dll", getprocaddress (getmodulehandle ("gdi32.dll "),
"Textoutw"), (Proc) & h_textoutw, null );
Unhookallapihooks ("gdi32.dll", getprocaddress (getmodulehandle ("gdi32.dll "),
"Textouta"), (Proc) & h_textouta, null );
}
}
/// // Uninstallhook function/ ///////////////////////////////////
// Uninstall the hook
Bool winapi uninstallhook ()
{
Unhookwindowshookex (hhook );
Return true;
}
/// // H_textouta function/ ////////////////////////////////////////
// Our replacement function can implement the functions we need to do in it
// Here, a dialog box is displayed to indicate which function is replaced.
Bool winapi h_textouta (HDC, int nxstart, int nystart, lpcstr lpstring, int cbstring)
{
MessageBox (null, "textouta", "apihook_dll --- rivershan", mb_ OK );
Textouta (HDC, nxstart, nystart, lpstring, cbstring); // return the original function to display characters
Return true;
}
/// // H_textoutw function/ ////////////////////////////////////////
// Same as above
Bool winapi h_textoutw (HDC, int nxstart, int nystart, lpcwstr lpstring, int cbstring)
{
MessageBox (null, "textoutw", "apihook_dll --- rivershan", mb_ OK );
Textoutw (HDC, nxstart, nystart, lpstring, cbstring); // return the original function to display characters
Return true;
}
**************************************** **************************************** **************
**************************************** **************************************** **************
//// // Apihook_dll.h /////// /////////////////////////////////
// Rivershan is written in 2002.9.23 //
//////////////////////////////////////// //////////////////////////////////////// /////////
// DLL header file for declaring Functions
Void _ declspec (dllexport) winapi installhook (bool, DWORD );
Bool winapi uninstallhook ();
Lresult callback getmsgproc (INT code, wparam, lparam );
Void winapi hookoneapi (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule );
Bool winapi hookallapi (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule );
Bool winapi unhookallapihooks (lpctstr pszcalleemodulename, Proc pfnoriginapiaddress,
Proc pfndummyfuncaddress, hmodule hmodcallermodule );
Bool winapi h_textouta (HDC, Int, Int, lpcstr, INT );
Bool winapi h_textoutw (HDC, Int, Int, lpcwstr, INT );
Bool winapi h_exttextouta (HDC, Int, Int, uint, const rect *, lpcstr, uint, const int *);
Bool winapi h_exttextoutw (HDC, Int, Int, uint, const rect *, lpcwstr, uint, const int *);
**************************************** **************************************** **************
**************************************** **************************************** **************
; Def file of apihook_dll
Library apihook_dll.dll
Export
Installhook
Ii. EXE part of apihook
/// // Apihook_exedlg.cpp /////////// //////////////////////////////
// Rivershan is written in 2002.9.23 //
//////////////////////////////////////// //////////////////////////////////////// /////////
# Include "stdafx. H"
# Include "apihook_exe.h"
# Include "apihook_exedlg.h"
# Include "apihook_dll.h"
# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif
//////////////////////////////////////// /////////////////////////////////////
// Capihook_exedlg Dialog
Capihook_exedlg: capihook_exedlg (cwnd * pparent/* = NULL */)
: Cdialog (capihook_exedlg: IDD, pparent)
{
// {Afx_data_init (capihook_exedlg)
// Note: The classwizard will add member initialization here
//} Afx_data_init
// Note that loadicon does not require a subsequent destroyicon in Win32
M_hicon = afxgetapp ()-> loadicon (idr_mainframe );
}
Void capihook_exedlg: dodataexchange (cdataexchange * PDX)
{
Cdialog: dodataexchange (PDX );
// {Afx_data_map (capihook_exedlg)
// Ddx_control (PDX, idc_edit1, m_edit );
//} Afx_data_map
}
Begin_message_map (capihook_exedlg, cdialog)
// {Afx_msg_map (capihook_exedlg)
On_wm_paint ()
On_wm_querydragicon ()
On_bn_clicked (idc_button_out, onbuttonout)
On_bn_clicked (idc_button_begin, onbuttonbegin)
On_bn_clicked (idc_button_stop, onbuttonstop)
//} Afx_msg_map
End_message_map ()
//////////////////////////////////////// /////////////////////////////////////
// Capihook_exedlg message handlers
Bool capihook_exedlg: oninitdialog ()
{
Cdialog: oninitdialog ();
// Set the icon for this dialog. The framework does this automatically
// When the application's main window is not a dialog
Seticon (m_hicon, true); // set big icon
Seticon (m_hicon, false); // set small icon
// Todo: add extra initialization here
Return true; // return true unless you set the focus to a control
}
// If you add a Minimize button to your dialog, you will need the code below
// To draw the icon. For MFC applications using the document/view model,
// This is automatically done for you by the framework.
Void capihook_exedlg: onpaint ()
{
If (isiconic ())
{
Cpaintdc DC (this); // device context for painting
Sendmessage (wm_iconerasebkgnd, (wparam) DC. getsafehdc (), 0 );
// Center icon in client rectangle
Int cxicon = getsystemmetrics (sm_cxicon );
Int cyicon = getsystemmetrics (sm_cyicon );
Crect rect;
Getclientrect (& rect );
Int x = (rect. Width ()-cxicon + 1)/2;
Int y = (rect. Height ()-cyicon + 1)/2;
// Draw the icon
DC. drawicon (X, Y, m_hicon );
}
Else
{
Cdialog: onpaint ();
}
}
// The system callthis to obtain the cursor to display while the user drags
// The minimized window.
Hcursor capihook_exedlg: onquerydragicon ()
{
Return (hcursor) m_hicon;
}
/// // Onbuttonout function/ /////////////////////////////////////
// Use the textout Function
Void capihook_exedlg: onbuttonout ()
{
// Todo: add your control notification handler code here
HDC =: getdc (getsafehwnd ());
: Textouta (HDC, 0, 0, "apihook_exe --- rivershan", 30 );
Updatewindow ();
}
/// // Onbuttonbegin function/ ///////////////////////////////////
// Start the hook. Here we are hanging our own apihook_exe program.
Void capihook_exedlg: onbuttonbegin ()
{
DWORD dwthreadid = getwindowthreadprocessid (m_hwnd, null); // obtain the process ID
Installhook (true, dwthreadid );
}
/// // Onbuttonstop function/ ///////////////////////////////////
// Cancel the hook
Void capihook_exedlg: onbuttonstop ()
{
Installhook (false, 0 );
}
Iii. Integration of apihook
1. Use VC ++ to create a Win32 dynamic-Link Library program named apihook_dll. Next, select the second a simple DLL project;
2. Create a new object named apihook_dll.h. Delete the original content in the apihook_dll.cpp file in the project, and copy all the content in the above apihook_dll.cpp and apihook_dll.h files to the. cpp and. H files of the new project;
3. Create a text file named apihook_dll.def. Copy the content of the def File above.
4. Compile;
5. Create an MFC Appwizard (exe) program named apihook_exe. Next, select the third item, based on the dialog box program, and Other Default items;
6. Delete the controls in the original dialog box, and create three buttons: idc_button_begin, idc_button_stop, idc_button_out, and caption: bigin hook, stop hook, and text out. Do not leave these three buttons at the top of the dialog box client area;
7. Copy the apihook_dll.h file to the directory of the apihook_exe program and add it to the header folder of apihook_exe.
8. Delete the original content in the apihook_exedlg.cpp file of the project, and copy all the content in the above apihook_exedlg.cpp file to the. cpp file of the new project;
9. Open the project-> setting menu, select the fourth link, and add the path to the Lib file of our DLL in object/library moduls: ../apihook_dll/debug/apihook_dll.lib;
10. Compile;
11. Place the apihook_dll.dll file in the same folder of the apihook_dll.exe program;
12. Run the program and click the bigin hook button to start the hook. Click the text out button to pop up the dialog box and display the words to be displayed in the program. Click Stop hook and then click the text out button. No dialog box is displayed.
Iv. Instructions
1. My hookapi is implemented using Jeffrey Richter's rewrite program IAT. You can also use the jump function entry point method. I have not studied this. :)
2. Some of my experiences:
The so-called hookapi is to rewrite the program's IAT, and then call the function that I wrote to replace the original API function. In our own API functions, we can do what we want. After that, you can pass back the original function or not, as long as you have designed it.
The so-called call of your own function is to pass all the original function parameters to my replacement function. We can use these parameters to do what we want to do. However, for the purpose of the hook set by Microsoft (I think so), I don't want to check whether the replacement function is the original function, as long as the parameters and return values meet the conditions, yes. The Return Value of the replacement function is preferably the original function. Otherwise, an error may occur.
During hookapi, the EXE program is used to hook, inject the DLL into the program to be hooked, and return the ID or global hook of the process to be hooked, to query the IAT of the module to be mounted. If it is not injected, the system will not ask you to query the IAT. The DLL is used to determine which function to be attached and which DLL is the same.
Rivershan was originally created on