正文
1.断点命中
2.设置全局断步标志
3.恢复断点处的原始字节码
4.设置单步
5.单步中读取全局断步标志
6.标志如果命中则需要将
eip-1
(因为这里的
INT3
指令是一个字节)使其eip回到指令该指令之前。
7.重新设置回断点在被单步的地方。
伪代码示例:
bool g_stepSingle = false;
DWORD g_dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
void HandleSingleStep(Regs& reg)
{
CONTEXT Ctx;
if (GetRegs(&Ctx) 0)
return -1;
if (g_stepSingle)
{
SetBreakPoint(Ctx.Eip + 1);
g_dwContinueStatus = DBG_CONTINUE;
}
}
void HandleDbg()
{
CONTEXT Ctx;
if (GetRegs(&Ctx) 0)
return;
if (IsMyBreak(Ctx.Eip))
{
ReserveBreakPoint(Ctx.Eip);
g_stepSingle = true;
Ctx.Eip -= 1;
SetSingleStep();
g_dwContinueStatus = DBG_CONTINUE;
}
}
而在Linux情况下我们一般如下进行处理
longWaitProcess(){
long result = waitpid(env.pid, nullptr, WNOHANG);
if (result == -1)
{
printf("waitpid err: %s",strerror(errno));
return result;
}
if (result == 0)
{
return result;
}
siginfo_t si{};
result = ptrace(PTRACE_GETSIGINFO, env.pid, nullptr, &si);
if (result == -1)
{
printf("ptrace PTRACE_GETSIGINFO err: %s",strerror(errno));
return result;
}
user_regs_struct reg{};
CCmdReg* pReg = (CCmdReg*)g_cmd[(int)DOR_IDX::EnumCmdReg];
CCmdBp* pBp = (CCmdBp*)g_cmd[(int)DOR_IDX::EnumCmdBp];
CCmdStepInto* pStepIn = (CCmdStepInto*)g_cmd[(int)DOR_IDX::EnumStepInto];
CCmdMem* pMem = (CCmdMem*)g_cmd[(int)DOR_IDX::EnumCmdMem];
pReg->ReadReg(®);
env.tag_currentAddress = reg.pc;
env.tag_disasmAddress = reg.pc;
uint8_t insn[12]{0};
if (env.tag_stepBpFlag)
{
pBp->SetBp(env.tag_stepBpReverseAddr);
env.tag_stepBpReverseAddr = 0;
env.tag_stepBpFlag = false;
}
if (env.tag_resumeFlag)
{
env.tag_resumeFlag = false;
CCmdResume* pResume = (CCmdResume*)g_cmd[(int)DOR_IDX::EnumCmdResume];
pResume ->Resume();
return result;
}
switch(si.si_signo)
{
case SIGSTOP:
{
printf("\nprocess stop.\n");
break;
}
case SIGTRAP:
{
switch (si.si_code) {
case TRAP_BRKPT:
{
pReg->ShowReg(®);
if (env.tag_stepOverFlag)
{
pMem->WriteMem(env.tag_currentAddress, env.tag_stepOverBuffer, 4);
env.tag_stepOverFlag = false;
}
if (env.tag_stepBpResFlag)
{
pBp->SetBp(env.tag_stepBpResAddr);
env.tag_stepBpResFlag = false;
env.tag_stepBpResAddr = 0;
}
if (pBp->IsBpExist(reg.pc))
{
printf("\nHit bp! at 0x%lx\n", reg.pc);
pBp->ReserveMem(reg.pc);
env.tag_stepBpReverseAddr = reg.pc;
env.tag_stepBpFlag = true;
}
pMem->ReadMem(reg.pc, insn, 12);
for (int i = 0; i 3; i++)
{
env.disasm.Disasm(reg.pc + i * 4, insn + i * 4, 4);
}
break;
}
case TRAP_TRACE:
{
if (env.tag_stepBpResFlag)
{
pBp->SetBp(env.tag_stepBpResAddr);
env.tag_stepBpResFlag = false;
env.tag_stepBpResAddr = 0;
}
if (env.tag_traceFlag)
{
if (reg.pc == env.tag_traceTargetAddr)
{
env.tag_traceTargetAddr = 0;
env.tag_traceFlag = false;
}
else
{
pMem->ReadMem(reg.pc, insn, 12);
for (int i = 0; i 1; i++) {
env.disasm.Disasm(reg.pc + i * 4, insn + i * 4, 4);
}
pStepIn->SetSingleStep();
break;
}
}
pReg->ShowReg(®);
pMem->ReadMem(reg.pc, insn, 12);
for (int i = 0; i 3; i++)
{
env.disasm.Disasm(reg.pc + i * 4, insn + i * 4, 4);
}
break;
}
}