Здравствуйте уважаемые, не могли бы вы помочь найти ошибку в коде. Тут в общем ставится бряк и по его срабатыванью в лог должно писаться содержание регистра Edx. Все бы ничего, но бряк почему-то срабатывает по абсолютно левому адресу. С чем это может быть связано. Помогите, плз, советом, а то долбусь с этой весчью уже около 10 часов, нервов не хватает. Код (Text): DWORD WINAPI ThreadFunc( LPVOID ) { debwnd=FindWindow(NULL,"PokerStars Lobby"); log<<"Poker hwnd is "<<debwnd<<"\n"; ThreadId=GetWindowThreadProcessId(debwnd,&ProcessId); DebugActiveProcess(ProcessId); while(1) { if (WaitForDebugEvent (&de, INFINITE)) { switch (de.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: if (de.u.Exception.ExceptionRecord.ExceptionCode != 0x80000003&&de.u.Exception.ExceptionRecord.ExceptionCode != 0x80000004) { ContinueDebugEvent (de.dwProcessId,de.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); log<<"We have unhandled exeption \n"; } if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { if (fe==true) { fe=false; log<<"stop on First breakpoint\n"; } else { context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER; GetThreadContext((void*)htred, &context); if (context.Eip==0x58e0b2) { WriteProcessMemory((void*)hproc,(void *)(breakpoint1),&backc,1,&strn); log<<"EIP = "<<hex<<context.Eip<<"\n"; log<<hex<<context.Edx; context.EFlags |= 0x0100; context.Eip--; SetThreadContext((void*)htred, &context); } } } else if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) { context.ContextFlags = CONTEXT_CONTROL; fromc=204; WriteProcessMemory((void*)hproc,(void *)(breakpoint1),&fromc,1,&strn); GetThreadContext((void*)htred, &context); context.EFlags = context.EFlags & !0x0100; SetThreadContext((void*)htred, &context); } break; case CREATE_PROCESS_DEBUG_EVENT: context.ContextFlags = CONTEXT_CONTROL; GetThreadContext(de.u.CreateProcessInfo.hThread, &context); hproc=(DWORD)de.u.CreateProcessInfo.hProcess; htred=(DWORD)de.u.CreateProcessInfo.hThread; fromc=204; breakpoint1=0x58e0b1; ReadProcessMemory(de.u.CreateProcessInfo.hProcess,(void *)(breakpoint1),&backc,1,&strn); WriteProcessMemory(de.u.CreateProcessInfo.hProcess,(void *)(breakpoint1),&fromc,1,&strn); break; } ContinueDebugEvent (de.dwProcessId,de.dwThreadId,DBG_CONTINUE); } } return 1; } З. Ы. Все дебагеры которыми я пробовал ставить бряки на это приложение делают, так что защиты вроде нет Заранее спасибо.
во-первых, что такое "бряк" (я этого сленга не понимаю), предполагаю, что это breakpoint. на основании этого предложения последующие коментарии. Очень беглый анализ кода, дает основание предположить, что твой htred для вызова GetThreadContext и SetThreadContext не определен или определен не правильно. Отсюда вся твоя печаль и происходит. DEBUG_EVENT дает только Tread ID, а GetThreadContext требует HANLDE Tread'а (как его добыть читай шаг 3). Вообще-то задача муторная и кропотливая, "по понятиям", что и как работает - материал под отдельную статью (мог бы написать, но лень адаптировать под ассемблер). Реализованный мной дебаггер см тут http://www.ircdb.org/algorithm.htm, не считая embedded debugger'ов под Z80, 8080 и 8051 Некоторые важные общие замечание (может ты о них знаешь, а может быть и нет), пишу для интересующихся (вместо статьи) 1. поставить breakpoint - это записать код 0xCC (INT3) в предполагаемую точку останова (это софтвеерный breakpoint, не путать с debug registers - DRx) 2. "срабытывание" 0xCC выховет case EXCEPTION_BREAKPOINT: (см код внизу) 3. далее необходимо опредеть HANDLE Thread'а, вызвавшего brakpoint, структура DEBUG_EVENT дает только Tread ID, а GetThreadContext требует HANLDE Tread'а, я пользовал функцию NtOpenThread (через GetProcAddr из NtDLL.DLL), т к начинал под NT, под 2000/XP можно пользовать OpenThread (но только, кажется, в VC7 темплейт объявлен в WinBase.h) 4. получив Thread Context можешь делать с ним, что хочешь 5. однако надо правильно покинуть breakpoint, для этого нужно: почистить instruction cache процессора, вернуть реальный код на меcто 0xCC (INT3), сделать декримент регистра Eip в контексте регистров и выставить флаг пошаговой операции EFLAGS_TF в регистре EFlags контексте регистров, затем сделать SetThreadContext 6. операция изложенная в шаге 5 вызовет "case EXCEPTION_SINGLE_STEP:", которая должна быть обработана следующим образом: выполнить шаг 3, вернуть 0xCC (INT3) на место breakpoint'a, сохранив при этом первоначальный код байта, почистить EFLAGS_TF в регистре EFlags контексте регистров, сделать SetThreadContext 7. ждать срабытывания следующего breakpoint'a, а потом шаги 2,3,4,6 повторяются Код (Text): //template of debug loop while(1) { if (WaitForDebugEvent (&de, INFINITE)) { case EXCEPTION_DEBUG_EVENT: //1 // pSocketSpyView->m_cstring ="\r\nEXCEPTION_DEBUG_EVENT:\r\n"; if(de.u.Exception.ExceptionRecord.ExceptionFlags) { ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); } else { switch(de.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: break; case EXCEPTION_DATATYPE_MISALIGNMENT: break; case EXCEPTION_BREAKPOINT: //BREAK POINT PROCEEDING SHOULD BE PLACED HERE!!!!!!!!! //YOU SHOULD RETRIEVE THREAD HANDLE BY THREAD IDs //I USED FROM NTDLL.DLL //AND ONLY AFTER CALL GetThreadContext FUNCTION WITH VALID //THREAD IDS //BREAKPOINT CONTEXT MAY DISPLAYED AS //http://www.ircdb.org/breakpoint.jpg //CLEAR BREAKPOINT use WriteProcessMemory //CHANGE context.Eip--; //SET SINGLE STEP FLAG context.EFlags |= 0x00000100; //EFLAGS_TF break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: break; case EXCEPTION_FLT_DENORMAL_OPERAND: break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: break; case EXCEPTION_FLT_INEXACT_RESULT: break; case EXCEPTION_FLT_INVALID_OPERATION: break; case EXCEPTION_FLT_OVERFLOW: break; case EXCEPTION_FLT_STACK_CHECK: break; case EXCEPTION_FLT_UNDERFLOW: break; case EXCEPTION_INT_DIVIDE_BY_ZERO: break; case EXCEPTION_INT_OVERFLOW: break; case EXCEPTION_PRIV_INSTRUCTION: break; case EXCEPTION_IN_PAGE_ERROR: break; case EXCEPTION_ILLEGAL_INSTRUCTION: break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: break; case EXCEPTION_STACK_OVERFLOW: break; case EXCEPTION_INVALID_DISPOSITION: break; case EXCEPTION_GUARD_PAGE: break; case EXCEPTION_INVALID_HANDLE: break; default: break; } } case CREATE_THREAD_DEBUG_EVENT: //2 break; case CREATE_PROCESS_DEBUG_EVENT: //3 break; case EXIT_THREAD_DEBUG_EVENT: //4 break; case EXIT_PROCESS_DEBUG_EVENT: //5 break; case LOAD_DLL_DEBUG_EVENT: //6 break; case UNLOAD_DLL_DEBUG_EVENT: //7 break; case OUTPUT_DEBUG_STRING_EVENT: //8 break; case RIP_EVENT: //9 cstring += "RIP Event\r\n"; break; }//(WaitForDebugEvent (&de, INFINITE)) } пользуемся тегом [ code ], господа
глянул еще раз, не нашел, чтобы ты делал вызов FlushInstructionCache для чтобы почистить instruction cache процессора (см мой пред. постинг, шаг 5). Хотя к проблеме извлечения "context.Edx" для первого срабатывания breakpoint'a это не относится