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);
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);
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);
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);
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);
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);
return false;
@ -946,6 +946,7 @@ bool cbDebugBpDll(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return false;
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
DWORD type = UE_ON_LIB_ALL;
if(argc > 2)
{
@ -967,7 +968,7 @@ bool cbDebugBpDll(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (BpNewDll)"));
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)"));
return false;
@ -993,6 +994,7 @@ bool cbDebugBcDll(int argc, char* argv[])
DebugUpdateBreakpointsViewAsync();
return true;
}
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT bp;
if(!BpGetAny(BPDLL, argv[1], &bp))
return false;
@ -1001,7 +1003,7 @@ bool cbDebugBcDll(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
return false;
}
if(!LibrarianRemoveBreakPoint(bp.mod, bp.titantype))
if(!dbgdeletedllbreakpoint(bp.mod, bp.titantype))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
return false;
@ -1026,6 +1028,7 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
GuiUpdateAllViews();
return true;
}
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT found;
duint addr = 0;
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);
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);
}
@ -1067,6 +1070,7 @@ bool cbDebugBpDllDisable(int argc, char* argv[])
GuiUpdateAllViews();
return true;
}
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
BREAKPOINT found;
duint addr = 0;
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);
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);
}

View File

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

View File

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

View File

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