1
0
Fork 0

DBG: implement DLL breakpoints directly in x64dbg

This commit is contained in:
Duncan Ogilvie 2017-10-24 02:49:39 +02:00
parent a514176750
commit 0762182973
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
4 changed files with 56 additions and 27 deletions

View File

@ -898,7 +898,7 @@ static bool cbDeleteAllDllBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (BpDelete)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (BpDelete)\n"), bp->mod);
return false; return false;
} }
if(!LibrarianRemoveBreakPoint(bp->mod, bp->titantype)) if(!dbgdeletedllbreakpoint(bp->mod, bp->titantype))
{ {
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
return false; return false;
@ -916,7 +916,7 @@ static bool cbEnableAllDllBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod);
return false; return false;
} }
if(!LibrarianSetBreakPoint(bp->mod, bp->titantype, bp->singleshoot, (void*)cbLibrarianBreakpoint)) if(!dbgsetdllbreakpoint(bp->mod, bp->titantype, bp->singleshoot))
{ {
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), bp->mod);
return false; return false;
@ -934,7 +934,7 @@ static bool cbDisableAllDllBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), bp->mod);
return false; return false;
} }
if(!LibrarianRemoveBreakPoint(bp->mod, bp->titantype)) if(!dbgdeletedllbreakpoint(bp->mod, bp->titantype))
{ {
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
return false; return false;
@ -946,6 +946,7 @@ bool cbDebugBpDll(int argc, char* argv[])
{ {
if(IsArgumentsLessThan(argc, 2)) if(IsArgumentsLessThan(argc, 2))
return false; return false;
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
DWORD type = UE_ON_LIB_ALL; DWORD type = UE_ON_LIB_ALL;
if(argc > 2) if(argc > 2)
{ {
@ -967,7 +968,7 @@ bool cbDebugBpDll(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (BpNewDll)")); dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (BpNewDll)"));
return false; return false;
} }
if(!LibrarianSetBreakPoint(argv[1], type, singleshoot, (void*)cbLibrarianBreakpoint)) if(!dbgsetdllbreakpoint(argv[1], type, singleshoot))
{ {
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (LibrarianSetBreakPoint)")); dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (LibrarianSetBreakPoint)"));
return false; return false;
@ -993,6 +994,7 @@ bool cbDebugBcDll(int argc, char* argv[])
DebugUpdateBreakpointsViewAsync(); DebugUpdateBreakpointsViewAsync();
return true; return true;
} }
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT bp; BREAKPOINT bp;
if(!BpGetAny(BPDLL, argv[1], &bp)) if(!BpGetAny(BPDLL, argv[1], &bp))
return false; return false;
@ -1001,7 +1003,7 @@ bool cbDebugBcDll(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint...")); dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
return false; return false;
} }
if(!LibrarianRemoveBreakPoint(bp.mod, bp.titantype)) if(!dbgdeletedllbreakpoint(bp.mod, bp.titantype))
{ {
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint...")); dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
return false; return false;
@ -1026,6 +1028,7 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
GuiUpdateAllViews(); GuiUpdateAllViews();
return true; return true;
} }
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT found; BREAKPOINT found;
duint addr = 0; duint addr = 0;
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
@ -1043,7 +1046,7 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), found.mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), found.mod);
return false; return false;
} }
if(!LibrarianSetBreakPoint(found.mod, found.titantype, found.singleshoot, (void*)cbLibrarianBreakpoint)) if(!dbgsetdllbreakpoint(found.mod, found.titantype, found.singleshoot))
{ {
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod);
} }
@ -1067,6 +1070,7 @@ bool cbDebugBpDllDisable(int argc, char* argv[])
GuiUpdateAllViews(); GuiUpdateAllViews();
return true; return true;
} }
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT found; BREAKPOINT found;
duint addr = 0; duint addr = 0;
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
@ -1084,7 +1088,7 @@ bool cbDebugBpDllDisable(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), found.mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), found.mod);
return false; return false;
} }
if(!LibrarianRemoveBreakPoint(found.mod, found.titantype)) if(!dbgdeletedllbreakpoint(found.mod, found.titantype))
{ {
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), found.mod); dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), found.mod);
} }

