debug breakpoints setzen in c / c++

08/07/2010 14:19 nkkk#1
Weiss hier jemand wie man mit einem selbstgeschriebenen programm ein anderes debugt bzw. breakpoints setzt? Sodass zb. eine funktion von mir immer ausgeführt wird, wenn in einem anderen prog. der instruction pointer bei einer bestimmten adresse ist .
08/07/2010 14:28 MrSm!th#2
Debugging is ein bisschen komplizierter, aber Hardware BPs gehen mithilfe von Get/SetThreadContext.

Hier mal ein kleines SEH (Structured Exception Handling) Example, was ich auf GD gefunden habe:

PHP Code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>        
#include "detours.h"    // download from http://research.microsoft.com/sn/detours/


LONG    WINAPI UnhandlerExceptionFilter(struct _EXCEPTION_POINTERSExceptionInfo);    // Our exception filter
DWORD    WINAPI GetTickCount_Detour(void);                                            // Our detoured GetTickCount()
BOOL    WINAPI GetThreadContext_Detour (HANDLE hThread,LPCONTEXT lpContext);        // Our detoured GetThreadContext()

DETOUR_TRAMPOLINE(BOOL WINAPI GetThreadContext_Trampoline(HANDLE ,LPCONTEXT) ,GetThreadContext);    // detour macro for (empty)trampoline

// Function defines
void    Set_SEH_and_BreakPoints(void);            // Set the SEH and breakpoints
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler=NULL;    // Pointer to existing exception handler

// Global variables
DWORD    dwBreakPoint=0x100334f;                    // The hardware-breakpoint (4 available)
int        nBreakPointJump=0x18;                    // How many bytes we make EIP to skip from this breakpoint
BYTE    opcodes[5];                                // Original opcodes in GetTickCount() entry-point to be stored for restoring


// DLL entrypoint which OS-loader calls for us after injecting
BOOL APIENTRY DllMainHANDLE hModuleDWORD  ul_reason_for_callLPVOID lpReserved)
{
    switch(
ul_reason_for_call)
    {
        case 
DLL_PROCESS_ATTACH:
            
DisableThreadLibraryCalls(GetModuleHandle(NULL));

            
MessageBox(NULL,"We are in and hooked !","SEH_example",0);

            
// Store original opcodes under GetTickCount()
            
ReadProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);
            
            
// Hijack GetTickCount to jmp to our GetTickCount_Detour 
            
DetourFunction((PBYTE)GetTickCount,(PBYTE)GetTickCount_Detour);

            
// Hijack also GetThreadContext() to hide debug-registers altering
            
DetourFunctionWithTrampoline((PBYTE)GetThreadContext_Trampoline,(PBYTE)GetThreadContext_Detour);    

        break;

        case 
DLL_PROCESS_DETACH:
            
// Try to remove all hooks and handlers.
            
DetourRemove((PBYTEGetThreadContext_Trampoline,(PBYTEGetThreadContext_Detour);
            
WriteProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);
            if (
oldHandlerSetUnhandledExceptionFilter(oldHandler);
        break;
    }

    return 
true;
}

// Hijacked GetTickCount. This is called when target-app (Notepad) is calling GetTickCount()
DWORD WINAPI GetTickCount_Detour()
{
    
// From here we add our Structured Exception Handler
    // We can't add it in the DLLmain since that function is called in 
    // different thread-context and the SEH and Breakpoints are per thread basis
    
Set_SEH_and_BreakPoints();

    
// Return original bytes to GetTickCount() i.e. unhook it. We only need this "callback" once.
    
WriteProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);

    
MessageBox(NULL,"HW-breakpoints are set !","SEH_example",0);

    
// Return actual function result
    
return GetTickCount();
}

// Add the SEH-handler and set HW-breakpoint(s)
void Set_SEH_and_BreakPoints()
{
    
// Store existing handler to global variable to reset later
    
oldHandler=SetUnhandledExceptionFilter(UnhandlerExceptionFilter);
    
    
// Set debug-registers for HW-breakpoint and activate it
    
CONTEXT ctx = {CONTEXT_DEBUG_REGISTERS};
    
ctx.Dr6 0x00000000;

    
ctx.Dr0 dwBreakPoint;        // Set Address of Breakpoint 1
    
ctx.Dr7 0x00000001;        // Activate Breakpoint 1

    /*
    use these for setting more breakpoints    

    ctx.Dr1=address;            // Set Address of Breakpoint 2
    ctx.Dr7 |= 0x00000004;        // Activate Breakpoint 2
    
    ctx.Dr2=address;            // Set Address of Breakpoint 3
    ctx.Dr7 |= 0x00000010;        // Activate Breakpoint 3
    
    ctx.Dr3=address;            // Set Address of Breakpoint 4
    ctx.Dr7 |= 0x00000040;        // Activate Breakpoint 4
    */


    // Write the values to registers. From now on the breakpoint is active 
    
SetThreadContext(GetCurrentThread(), &ctx); 
}

