Anti-debugging technology and debugging technology
When debugging a virus program, you may encounter some anti-Debugging techniques. That is to say, the debugged program can detect whether it has been attached to the debugger. If you find that you are being debugged, it must be someone trying to crack themselves through disassembly or other methods. To learn how to crack the anti-debugging technology, Let's first look at the anti-debugging technology. I. Windows API method Win32 provides two APIs: IsDebuggerPresent and CheckRemoteDebuggerPresent, which can be used to detect whether the current process is being debugged. Take the IsDebuggerPresent function as an example. The following is an example: BOOL ret = isdebug (); printf ("ret = % d \ n", ret); the method of cracking is very simple, that is, to hook the two functions in the system, so that the two functions can always return false, there are a lot of tools for hook APIs on the Internet, and the source code of many tools is open, so I will not discuss them here. 2. query the BeingDebugged flag of the PEB process. When the process is attached to the debugger, the operating system automatically sets this flag. Therefore, you can periodically query this flag in the program, example: bool PebIsDebuggedApproach () {char result = 0; _ asm {// The PEB address of the process is placed on the fs register location mov eax, fs: [30 h] // query BeingDebugged flag mov al, byte ptr [eax + 2] mov result, al} return result! = 0;} 3. The NtGlobal flag of the Query Process PEB is the same as that of the second method. when the process is debugged, the operating system not only modifies the BeingDebugged flag, in addition, the flag of some functions that control Heap operations in NtDll will be modified. Therefore, you can query the flag as follows: bool PebNtGlobalFlagsApproach () {int result = 0; _ asm {// PEB mov eax, fs of the process: [30 h] // indicates the position mov eax, [eax + 68 h] for controlling the way heap operation functions work. // The operating system will add these flag FLG_HEAP_ENABLE_TAIL_CHECK, // FLG_HEAP_ENABLE_FREE_CHECK and FLG_HEAP_VALIDATE_PARAMETERS. // the union of these parameters is the same as that of the following code in the cross-site scripting (c1.0.0) /// C/C ++ // eax = eax & 0x70 and eax, 0x70 mov result, eax} return result! = 0;} 4. query some symbols of the Process heap. This method is a variant of the third method. As long as the process is debugged, the memory allocated by the process on the heap, in the header information of the allocated heap, The ForceFlags flag will be modified. Therefore, debugging can be performed by judging this flag. Because the process can have a lot of heap, you only need to check the header information of any heap. Therefore, this method seems very powerful. Example: bool HeapFlagsApproach () {int result = 0; _ asm {// process's PEB mov eax, fs: [30 h] // process's heap. We randomly access a heap, the following is the default heap mov eax, [eax + 18 h] // check the ForceFlag flag. If not debugged, it should be mov eax, [eax + 10 h] mov result, eax} return result! = 0;} 5. Using the NtQueryInformationProcess function NtQueryInformationProcess is an undisclosed API. Its second parameter can be used to query the debugging port of a process. If the process is debugged, the returned port value is-1; otherwise, it is another value. Because this function is an undisclosed function, you need to use the LoadLibrary and GetProceAddress methods to obtain the call address. The sample code is as follows: // declare a function pointer. Typedef NTSTATUS (WINAPI * HANDLE) (HANDLE processHandle, PROCESSINFOCLASS processInformationClass, PVOID processInformation, ULONG processInformationLength, PULONG returnLength); bool destroy () {int debugPort = 0; HMODULE hModule = LoadLibrary (TEXT ("Ntdll. dll "); NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr) G EtProcAddress (hModule, "NtQueryInformationProcess"); if (NtQueryInformationProcess (GetCurrentProcess (), (PROCESSINFOCLASS) 7, & debugPort, sizeof (debugPort), NULL )) printf ("[ERROR NtQueryInformationProcessApproach] NtQueryInformationProcess failed \ n"); else return debugPort =-1; return false ;} 6. NtSetInformationThread method this is also an undisclosed Function Method in Windows. You can call NtSetInformationThread in the current thread. If you call this function in the second parameter Specify the value 0x11 (ThreadHideFromDebugger) to tell the operating system to cancel all the attached debuggers. Sample Code: // declare a function pointer. Typedef NTSTATUS (* NtSetInformationThreadPtr) (HANDLE threadHandle, THREADINFOCLASS threadInformationClass, PVOID threadInformation, ULONG threadInformationLength); void NtSetInformationThreadApproach () {HMODULE hModule = LoadLibrary (TEXT ("ntdll. dll "); NtSetInformationThreadPtr NtSetInformationThread = (NtSetInformationThreadPtr) GetProcAddress (hModule," NtSetInformationThread "); NtSetInformationThr Ead (GetCurrentThread (), (THREADINFOCLASS) 0x11, 0, 0);} 7. How to trigger an exception, the process uses the SetUnhandledExceptionFilter function to register an unhandled exception handler function A. if the process is not debugged, an unhandled exception is triggered, causing the operating system to give control to the previously registered function; if the process is debugged, this unprocessed exception will be captured by the debugger, so that function A has no chance to run. Here is a tip: When an unhandled exception is triggered, if you jump back to the original code to continue the execution, rather than letting the operating system shut down the process. The solution is to modify the eip value in function A, because in the _ EXCEPTION_POINTERS parameter of function A, the command address that triggered the exception at that time will be saved, therefore, you can modify the eip value of the register according to the instruction address in function A. The sample code is as follows: // The unprocessed exception handler along winapi MyUnhandledExceptionFilter (struct _ EXCEPTION_POINTERS * pei) {SetUnhandledExceptionFilter (callback) pei-> ContextRecord-> Eax) to be registered by the process ); // modify the eip value of the Register pei-> ContextRecord-> Eip + = 2; // tell the operating system to continue executing the remaining commands of the process (the commands are saved in the eip ), instead of disabling the process return EXCEPTION_CONTINUE_EXECUTION;} bo Ol UnhandledExceptionFilterApproach () {SetUnhandledExceptionFilter (MyUnhandledExceptionFilter); _ asm {// reset eax to xor eax, eax // trigger a division by zero exception div eax} return false ;} 8. Call the DeleteFiber function. If an invalid parameter is passed to the DeleteFiber function, the DeleteFiber function will not only throw an exception, but also set the LastError value of the process to the code of the specific error cause. However, if the process is being debugged, The LastError value will be modified. Therefore, if the debugger bypasses the anti-debugging technology described in Step 7, we can also verify whether the LastError value is modified to check the existence of the debugger. Example code: bool DeleteFiberApproach () {char fib [1024] = {0 }; // an exception is thrown and the debugger captures DeleteFiber (fib); // 0x57 indicates ERROR_INVALID_PARAMETER return (GetLastError ()! = 0x57 );}