View File

@ -52,7 +52,6 @@ static bool isDetachedByUser = false;
static bool bIsAttached = false; static bool bIsAttached = false;
static bool bSkipExceptions = false; static bool bSkipExceptions = false;
static duint skipExceptionCount = 0; static duint skipExceptionCount = 0;
static bool bBreakOnNextDll = false;
static bool bFreezeStack = false; static bool bFreezeStack = false;
static std::vector<ExceptionRange> ignoredExceptionRange; static std::vector<ExceptionRange> ignoredExceptionRange;
static HANDLE hEvent = 0; static HANDLE hEvent = 0;
@ -386,6 +385,39 @@ void dbgtracebrowserneedsupdate()
bTraceBrowserNeedsUpdate = true; bTraceBrowserNeedsUpdate = true;
} }
static std::unordered_map<std::string, std::pair<DWORD, bool>> dllBreakpoints;
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot)
{
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
return dllBreakpoints.insert({ mod, { type, singleshoot } }).second;
}
bool dbgdeletedllbreakpoint(const char* mod, DWORD type)
{
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
auto found = dllBreakpoints.find(mod);
if(found == dllBreakpoints.end())
return false;
dllBreakpoints.erase(found);
return true;
}
bool dbghandledllbreakpoint(const char* mod, bool loadDll)
{
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
auto shouldBreak = false;
auto found = dllBreakpoints.find(mod);
if(found != dllBreakpoints.end())
{
if(found->second.first == UE_ON_LIB_ALL || found->second.first == (loadDll ? UE_ON_LIB_LOAD : UE_ON_LIB_UNLOAD))
shouldBreak = true;
if(found->second.second)
dllBreakpoints.erase(found);
}
return shouldBreak;
}
static DWORD WINAPI updateCallStackThread(duint ptr) static DWORD WINAPI updateCallStackThread(duint ptr)
{ {
stackupdatecallstack(ptr); stackupdatecallstack(ptr);
@ -920,11 +952,6 @@ void cbRunToUserCodeBreakpoint(void* ExceptionAddress)
wait(WAITID_RUN); wait(WAITID_RUN);
} }
void cbLibrarianBreakpoint(void* lpData)
{
bBreakOnNextDll = true;
}
static BOOL CALLBACK SymRegisterCallbackProc64(HANDLE, ULONG ActionCode, ULONG64 CallbackData, ULONG64) static BOOL CALLBACK SymRegisterCallbackProc64(HANDLE, ULONG ActionCode, ULONG64 CallbackData, ULONG64)
{ {
PIMAGEHLP_CBA_EVENT evt; PIMAGEHLP_CBA_EVENT evt;
@ -1060,8 +1087,7 @@ bool cbSetDLLBreakpoints(const BREAKPOINT* bp)
return true; return true;
if(bp->type != BPDLL) if(bp->type != BPDLL)
return true; return true;
dputs("debug:dll breakpoint in database\n"); dbgsetdllbreakpoint(bp->mod, bp->titantype, bp->singleshoot);
LibrarianSetBreakPoint(bp->mod, bp->titantype, bp->singleshoot, (void*)cbLibrarianBreakpoint);
return true; return true;
} }
@ -1674,7 +1700,9 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
} }
} }
if((bBreakOnNextDll || settingboolget("Events", "DllEntry")) && !bAlreadySetEntry) auto breakOnDll = dbghandledllbreakpoint(modname, true);
if((breakOnDll || settingboolget("Events", "DllEntry")) && !bAlreadySetEntry)
{ {
auto entry = ModEntryFromAddr(duint(base)); auto entry = ModEntryFromAddr(duint(base));
if(entry) if(entry)
@ -1722,9 +1750,8 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
callbackInfo.modname = modname; callbackInfo.modname = modname;
plugincbcall(CB_LOADDLL, &callbackInfo); plugincbcall(CB_LOADDLL, &callbackInfo);
if(bBreakOnNextDll) if(breakOnDll)
{ {
bBreakOnNextDll = false;
cbGenericBreakpoint(BPDLL, DLLDebugFileName); cbGenericBreakpoint(BPDLL, DLLDebugFileName);
} }
else if(settingboolget("Events", "DllLoad")) else if(settingboolget("Events", "DllLoad"))
@ -1756,9 +1783,8 @@ static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base); SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base);
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Unloaded: %p %s\n"), base, modname); dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Unloaded: %p %s\n"), base, modname);
if(bBreakOnNextDll) if(dbghandledllbreakpoint(modname, false))
{ {
bBreakOnNextDll = false;
cbGenericBreakpoint(BPDLL, modname); cbGenericBreakpoint(BPDLL, modname);
} }
else if(settingboolget("Events", "DllUnload")) else if(settingboolget("Events", "DllUnload"))
@ -2534,7 +2560,6 @@ static void debugLoopFunction(void* lpParameter, bool attach)
//initialize variables //initialize variables
bIsAttached = attach; bIsAttached = attach;
dbgsetskipexceptions(false); dbgsetskipexceptions(false);
bBreakOnNextDll = false;
bFreezeStack = false; bFreezeStack = false;
//prepare attach/createprocess //prepare attach/createprocess
@ -2711,12 +2736,10 @@ static void debugLoopFunction(void* lpParameter, bool attach)
//message the user/do final stuff //message the user/do final stuff
RemoveAllBreakPoints(UE_OPTION_REMOVEALL); //remove all breakpoints RemoveAllBreakPoints(UE_OPTION_REMOVEALL); //remove all breakpoints
BpEnumAll([](const BREAKPOINT * bp) //RemoveAllBreakPoints doesn't remove librarian breakpoints
{ {
if(bp->type == BPDLL) EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
LibrarianRemoveBreakPoint(bp->mod, bp->titantype); dllBreakpoints.clear(); //RemoveAllBreakPoints doesn't remove librarian breakpoints
return true; }
});
//cleanup //cleanup
dbgcleartracestate(); dbgcleartracestate();

