Skip to content

Commit

Permalink
Load/Free Modules in Symbols window
Browse files Browse the repository at this point in the history
- Added command "freelib" to free a module previously loaded
- Added menu entries for load/free modules in the symbols view
  • Loading branch information
ThunderCls committed Dec 14, 2016
1 parent 9b4d140 commit 22108bd
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 0 deletions.
124 changes: 124 additions & 0 deletions src/dbg/commands/cmd-misc.cpp
Expand Up @@ -49,6 +49,7 @@ bool cbDebugHide(int argc, char* argv[])
}

static duint LoadLibThreadID;
static duint FreeLibThreadID;
static duint DLLNameMem;
static duint ASMAddr;
static TITAN_ENGINE_CONTEXT_t backupctx = { 0 };
Expand Down Expand Up @@ -77,6 +78,29 @@ static void cbDebugLoadLibBPX()
wait(WAITID_RUN);
}

static void cbDebugFreeLibBPX()
{
HANDLE FreeLibThread = ThreadGetHandle((DWORD)FreeLibThreadID);
#ifdef _WIN64
duint LibAddr = GetContextDataEx(FreeLibThread, UE_RAX);
#else
duint LibAddr = GetContextDataEx(FreeLibThread, UE_EAX);
#endif //_WIN64
varset("$result", LibAddr, false);
backupctx.eflags &= ~0x100;
SetFullContextDataEx(FreeLibThread, &backupctx);
MemFreeRemote(ASMAddr);
ThreadResumeAll();
//update GUI
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
dbgsetforeground();
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
wait(WAITID_RUN);
}

bool cbDebugLoadLib(int argc, char* argv[])
{
if(argc < 2)
Expand Down Expand Up @@ -150,6 +174,106 @@ bool cbDebugLoadLib(int argc, char* argv[])
return ok;
}

bool GetModuleEntry(MODULEENTRY32* me32, DWORD pID, char* module_name)
{
HANDLE hModuleSnap;
bool found = false;

hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
return false;

if(Module32First(hModuleSnap, me32))
{
do
{
if(_strcmpi(module_name, me32->szModule) == 0)
found = true;
}
while(!found && Module32Next(hModuleSnap, me32));
}

CloseHandle(hModuleSnap);
return found;
}

bool cbDebugFreeLib(int argc, char* argv[])
{
MODULEENTRY32 unloadModule;

ZeroMemory(&unloadModule, sizeof(MODULEENTRY32));
unloadModule.dwSize = sizeof(MODULEENTRY32);

if(argc < 2)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Error: you must specify the name of the DLL to unload\n"));
return false;
}

FreeLibThreadID = fdProcessInfo->dwThreadId;
HANDLE UnLoadLibThread = ThreadGetHandle((duint)FreeLibThreadID);

if(!GetModuleEntry(&unloadModule, DbgGetProcessId(), argv[1]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't get library handle"));
return false;
}

ASMAddr = MemAllocRemote(0, 0x1000);
if(!ASMAddr)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't allocate memory in debuggee"));
return false;
}

int size = 0;
int counter = 0;
duint FreeLibrary = 0;
char command[50] = "";
char error[MAX_ERROR_SIZE] = "";

GetFullContextDataEx(UnLoadLibThread, &backupctx);

if(!valfromstring("kernel32:FreeLibrary", &FreeLibrary, false))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't get kernel32:FreeLibrary"));
return false;
}

// Arch specific asm code
#ifdef _WIN64
sprintf_s(command, "mov rcx, %p", unloadModule.hModule);
#else
sprintf_s(command, "push %p", unloadModule.hModule);
#endif // _WIN64

assembleat(ASMAddr, command, &size, error, true);
counter += size;

#ifdef _WIN64
sprintf_s(command, "mov rax, %p", FreeLibrary);
assembleat(ASMAddr + counter, command, &size, error, true);
counter += size;
sprintf_s(command, "call rax");
#else
sprintf_s(command, "call %p", FreeLibrary);
#endif // _WIN64

assembleat(ASMAddr + counter, command, &size, error, true);
counter += size;

SetContextDataEx(UnLoadLibThread, UE_CIP, ASMAddr);
auto ok = SetBPX(ASMAddr + counter, UE_SINGLESHOOT | UE_BREAKPOINT_TYPE_INT3, (void*)cbDebugFreeLibBPX);

ThreadSuspendAll();
ResumeThread(UnLoadLibThread);

unlock(WAITID_RUN);

return ok;

}

