The above finally finds the start position and end position of the game, so that you can perform dynamic scanning. This method is a pull method, which is very similar to the HTTP protocol. That is to say, you don't know when or when the game memory data is changed. Similar to this method, such as constantly scanning the database and checking whether records are added. Because the recipient will not notify you, you need to actively read the data, and the disadvantages are also shown. There are many problems like other active scans. This is not detailed here. Many game plug-ins also use this idea. For example, automatic drinking of blood and drinking of blue plug-ins usually scan the memory actively. The first point is to simulate the keyboard, call is advanced. In fact, call can be used in any language, including C # and VB. The principle is to write binary into the memory.CodeThe Code executed by a computer is essentially a binary number.
Now we can say that the method of hook api is passive and similar to IOC injection. I provide a function that allows the game to actively call, instead of actively querying the game status.
To Use API injection, we need to find a good injection point. For convenience of testing, we will take the following example. When Player A's pawns eat Player B's pawns, we need to deal with them now.
The hook api has multiple processing methods. Aside from non-standard PE file formats such as C #, the following describes the implementation of C ++. C ++ has two implementation methods: hook injection and DLL injection. There is an essential difference between hook injection and DLL injection. Hook injection is generally hotkey injection. For example, you can let the game use the F12 key to call out the code that we need to execute. This article also describes this method. DLL injection requires the game process to allocate a space, and then place the DLL in the space, so that the DLL and the game are in the same starting address, you can use the offset to directly operate. Their essential difference is that the processes loaded by DLL are different. I think Hook injection is more convenient.
First, create two projects. One is the dialog box application.ProgramOne is DLL, so you can use the MFC library for convenience. The application is relatively simple. There are two buttons on it. The events corresponding to the two buttons are the process of loading and releasing hooks.
// DLL handle
Hinstance hmod;
Dword pid;
// Enable the card recording function
Void Cjunqirpgplugdlg: onbnclickedok ()
{
// Todo: add the control notification handler code here
Hwnd = : Findwindow (null, l " Role Edition " );
If ( ! Hwnd ){
Afxmessagebox (L " Start the game first. " );
Return ;
}
DWORD tid = Getwindowthreadprocessid (hwnd, & PID );
Typedef bool (winapi * Installhook) (DWORD dwthreadid );
Hmod = Loadlibrary (L " Junqirpgext. dll " );
If (Hmod = Null ){
Afxmessagebox (L " DLL loading failed. " );
Return ;
}
Installhook enblehook;
Enblehook = (Installhook) getprocaddress (hmod, " _ Installhook @ 4 " );
If (Enblehook ){
( * Enblehook) (TID );
} Else {
Afxmessagebox (L " An error occurred while calling the method. " );
}
}
// Exit the card Recorder
Void Cjunqirpgplugdlg: onbnclickedcancel ()
{
// Todo: add the control notification handler code here
Typedef bool (winapi * Uninstallhook )();
Uninstallhook uhook;
Uhook = (Uninstallhook) getprocaddress (hmod, " _ Uninstallhook @ 0 " );
If (Uhook ! = Null ){
( * Uhook )();
Oncancel ();
} Else {
Afxmessagebox (L " The unmount function cannot be found. " , Mb_ OK, null );
Oncancel ();
}
}
DLL is the most important thing. Here, the injection point is the place where the sub-audio is played: 004119ed |. /75 0f jnz short junqirpg.004119fe004119ef |. | 68 acce4500 push junqirpg.0045ceac; Res \ eat.wav 004119f4 |> | B9 00bc4900 mov ECx, junqirpg.0049bc1_4119f9 |. | E8 c22b0100 call junqirpg.004255c0004119fe |> \ f605 c59a4900> test byte ptr ds: [499ac5], 40 select 004119ef |. | 68 acce4500 push junqirpg.0045ceac; Res \ eat.wav is used as the injection port. Generally, call or JMP is used as the injection method. The two statements and the subsequent data are five bytes, while the four-nation military flag occupies five bytes of several words, this operation is more convenient. If there are no five pieces of your own code nearby, the injection assembly code you write will be more complicated. First, the DLL needs to implement the two export functions installhook and uninstallhook called by the application. In. hfile definition # ifndef junqirpgapi # define junqirpgapi extern "C" _ declspec (dllimport) # endifjunqirpgapi bool winapi installhook (DWORD dwprocessid); junqirpgapi bool winapi uninstallhook. CPP file definition # define junqirpgapi extern "C" _ declspec (dllexport) // before the file header # include "junqirpgext. H "// defines variables and callback functions hhook g_hhook; handle hprocess; bool enable = false; // keyboard Event Callback (this is the hook) lresult callback keyboardproc (INT ncode, wparam, lparam); // cjunqirpgextapp initialize bool cjunqirpgextapp: initinstance (){ Cwinapp: initinstance (); DWORD pid = getcurrentprocessid (); hprocess =: OpenProcess (process_all_access, false, pid ); Return true;} // export function entry point: junqirpgapi bool winapi installhook (DWORD dwprocessid ){ If (g_hhook = NULL ){ G_hhook =: setwindowshookex (wh_keyboard, (hookproc) keyboardproc, theapp. m_hinstance, dwprocessid ); If (g_hhook! = NULL) Return true; } Return false;} // keyboard event. Press F12 to enable or disable the lresult callback keyboardproc (INT ncode, wparam, lparam ){ Lparam bkeyup = lparam & (1 <31 ); If (bkeyup & wparam = vk_f12 & ncode = hc_action ){ If (! Enable ){ Enable = true; Afxmessagebox (L "card reader opened! ", Mb_ OK, null ); Junqirpgcall call; Call. registercall (); } Else { Afxmessagebox (L "card reader closed! ", Mb_ OK, null ); Junqirpgcall call; Call. unregistercall (); } } Return: callnexthookex (g_hhook, ncode, wparam, lparam);} // export function entry point junqirpgapi bool winapi uninstallhook () {return: unhookwindowshookex (g_hhook );} now we need to implement the junqirpgcall class. The registercall of this class is responsible for injecting the hook api and the unregistercall is responsible for restoring. The following describes how to implement Sub-segmentation. // What we need to do when eating a child occurs is void _ stdcall insideeataction () {afxmessagebox (L "eat a child! ", Mb_ OK, null);} // set the address access permission bool junqirpgcall: insideto (lpcvoid lpaddress) {region minfo; memory_basic_information * lpminfo = & minfo; virtualquery (lpaddress, lpminfo, sizeof (minfo); If (lpminfo-> protect = page_execute_readwrite) {return true;} else {DWORD dwoldprotect; If (virtualprotect (lpminfo-> baseaddress, lpminfo-> regionsize, page_execute_readwrite, & dwoldprotect) {return True;} else {return false ;}}// game sub-injection point/* 004119ef |. 68 acce4500 push junqirpg.0045ceac; Res \ eat.wav // injection point 004119f4 |> B9 00bc4900 mov ECx, junqirpg.0049bc4174119f9 |. e8 c22b0100 call junqirpg.004175c0 */_ declspec (naked) byte * _ stdcall insideeat () {_ ASM {pushad call insideeataction // call our own method popad push 0x0045ceac // restore stack mov ECx, 0x004119f4 JMP ECx; // jump to the next execution }}/*************************** * ****************************** Inject and eat sub-call ***** **************************************** * ************/void junqirpgcall:: insideeatcall (void) {If (insideto (lpcvoid) 0x004119f4) {// the address of this parameter is not important, it is important that the array of this address is 5 bytes * (byte *) 0x004119ef = 0xe9; // E9 is the JMP long hop machine code * (DWORD *) 0x004119f0 = (DWORD) insideeat-0x004119ef-5; // calculate the cheap insideeat address }}/****************************** ********** *** **************************************** * ***/Void junqirpgcall:: uninsideeatcall (void) {If (insideto (lpcvoid) 0x004119ef) {* (byte *) 0x004119ef = 0x68; // 68 is the push machine code * (DWORD *) 0x004119f0 = 0x45ceac; // 0x45ceac is the original value. After being pushed into the stack, it will become acce4500} Here, the restored data segment must exist. Otherwise, when the game does not exit, if the plug-in exits, an error is reported. The reason is that the game code is changed and will jump to a function pointer of the DLL. Now that the DLL exits, this function will be gone and a memory read/write error will be reported. In this case, after testing (you must press F12 to start it, which is a problem with Hook injection), you will find that the Eat sub-dialog box will pop up when there is a eat sub-action, and this dialog box appears too many times, it is a huge disturbance to the game, and the child is gone. This indicates that the dialog box cannot be used for disconnection. This problem is caused by a State that has not been changed. The solution is to find a place that only calls once and inject code again.