DRX debug register uses two
In the previous article, the easiest way of use of DRX is preliminarily introduced. Since the object is operated is a DRX register, the programming language employed is the compilation language closest to the hardware. It has advantages to use assembly language: the operation of the register is clear, and it can also control all the feelings; however, its disadvantages cannot be ignored: the encapsulation and reusability of the code is too bad. In the next article, I will write the program while I gradually introduce the DRX register, and the C language will be written, so that the program can be enhanced (after all, I can understand 32-bit assembly language friends) Not much - For the entire programmer group), two can also gradually package the use of DRX, enhance the retrofitability of the code.
The example of the last article msg.exe is actually the ASM version of the Hello, World program, the program is compiled with MASM32V8, so the entry point is 401000h, we choose to set up a DRX breakpoint at 401000H, in fact, in the entry point of the program Breakpoint.
The example of this article will be introduced is the most famous Win32ASM tutorial in the world: a program proposed in ICZelion Win32ASM Tutorial: count the number of instructions running throughout the program, when the program exits, then display the recorded program operation The total number of commands. In the example of this issue, the recorded instruction includes instructions within the Windows system (that is, instructions in system files such as kernel32.dll, user32.dll), as for how to separately record the number of instructions running in the user program, Solutions will be available in subsequent articles.
To reach the purpose of recording the number of execution instructions, another debugging function of the CPU: "Single-step breakpoint" is essential, the following is a schematic diagram of the EFLAGS of the X86 series CPU:
The single-step breakpoint we want to use is to implement one of the eight-bit sf sets of EFLAGS above. When the sf is 1, the CPU will issue a single step interrupt, we can use this Interrupt function to record the total number of command executed.
The overall idea of the program is very simple:
1. In accordance with the method described in the last article, it is interrupted in the first address of the program.
2, after the first address is interrupted, clear the DRX breakpoint, set the sf logo
3, then receive the exception_single_step breakpoint message, on behalf of the program is running step, at this time, the program command counter can be operated, thereby achieving the function of the record instruction execution bar.
4. When receiving an exit_process_debug_event message, the program is executed, ready to exit memory, indicating that the contents within the instruction counter are displayed.
(Pictured with Visio has diced me, this program is a big frame with the previous one, everyone should figure it out, I will not draw a flow chart)
From the previous article, there is a large branch structure in the program. This time we use the C language to implement the program function. There is a switch statement in the C language, which is specifically used to deal with a wide range of branches, so C The code looks simpler and clear than the ASM code:
Theory to this, the following is the code implementation:
// bpm1.cpp: Define the entry point of the application.
//
#include
#include
#include
#include
#include
INT apientry _twinmain (Hinstance Hinstance, Hinstance Hprevinstance,
LPTSTR LPCMDLINE,
INT ncmdshow)
{
STARTUPINFO SIF;
Process_information pi;
:: ZeromeMory (& SIF, SIZEOF (STARTUPINFO);
:: ZeromeMory (& Pi, Sizeof (Process_Information));
SIF.CB = SizeOf (Startupinfo);
Bool hres;
Bool stop;
Hres = :: CreateProcess (_T ("msg.exe"), null, null, null, null, debug_process | debug_only_this_process, /
NULL, NULL, & SIF, & PI;
IF (hres! = true)
{
:: MessageBox (NULL, _T ("Establishing Procedure"), _T ("Error", MB_OK);
:: EXITPROCESS (-1);
}
Debug_event dbevent;
CONTEXT regs;
DWORD DWSTATE, DWBPCNT, DWSSCNT, DWADDRPROC
Static Const DWORD DWBREAKADDR = 0x401000;
Unsigned int ketalcommandnum;
TCHAR TBUFFER [256];
DWBPCNT = DWSSCNT = 0;
iTotalCommandNum = 0;
STOP = false;
Regs.ContextFlags = context_full | context_debug_registers;
DO
{
:: Waitfordebugevent (& dbEvent, Infinite);
DWSTATE = DBG_EXCEPTION_NOT_HANDLED;
Switch (dbevent.dwdebugeventcode)
{
Case exception_debug_event:
{
Switch (dbevent.u.exception.exceptionRecord.exceptioncode)
{
Case Exception_breakpoint:
{
DWBPCNT;
IF (DWBPCNT == 1)
{
:: GetThreadContext (Pi.hthread, & regs);
Regs.dr0 = (DWORD) (:: getProcaddress (:: getModuleHandle (_T ("ntdll.dll"), _t ("ntcontinue")))));
Regs.dr7 = 0x101;
:: SetthreadContext (Pi.hthread, & regs);
DWSTATE = DBG_CONTINUE;
}
Break;
}
Case exception_single_step:
{
DWSSCNT;
IF (dwsscnt == 1)
{
:: GetThreadContext (Pi.hthread, & regs);
Regs.dr0 = regs.dr7 = 0;
:: SetthreadContext (Pi.hthread, & regs);
:: ReadProcessMemory (Pi.hprocess, (LPCVOID) (Regs.esp 4), & DwaddrProc, Sizeof (DWORD), NULL
:: ReadProcessMemory (Pi.hprocess, (LPCVOID) DWADDRPROC, & Regs, SizeOf (Context), NULL
Regs.dr0 = dwbreakaddr;
Regs.dr7 = 0x101;
:: WriteProcessMemory (Pi.hprocess, (LPVOID) DWADDRPROC, & Regs, SizeOf (Context), NULL
DWSTATE = DBG_CONTINUE;
}
Else IF (dwsscnt == 2)
{
:: GetThreadContext (Pi.hthread, & regs);
Regs.dr0 = regs.dr7 = 0;
Regs.eflags | = 0x100;
:: SetthreadContext (Pi.hthread, & regs);
itotalcommandnum;
DWSTATE = DBG_CONTINUE;
}
Else
{
:: GetThreadContext (Pi.hthread, & regs);
Regs.eflags | = 0x100;
:: SetthreadContext (Pi.hthread, & regs);
itotalcommandnum;
DWSTATE = DBG_CONTINUE;
}
Break;
}
}
Break;
}
Case EXIT_PROCESS_DEBUG_EVENT:
{
ITOTALCOMMANDNUM;
STOP = True;
:: Sprintf (TBuffer, _T ("The number of programs total instructions:% 08LX"), itotalcommandnum;
:: MessageBox (Null, TBuffer, _T ("End"), MB_OK;
:: EXITPROCESS (-1);
Break;
}
}
IF (! stop)
{
:: ContinueDebugevent (Pi.dwprocessid, Pi.dwthreadID, DWState);
}
} while (!!);
:: CloseHandle (Pi.hprocess);
:: Closehandle (pi.hthread);
:: EXITPROCESS (0);
}
What needs to be pointed out is that there is no more new techniques, after the above programs, after (1), I wrote again (2), not to draw snakes, but want to leave some common use of DRX registers to do debugprues The architecture, the previous ASM architecture, this article is the architecture of C, will also write a C architecture in the future, I believe that the reuse of these code will get more and more high! I posted these code, that is, it is convenient and convenient for others. The computer's things, there is no technical confidentiality, today you think is baby, I will not write it out, after a while, it turns into the garbage of unmanned people ......... I really hope that domestic programmers Strengthen exchanges, write more articles, let 9CBS be China's CodeGuru.