bool cbInstrAssemble(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
Expand Down
1 change: 1 addition & 0 deletions src/dbg/commands/cmd-misc.h
Expand Up @@ -7,6 +7,7 @@ bool cbInstrZzz(int argc, char* argv[]);

bool cbDebugHide(int argc, char* argv[]);
bool cbDebugLoadLib(int argc, char* argv[]);
bool cbDebugFreeLib(int argc, char* argv[]);
bool cbInstrAssemble(int argc, char* argv[]);
bool cbInstrGpa(int argc, char* argv[]);

Expand Down
1 change: 1 addition & 0 deletions src/dbg/x64dbg.cpp
Expand Up @@ -398,6 +398,7 @@ static void registercommands()

dbgcmdnew("HideDebugger\1dbh\1hide", cbDebugHide, true); //HideDebugger
dbgcmdnew("loadlib", cbDebugLoadLib, true); //Load DLL
dbgcmdnew("freelib", cbDebugFreeLib, true); //Unload DLL
dbgcmdnew("asm", cbInstrAssemble, true); //assemble instruction
dbgcmdnew("gpa", cbInstrGpa, true); //get proc address

Expand Down
55 changes: 55 additions & 0 deletions src/gui/Src/Gui/SymbolView.cpp
Expand Up @@ -8,6 +8,7 @@
#include "LineEditDialog.h"
#include <QVBoxLayout>
#include <QProcess>
#include <QFileDialog>

SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView)
{
Expand Down Expand Up @@ -170,6 +171,20 @@ void SymbolView::setupContextMenu()
mModuleList->mSearchList->addAction(mBrowseInExplorer);
connect(mBrowseInExplorer, SIGNAL(triggered()), this, SLOT(moduleBrowse()));

mLoadLib = new QAction(DIcon("lib_load.png"), tr("Load library..."), this);
mLoadLib->setShortcutContext(Qt::WidgetWithChildrenShortcut);
this->addAction(mLoadLib);
mModuleList->mList->addAction(mLoadLib);
mModuleList->mSearchList->addAction(mLoadLib);
connect(mLoadLib, SIGNAL(triggered()), this, SLOT(moduleLoad()));

mFreeLib = new QAction(DIcon("lib_free.png"), tr("Free library"), this);
mFreeLib->setShortcutContext(Qt::WidgetWithChildrenShortcut);
this->addAction(mFreeLib);
mModuleList->mList->addAction(mFreeLib);
mModuleList->mSearchList->addAction(mFreeLib);
connect(mFreeLib, SIGNAL(triggered()), this, SLOT(moduleFree()));

mYaraAction = new QAction(DIcon("yara.png"), tr("&Yara Memory..."), this);
connect(mYaraAction, SIGNAL(triggered()), this, SLOT(moduleYara()));

Expand Down Expand Up @@ -381,6 +396,8 @@ void SymbolView::moduleContextMenu(QMenu* wMenu)
wMenu->addAction(mCopyPathAction);
wMenu->addAction(mBrowseInExplorer);
}
wMenu->addAction(mLoadLib);
wMenu->addAction(mFreeLib);
wMenu->addAction(mYaraAction);
wMenu->addAction(mYaraFileAction);
wMenu->addAction(mEntropyAction);
Expand Down Expand Up @@ -461,6 +478,44 @@ void SymbolView::moduleDownloadAllSymbols()
DbgCmdExec("symdownload");
}

void SymbolView::moduleLoad()
{
QString cmd;
if(!DbgIsDebugging())
return;

QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("Dll Files (*.dll)"));
if(fileName.size() != 0)
{
cmd = "loadlib " + fileName;
DbgCmdExec(cmd.toUtf8().constData());
}
}

void SymbolView::moduleFree()
{
QString cmd;
if(!DbgIsDebugging())
return;

QString moduleName = mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), 1);
if(moduleName.length() != 0)
{
QMessageBox::StandardButton reply;
QString question = "Are you sure you want to free the module: " + moduleName + "\r\nThis could bring an unexpected behaviour to your debugging sesion";
reply = QMessageBox::question(this,
tr("Free Library").toUtf8().constData(),
question.toUtf8().constData(),
QMessageBox::Yes | QMessageBox::No);
if(reply == QMessageBox::Yes)
{
cmd = "freelib " + moduleName;
DbgCmdExec(cmd.toUtf8().constData());
mSearchListView->mCurList->setRowCount(0);
}
}
}

void SymbolView::toggleBreakpoint()
{
if(!DbgIsDebugging())
Expand Down
4 changes: 4 additions & 0 deletions src/gui/Src/Gui/SymbolView.h
Expand Up @@ -52,6 +52,8 @@ private slots:
void moduleEntropy();
void emptySearchResultSlot();
void selectionGetSlot(SELECTIONDATA* selection);
void moduleLoad();
void moduleFree();

signals:
void showReferences();
Expand Down Expand Up @@ -81,6 +83,8 @@ private slots:
QAction* mModSetPartyAction;
QAction* mBrowseInExplorer;
QAction* mFollowInMemMap;
QAction* mLoadLib;
QAction* mFreeLib;

static void cbSymbolEnum(SYMBOLINFO* symbol, void* user);
};
Expand Down
Binary file added src/gui/images/lib_free.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/gui/images/lib_load.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/gui/resource.qrc
Expand Up @@ -278,5 +278,7 @@
<file>images/uac.png</file>
<file>images/hidetab.png</file>
<file>images/variables.png</file>
<file>images/lib_load.png</file>
<file>images/lib_free.png</file>
</qresource>
</RCC>

0 comments on commit 22108bd

Please sign in to comment.