How to write a global hook to hook the API in the system

HOOK API is an eternal topic. Without HOOK, many technologies will be difficult to realize, or may not be realized at all. The API mentioned here is an API in a broad sense, including interrupts in DOS, APIs in WINDOWS, interrupt services, IFS and NDIS filtering, etc. For example, the familiar instant translation software is realized by HOOK TextOut () or ExtTextOut (). Before using these two functions to output text, the operating system will replace the corresponding English with Chinese to realize instant translation. The same is true for IFS and NDIS filtering. Before reading and writing the disk and sending and receiving data, the system will call the callback function provided by the third party to judge whether the operation can be released. It is different from the ordinary HOOK and is allowed by the operating system, which provides an interface for installing callback functions. Even if there is no HOOK, there is no virus, because the viruses in DOS and WINDOWS realize their functions through HOOK system services: the virus in DOS infects files (file viruses) through HOOK INT 2 1 and infects boot sectors through HOOK INT 13; Viruses under WINDOWS infect files by hooking system API (including RING0 layer and RING3 layer) or installing IFS (the method used by CIH virus). Therefore, it can be said that "without HOOK, there would be no colorful software world today". Because it involves patents and intellectual property rights, or trade secrets, Microsoft has always discouraged people from hooking its system API, and provided other filtering interfaces such as IFS and NDIS, which are also open to meet the needs of anti-virus software and firewalls. So many times HOOK API has to do it by itself. HOOK API has a principle that it cannot affect the original function of the hooked API in any way. Just like doctors cure diseases and save lives, if the virus in the patient is killed, the patient will die, so this "curing diseases and saving lives" is meaningless. If you hook the API, your goal is achieved, but the original function of the API is invalid, so it is not a hook, but a replacement, and the normal function of the operating system will be affected or even collapsed. HOOK API technology, which is not complicated, is the technology to change the program flow. Among the instructions of CPU, there are several instructions that can change the flow of the program: JMP, CALL, INT, RET, RETF, IRET and so on. Theoretically, you can hook any machine code that changes the entrance and exit of the API, but it is much more complicated in practice, because you need to deal with the following problems: 1, the length of CPU instructions, in a 32-bit system, the length of a JMP/CALL instruction is 5 bytes, so you have to replace the machine code in the API that exceeds 5 bytes (or replace several instructions that add up to 5 bytes), otherwise it will be. 2, parameter problem, in order to access the parameters of the original API, you have to refer to the parameters through EBP or ESP, so at this time you should be very clear about the value of EBP/ESP in your hook code; 3, timing, some hooks must be at the beginning of the API, and some must be at the end of the API, such as HOOK CreateFilaA (). If the API is hooked at the end of the API, then the file cannot be written or even accessed at this time; Hook RECV (), if you are at the top of the API hook and have not received the data at this time, you can check the receiving buffer of RECV (), of course, there is no data you want. You must wait for the normal execution of RECV (), and then check the buffer of RECV () to get the required data. 4. Context problem. Some hook codes cannot perform certain operations, otherwise the context of the original API will be destroyed and the original API will be invalid. 5, synchronization problem, try not to use global variables in hook code, but use local variables, which is also the need of modular programs; 6. Finally, it should be noted that the original function of the replaced CPU instruction must be simulated somewhere in the hook code. Let's take send () in ws2_32.dll as an example to illustrate how to hook this function: Exported fn (). : send-Ord:00 13h address machine code assembly code: 71a 21af455pushebep//machine code to be hooked (method1): 71a 21f. ESP// machine code to be hooked (method 2): 71a 2100065438+) dword ptr [EBP-08]: 71a 21b1/kloc-. Kloc-0/2 e 869 f 7 ffff calls 71a21280: 71a21b65438+073bcfdword ptr [EBP+08]: 71a. Kloc-0/A2 1B43 57 Push EDI: 71A21B44ff7514 Push [EBP+14]: 71A2/Kloc-. a 2 1B6B 5B pop ebx:7 1a 2 1B6C 0f 855 f 940000 jne 7 1a 2 AFD 1a 2 1b 72 8b 4508 mov eax, Dword ptr [EBP+08]: 71a265448 This method is widely used by DEBUGER such as Sofice. It sets an INT 3 instruction at the corresponding place through BPX to break points. But this method is not recommended, because it will conflict with WINDOWS or debugging tools, and the assembly code is basically debugged; 2. Replace the second mov ebp, esp instruction (machine code 8BEC, 2 bytes) with INT F0 instruction (machine code CDF0), and then set an interrupt gate in IDT to point to our code. I give a hook code here: lea ebp, [esp+ 12] // Simulate the function of the original instruction mov ebp and esp pushfd//Save the scene pushad // Do what you want to do here//Restore the scene popfd // Return to the next instruction of the original instruction and continue to execute the original function (the address is 7/) This method is very good, but the disadvantage is that an interrupt gate is set in IDT. 3. Change the relative address of the calling instruction (calling at 7 1A2 1B 12, 7 1A2 1B25, 71a2/b64 respectively, but the previous two calls. Why are you looking for call instructions? Because they are all 5-byte instructions, and they are all calling instructions, as long as the operation code 0xE8 remains unchanged, we can go to our hook code for execution by changing the relative address behind it, and then go to the target address after our hook code for execution. Suppose our hook code is 7 1A20400, then we change the calling instruction at 7 1A2 1A64 to call 7 1A20400 (the original instruction is as follows: call 7 1A2 1230. Do what you want here. Popadjmp71a 21230/jumps to the target address of the original calling instruction. The original instruction is as follows: call 7 1A2 1230. This method is very hidden, but it is difficult to find this 5-byte call instruction, and it is complicated to calculate the relative address. 4. Replace CMP DWORD PTR [71A 3201C] and 7 1A2 1C93 with address 7 1A265438 (machine code: 813D/kloc). 10 byte) becomes call71a20400noponop (machine code: E8XX XX XX 90 90 90 90 90 90, 10 byte). The hook code at 7 1A20400 is: Pushed MOVEDX x. 7 1A320 1Ch // simulate the original instruction cmpdword ptr [71a3201c], 71a 21c93c cmpdword ptr [EDX], 7 1a 2 193h// Simulate the original instruction cmpdword ptr [71a 3201c], 765438 This method is the most hidden, but not every API has such an instruction. The above methods are commonly used. It is worth mentioning that many people modify the first five bytes of the API, but now many antivirus software use this method to check whether the API has been hooked, or other virus Trojans modify the first five bytes after you, so that they will cover each other, and the last operation of hooking the API is effective.