// Our ExceptionHandler
// study the ExceptionInfo-struct for stuff you need
LONG WINAPI UnhandlerExceptionFilter(struct _EXCEPTION_POINTERSExceptionInfo)
{
    
// HW-breakpoints DON'T generate EXCEPTION_BREAKPOINT but EXCEPTION_SINGLE_STEP so we check for that
    
if(ExceptionInfo->ExceptionRecord->ExceptionCode==EXCEPTION_SINGLE_STEP )
    {    
        
// Verify that the breakpoint was the one we set
        
if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress==dwBreakPoint
        {
            
// move instruction pointer forward to skip unwanted instructions and let 
            // the process continue as nothing has happened
            
ExceptionInfo->ContextRecord->Eip+=nBreakPointJump;
            return 
EXCEPTION_CONTINUE_EXECUTION;
        }
    }

    
// Some other exception occured. Pass it to next handler
    
return EXCEPTION_CONTINUE_SEARCH;
}

// Hijacked GetThreadContext(). We don't actually need this in our notepad-example
// I included it just for help since for a real hack you need to fake 
// DEBUG-registers so that the game doesn't see they that are altered
//
BOOL WINAPI GetThreadContext_Detour (HANDLE hThread,LPCONTEXT lpContext)
{
    
// Get the Real values from original API-function (see the _trampoline)
    
BOOL ret=GetThreadContext_TrampolinehThreadlpContext);

    
// If target is interested in Debug-registers return fake values 
    
if (lpContext->ContextFlags && CONTEXT_DEBUG_REGISTERS) {
        
lpContext->Dr0=0;
        
lpContext->Dr1=0;
        
lpContext->Dr2=0;
        
lpContext->Dr3=0;
        
lpContext->Dr6=0;
        
lpContext->Dr7=0;
    }

    return 
ret;

08/07/2010 14:39 Akorn#3
Allerdings kann man nur 4 hardware breakpoints setzten.
Alternativ gibt es noch Softwarebreakpoints.
08/07/2010 14:51 P-a-i-n#4
was smith kopiert hat nutz ich auch geht bestens wenn jemand dadrin nicht durchsieht hier ist ein tut(englisch)
08/07/2010 15:04 MrSm!th#5
Jau, Software BPs gehen auch, allerdings nutzt man Breakpoint Hooks ja wohl nur, wenn andere detected sind, sonst macht es ja keinen Sinn, da es sehr unsicher ist.
Also würde ich direkt zu Hardware BPs greifen.

0xCC musst du btw. für nen Int3 BP schreiben, ich glaube die Exception dafür lautet nicht Single Step, sondern wirklich EXCEPTION_BREAKPOINT oder so...
08/07/2010 15:09 Akorn#6
Quote:
Originally Posted by MrSm!th View Post
Jau, Software BPs gehen auch, allerdings nutzt man Breakpoint Hooks ja wohl nur, wenn andere detected sind, sonst macht es ja keinen Sinn, da es sehr unsicher ist.
Also würde ich direkt zu Hardware BPs greifen.

0xCC musst du btw. für nen Int3 BP schreiben, ich glaube die Exception dafür lautet nicht Single Step, sondern wirklich EXCEPTION_BREAKPOINT oder so...
Ja der Rückgabewert von GetExceptionCode() muss EXCEPTION_BREAKPOINT sein.

Allerdings ist es auch nicht gerade schwer hardware breakpoints zu detecten.
08/07/2010 15:30 MrSm!th#7
Wenn GetThreadContext gehookt ist (mit einem Breakpoint :p) dann schon ohne kernelmode zugriff ;O
08/07/2010 15:40 Akorn#8
Quote:
Originally Posted by MrSm!th View Post
Wenn GetThreadContext gehookt ist (mit einem Breakpoint :p) dann schon ohne kernelmode zugriff ;O
Ist ja eigentlich recht bekannt das man das problem mit der detection durch das hooken von GetThreadContext und anschliessendes ändern der CONTEXT structur lösen kann.
08/07/2010 16:05 nkkk#9
so danke für diese infos, werde das testdn wenn ich wieder zuhause bin.
08/07/2010 18:18 rEdoX#10
Quote:
Originally Posted by MrSm!th View Post
Wenn GetThreadContext gehookt ist (mit einem Breakpoint :p) dann schon ohne kernelmode zugriff ;O
DLL-Mirror, NtGetContextThread, Exception-Handler, KiFastSystemCall usw usw (:
08/07/2010 19:10 MrSm!th#11
Naja, NtGetContextThread hätte ich eh gehookt und nicht die Win32 API :p

was den rest angeht....kernelmode hooks ftw ;O