http://ucooper.com hModule = GetModuleHandleA(\ //地址要从模块中动态获得 CheckRemoteDebuggerPresent =
(CHECK_REMOTE_DEBUGGER_PRESENT)GetProcAddress(hModule, \ //获取地址 hProcess = GetCurrentProcess();
CheckRemoteDebuggerPresent(hProcess,&bDebuggerPresent); //调用 }
if(bDebuggerPresent==TRUE) { } else { }
AfxMessageBox(\没有OD\AfxMessageBox(\发现OD\
ntdll!NtQueryInformationProcess()有5个参数。
为了检测调试器的存在,需要将ProcessInformationclass参数设为ProcessDebugPort(7)。 NtQueryInformationProcess()检索内核结构EPROCESS5的DebugPort成员,这个成员是系统用来与调试器通信的端口句柄。非0的DebugPort成员意味着进程正在被用户模式的调试器调试。如果是这样的话,ProcessInformation 将被置为0xFFFFFFFF ,否则ProcessInformation 将被置为0。
ZwQueryInformationProcess( IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL );
//********************************************************
typedef NTSTATUS (_stdcall *ZW_QUERY_INFORMATION_PROCESS)( HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass, //该参数也需要上面声明的数据结构 PVOID ProcessInformation,
ULONG ProcessInformationLength, PULONG ReturnLength ); //定义函数指针
void CDetectODDlg::OnZwqueryinfomationprocess() { // TODO: Add your control notification handler code here HANDLE hProcess; HINSTANCE hModule; DWORD dwResult;
ZW_QUERY_INFORMATION_PROCESS MyFunc;
写意互联网,关注搜索引擎技术,涉猎搜索引擎优化、软件破解、PHP网站建设、Wordpress应用等
http://ucooper.com hModule = GetModuleHandle(\
MyFunc=(ZW_QUERY_INFORMATION_PROCESS)GetProcAddress(hModule,\mationProcess\
hProcess = GetCurrentProcess(); MyFunc( hProcess, ProcessDebugPort, &dwResult, 4, NULL); if(dwResult!=0) { AfxMessageBox(\发现OD\ } else { AfxMessageBox(\没有OD\ } }
9. SetUnhandledExceptionFilter/ Debugger Interrupts
调试器中步过INT3和INT1指令的时候,由于调试器通常会处理这些调试中断,所以设置的异常处理例程默认情况下不会被调用,Debugger Interrupts就利用了这个事实。这样我们可以在异常处理例程中设置标志,通过INT指令后如果这些标志没有被设置则意味着进程正在被调试。另外,kernel32!DebugBreak()内部是调用了INT3来实现的,有些壳也会使用这个API。注意测试时,在异常处理里取消选中INT3 breaks 和 Singal-step break 安全地址的获取是关键
//******************************************************** static DWORD lpOldHandler;
typedef LPTOP_LEVEL_EXCEPTION_FILTER (_stdcall *pSetUnhandledExceptionFilter)( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );
pSetUnhandledExceptionFilter lpSetUnhandledExceptionFilter;
LONG WINAPI TopUnhandledExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo ) { _asm pushad AfxMessageBox(\回调函数\ lpSetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER )lpOldHandler);
写意互联网,关注搜索引擎技术,涉猎搜索引擎优化、软件破解、PHP网站建设、Wordpress应用等
http://ucooper.com ExceptionInfo->ContextRecord->Eip=NewEip;//转移到安全位置 _asm popad return EXCEPTION_CONTINUE_EXECUTION; }
void CDetectODDlg::OnSetUnhandledExceptionFilter() { bool isDebugged=0; // TODO: Add your control notification handler code here lpSetUnhandledExceptionFilter = (pSetUnhandledExceptionFilter)GetProcAddress(LoadLibrary((\ \ lpOldHandler=(DWORD)lpSetUnhandledExceptionFilter(TopUnhandledExceptionFilter); _asm{ //获取这个安全地址 call me //方式一,需要NewEip加上一个偏移值 me: pop NewEip //方式一结束 mov NewEip,offset safe //方式二,更简单 int 3 //触发异常 } AfxMessageBox(\检测到OD\ isDebugged=1; _asm{ safe: } if(1==isDebugged){ }else{ AfxMessageBox(\没有OD\ } }
//********************************************************
由于调试中断而导致执行停止时,在OllyDbg中识别出异常处理例程(通过视图->SEH链)并下断点,然后Shift+F9将调试中断/异常传递给异常处理例程,最终异常处理例程中的断点会断下来,这时就可以跟踪了。
另一个方法是允许调试中断自动地传递给异常处理例程。在OllyDbg中可以通过 选项-> 调试选项 -> 异常 -> 忽略下列异常 选项卡中钩选\中断\和\单步中断\复选框来完成设置。
写意互联网,关注搜索引擎技术,涉猎搜索引擎优化、软件破解、PHP网站建设、Wordpress应用等
http://ucooper.com 10. Trap Flag单步标志异常
TF=1的时候,会触发单步异常。该方法属于异常处理,不过比较特殊:未修改的OD无论是F9还是F8都不能处理异常,有插件的OD在F9时能正确处理,F8时不能正确处理。 void CDetectODDlg::OnTrapFlag() { try{ _asm{ pushfd //触发单步异常 or dword ptr [esp],100h ;TF=1 popfd } AfxMessageBox(\检测到OD\ }catch(...){ AfxMessageBox(\没有OD\ } }
11. SeDebugPrivilege 进程权限
默认情况下进程没有SeDebugPrivilege权限,调试时,会从调试器继承这个权限,可以通过打开CSRSS.EXE进程间接地使用SeDebugPrivilege确定进程是否被调试。注意默认情况下这一权限仅仅授予了Administrators组的成员。可以使用ntdll!CsrGetProcessId() API获取CSRSS.EXE的PID,也可以通过枚举进程来得到CSRSS.EXE的PID。 实例测试中,OD载入后,第一次不能正确检测,第二次可以,不知为何。 void CDetectODDlg::OnSeDebugPrivilege() { // TODO: Add your control notification handler code here HANDLE hProcessSnap; HANDLE hProcess; PROCESSENTRY32 tp32; //结构体 CString str=\ hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL); if(INVALID_HANDLE_VALUE!=hProcessSnap) { Process32First(hProcessSnap,&tp32); do{ if(0==lstrcmpi(str,tp32.szExeFile)) { hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,NULL,tp32.th32ProcessID); if(NULL!=hProcess) {
写意互联网,关注搜索引擎技术,涉猎搜索引擎优化、软件破解、PHP网站建设、Wordpress应用等