View File

@ -79,6 +79,8 @@ const char* dbggetdebuggeeinitscript();
void dbgsetforeground(); void dbgsetforeground();
bool dbggetwintext(std::vector<std::string>* winTextList, const DWORD dwProcessId); bool dbggetwintext(std::vector<std::string>* winTextList, const DWORD dwProcessId);
void dbgtracebrowserneedsupdate(); void dbgtracebrowserneedsupdate();
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot);
bool dbgdeletedllbreakpoint(const char* mod, DWORD type);
void cbStep(); void cbStep();
void cbRtrStep(); void cbRtrStep();
@ -88,7 +90,6 @@ void cbMemoryBreakpoint(void* ExceptionAddress);
void cbHardwareBreakpoint(void* ExceptionAddress); void cbHardwareBreakpoint(void* ExceptionAddress);
void cbUserBreakpoint(); void cbUserBreakpoint();
void cbDebugLoadLibBPX(); void cbDebugLoadLibBPX();
void cbLibrarianBreakpoint(void* lpData);
DWORD WINAPI threadDebugLoop(void* lpParameter); DWORD WINAPI threadDebugLoop(void* lpParameter);
void cbTraceOverConditionalStep(); void cbTraceOverConditionalStep();
void cbTraceIntoConditionalStep(); void cbTraceIntoConditionalStep();

View File

@ -73,6 +73,7 @@ enum SectionLock
LockTypeManager, LockTypeManager,
LockModuleHashes, LockModuleHashes,
LockFormatFunctions, LockFormatFunctions,
LockDllBreakpoints,
// Number of elements in this enumeration. Must always be the last index. // Number of elements in this enumeration. Must always be the last index.
LockLast LockLast