写一篇关于双进程保护的心得,因为我也是新手兼菜鸟,所以写的比较简单。
windows下一个ring3进程只能对应一个调试器,那么我们就可以预先给自己的应用程序加个调试器,以防止别人跟踪调试。
1.双进程实现:
程序一开始,先判断是否为调试状态,由于刚启动默认为非调试状态,那这样就作为调试器进程运行,作为调试进程运行后,会用自身程序文件再创建一个被调试进程。被调试进程判断出自己处于调试状态,就会沿着不同于调试进程的软件逻辑运行。被调试进程是我们主要运行的进程,而调试进程是用来保护被调试进程的。好像很嗦,还是看代码,代码比较简单:
代码:
#include "windows.h" int DebugMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { if(!IsDebuggerPresent()) //区分调试进程与被调试进程,以执行不同的代码。 { return DebugMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow); } __asm int 3; MessageBox(0,"这是一个简单的例子","TraceMe",0); return 0; } int DebugMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) //调试进程主函数 { char filename[MAX_PATH]; GetModuleFileName(0,filename,MAX_PATH); //获取自身文件名 STARTUPINFO si={0}; GetStartupInfo(&si); PROCESS_INFORMATION pi={0}; if(!CreateProcess(filename,NULL,NULL,NULL,FALSE,DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi)) //创建被调试进程 { return 0; } BOOL WhileDoFlag=TRUE; DEBUG_EVENT DBEvent ; DWORD dwState; while (WhileDoFlag) { WaitForDebugEvent (&DBEvent, INFINITE); dwState = DBG_EXCEPTION_NOT_HANDLED ; switch (DBEvent.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: dwState = DBG_CONTINUE ; break; case EXIT_PROCESS_DEBUG_EVENT : WhileDoFlag=FALSE; break ; case EXCEPTION_DEBUG_EVENT: switch (DBEvent.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: { dwState = DBG_CONTINUE ; break; } } break; } ContinueDebugEvent(pi.dwProcessId, pi.dwThreadId, dwState) ; } CloseHandle(pi.hProcess) ; CloseHandle(pi.hThread) ; return 0; }
有了自己的调试进程,异常的处理更加灵活了,我们可以将有些异常交给被调试进程自己处理,有些异常交给调试进程处理。总之,为了反跟踪,越乱越好:
代码:
__try { __asm int 3 //这个断点异常想让调试进程处理 } __except(1) { __asm pop eax; //如果调试器不处理断点异常,把异常扔回来了,这里会被执行,那就做点坏事,这里简单地破坏一下堆栈。 __asm pop esp; } int div=0; __try { __asm int 3 //这个断点异常想让被调试进程处理 } __except(1) { div++; } div=1/div; //如果被调试进程的异常处理模块未被执行,那么这里会产生除0异常,接着就exit了。 。。。。。。 case EXCEPTION_BREAKPOINT: { GetThreadContext(pi.hThread, &Regs) ; if(Regs.Eip==(DWORD)0x0040CC10) //地址需纠正,上面第一个int 3指令的地址+1 dwState = DBG_CONTINUE ; else if(Regs.Eip==(DWORD)0x0040CC20) //地址需纠正,上面第二个int 3指令的地址+1 dwState = DBG_EXCEPTION_NOT_HANDLED ; else dwState = DBG_CONTINUE ; break; } 。。。。。。
3.加密代码
做个简单的加密,将代码MessageBox(0,"这是一个简单的例子","TraceMe",0)给加密起来,运行时由调试进程将被调试进程代码还原,有点像smc,不过是跨进程的,该叫什么?代码它(自)修改 ?^_^。先在DebugMain函数中准备代码,因为只是测试,所以用最简单的异或算法:
代码:
void DecryptCode(HANDLE hProcess,DWORD begin,DWORD end) { DWORD flOldProtect; BYTE ch[1]={0}; DWORD num=end-begin; VirtualProtectEx(hProcess, (LPVOID)begin,num,PAGE_EXECUTE_READWRITE,&flOldProtect); for(DWORD i=begin;i<end;i++) { ReadProcessMemory(hProcess,(LPCVOID)i,&ch,sizeof(ch),NULL) ; ch[0]^=0xDE; WriteProcessMemory(hProcess,(LPVOID)i,&ch,sizeof(ch),NULL); } VirtualProtectEx(hProcess,(LPVOID)begin,num,flOldProtect,NULL); } 。。。。。。 else if(Regs.Eip==(DWORD)0x0040CC30) //地址值需纠正 { DecryptCode(pi.hProcess,0x0040CC30,0x0041200); //地址值需纠正 dwState = DBG_CONTINUE; } else dwState = DBG_CONTINUE ; 。。。。。。
首先定位到: