微型调试器

不知道你有没有听说过OD,我们可以模仿他的思路

下int 3软件断点,然后获得线程上下文就可以了。

MSDN里面有大量的Debugging Functions,你可以去看下。下面是一段微型调试器的代码

C/C++ code
   
   
#include < windows.h > #include < stdio.h > #include < assert.h > int main() { DEBUG_EVENT d; DWORD mark; BOOL initBP,r; DWORD pid; initBP = 0 ; printf( " set pid=? " ); scanf( " %d " , & pid); r = DebugActiveProcess(pid); /* 开始调试 */ assert(r); printf( " debugging... " ); for (;;) { if ( ! WaitForDebugEvent( & d,INFINITE)) /* 等待调试事件 */ assert( 0 ); switch (d.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: case EXIT_PROCESS_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT: case LOAD_DLL_DEBUG_EVENT: case UNLOAD_DLL_DEBUG_EVENT: case OUTPUT_DEBUG_STRING_EVENT: case RIP_EVENT: mark = DBG_CONTINUE; /* 这些事件都不需要处理,让目标直接运行 */ break ; case EXCEPTION_DEBUG_EVENT: if (initBP) { mark = DBG_EXCEPTION_NOT_HANDLED; /* 没处理就是没处理 */ } else { initBP = 1 ; mark = DBG_CONTINUE; /* 初始断点要特别留意 */ } break ; } if ( ! ContinueDebugEvent( d.dwProcessId, d.dwThreadId,mark)) /* 继续执行目标程序 */ assert( 0 ); if (d.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break ; } printf( " stopped/n " ); return 0 ; }




如上是直接附加到活动进程,如果我们学着OD,加载进程后,在OEP那里断下的话,用CreateProcess创建进程,标志位打上Debug标志即可,类似下面这样

C/C++ code
   
   
STARTUPINFO st = { 0 }; PROCESS_INFORMATION pro = { 0 }; st.cb = sizeof (st); CreateProcess(NULL, " d://test.exe " , NULL, NULL, TRUE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, & st, & pro); CloseHandle(pro.hThread); CloseHandle(pro.hProcess); DEBUG_EVENT dbe; BOOL rc; while (WaitForDebugEvent( & dbe, INFINITE)) { if (dbe. dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break ; ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId ,DBG_CONTINUE ); } // 有的代码我就略过了,在上课,不方便写很多




软件断点(INT3):对应的异常是 EXCEPTION_BREAKPOINT,处理方式为恢复代码为原来字节,并将EIP减一,并设置单步以便进入单步后重新设置这个一般断点。

那么现在要解决的问题就剩一个了,就是写入断点int3,OEP那边断下之后就要写,然后开始执行。

这个可以用WriteProcess实现,当你初次加载之后,进程虽然断下来了,但是PE已经加载进了内存空间中。
根据偏移,把int 3对应的十六进制0xCC指令写入

断下来之后,用GetThreadContext获得线程上下文就可以得到寄存器的值了

这里有些注意点,看下面的代码

C/C++ code
   
   
if (r -> ExceptionCode == EXCEPTION_BREAKPOINT) /* 触发了断点中断 */ { /* 根据中断地点查找断点记录 */ bp = find(ps -> bps,MAX_BP,(DWORD)r -> ExceptionAddress); if (bp) /* 是调试器安置的断点 */ { t = find(ps -> ts,MAX_THRD,d.dwThreadId); /* 取线程上下文 */ memset( & ctx, 0 , sizeof (ctx)); ctx.ContextFlags = CONTEXT_FULL; f = GetThreadContext(t -> h, & ctx); assert(f); ctx.Eip -- ; /* 将指令指针值减1 */ ctx.EFlags |= TF_BIT; /* 打开CPU单步标记 */ f = SetThreadContext(t -> h, & ctx); /* 向目标写入修改过的上下文 */ assert(f); ps -> write_back = bp; /* 标记该进程在单步结束后准备写回的断点 */ safe_write(ps -> h,bp -> addr,bp -> c); /* 写入被断点覆盖的代码 */ on_bp(d.dwProcessId,d.dwThreadId,bp -> addr); /* 用户处理 */ suspend_except(ps -> ts,d.dwThreadId); /* 挂起除异常线程外的所有线程 */ mark = DBG_CONTINUE; } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值