To let the program stop:
An important feature of the dynamic debugger is that it stops the program so that we can observe the immediate situation of the program.
But now we do not need to study how to break the breakpoint, the system has helped us to activate the first breakpoint. When the debugging process is created, the system will help us set a INT3 breakpoint in Ntdll.dll, and we'll let the program break down here.
Switch (debugevent->u.exception.exceptionrecord.exceptioncode)//int3 the breakpoint event
{
Case exception_breakpoint://((DWORD) 0x80000003l)
First Chance:display the current
instruction and register values.
Breakpoint_int3 (DebugEvent);//In this function we are doing various processing of the debugged program
}
Get the debugger register and flag bit:
We only need to use GetThreadContext to get the context of the debugged process
BOOL WINAPI GetThreadContext (
HANDLE hthread,//thread handle
Lpcontext lpcontext//structure pointer
);
(thread handle can be saved at CreateProcess Pinfo.hthread)
For the flag register, we need to do the bitwise and calculate the price parity trouble.
CF in No. 0 place
printf ("CF:%d", (context). EFlags & 0x1)! = 0);
PF in 2nd place
printf ("PF:%d", (context). EFlags & 0x4)! = 0);
AF in 4th place
printf ("AF:%d", (context). EFlags & 0x10)! = 0);
ZF in 6th place
printf ("ZF:%d", (context). EFlags & 0x40)! = 0);
SF in 7th place
printf ("SF:%d", (context). EFlags & 0x80)! = 0);
of in 11th place
printf ("Of:%d", (context). EFlags & 0x400)! = 0);
DF in 10th place
printf ("DF:%d", (context). EFlags & 0x200)! = 0);
Use of the Disassembly engine:
First introduce a api:readprocessmemory, he reads the contents of the specified address
BOOL WINAPI ReadProcessMemory (
HANDLE hprocess,//process handle, pinfo.hprocess save at CreateProcess
Lpcvoid lpbaseaddress,//address to read
LPVOID lpbuffer,//A buffer pointer, save read to the content
size_t nSize,//number of bytes to read
size_t* lpnumberofbytesread//A variable pointer to save the actual number of bytes read to
);
How to use the Disasm function:
In giving the disassembly engine the source code, what we need is disasm this function
ULONG Disasm (
Char *SRC,//machine code required for disassembly
ULONG Srcsize,//Machine code length
ULONG Srcip,//Disassembly machine code address
T_disasm *disasm,//output
int Disasmmode//Disassembly form
)
Parameters:
SRC: Use readprocessmemory to obtain the machine code content that needs to disassemble the code address.
Srcsize: Just fill in 20 here.
SRCIP: An EIP for the current disassembly process, where the address is required because some directives (for example, E8 call) need to calculate offsets, otherwise they cannot be displayed correctly.
*DISASM: the output pointer.
Disasmmode: Just like using Disasm_code in the example.
(#define DISASM_CODE 4//Full disassembly).
return value:
Returns the length of the actual machine code being processed.
It also has several global variables that need to be set: (This is 1, no 0)
Ideal: Whether to use mode of ideal form or otherwise be MASM form;
Lowercase: Whether to output lowercase letters;
PUTDEFSEG: Whether to display the segment register.
Part of the code:
Ideal = 0; lowercase = 1; putdefseg = 0;
for (i = 0; i < 5; i++)//Output 5 lines
{
if (FALSE = = ReadProcessMemory (g_process, DISASMADDR,
Lpbuff, &bytesread))//DISASMADDR, disassembly address
{
Switch (GetLastError ())
{
Case 299:return 3; Indicates that the address cannot be read correctly
Default:return 1;
}
}
L = Disasm (Lpbuff, ten, Disasmaddr, &da, Disasm_code);
printf ("%-10x%-12s%-12s \ n", Disasmaddr, Da.dump, Da.result);
DISASMADDR = disasmaddr + L;
}
Now we can write the simplest assembly viewer:
:
Implementation of the Simple Debugger (ii) using the Disassembly engine & establishing the first program