让程序停下来:
动态调试器的一个重要特点就是:让程序停下来,这样我们才可以观测到程序的即时情况。
不过现在我们并不需要研究怎么下断点,系统已经帮我们激活了第一个断点。在创建调试进程时,系统会帮我们在ntdll.dll中设置一个INT3断点,我们就让程序在这里断下来。
switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode)//Int3断点的事件
{
case EXCEPTION_BREAKPOINT: // ((DWORD )0x80000003L)
// First chance: Display the current
// instruction and register values.
BreakPoint_Int3(DebugEvent);//这个函数中我们对被调试程序进行各种处理
}
获得调试程序的寄存器与标志位:
我们只需要使用GetThreadContext 获得被调试进程的上下文环境
BOOL WINAPI GetThreadContext(
HANDLE hThread, //线程句柄
LPCONTEXT lpContext //结构指针
);
(线程句柄可以在CreateProcess时的pInfo.hThread保存)
对于标志寄存器,比价麻烦,我们需要按位进行与计算。
//CF 在第0位
printf(" CF :%d", (context.EFlags & 0x1) != 0);
//PF 在第2位
printf(" PF :%d", (context.EFlags & 0x4) != 0);
//AF 在第4位
printf(" AF :%d", (context.EFlags & 0x10) != 0);
//ZF 在第6位
printf(" ZF :%d", (context.EFlags & 0x40) != 0);
//SF 在第7位
printf(" SF :%d", (context.EFlags & 0x80) != 0);
//OF 在第11位
printf(" OF :%d", (context.EFlags & 0x400) != 0);
//DF 在第10位
printf(" DF :%d", (context.EFlags & 0x200) != 0);
反汇编引擎的使用:
先介绍一个API:ReadProcessMemory,他读取指定的地址的内容
BOOL WINAPI ReadProcessMemory(
HANDLE hProcess, //进程句柄,在CreateProcess时的pInfo.hProcess保存
LPCVOID lpBaseAddress, //要读取的地址
LPVOID lpBuffer, //一个缓冲区的指针,保存读取到的内容
SIZE_T nSize, //要读取的字节数
SIZE_T* lpNumberOfBytesRead //一个变量的指针,保存实际读取到的字节数
);
如何使用Disasm这个函数:
在给予反汇编引擎源码中,我们需要的是Disasm这个函数
ulong Disasm(
char *src, //需要反汇编的机器码
ulong srcsize, //机器码长度
ulong srcip, //反汇编机器码地址
t_disasm *disasm, //输出
int disasmmode //反汇编形式
)
参数:
src:用ReadProcessMemory获得需反汇编代码地址的机器码内容。
srcsize:这里直接填写20即可。
srcip:当前反汇编进程的EIP,这里需要地址是因为一些指令(例如E8 Call)需要计算偏移,否则没法正确显示。
*disasm:输出的指针。
disasmmode:就如同例子中使用DISASM_CODE即可.
(#define DISASM_CODE 4 // Full disassembly)。
返回值:
返回实际处理的机器码的长度。
它还有几个需要设置的全局变量:(这里是为1, 否为 0)
ideal:是否使用IDEAL 形式的MODE否则为MASM形式;
lowercase:是否输出小写字母;
putdefseg:是否显示段寄存器。
部分代码:
ideal = 0; lowercase = 1; putdefseg = 0;
for (i = 0; i < 5; i++)//输出5行
{
if (FALSE == ReadProcessMemory(G_Process, DisasmAddr,
lpBuff, 10, &bytesRead))//DisasmAddr,反汇编地址
{
switch (GetLastError())
{
case 299: return 3; //表示该地址无法被正确读取
default: return 1;
}
}
l = Disasm(lpBuff, 10, DisasmAddr, &da, DISASM_CODE);
printf("%-10x %-12s %-12s \n", DisasmAddr, da.dump, da.result);
DisasmAddr = DisasmAddr + l;
}
现在我们可以编写最简单的汇编查看器了:
: