diff --git a/Scylla/AboutGui.cpp b/Scylla/AboutGui.cpp index 5fb88ed..614a7d5 100644 --- a/Scylla/AboutGui.cpp +++ b/Scylla/AboutGui.cpp @@ -1,125 +1,117 @@ #include "AboutGui.h" #include "definitions.h" const WCHAR AboutGui::TEXT_VISIT[] = L"Visit http://kickme.to/grn and http://forum.tuts4you.com"; const WCHAR AboutGui::TEXT_DEVELOPED[] = L"Developed with Microsoft Visual Studio, written in pure C/C++"; const WCHAR AboutGui::TEXT_CREDIT_DISTORM[] = L"This tool uses the diStorm disassembler library v3"; const WCHAR AboutGui::TEXT_CREDIT_YODA[] = L"The PE Rebuilder engine is based on Realign DLL v1.5 by yoda"; const WCHAR AboutGui::TEXT_CREDIT_SILK[] = L"The small icons are taken from the Silk icon package"; const WCHAR AboutGui::TEXT_CREDIT_WTL[] = L"Windows Template Library v8 is used for the GUI"; const WCHAR AboutGui::TEXT_GREETINGS[] = L"Greetz: metr0, G36KV and all from the gRn Team"; const WCHAR AboutGui::TEXT_LICENSE[] = L"Scylla is licensed under the GNU General Public License v3"; const WCHAR AboutGui::URL_VISIT1[] = L"http://kickme.to/grn"; const WCHAR AboutGui::URL_VISIT2[] = L"http://forum.tuts4you.com"; const WCHAR AboutGui::URL_DISTORM[] = L"http://code.google.com/p/distorm/"; const WCHAR AboutGui::URL_WTL[] = L"http://wtl.sourceforge.net"; const WCHAR AboutGui::URL_SILK[] = L"http://www.famfamfam.com"; const WCHAR AboutGui::URL_LICENSE[] = L"http://www.gnu.org/licenses/gpl-3.0.html"; BOOL AboutGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - StaticTitle.Attach(GetDlgItem(IDC_STATIC_ABOUT_TITLE)); - StaticDeveloped.Attach(GetDlgItem(IDC_STATIC_DEVELOPED)); - StaticGreetings.Attach(GetDlgItem(IDC_STATIC_GREETINGS)); - StaticYoda.Attach(GetDlgItem(IDC_STATIC_YODA)); - LinkVisit.Attach(GetDlgItem(IDC_SYSLINK_VISIT)); - LinkDistorm.Attach(GetDlgItem(IDC_SYSLINK_DISTORM)); - LinkWTL.Attach(GetDlgItem(IDC_SYSLINK_WTL)); - LinkSilk.Attach(GetDlgItem(IDC_SYSLINK_SILK)); - LinkLicense.Attach(GetDlgItem(IDC_SYSLINK_LICENSE)); + DoDataExchange(); // attach controls // Create a bold font for the title LOGFONT lf; CFontHandle font = StaticTitle.GetFont(); font.GetLogFont(&lf); lf.lfWeight = FW_BOLD; FontBold.CreateFontIndirect(&lf); StaticTitle.SetFont(FontBold, FALSE); StaticTitle.SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); StaticDeveloped.SetWindowText(TEXT_DEVELOPED); StaticGreetings.SetWindowText(TEXT_GREETINGS); StaticYoda.SetWindowText(TEXT_CREDIT_YODA); setupLinks(); CenterWindow(); // Set focus to the OK button GotoDlgCtrl(GetDlgItem(IDOK)); return FALSE; } void AboutGui::OnClose() { TooltipDistorm.DestroyWindow(); TooltipWTL.DestroyWindow(); TooltipSilk.DestroyWindow(); TooltipLicense.DestroyWindow(); FontBold.DeleteObject(); EndDialog(0); } LRESULT AboutGui::OnLink(NMHDR* pnmh) { const NMLINK* link = (NMLINK*)pnmh; ShellExecute(NULL, L"open", link->item.szUrl, NULL, NULL, SW_SHOW); return 0; } void AboutGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { SendMessage(WM_CLOSE); } void AboutGui::setupLinks() { // Set link text (must be set before assigning URLs) LinkVisit.SetWindowText(TEXT_VISIT); LinkDistorm.SetWindowText(TEXT_CREDIT_DISTORM); LinkWTL.SetWindowText(TEXT_CREDIT_WTL); LinkSilk.SetWindowText(TEXT_CREDIT_SILK); LinkLicense.SetWindowText(TEXT_LICENSE); // Assign URLs to anchors in the link text setLinkURL(LinkVisit, URL_VISIT1, 0); setLinkURL(LinkVisit, URL_VISIT2, 1); setLinkURL(LinkDistorm, URL_DISTORM); setLinkURL(LinkWTL, URL_WTL); setLinkURL(LinkSilk, URL_SILK); setLinkURL(LinkLicense, URL_LICENSE); // Create tooltips for the links TooltipDistorm.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); TooltipWTL.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); TooltipSilk.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); TooltipLicense.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); // Assign control and text to the tooltips setupTooltip(TooltipDistorm, LinkDistorm, URL_DISTORM); setupTooltip(TooltipWTL, LinkWTL, URL_WTL); setupTooltip(TooltipSilk, LinkSilk, URL_SILK); setupTooltip(TooltipLicense, LinkLicense, URL_LICENSE); } void AboutGui::setLinkURL(CLinkCtrl& link, const WCHAR* url, int index) { LITEM item; item.mask = LIF_ITEMINDEX | LIF_URL; item.iLink = index; wcscpy_s(item.szUrl, _countof(item.szUrl), url); link.SetItem(&item); } void AboutGui::setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text) { CToolInfo ti(TTF_SUBCLASS, window); window.GetClientRect(&ti.rect); ti.lpszText = const_cast(text); tooltip.AddTool(ti); } diff --git a/Scylla/AboutGui.h b/Scylla/AboutGui.h index faedc53..4f38e77 100644 --- a/Scylla/AboutGui.h +++ b/Scylla/AboutGui.h @@ -1,93 +1,106 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange -class AboutGui : public CDialogImpl +class AboutGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_ABOUT }; + BEGIN_DDX_MAP(AboutGui) + DDX_CONTROL_HANDLE(IDC_STATIC_ABOUT_TITLE, StaticTitle) + DDX_CONTROL_HANDLE(IDC_STATIC_DEVELOPED, StaticDeveloped) + DDX_CONTROL_HANDLE(IDC_STATIC_GREETINGS, StaticGreetings) + DDX_CONTROL_HANDLE(IDC_STATIC_YODA, StaticYoda) + DDX_CONTROL_HANDLE(IDC_SYSLINK_VISIT, LinkVisit) + DDX_CONTROL_HANDLE(IDC_SYSLINK_DISTORM, LinkDistorm) + DDX_CONTROL_HANDLE(IDC_SYSLINK_WTL, LinkWTL) + DDX_CONTROL_HANDLE(IDC_SYSLINK_SILK, LinkSilk) + DDX_CONTROL_HANDLE(IDC_SYSLINK_LICENSE, LinkLicense) + END_DDX_MAP() + BEGIN_MSG_MAP(AboutGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CLOSE(OnClose) NOTIFY_HANDLER_EX(IDC_SYSLINK_DISTORM, NM_CLICK, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_DISTORM, NM_RETURN, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_WTL, NM_CLICK, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_WTL, NM_RETURN, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_SILK, NM_CLICK, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_SILK, NM_RETURN, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_VISIT, NM_CLICK, OnLink) NOTIFY_HANDLER_EX(IDC_SYSLINK_VISIT, NM_RETURN, OnLink) COMMAND_ID_HANDLER_EX(IDOK, OnExit) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) END_MSG_MAP() protected: // Controls CStatic StaticTitle; CStatic StaticDeveloped; CStatic StaticGreetings; CStatic StaticYoda; CLinkCtrl LinkVisit; CLinkCtrl LinkDistorm; CLinkCtrl LinkWTL; CLinkCtrl LinkSilk; CLinkCtrl LinkLicense; CToolTipCtrl TooltipDistorm; CToolTipCtrl TooltipWTL; CToolTipCtrl TooltipSilk; CToolTipCtrl TooltipLicense; // Handles CFontHandle FontBold; // Texts static const WCHAR TEXT_VISIT[]; static const WCHAR TEXT_DEVELOPED[]; static const WCHAR TEXT_CREDIT_DISTORM[]; static const WCHAR TEXT_CREDIT_YODA[]; static const WCHAR TEXT_CREDIT_WTL[]; static const WCHAR TEXT_CREDIT_SILK[]; static const WCHAR TEXT_GREETINGS[]; static const WCHAR TEXT_LICENSE[]; // URLs static const WCHAR URL_VISIT1[]; static const WCHAR URL_VISIT2[]; static const WCHAR URL_DISTORM[]; static const WCHAR URL_WTL[]; static const WCHAR URL_SILK[]; static const WCHAR URL_LICENSE[]; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnClose(); LRESULT OnLink(NMHDR* pnmh); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI helpers void setupLinks(); void setLinkURL(CLinkCtrl& link, const WCHAR* url, int index = 0); void setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text); }; diff --git a/Scylla/DisassemblerGui.cpp b/Scylla/DisassemblerGui.cpp index cd0927a..bc48c85 100644 --- a/Scylla/DisassemblerGui.cpp +++ b/Scylla/DisassemblerGui.cpp @@ -1,145 +1,145 @@ #include "DisassemblerGui.h" #include "ProcessAccessHelp.h" DisassemblerGui::DisassemblerGui(DWORD_PTR startAddress) : startAddress(startAddress) { hMenuDisassembler.LoadMenu(IDR_MENU_DISASSEMBLER); } BOOL DisassemblerGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - ListDisassembler.Attach(GetDlgItem(IDC_LIST_DISASSEMBLER)); + DoDataExchange(); // attach controls addColumnsToDisassembler(ListDisassembler); displayDisassembly(ListDisassembler); CenterWindow(); return TRUE; } void DisassemblerGui::OnContextMenu(CWindow wnd, CPoint point) { if (wnd.GetDlgCtrlID() == IDC_LIST_DISASSEMBLER) { int selection = ListDisassembler.GetSelectionMark(); if(selection == -1) // no item selected return; if(hMenuDisassembler) { if(point.x == -1 && point.y == -1) // invoked by keyboard { ListDisassembler.EnsureVisible(selection, TRUE); ListDisassembler.GetItemPosition(selection, &point); ListDisassembler.ClientToScreen(&point); } CMenuHandle hSub = hMenuDisassembler.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, wnd); if (menuItem) { int column = -1; switch (menuItem) { case ID__DIS_ADDRESS: column = COL_ADDRESS; break; case ID__DIS_SIZE: column = COL_INSTRUCTION_SIZE; break; case ID__DIS_OPCODES: column = COL_OPCODES; break; case ID__DIS_INSTRUCTIONS: column = COL_INSTRUCTION; break; } if(column != -1) { tempBuffer[0] = '\0'; ListDisassembler.GetItemText(selection, column, tempBuffer, _countof(tempBuffer)); copyToClipboard(tempBuffer); } } } } } void DisassemblerGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void DisassemblerGui::addColumnsToDisassembler(CListViewCtrl& list) { list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); list.InsertColumn(COL_ADDRESS, L"Address", LVCFMT_LEFT); list.InsertColumn(COL_INSTRUCTION_SIZE, L"Size", LVCFMT_CENTER); list.InsertColumn(COL_OPCODES, L"Opcodes", LVCFMT_LEFT); list.InsertColumn(COL_INSTRUCTION, L"Instructions", LVCFMT_LEFT); } void DisassemblerGui::displayDisassembly(CListViewCtrl& list) { BYTE data[DISASSEMBLER_GUI_MEMORY_SIZE]; list.DeleteAllItems(); if(!ProcessAccessHelp::readMemoryFromProcess(startAddress, sizeof(data), data)) return; ProcessAccessHelp::disassembleMemory(data, sizeof(data), startAddress); for (unsigned int i = 0; i < ProcessAccessHelp::decodedInstructionsCount; i++) { #ifdef _WIN64 swprintf_s(tempBuffer, _countof(tempBuffer),L"%016I64X",ProcessAccessHelp::decodedInstructions[i].offset); #else swprintf_s(tempBuffer, _countof(tempBuffer),L"%08X",ProcessAccessHelp::decodedInstructions[i].offset); #endif list.InsertItem(i, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%02d",ProcessAccessHelp::decodedInstructions[i].size); list.SetItemText(i, COL_INSTRUCTION_SIZE, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%S",(char *)ProcessAccessHelp::decodedInstructions[i].instructionHex.p); list.SetItemText(i, COL_OPCODES, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%S%S%S",(char*)ProcessAccessHelp::decodedInstructions[i].mnemonic.p, ProcessAccessHelp::decodedInstructions[i].operands.length != 0 ? " " : "", (char*)ProcessAccessHelp::decodedInstructions[i].operands.p); list.SetItemText(i, COL_INSTRUCTION, tempBuffer); } list.SetColumnWidth(COL_ADDRESS, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_INSTRUCTION_SIZE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_OPCODES, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_INSTRUCTION, LVSCW_AUTOSIZE_USEHEADER); } void DisassemblerGui::copyToClipboard(const WCHAR * text) { if(OpenClipboard()) { EmptyClipboard(); size_t len = wcslen(text); HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len+1)*sizeof(WCHAR)); if(hMem) { wcscpy_s((WCHAR *)GlobalLock(hMem), len+1, text); GlobalUnlock(hMem); if(!SetClipboardData(CF_UNICODETEXT, hMem)) { GlobalFree(hMem); } } CloseClipboard(); } } diff --git a/Scylla/DisassemblerGui.h b/Scylla/DisassemblerGui.h index 8605352..5560782 100644 --- a/Scylla/DisassemblerGui.h +++ b/Scylla/DisassemblerGui.h @@ -1,69 +1,74 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange -class DisassemblerGui : public CDialogImpl +class DisassemblerGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_DISASSEMBLER }; + BEGIN_DDX_MAP(DisassemblerGui) + DDX_CONTROL_HANDLE(IDC_LIST_DISASSEMBLER, ListDisassembler) + END_DDX_MAP() + BEGIN_MSG_MAP(DisassemblerGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CONTEXTMENU(OnContextMenu) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) COMMAND_ID_HANDLER_EX(IDOK, OnExit) END_MSG_MAP() DisassemblerGui(DWORD_PTR startAddress); protected: // Variables static const size_t DISASSEMBLER_GUI_MEMORY_SIZE = 0x100; WCHAR tempBuffer[100]; DWORD_PTR startAddress; // Controls CListViewCtrl ListDisassembler; enum DisassemblerColumns { COL_ADDRESS = 0, COL_INSTRUCTION_SIZE, COL_OPCODES, COL_INSTRUCTION }; // Handles CMenu hMenuDisassembler; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnContextMenu(CWindow wnd, CPoint point); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void addColumnsToDisassembler(CListViewCtrl& list); void displayDisassembly(CListViewCtrl& list); // Misc void copyToClipboard(const WCHAR * text); }; diff --git a/Scylla/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp index 764e481..bbe7ab4 100644 --- a/Scylla/ImportsHandling.cpp +++ b/Scylla/ImportsHandling.cpp @@ -1,784 +1,784 @@ #include "ImportsHandling.h" #include "Thunks.h" #include "definitions.h" #include "resource.h" //#define DEBUG_COMMENTS -ImportsHandling::ImportsHandling(CTreeViewCtrl& TreeImports) : TreeImports(TreeImports) +ImportsHandling::ImportsHandling(CTreeViewCtrlEx& TreeImports) : TreeImports(TreeImports) { hIconCheck.LoadIcon(IDI_ICON_CHECK); hIconWarning.LoadIcon(IDI_ICON_WARNING); hIconError.LoadIcon(IDI_ICON_ERROR); TreeIcons.Create(16, 16, ILC_COLOR32, 3, 1); TreeIcons.AddIcon(hIconCheck); TreeIcons.AddIcon(hIconWarning); TreeIcons.AddIcon(hIconError); } ImportsHandling::~ImportsHandling() { TreeIcons.Destroy(); } bool ImportModuleThunk::isValid() const { std::map::const_iterator iterator = thunkList.begin(); while (iterator != thunkList.end()) { if (iterator->second.valid == false) { return false; } iterator++; } return true; } DWORD_PTR ImportModuleThunk::getFirstThunk() const { if (thunkList.size() > 0) { const std::map::const_iterator iterator = thunkList.begin(); return iterator->first; } else { return 0; } } /*bool ImportsHandling::addModule(WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, moduleName); moduleList.insert(std::pair(firstThunk,module)); return true; }*/ /*bool ImportsHandling::addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if (moduleList.size() > 1) { iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleList.end()) { iterator1--; module = &(iterator1->second); break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } } } else { iterator1 = moduleList.begin(); module = &(iterator1->second); } if (!module) { Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(""),rva); return false; } //TODO import.suspect = true; import.valid = false; import.va = va; import.rva = rva; import.ordinal = ordinal; wcscpy_s(import.moduleName, MAX_PATH, moduleName); strcpy_s(import.name, MAX_PATH, name); module->thunkList.insert(std::pair(import.rva, import)); return true; }*/ void ImportsHandling::displayAllImports() { std::map::iterator it_module; std::map::iterator it_thunk; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; CTreeItem module; CTreeItem apiFunction; TreeImports.DeleteAllItems(); TreeImports.SetImageList(TreeIcons); it_module = moduleList.begin(); while (it_module != moduleList.end()) { moduleThunk = &(it_module->second); module = addDllToTreeView(TreeImports,moduleThunk); moduleThunk->hTreeItem = module; it_thunk = moduleThunk->thunkList.begin(); while (it_thunk != moduleThunk->thunkList.end()) { importThunk = &(it_thunk->second); apiFunction = addApiToTreeView(TreeImports,module,importThunk); importThunk->hTreeItem = apiFunction; it_thunk++; } it_module++; } } -CTreeItem ImportsHandling::addDllToTreeView(CTreeViewCtrl& idTreeView, const ImportModuleThunk * importThunk) +CTreeItem ImportsHandling::addDllToTreeView(CTreeViewCtrlEx& idTreeView, const ImportModuleThunk * importThunk) { CTreeItem item = idTreeView.InsertItem(L"", NULL, TVI_ROOT); updateModuleInTreeView(importThunk, item); return item; } -CTreeItem ImportsHandling::addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk) +CTreeItem ImportsHandling::addApiToTreeView(CTreeViewCtrlEx& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk) { CTreeItem item = idTreeView.InsertItem(L"", parentDll, TVI_LAST); updateImportInTreeView(importThunk, item); return item; } void ImportsHandling::showImports(bool invalid, bool suspect) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; TreeImports.SetFocus(); TreeImports.SelectItem(NULL); //remove selection iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (invalid && !importThunk->valid) { - selectItem(TreeImports, importThunk->hTreeItem); + selectItem(importThunk->hTreeItem); setFocus(TreeImports, importThunk->hTreeItem); } else if (suspect && importThunk->suspect) { - selectItem(TreeImports, importThunk->hTreeItem); + selectItem(importThunk->hTreeItem); setFocus(TreeImports, importThunk->hTreeItem); } else { - unselectItem(TreeImports, importThunk->hTreeItem); + unselectItem(importThunk->hTreeItem); } iterator2++; } iterator1++; } } -bool ImportsHandling::isItemSelected(const CTreeViewCtrl& hwndTV, CTreeItem hItem) +bool ImportsHandling::isItemSelected(CTreeItem hItem) { const UINT state = TVIS_SELECTED; - return ((hwndTV.GetItemState(hItem, state) & state) == state); + return ((hItem.GetState(state) & state) == state); } -void ImportsHandling::unselectItem(CTreeViewCtrl& hwndTV, CTreeItem htItem) +void ImportsHandling::unselectItem(CTreeItem htItem) { - selectItem(hwndTV, htItem, false); + selectItem(htItem, false); } -bool ImportsHandling::selectItem(CTreeViewCtrl& hwndTV, CTreeItem hItem, bool select) +bool ImportsHandling::selectItem(CTreeItem hItem, bool select) { const UINT state = TVIS_SELECTED; - return FALSE != hwndTV.SetItemState(hItem, (select ? state : 0), state); + return FALSE != hItem.SetState((select ? state : 0), state); } -void ImportsHandling::setFocus(CTreeViewCtrl& hwndTV, CTreeItem htItem) +void ImportsHandling::setFocus(CTreeViewCtrlEx& hwndTV, CTreeItem htItem) { // the current focus CTreeItem htFocus = hwndTV.GetSelectedItem(); if ( htItem ) { // set the focus if ( htItem != htFocus ) { // remember the selection state of the item - bool wasSelected = isItemSelected(hwndTV, htItem); + bool wasSelected = isItemSelected(htItem); - if ( htFocus && isItemSelected(hwndTV, htFocus) ) + if ( htFocus && isItemSelected(htFocus) ) { // prevent the tree from unselecting the old focus which it // would do by default (TreeView_SelectItem unselects the // focused item) hwndTV.SelectItem(NULL); - selectItem(hwndTV, htFocus); + selectItem(htFocus); } hwndTV.SelectItem(htItem); if ( !wasSelected ) { // need to clear the selection which TreeView_SelectItem() gave // us - unselectItem(hwndTV, htItem); + unselectItem(htItem); } //else: was selected, still selected - ok } //else: nothing to do, focus already there } else { if ( htFocus ) { - bool wasFocusSelected = isItemSelected(hwndTV, htFocus); + bool wasFocusSelected = isItemSelected(htFocus); // just clear the focus hwndTV.SelectItem(NULL); if ( wasFocusSelected ) { // restore the selection state - selectItem(hwndTV, htFocus); + selectItem(htFocus); } } //else: nothing to do, no focus already } } bool ImportsHandling::invalidateFunction(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { importThunk->ordinal = 0; importThunk->hint = 0; importThunk->valid = false; importThunk->suspect = false; importThunk->moduleName[0] = 0; importThunk->name[0] = 0; updateImportInTreeView(importThunk, importThunk->hTreeItem); updateModuleInTreeView(moduleThunk, moduleThunk->hTreeItem); return true; } iterator2++; } iterator1++; } return false; } void ImportsHandling::updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item) { if (importThunk->valid) { + WCHAR tempString[300]; + if (importThunk->name[0] != 0x00) { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name); } else { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal); } swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->rva,importThunk->moduleName,tempString); } else { swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" ptr: ")TEXT(PRINTF_DWORD_PTR_FULL),importThunk->rva,importThunk->apiAddressVA); } - TreeImports.SetItemText(item, stringBuffer); + item.SetText(stringBuffer); Icon icon = getAppropiateIcon(importThunk); - TreeImports.SetItemImage(item, icon, icon); + item.SetImage(icon, icon); } void ImportsHandling::updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item) { - //swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" NbThunk: %d"),importThunk->moduleName,importThunk->firstThunk,importThunk->thunkList.size()); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s (%d) FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF),importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk); - TreeImports.SetItemText(item, stringBuffer); + item.SetText(stringBuffer); Icon icon = getAppropiateIcon(importThunk->isValid()); - TreeImports.SetItemImage(item, icon, icon); + item.SetImage(icon, icon); } ImportsHandling::Icon ImportsHandling::getAppropiateIcon(const ImportThunk * importThunk) { if(importThunk->valid) { if(importThunk->suspect) { return iconWarning; } else { return iconCheck; } } else { return iconError; } } ImportsHandling::Icon ImportsHandling::getAppropiateIcon(bool valid) { if(valid) { return iconCheck; } else { return iconError; } } bool ImportsHandling::cutThunk(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { - TreeImports.DeleteItem(importThunk->hTreeItem); + importThunk->hTreeItem.Delete(); moduleThunk->thunkList.erase(iterator2); if (moduleThunk->thunkList.empty()) { - TreeImports.DeleteItem(moduleThunk->hTreeItem); + moduleThunk->hTreeItem.Delete(); moduleList.erase(iterator1); } else { updateModuleInTreeView(moduleThunk, moduleThunk->hTreeItem); } return true; } iterator2++; } iterator1++; } return false; } bool ImportsHandling::deleteTreeNode(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); if (moduleThunk->hTreeItem == selectedTreeNode) { - TreeImports.DeleteItem(moduleThunk->hTreeItem); + moduleThunk->hTreeItem.Delete(); moduleThunk->thunkList.clear(); moduleList.erase(iterator1); return true; } else { iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { - TreeImports.DeleteItem(moduleThunk->hTreeItem); + moduleThunk->hTreeItem.Delete(); moduleThunk->thunkList.clear(); moduleList.erase(iterator1); return true; } iterator2++; } } iterator1++; } return false; } DWORD_PTR ImportsHandling::getApiAddressByNode(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { return importThunk->apiAddressVA; } iterator2++; } iterator1++; } return 0; } void ImportsHandling::scanAndFixModuleList() { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->moduleName[0] == 0 || importThunk->moduleName[0] == L'?') { addNotFoundApiToModuleList(importThunk); } else { if (isNewModule(importThunk->moduleName)) { addModuleToModuleList(importThunk->moduleName, importThunk->rva); } addFunctionToModuleList(importThunk); } iterator2++; } moduleThunk->thunkList.clear(); iterator1++; } - moduleList.clear(); - moduleList.insert(moduleListNew.begin(), moduleListNew.end()); + moduleList = moduleListNew; moduleListNew.clear(); } bool ImportsHandling::findNewModules(std::map & thunkList) { throw std::exception("The method or operation is not implemented."); } bool ImportsHandling::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, moduleName); moduleListNew.insert(std::pair(firstThunk,module)); return true; } bool ImportsHandling::isNewModule(const WCHAR * moduleName) { std::map::iterator iterator1; iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (!_wcsicmp(iterator1->second.moduleName, moduleName)) { return false; } iterator1++; } return true; } void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, L"?"); moduleListNew.insert(std::pair(firstThunk,module)); } bool ImportsHandling::addNotFoundApiToModuleList(const ImportThunk * apiNotFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; DWORD_PTR rva = apiNotFound->rva; if (moduleListNew.size() > 0) { iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleListNew.end()) { iterator1--; //new unknown module if (iterator1->second.moduleName[0] == L'?') { module = &(iterator1->second); } else { addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog("Error iterator1 != (*moduleThunkList).end()\r\n"); #endif break; } } } else { //new unknown module addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); #endif return false; } import.suspect = true; import.valid = false; import.va = apiNotFound->va; import.rva = apiNotFound->rva; import.apiAddressVA = apiNotFound->apiAddressVA; import.ordinal = 0; wcscpy_s(import.moduleName, MAX_PATH, L"?"); strcpy_s(import.name, MAX_PATH, "?"); module->thunkList.insert(std::pair(import.rva, import)); return true; } bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if (moduleListNew.size() > 1) { iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (apiFound->rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleListNew.end()) { iterator1--; module = &(iterator1->second); break; } else if (apiFound->rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("Error iterator1 != moduleListNew.end()\r\n")); #endif break; } } } else { iterator1 = moduleListNew.begin(); module = &(iterator1->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),apiFound->rva); #endif return false; } import.suspect = apiFound->suspect; import.valid = apiFound->valid; import.va = apiFound->va; import.rva = apiFound->rva; import.apiAddressVA = apiFound->apiAddressVA; import.ordinal = apiFound->ordinal; import.hint = apiFound->hint; wcscpy_s(import.moduleName, MAX_PATH, apiFound->moduleName); strcpy_s(import.name, MAX_PATH, apiFound->name); module->thunkList.insert(std::pair(import.rva, import)); return true; } void ImportsHandling::expandAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_EXPAND); } void ImportsHandling::collapseAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_COLLAPSE); } void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag) { std::map::iterator iterator1; ImportModuleThunk * moduleThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); - TreeImports.Expand(moduleThunk->hTreeItem, flag); + moduleThunk->hTreeItem.Expand(flag); iterator1++; } } diff --git a/Scylla/ImportsHandling.h b/Scylla/ImportsHandling.h index 2015c38..3c4f8ab 100644 --- a/Scylla/ImportsHandling.h +++ b/Scylla/ImportsHandling.h @@ -1,76 +1,75 @@ #pragma once #include // WTL #include #include -#include // CTreeViewCtrl, CTreeItem +#include // CTreeViewCtrlEx, CTreeItem class ImportThunk; class ImportModuleThunk; class ImportsHandling { public: std::map moduleList; std::map moduleListNew; //bool addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect); //bool addModule(WCHAR * moduleName, DWORD_PTR firstThunk); - ImportsHandling(CTreeViewCtrl& TreeImports); + ImportsHandling(CTreeViewCtrlEx& TreeImports); ~ImportsHandling(); void displayAllImports(); void showImports(bool invalid, bool suspect); bool invalidateFunction(CTreeItem selectedTreeNode); bool cutThunk(CTreeItem selectedTreeNode); bool deleteTreeNode(CTreeItem selectedTreeNode); void updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item); void updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item); DWORD_PTR getApiAddressByNode(CTreeItem selectedTreeNode); void scanAndFixModuleList(); void expandAllTreeNodes(); void collapseAllTreeNodes(); private: DWORD numberOfFunctions; - WCHAR stringBuffer[600]; // o_O - WCHAR tempString[300]; + WCHAR stringBuffer[600]; - CTreeViewCtrl& TreeImports; + CTreeViewCtrlEx& TreeImports; CImageList TreeIcons; CIcon hIconCheck; CIcon hIconWarning; CIcon hIconError; // They have to be added to the image list in that order! enum Icon { iconCheck = 0, iconWarning, iconError }; - CTreeItem addDllToTreeView(CTreeViewCtrl& idTreeView, const ImportModuleThunk * importThunk); - CTreeItem addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk); + CTreeItem addDllToTreeView(CTreeViewCtrlEx& idTreeView, const ImportModuleThunk * importThunk); + CTreeItem addApiToTreeView(CTreeViewCtrlEx& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk); - bool isItemSelected(const CTreeViewCtrl& hwndTV, CTreeItem hItem); - void unselectItem(CTreeViewCtrl& hwndTV, CTreeItem htItem); - bool selectItem(CTreeViewCtrl& hwndTV, CTreeItem hItem, bool select = true); - void setFocus(CTreeViewCtrl& hwndTV, CTreeItem htItem); + bool isItemSelected(CTreeItem hItem); + void unselectItem(CTreeItem htItem); + bool selectItem(CTreeItem hItem, bool select = true); + void setFocus(CTreeViewCtrlEx& hwndTV, CTreeItem htItem); bool findNewModules(std::map & thunkList); Icon getAppropiateIcon(const ImportThunk * importThunk); Icon getAppropiateIcon(bool valid); bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk); void addUnknownModuleToModuleList(DWORD_PTR firstThunk); bool addNotFoundApiToModuleList(const ImportThunk * apiNotFound); bool addFunctionToModuleList(const ImportThunk * apiFound); bool isNewModule(const WCHAR * moduleName); void changeExpandStateOfTreeNodes(UINT flag); }; diff --git a/Scylla/Logger.h b/Scylla/Logger.h index 2ff6a97..5e6a2e7 100644 --- a/Scylla/Logger.h +++ b/Scylla/Logger.h @@ -1,20 +1,20 @@ #pragma once #include #define DEBUG_LOG_FILENAME "Scylla_debug.log" class Logger { public: static void debugLog(const WCHAR * format, ...); static void debugLog(const CHAR * format, ...); static void printfDialog(const WCHAR * format, ...); static void getDebugLogFilePath(); private: static WCHAR debugLogFile[MAX_PATH]; static WCHAR logbuf[300]; static char logbufChar[300]; -}; \ No newline at end of file +}; diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp index 3bea1e5..73f39b4 100644 --- a/Scylla/MainGui.cpp +++ b/Scylla/MainGui.cpp @@ -1,1141 +1,1129 @@ #include "MainGui.h" #include // WTL common dialogs #include "definitions.h" #include "PluginLoader.h" #include "ConfigurationHolder.h" #include "PeDump.h" #include "PeRebuild.h" #include "DllInjectionPlugin.h" #include "DisassemblerGui.h" #include "PickApiGui.h" #include "NativeWinApi.h" #include "ImportRebuild.h" #include "SystemInformation.h" #include "AboutGui.h" #include "OptionsGui.h" #include "WindowDeferrer.h" const WCHAR MainGui::filterExe[] = L"Executable (*.exe)\0*.exe\0All files\0*.*\0"; const WCHAR MainGui::filterDll[] = L"Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0"; const WCHAR MainGui::filterExeDll[] = L"Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0"; const WCHAR MainGui::filterTxt[] = L"Text file (*.txt)\0*.txt\0All files\0*.*\0"; MainGui::MainGui() : selectedProcess(0), importsHandling(TreeImports) { Logger::getDebugLogFilePath(); ConfigurationHolder::loadConfiguration(); PluginLoader::findAllPlugins(); NativeWinApi::initialize(); SystemInformation::getSystemInformation(); hIcon.LoadIcon(IDI_ICON_SCYLLA); hMenuImports.LoadMenu(IDR_MENU_IMPORTS); hMenuLog.LoadMenu(IDR_MENU_LOG); if(hMenuImports) { appendPluginListToMenu(hMenuImports.GetSubMenu(0)); } } BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { if (SystemInformation::currenOS == UNKNOWN_OS) { if(IDCANCEL == MessageBox(L"Operating System is not supported\r\nContinue anyway?", L"Scylla", MB_ICONWARNING | MB_OKCANCEL)) { EndDialog(0); return FALSE; } } if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue()) { processLister.setDebugPrivileges(); } processAccessHelp.getProcessModules(GetCurrentProcessId(), processAccessHelp.ownModuleList); - TreeImports.Attach(GetDlgItem(IDC_TREE_IMPORTS)); - ComboProcessList.Attach(GetDlgItem(IDC_CBO_PROCESSLIST)); - ListLog.Attach(GetDlgItem(IDC_LIST_LOG)); - - EditOEPAddress.Attach(GetDlgItem(IDC_EDIT_OEPADDRESS)); - EditIATAddress.Attach(GetDlgItem(IDC_EDIT_IATADDRESS)); - EditIATSize.Attach(GetDlgItem(IDC_EDIT_IATSIZE)); + DoDataExchange(); // attach controls EditOEPAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); EditIATAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); EditIATSize.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); appendPluginListToMenu(CMenuHandle(GetMenu()).GetSubMenu(MenuImportsOffsetTrace)); enableDialogControls(FALSE); setIconAndDialogCaption(); GetWindowRect(&minDlgSize); return TRUE; } void MainGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { - lpMMI->ptMinTrackSize.x = minDlgSize.Width(); - lpMMI->ptMinTrackSize.y = minDlgSize.Height(); + lpMMI->ptMinTrackSize = CPoint(minDlgSize.Size()); } void MainGui::OnSizing(UINT fwSide, RECT* pRect) { // Get size difference CRect rectOld; GetWindowRect(&rectOld); CRect rectNew = *pRect; - int deltaX = rectNew.Width() - rectOld.Width(); - int deltaY = rectNew.Height() - rectOld.Height(); - - CSize delta(deltaX, deltaY); - sizeOffset = delta; + sizeOffset = rectNew.Size() - rectOld.Size(); } void MainGui::OnSize(UINT nType, CSize size) { const WindowDeferrer::Deferrable controls[] = { {IDC_GROUP_ATTACH, false, false, true, false}, {IDC_CBO_PROCESSLIST, false, false, true, false}, {IDC_BTN_PICKDLL, true, false, false, false}, {IDC_GROUP_IMPORTS, false, false, true, true}, {IDC_TREE_IMPORTS, false, false, true, true}, {IDC_BTN_INVALIDIMPORTS, false, true, false, false}, {IDC_BTN_SUSPECTIMPORTS, false, true, false, false}, {IDC_BTN_SAVETREE, true, true, false, false}, {IDC_BTN_LOADTREE, true, true, false, false}, {IDC_BTN_CLEARIMPORTS, true, true, false, false}, {IDC_GROUP_IATINFO, false, true, false, false}, {IDC_STATIC_OEPADDRESS, false, true, false, false}, {IDC_STATIC_IATADDRESS, false, true, false, false}, {IDC_STATIC_IATSIZE, false, true, false, false}, {IDC_EDIT_OEPADDRESS, false, true, false, false}, {IDC_EDIT_IATADDRESS, false, true, false, false}, {IDC_EDIT_IATSIZE, false, true, false, false}, {IDC_BTN_IATAUTOSEARCH, false, true, false, false}, {IDC_BTN_GETIMPORTS, false, true, false, false}, {IDC_GROUP_ACTIONS, false, true, false, false}, {IDC_BTN_AUTOTRACE, false, true, false, false}, {IDC_GROUP_DUMP, false, true, false, false}, {IDC_BTN_DUMP, false, true, false, false}, {IDC_BTN_PEREBUILD, false, true, false, false}, {IDC_BTN_FIXDUMP, false, true, false, false}, {IDC_GROUP_LOG, false, true, true, false}, {IDC_LIST_LOG, false, true, true, false} }; if(nType == SIZE_RESTORED) { WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(sizeOffset.cx, sizeOffset.cy); sizeOffset.SetSize(0, 0); } } void MainGui::OnLButtonDown(UINT nFlags, CPoint point) { SetMsgHandled(false); } void MainGui::OnContextMenu(CWindow wnd, CPoint point) { // point = -1, -1 for keyboard invoked shortcut! switch(wnd.GetDlgCtrlID()) { case IDC_TREE_IMPORTS: DisplayContextMenuImports(wnd, point); return; case IDC_LIST_LOG: DisplayContextMenuLog(wnd, point); return; //default: // wnd == m_hWnd? // DisplayContextMenu(wnd, point); // return; } SetMsgHandled(false); } void MainGui::OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl) { // Make sure it's a menu if(uNotifyCode == 0 && !wndCtl.IsWindow()) { if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { pluginActionHandler(nID); return; } } SetMsgHandled(false); } LRESULT MainGui::OnTreeImportsClick(const NMHDR* pnmh) { SetMsgHandled(false); return false; } LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh) { - CPoint pt = GetMessagePos(); SetMsgHandled(false); if(TreeImports.GetCount() < 1) return false; // Get item under cursor CPoint client = GetMessagePos(); TreeImports.ScreenToClient(&client); UINT flags; CTreeItem over = TreeImports.HitTest(client, &flags); CTreeItem parent; if(over) { if(!(flags & TVHT_ONITEM)) { over = NULL; } else { - parent = TreeImports.GetParentItem(over); + parent = over.GetParent(); } } if(!over.IsNull() && !parent.IsNull()) { PickApiGui dlgPickApi(processAccessHelp.moduleList); if(dlgPickApi.DoModal()) { const ApiInfo* api = dlgPickApi.getSelectedApi(); if(api && api->module) { std::map::iterator iterator1; std::map::iterator iterator2; iterator1 = importsHandling.moduleList.begin(); while(iterator1 != importsHandling.moduleList.end()) { if(iterator1->second.hTreeItem == parent) { iterator2 = iterator1->second.thunkList.begin(); while(iterator2 != iterator1->second.thunkList.end()) { if(iterator2->second.hTreeItem == over) { ImportThunk &imp = iterator2->second; wcscpy_s(imp.moduleName, MAX_PATH, api->module->getFilename()); strcpy_s(imp.name, MAX_PATH, api->name); imp.ordinal = api->ordinal; //imp.apiAddressVA = api->va; imp.hint = api->hint; imp.valid = true; imp.suspect = api->isForwarded; importsHandling.updateImportInTreeView(&imp, over); break; } iterator2++; } break; } iterator1++; } } } } return false; } LRESULT MainGui::OnTreeImportsRightClick(const NMHDR* pnmh) { /* HTREEITEM selectedTreeNode = TreeImports.GetNextItem(NULL, TVGN_DROPHILITE); if(selectedTreeNode != NULL) { TreeImports.Select(selectedTreeNode, TVGN_CARET); } */ SetMsgHandled(false); return false; } LRESULT MainGui::OnTreeImportsRightDoubleClick(const NMHDR* pnmh) { SetMsgHandled(false); return false; } void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl) { fillProcessListComboBox(ComboProcessList); } void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { processSelectedActionHandler(ComboProcessList.GetCurSel()); } void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl) { pickDllActionHandler(); } void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl) { optionsActionHandler(); } void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpActionHandler(); } void MainGui::OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpFixActionHandler(); } void MainGui::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl) { peRebuildActionHandler(); } void MainGui::OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl) { dllInjectActionHandler(); } void MainGui::OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl) { iatAutosearchActionHandler(); } void MainGui::OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl) { getImportsActionHandler(); } void MainGui::OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl) { showInvalidImportsActionHandler(); } void MainGui::OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl) { showSuspectImportsActionHandler(); } void MainGui::OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl) { clearImportsActionHandler(); } void MainGui::OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl) { showAboutDialog(); } bool MainGui::showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter, const WCHAR * defExtension, const WCHAR * directory) { OPENFILENAME ofn = {0}; // WTL doesn't support new explorer styles on Vista and up // This is because it uses a custom hook, we could remove it or derive // from CFileDialog but this solution is easier and allows more control anyway (e.g. initial dir) if(defFileName) { wcscpy_s(selectedFile, MAX_PATH, defFileName); } else { selectedFile[0] = _T('\0'); } ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = m_hWnd; ofn.lpstrFilter = filter; ofn.lpstrDefExt = defExtension; // only first 3 chars are used, no dots! ofn.lpstrFile = selectedFile; ofn.lpstrInitialDir = directory; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; /* *OFN_EXPLORER is automatically used, it only has to be specified *if using a custom hook *OFN_LONGNAMES is automatically used by explorer-style dialogs */ if(save) ofn.Flags |= OFN_OVERWRITEPROMPT; else ofn.Flags |= OFN_FILEMUSTEXIST; if(save) return 0 != GetSaveFileName(&ofn); else return 0 != GetOpenFileName(&ofn); } void MainGui::setIconAndDialogCaption() { SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); } void MainGui::pickDllActionHandler() { if(!selectedProcess) return; PickDllGui dlgPickDll(processAccessHelp.moduleList); if(dlgPickDll.DoModal()) { //get selected module processAccessHelp.selectedModule = dlgPickDll.getSelectedModule(); Logger::printfDialog(TEXT("->>> Module %s selected."), processAccessHelp.selectedModule->getFilename()); Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),processAccessHelp.selectedModule->modBaseAddr,processAccessHelp.selectedModule->modBaseSize); } else { processAccessHelp.selectedModule = 0; } } void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode) { if(!selectedProcess) return; DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode); if (address) { BYTE test; if(!ProcessAccessHelp::readMemoryFromProcess(address, sizeof(test), &test)) { swprintf_s(stringBuffer, _countof(stringBuffer), TEXT("Can't read memory at ")TEXT(PRINTF_DWORD_PTR_FULL),address); MessageBox(stringBuffer, L"Failure", MB_ICONERROR); } else { DisassemblerGui dlgDisassembler(address); dlgDisassembler.DoModal(); } } } void MainGui::processSelectedActionHandler(int index) { std::vector& processList = processLister.getProcessList(); Process &process = processList.at(index); selectedProcess = 0; clearImportsActionHandler(); Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath); if (processAccessHelp.hProcess != 0) { processAccessHelp.closeProcessHandle(); apiReader.clearAll(); } if (!processAccessHelp.openProcessHandle(process.PID)) { enableDialogControls(FALSE); Logger::printfDialog(TEXT("Error: Cannot open process handle.")); return; } processAccessHelp.getProcessModules(process.PID, processAccessHelp.moduleList); apiReader.readApisFromModuleList(); Logger::printfDialog(TEXT("Loading modules done.")); //TODO improve processAccessHelp.selectedModule = 0; processAccessHelp.targetSizeOfImage = process.imageSize; processAccessHelp.targetImageBase = process.imageBase; ProcessAccessHelp::getSizeOfImageCurrentProcess(); process.imageSize = (DWORD)processAccessHelp.targetSizeOfImage; Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),process.imageBase, process.imageSize); process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),process.entryPoint + process.imageBase); EditOEPAddress.SetWindowText(stringBuffer); selectedProcess = &process; enableDialogControls(TRUE); } void MainGui::fillProcessListComboBox(CComboBox& hCombo) { hCombo.ResetContent(); std::vector& processList = processLister.getProcessListSnapshot(); for (size_t i = 0; i < processList.size(); i++) { swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("0x%04X - %s - %s"),processList[i].PID,processList[i].filename,processList[i].fullPath); hCombo.AddString(stringBuffer); } } void MainGui::addTextToOutputLog(const WCHAR * text) { if (m_hWnd) { ListLog.SetCurSel(ListLog.AddString(text)); } } void MainGui::clearOutputLog() { if (m_hWnd) { ListLog.ResetContent(); } } bool MainGui::saveLogToFile(const WCHAR * file) { const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian const WCHAR newLine[] = L"\r\n"; bool success = true; HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile != INVALID_HANDLE_VALUE) { ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM); WCHAR * buffer = 0; int bufsize = 0; for(int i = 0; i < ListLog.GetCount(); i++) { int size = ListLog.GetTextLen(i); size += _countof(newLine)-1; if(size+1 > bufsize) { bufsize = size+1; delete[] buffer; try { buffer = new WCHAR[bufsize]; } catch(std::bad_alloc&) { buffer = 0; success = false; break; } } ListLog.GetText(i, buffer); wcscat_s(buffer, bufsize, newLine); ProcessAccessHelp::writeMemoryToFileEnd(hFile, size * sizeof(WCHAR), buffer); } delete[] buffer; CloseHandle(hFile); } return success; } void MainGui::showInvalidImportsActionHandler() { importsHandling.showImports(true, false); } void MainGui::showSuspectImportsActionHandler() { importsHandling.showImports(false, true); } void MainGui::iatAutosearchActionHandler() { DWORD_PTR searchAddress = 0; DWORD_PTR addressIAT = 0; DWORD sizeIAT = 0; IATSearch iatSearch; if(!selectedProcess) return; if(EditOEPAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 1) { searchAddress = stringToDwordPtr(stringBuffer); if (searchAddress) { if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT)) { Logger::printfDialog(TEXT("IAT found at VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d)"),addressIAT, addressIAT - processAccessHelp.targetImageBase,sizeIAT,sizeIAT); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),addressIAT); EditIATAddress.SetWindowText(stringBuffer); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%08X"),sizeIAT); EditIATSize.SetWindowText(stringBuffer); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("IAT found! Start Address ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d) "),addressIAT,sizeIAT,sizeIAT); MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION); } else { Logger::printfDialog(TEXT("IAT not found at OEP ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("!"),searchAddress); } } } } void MainGui::getImportsActionHandler() { DWORD_PTR addressIAT = 0; DWORD sizeIAT = 0; if(!selectedProcess) return; if (EditIATAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { addressIAT = stringToDwordPtr(stringBuffer); } if (EditIATSize.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { sizeIAT = wcstoul(stringBuffer, NULL, 16); } if (addressIAT && sizeIAT) { apiReader.readAndParseIAT(addressIAT, sizeIAT,importsHandling.moduleList); importsHandling.displayAllImports(); } } DWORD_PTR MainGui::stringToDwordPtr(const WCHAR * hexString) { DWORD_PTR address = 0; #ifdef _WIN64 address = _wcstoui64(hexString, NULL, 16); #else address = wcstoul(hexString, NULL, 16); #endif if (address == 0) { #ifdef DEBUG_COMMENTS Logger::debugLog(L"stringToDwordPtr :: address == 0, %s",hexString); #endif return 0; } else { return address; } } void MainGui::SetupImportsMenuItems(bool isItem, bool isThunk) { // assert(!(!isItem && isThunk)); CMenuHandle hSub = hMenuImports.GetSubMenu(0); UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED; UINT thunkOnly = isThunk ? MF_ENABLED : MF_GRAYED; hSub.EnableMenuItem(ID__INVALIDATEFUNCTION, thunkOnly); hSub.EnableMenuItem(ID__DISASSEMBLE, thunkOnly); hSub.EnableMenuItem(ID__CUTTHUNK, thunkOnly); hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly); } void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt) { if(TreeImports.GetCount() < 1) return; CTreeItem over, parent; if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; over = TreeImports.GetSelectedItem(); if(over) { - TreeImports.EnsureVisible(over); - TreeImports.GetItemRect(over, &pos, TRUE); + over.EnsureVisible(); + over.GetRect(&pos, TRUE); TreeImports.ClientToScreen(&pos); } else { TreeImports.GetWindowRect(&pos); } pt = pos.TopLeft(); } else { // Get item under cursor CPoint client = pt; TreeImports.ScreenToClient(&client); UINT flags; over = TreeImports.HitTest(client, &flags); if(over && !(flags & TVHT_ONITEM)) { over = NULL; } } if(over) { - parent = TreeImports.GetParentItem(over); + parent = over.GetParent(); } if (hMenuImports) { // Prepare hmenuImports SetupImportsMenuItems(!over.IsNull(), !parent.IsNull()); CMenuHandle hSub = hMenuImports.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { //wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName); //MessageBox(stringBuffer, L"plugin selection"); pluginActionHandler(menuItem); return; } switch (menuItem) { case ID__INVALIDATEFUNCTION: importsHandling.invalidateFunction(over); break; case ID__DISASSEMBLE: startDisassemblerGui(over); break; case ID__EXPANDALLNODES: importsHandling.expandAllTreeNodes(); break; case ID__COLLAPSEALLNODES: importsHandling.collapseAllTreeNodes(); break; case ID__CUTTHUNK: importsHandling.cutThunk(over); break; case ID__DELETETREENODE: importsHandling.deleteTreeNode(parent ? parent : over); break; } } } } void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt) { if (hMenuLog) { if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; ListLog.GetWindowRect(&pos); pt = pos.TopLeft(); } CMenuHandle hSub = hMenuLog.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { switch (menuItem) { case ID__SAVE: WCHAR selectedFilePath[MAX_PATH]; if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt")) { saveLogToFile(selectedFilePath); } break; case ID__CLEAR: clearOutputLog(); break; } } } } void MainGui::appendPluginListToMenu(CMenuHandle hMenu) { std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); std::vector &imprecPluginList = PluginLoader::getImprecPluginList(); if (scyllaPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < scyllaPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins"); } if (imprecPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < imprecPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins"); } } void MainGui::dumpActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; const WCHAR * defExtension; PeDump peDump; if (processAccessHelp.selectedModule) { fileFilter = filterDll; defExtension = L"dll"; } else { fileFilter = filterExe; defExtension = L"exe"; } if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension)) { if (processAccessHelp.selectedModule) { //dump DLL peDump.imageBase = processAccessHelp.selectedModule->modBaseAddr; peDump.sizeOfImage = processAccessHelp.selectedModule->modBaseSize; //get it from gui peDump.entryPoint = getOEPFromGui(); wcscpy_s(peDump.fullpath, MAX_PATH, processAccessHelp.selectedModule->fullPath); } else { peDump.imageBase = ProcessAccessHelp::targetImageBase; peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage; //get it from gui peDump.entryPoint = getOEPFromGui(); wcscpy_s(peDump.fullpath, MAX_PATH, selectedProcess->fullPath); } peDump.useHeaderFromDisk = ConfigurationHolder::getConfigObject(USE_PE_HEADER_FROM_DISK)->isTrue(); if (peDump.dumpCompleteProcessToDisk(selectedFilePath)) { Logger::printfDialog(TEXT("Dump success %s"),selectedFilePath); //MessageBox(L"Image dumped successfully.", L"Success"); } else { Logger::printfDialog(TEXT("Error: Cannot dump image.")); MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR); } } } DWORD_PTR MainGui::getOEPFromGui() { if (EditOEPAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { return stringToDwordPtr(stringBuffer); } else { return 0; } } void MainGui::peRebuildActionHandler() { DWORD newSize = 0; WCHAR selectedFilePath[MAX_PATH]; PeRebuild peRebuild; if(showFileDialog(selectedFilePath, false, NULL, filterExeDll)) { if (ConfigurationHolder::getConfigObject(CREATE_BACKUP)->isTrue()) { if (!ProcessAccessHelp::createBackupFile(selectedFilePath)) { Logger::printfDialog(TEXT("Creating backup file failed %s"), selectedFilePath); } } LONGLONG fileSize = ProcessAccessHelp::getFileSize(selectedFilePath); LPVOID mapped = peRebuild.createFileMappingViewFull(selectedFilePath); newSize = peRebuild.realignPE(mapped, (DWORD)fileSize); peRebuild.closeAllMappingHandles(); if (newSize < 10) { Logger::printfDialog(TEXT("Rebuild failed %s"), selectedFilePath); MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR); } else { peRebuild.truncateFile(selectedFilePath, newSize); Logger::printfDialog(TEXT("Rebuild success %s"), selectedFilePath); Logger::printfDialog(TEXT("-> Old file size 0x%08X new file size 0x%08X (%d %%)"), (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) ); //MessageBox(L"Image rebuilded successfully.", L"Success", MB_ICONINFORMATION); } } } void MainGui::dumpFixActionHandler() { if(!selectedProcess) return; if (TreeImports.GetCount() < 2) { Logger::printfDialog(TEXT("Nothing to rebuild")); return; } WCHAR newFilePath[MAX_PATH]; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; ImportRebuild importRebuild; if (processAccessHelp.selectedModule) { fileFilter = filterDll; } else { fileFilter = filterExe; } if (showFileDialog(selectedFilePath, false, NULL, fileFilter)) { wcscpy_s(newFilePath,MAX_PATH,selectedFilePath); const WCHAR * extension = 0; WCHAR* dot = wcsrchr(newFilePath, L'.'); if (dot) { *dot = L'\0'; extension = selectedFilePath + (dot - newFilePath); //wcsrchr(selectedFilePath, L'.'); } wcscat_s(newFilePath, MAX_PATH, L"_SCY"); if(extension) { wcscat_s(newFilePath, MAX_PATH, extension); } if (importRebuild.rebuildImportTable(selectedFilePath,newFilePath,importsHandling.moduleList)) { //MessageBox(L"Imports rebuilding successful", L"Success", MB_ICONINFORMATION); Logger::printfDialog(TEXT("Import Rebuild success %s"), newFilePath); } else { Logger::printfDialog(TEXT("Import Rebuild failed, target %s"), selectedFilePath); MessageBox(L"Imports rebuilding failed", L"Failure", MB_ICONERROR); } } } void MainGui::enableDialogControls(BOOL value) { GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(value); GetDlgItem(IDC_BTN_DUMP).EnableWindow(value); GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(value); GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(value); GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(value); CMenuHandle menu = GetMenu(); menu.EnableMenuItem(ID_FILE_DUMP, value ? MF_ENABLED : MF_GRAYED); menu.EnableMenuItem(ID_FILE_FIXDUMP, value ? MF_ENABLED : MF_GRAYED); menu.EnableMenuItem(ID_MISC_DLLINJECTION, value ? MF_ENABLED : MF_GRAYED); menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetScylla, MF_BYPOSITION | (value ? MF_ENABLED : MF_GRAYED)); menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetImpRec, MF_BYPOSITION | (value ? MF_ENABLED : MF_GRAYED)); //not yet implemented GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_SAVETREE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_LOADTREE).EnableWindow(FALSE); menu.EnableMenuItem(ID_IMPORTS_INVALIDATESELECTED, MF_GRAYED); menu.EnableMenuItem(ID_IMPORTS_CUTSELECTED, MF_GRAYED); menu.EnableMenuItem(ID_IMPORTS_SAVETREE, MF_GRAYED); menu.EnableMenuItem(ID_IMPORTS_SAVETREE, MF_GRAYED); menu.EnableMenuItem(ID_IMPORTS_LOADTREE, MF_GRAYED); menu.EnableMenuItem(ID_TRACE_AUTOTRACE, MF_GRAYED); } void MainGui::showAboutDialog() { AboutGui dlgAbout; dlgAbout.DoModal(); } void MainGui::dllInjectActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; HMODULE hMod = 0; DllInjection dllInjection; if (showFileDialog(selectedFilePath, false, NULL, filterDll)) { hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, selectedFilePath); if (hMod && ConfigurationHolder::getConfigObject(DLL_INJECTION_AUTO_UNLOAD)->isTrue()) { if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod)) { Logger::printfDialog(TEXT("DLL unloading failed, target %s"), selectedFilePath); } } if (hMod) { Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), selectedFilePath); } else { Logger::printfDialog(TEXT("DLL Injection failed, target %s"), selectedFilePath); } } } void MainGui::optionsActionHandler() { OptionsGui dlgOptions; dlgOptions.DoModal(); } void MainGui::clearImportsActionHandler() { TreeImports.DeleteAllItems(); importsHandling.moduleList.clear(); } void MainGui::pluginActionHandler( int menuItem ) { if(!selectedProcess) return; DllInjectionPlugin dllInjectionPlugin; std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); std::vector &imprecPluginList = PluginLoader::getImprecPluginList(); menuItem -= PLUGIN_MENU_BASE_ID; dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess; dllInjectionPlugin.apiReader = &apiReader; if (menuItem < (int)scyllaPluginList.size()) { //scylla plugin dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); } else { #ifndef _WIN64 menuItem -= (int)scyllaPluginList.size(); //imprec plugin dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); #endif } importsHandling.scanAndFixModuleList(); importsHandling.displayAllImports(); } diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h index e5e7315..b676982 100644 --- a/Scylla/MainGui.h +++ b/Scylla/MainGui.h @@ -1,207 +1,217 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange //#define _CRTDBG_MAP_ALLOC //#include //#include #include #include "Logger.h" #include "ProcessLister.h" #include "IATSearch.h" #include "PickDllGui.h" #include "ImportsHandling.h" -class MainGui : public CDialogImpl +class MainGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_MAIN }; + BEGIN_DDX_MAP(MainGui) + DDX_CONTROL_HANDLE(IDC_TREE_IMPORTS, TreeImports) + DDX_CONTROL_HANDLE(IDC_CBO_PROCESSLIST, ComboProcessList) + DDX_CONTROL_HANDLE(IDC_LIST_LOG, ListLog) + DDX_CONTROL_HANDLE(IDC_EDIT_OEPADDRESS, EditOEPAddress) + DDX_CONTROL_HANDLE(IDC_EDIT_IATADDRESS, EditIATAddress) + DDX_CONTROL_HANDLE(IDC_EDIT_IATSIZE, EditIATSize) + END_DDX_MAP() + BEGIN_MSG_MAP(MainGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_SIZE(OnSize) MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_LBUTTONDOWN(OnLButtonDown) MSG_WM_COMMAND(OnCommand) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_CLICK, OnTreeImportsClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_DBLCLK, OnTreeImportsDoubleClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_RCLICK, OnTreeImportsRightClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_RDBLCLK, OnTreeImportsRightDoubleClick) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_DROPDOWN, OnProcessListDrop) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_SELENDOK, OnProcessListSelected) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL, OnPickDLL) COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMP, OnDump) COMMAND_ID_HANDLER_EX(IDC_BTN_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(IDC_BTN_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(IDC_BTN_IATAUTOSEARCH, OnIATAutoSearch) COMMAND_ID_HANDLER_EX(IDC_BTN_GETIMPORTS, OnGetImports) COMMAND_ID_HANDLER_EX(IDC_BTN_INVALIDIMPORTS, OnInvalidImports) COMMAND_ID_HANDLER_EX(IDC_BTN_SUSPECTIMPORTS, OnSuspectImports) COMMAND_ID_HANDLER_EX(IDC_BTN_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_FILE_DUMP, OnDump) COMMAND_ID_HANDLER_EX(ID_FILE_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(ID_FILE_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(ID_FILE_EXIT, OnExit) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWINVALID, OnInvalidImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWSUSPECT, OnSuspectImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_INVALIDATESELECTED, OnInvalidateSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CUTSELECTED, OnCutSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SAVETREE, OnSaveTree) COMMAND_ID_HANDLER_EX(ID_IMPORTS_LOADTREE, OnLoadTree) COMMAND_ID_HANDLER_EX(ID_TRACE_AUTOTRACE, OnAutotrace) COMMAND_ID_HANDLER_EX(ID_MISC_DLLINJECTION, OnDLLInject) COMMAND_ID_HANDLER_EX(ID_MISC_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) END_MSG_MAP() MainGui(); void addTextToOutputLog(const WCHAR * text); protected: // Variables ProcessLister processLister; WCHAR stringBuffer[600]; ImportsHandling importsHandling; ProcessAccessHelp processAccessHelp; ApiReader apiReader; Process * selectedProcess; // File selection stuff static const WCHAR filterExe[]; static const WCHAR filterDll[]; static const WCHAR filterExeDll[]; static const WCHAR filterTxt[]; // Controls - CTreeViewCtrl TreeImports; + CTreeViewCtrlEx TreeImports; CComboBox ComboProcessList; CEdit EditOEPAddress; CEdit EditIATAddress; CEdit EditIATSize; CListBox ListLog; CRect minDlgSize; CSize sizeOffset; // Handles CIcon hIcon; CMenu hMenuImports; CMenu hMenuLog; static const int MenuImportsOffsetTrace = 2; static const int MenuImportsTraceOffsetScylla = 2; static const int MenuImportsTraceOffsetImpRec = 4; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); void OnSize(UINT nType, CSize size); void OnLButtonDown(UINT nFlags, CPoint point); void OnContextMenu(CWindow wnd, CPoint point); void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl); LRESULT OnTreeImportsClick(const NMHDR* pnmh); LRESULT OnTreeImportsDoubleClick(const NMHDR* pnmh); LRESULT OnTreeImportsRightClick(const NMHDR* pnmh); LRESULT OnTreeImportsRightDoubleClick(const NMHDR* pnmh); void OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl); void OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl); void OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl); void OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl); void OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions bool showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter = NULL, const WCHAR * defExtension = NULL, const WCHAR * directory = NULL); void fillProcessListComboBox(CComboBox& hCombo); void setIconAndDialogCaption(); void enableDialogControls(BOOL value); // Actions void pickDllActionHandler(); void processSelectedActionHandler(int index); void showInvalidImportsActionHandler(); void showSuspectImportsActionHandler(); void iatAutosearchActionHandler(); void getImportsActionHandler(); void dumpActionHandler(); void peRebuildActionHandler(); void startDisassemblerGui(CTreeItem selectedTreeNode); void dumpFixActionHandler(); void showAboutDialog(); void dllInjectActionHandler(); void optionsActionHandler(); void clearImportsActionHandler(); void pluginActionHandler(int menuItem); // Popup menu functions void SetupImportsMenuItems(bool isItem, bool isThunk); void appendPluginListToMenu(CMenuHandle hMenuTrackPopup); void DisplayContextMenuImports(CWindow, CPoint); void DisplayContextMenuLog(CWindow, CPoint); // Log void clearOutputLog(); bool saveLogToFile(const WCHAR * file); // Misc DWORD_PTR getOEPFromGui(); static DWORD_PTR stringToDwordPtr(const WCHAR * hexString); }; diff --git a/Scylla/OptionsGui.cpp b/Scylla/OptionsGui.cpp index c4b9b98..1176435 100644 --- a/Scylla/OptionsGui.cpp +++ b/Scylla/OptionsGui.cpp @@ -1,158 +1,159 @@ #include "OptionsGui.h" #include "ConfigurationHolder.h" #include "definitions.h" BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - EditSectionName.Attach(GetDlgItem(IDC_OPTIONS_SECTIONNAME)); + DoDataExchange(); // attach controls + EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME); loadOptions(); CenterWindow(); return TRUE; } void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { saveOptions(); ConfigurationHolder::saveConfiguration(); EndDialog(0); } void OptionsGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void OptionsGui::saveOptions() { std::map::iterator mapIter; for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++) { getConfigOptionsFromDlg((*mapIter).second); } } void OptionsGui::loadOptions() { std::map::iterator mapIter; for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++) { displayConfigInDlg((*mapIter).second); } } void OptionsGui::setCheckBox( int nIDDlgItem, bool bValue ) { CButton Button(GetDlgItem(nIDDlgItem)); Button.SetCheck(bValue ? BST_CHECKED : BST_UNCHECKED); } void OptionsGui::displayConfigInDlg( ConfigObject & config ) { switch (config.configType) { case String: { setEditControl(config.dialogItemValue, config.valueString); } break; case Boolean: { setCheckBox(config.dialogItemValue, config.isTrue()); } break; case Decimal: { swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT(PRINTF_INTEGER),config.valueNumeric); setEditControl(config.dialogItemValue, config.valueString); } break; case Hexadecimal: { swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT(PRINTF_DWORD_PTR_FULL),config.valueNumeric); setEditControl(config.dialogItemValue, config.valueString); } break; } } void OptionsGui::setEditControl( int nIDDlgItem, const WCHAR * valueString ) { CEdit Edit(GetDlgItem(nIDDlgItem)); Edit.SetWindowText(valueString); } void OptionsGui::getConfigOptionsFromDlg( ConfigObject & config ) { switch (config.configType) { case String: { getEditControl(config.dialogItemValue, config.valueString); } break; case Boolean: { getCheckBox(config.dialogItemValue, &config.valueNumeric); } break; case Decimal: { getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 10); } break; case Hexadecimal: { getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 16); } break; } } bool OptionsGui::getEditControl( int nIDDlgItem, WCHAR * valueString ) { CEdit Edit(GetDlgItem(nIDDlgItem)); return (Edit.GetWindowText(valueString, CONFIG_OPTIONS_STRING_LENGTH) > 0); } void OptionsGui::getCheckBox( int nIDDlgItem, DWORD_PTR * valueNumeric ) { CButton Button(GetDlgItem(nIDDlgItem)); switch (Button.GetCheck()) { case BST_CHECKED: *valueNumeric = 1; return; case BST_UNCHECKED: *valueNumeric = 0; return; default: *valueNumeric = 0; } } void OptionsGui::getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase ) { WCHAR temp[CONFIG_OPTIONS_STRING_LENGTH] = {0}; if (getEditControl(nIDDlgItem, temp)) { #ifdef _WIN64 *valueNumeric = _wcstoui64(temp, NULL, nBase); #else *valueNumeric = wcstoul(temp, NULL, nBase); #endif } else { *valueNumeric = 0; } } diff --git a/Scylla/OptionsGui.h b/Scylla/OptionsGui.h index fed16c8..c993c98 100644 --- a/Scylla/OptionsGui.h +++ b/Scylla/OptionsGui.h @@ -1,47 +1,52 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange class ConfigObject; -class OptionsGui : public CDialogImpl +class OptionsGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_OPTIONS }; + BEGIN_DDX_MAP(OptionsGui) + DDX_CONTROL_HANDLE(IDC_OPTIONS_SECTIONNAME, EditSectionName) + END_DDX_MAP() + BEGIN_MSG_MAP(OptionsGui) MSG_WM_INITDIALOG(OnInitDialog) COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) END_MSG_MAP() private: CEdit EditSectionName; BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); void saveOptions(); void loadOptions(); void setCheckBox( int nIDDlgItem, bool bValue ); void displayConfigInDlg( ConfigObject & config ); void setEditControl( int nIDDlgItem, const WCHAR * valueString ); void getConfigOptionsFromDlg( ConfigObject & config ); bool getEditControl( int nIDDlgItem, WCHAR * valueString ); void getCheckBox( int dialogItemValue, DWORD_PTR * valueNumeric ); void getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase ); }; diff --git a/Scylla/PickApiGui.cpp b/Scylla/PickApiGui.cpp index cd054b0..d08da45 100644 --- a/Scylla/PickApiGui.cpp +++ b/Scylla/PickApiGui.cpp @@ -1,175 +1,168 @@ #include "PickApiGui.h" #include // string conversion #include "WindowDeferrer.h" PickApiGui::PickApiGui(const std::vector &moduleList) : moduleList(moduleList) { selectedApi = 0; hIcon.LoadIcon(IDI_ICON_SCYLLA); } BOOL PickApiGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - ComboDllSelect.Attach(GetDlgItem(IDC_CBO_DLLSELECT)); - ListApiSelect.Attach(GetDlgItem(IDC_LIST_APISELECT)); - EditApiFilter.Attach(GetDlgItem(IDC_EDIT_APIFILTER)); + DoDataExchange(); // attach controls fillDllComboBox(ComboDllSelect); CenterWindow(); SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); GetWindowRect(&minDlgSize); return TRUE; } void PickApiGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { - lpMMI->ptMinTrackSize.x = minDlgSize.Width(); - lpMMI->ptMinTrackSize.y = minDlgSize.Height(); + lpMMI->ptMinTrackSize = CPoint(minDlgSize.Size()); } void PickApiGui::OnSizing(UINT fwSide, RECT* pRect) { // Get size difference CRect rectOld; GetWindowRect(&rectOld); CRect rectNew = *pRect; - int deltaX = rectNew.Width() - rectOld.Width(); - int deltaY = rectNew.Height() - rectOld.Height(); - - CSize delta(deltaX, deltaY); - sizeOffset = delta; + sizeOffset = rectNew.Size() - rectOld.Size(); } void PickApiGui::OnSize(UINT nType, CSize size) { const WindowDeferrer::Deferrable controls[] = { {IDC_GROUP_DLL, false, false, true, false}, {IDC_CBO_DLLSELECT, false, false, true, false}, {IDC_GROUP_APIS, false, false, true, true}, {IDC_LIST_APISELECT, false, false, true, true}, {IDC_STATIC_APIFILTER, false, true, false, false}, {IDC_EDIT_APIFILTER, false, true, true, false}, {IDC_BTN_PICKAPI_OK, true, true, false, false}, {IDC_BTN_PICKAPI_CANCEL, true, true, false, false} }; if(nType == SIZE_RESTORED) { WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(sizeOffset.cx, sizeOffset.cy); sizeOffset.SetSize(0, 0); } } void PickApiGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { int indexDll = ComboDllSelect.GetCurSel(); int indexApi = ListApiSelect.GetCurSel(); if (indexDll != CB_ERR && indexApi != CB_ERR) { selectedApi = apiListTemp[indexApi]; EndDialog(1); } } void PickApiGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void PickApiGui::OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { int indexDll = ComboDllSelect.GetCurSel(); if (indexDll != CB_ERR) { apiListTemp = moduleList[indexDll].apiList; fillApiListBox(ListApiSelect, apiListTemp); EditApiFilter.SetWindowText(L""); } } void PickApiGui::OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl) { // remove from apiListTemp that don't fit int indexDll = ComboDllSelect.GetCurSel(); if (indexDll != CB_ERR) { WCHAR filter[MAX_PATH]; int lenFilter = EditApiFilter.GetWindowText(filter, _countof(filter)); if(lenFilter > 0) { apiListTemp.clear(); const std::vector &apis = moduleList[indexDll].apiList; for (size_t i = 0; i < apis.size(); i++) { ApiInfo* api = apis[i]; if(api->name[0] != '\0') { CA2WEX wStr(api->name); if(!_wcsnicmp(wStr, filter, lenFilter)) { apiListTemp.push_back(api); } } else { WCHAR buf[6]; swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal); if(!_wcsnicmp(buf, filter, lenFilter)) { apiListTemp.push_back(api); } } } } else { apiListTemp = moduleList[indexDll].apiList; } fillApiListBox(ListApiSelect, apiListTemp); } } void PickApiGui::fillDllComboBox(CComboBox& combo) { combo.ResetContent(); for (size_t i = 0; i < moduleList.size(); i++) { combo.AddString(moduleList[i].fullPath); } } void PickApiGui::fillApiListBox(CListBox& list, const std::vector &apis) { list.ResetContent(); for (size_t i = 0; i < apis.size(); i++) { const ApiInfo* api = apis[i]; if(api->name[0] != '\0') { CA2WEX wStr(api->name); list.AddString(wStr); } else { WCHAR buf[6]; swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal); list.AddString(buf); } } } diff --git a/Scylla/PickApiGui.h b/Scylla/PickApiGui.h index 07023de..8b152dc 100644 --- a/Scylla/PickApiGui.h +++ b/Scylla/PickApiGui.h @@ -1,80 +1,85 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange #include #include "ProcessAccessHelp.h" -class PickApiGui : public CDialogImpl +class PickApiGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_PICKAPI }; + BEGIN_DDX_MAP(PickApiGui) + DDX_CONTROL_HANDLE(IDC_CBO_DLLSELECT, ComboDllSelect) + DDX_CONTROL_HANDLE(IDC_LIST_APISELECT, ListApiSelect) + DDX_CONTROL_HANDLE(IDC_EDIT_APIFILTER, EditApiFilter) + END_DDX_MAP() + BEGIN_MSG_MAP(PickDllGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_SIZE(OnSize) COMMAND_HANDLER_EX(IDC_CBO_DLLSELECT, CBN_SELENDOK, OnDllListSelected) COMMAND_HANDLER_EX(IDC_EDIT_APIFILTER, EN_UPDATE, OnApiFilterUpdated) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) END_MSG_MAP() PickApiGui(const std::vector &moduleList); ApiInfo* getSelectedApi() const { return selectedApi; } protected: // Variables const std::vector &moduleList; std::vector apiListTemp; ApiInfo* selectedApi; // Controls CComboBox ComboDllSelect; CListBox ListApiSelect; CEdit EditApiFilter; CRect minDlgSize; CSize sizeOffset; // Handles CIcon hIcon; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); void OnSize(UINT nType, CSize size); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void fillDllComboBox(CComboBox& combo); void fillApiListBox(CListBox& list, const std::vector &apis); - - //void displayModuleList(CListViewCtrl& list); }; diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp index 2262b95..1808c18 100644 --- a/Scylla/PickDllGui.cpp +++ b/Scylla/PickDllGui.cpp @@ -1,176 +1,171 @@ #include "PickDllGui.h" #include "WindowDeferrer.h" PickDllGui::PickDllGui(std::vector &moduleList) : moduleList(moduleList) { prevColumn = -1; ascending = true; selectedModule = 0; hIcon.LoadIcon(IDI_ICON_SCYLLA); } BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - ListDLLSelect.Attach(GetDlgItem(IDC_LIST_DLLSELECT)); + DoDataExchange(); // attach controls addColumnsToModuleList(ListDLLSelect); displayModuleList(ListDLLSelect); CenterWindow(); SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); GetWindowRect(&minDlgSize); return TRUE; } void PickDllGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { - lpMMI->ptMinTrackSize.x = minDlgSize.Width(); - lpMMI->ptMinTrackSize.y = minDlgSize.Height(); + lpMMI->ptMinTrackSize = CPoint(minDlgSize.Size()); } void PickDllGui::OnSizing(UINT fwSide, RECT* pRect) { // Get size difference CRect rectOld; GetWindowRect(&rectOld); CRect rectNew = *pRect; - int deltaX = rectNew.Width() - rectOld.Width(); - int deltaY = rectNew.Height() - rectOld.Height(); - - CSize delta(deltaX, deltaY); - sizeOffset = delta; + sizeOffset = rectNew.Size() - rectOld.Size(); } void PickDllGui::OnSize(UINT nType, CSize size) { const WindowDeferrer::Deferrable controls[] = { {IDC_LIST_DLLSELECT, false, false, true, true}, {IDC_BTN_PICKDLL_OK, true, true, false, false}, {IDC_BTN_PICKDLL_CANCEL, true, true, false, false}, }; if(nType == SIZE_RESTORED) { WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(sizeOffset.cx, sizeOffset.cy); sizeOffset.SetSize(0, 0); } } LRESULT PickDllGui::OnListDllColumnClicked(NMHDR* pnmh) { NMLISTVIEW* list = (NMLISTVIEW*)pnmh; int column = list->iSubItem; - if(column == prevColumn) + if(column == prevColumn) { - ascending = !ascending; + ascending = !ascending; } - else - { + else + { prevColumn = column; - ascending = true; - } + ascending = true; + } // lo-byte: column, hi-byte: sort-order ListDLLSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); return 0; } void PickDllGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { int index = ListDLLSelect.GetSelectionMark(); if (index != -1) { selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(index); EndDialog(1); } } void PickDllGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void PickDllGui::addColumnsToModuleList(CListViewCtrl& list) { list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); list.InsertColumn(COL_NAME, L"Name", LVCFMT_LEFT); list.InsertColumn(COL_IMAGEBASE, L"ImageBase", LVCFMT_CENTER); list.InsertColumn(COL_IMAGESIZE, L"ImageSize", LVCFMT_CENTER); list.InsertColumn(COL_PATH, L"Path", LVCFMT_LEFT); } void PickDllGui::displayModuleList(CListViewCtrl& list) { WCHAR temp[20]; list.DeleteAllItems(); std::vector::const_iterator iter; int count = 0; for( iter = moduleList.begin(); iter != moduleList.end(); iter++ , count++) { list.InsertItem(count, iter->getFilename()); #ifdef _WIN64 swprintf_s(temp, _countof(temp), L"%016I64X", iter->modBaseAddr); #else swprintf_s(temp, _countof(temp), L"%08X", iter->modBaseAddr); #endif list.SetItemText(count, COL_IMAGEBASE, temp); swprintf_s(temp, _countof(temp),L"%08X",iter->modBaseSize); list.SetItemText(count, COL_IMAGESIZE, temp); list.SetItemText(count, COL_PATH, iter->fullPath); list.SetItemData(count, (DWORD_PTR)&(*iter)); } list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_IMAGEBASE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_IMAGESIZE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_PATH, LVSCW_AUTOSIZE_USEHEADER); } // lParamSort - lo-byte: column, hi-byte: sort-order int PickDllGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { const ModuleInfo * module1 = (ModuleInfo *)lParam1; const ModuleInfo * module2 = (ModuleInfo *)lParam2; int column = LOBYTE(lParamSort); bool ascending = HIBYTE(lParamSort) == true; int diff = 0; switch(column) { case COL_NAME: diff = _wcsicmp(module1->getFilename(), module2->getFilename()); break; case COL_IMAGEBASE: diff = module1->modBaseAddr < module2->modBaseAddr ? -1 : 1; break; case COL_IMAGESIZE: diff = module1->modBaseSize < module2->modBaseSize ? -1 : 1; break; case COL_PATH: diff = _wcsicmp(module1->fullPath, module2->fullPath); break; } return ascending ? diff : -diff; } diff --git a/Scylla/PickDllGui.h b/Scylla/PickDllGui.h index 9197b4c..c494c78 100644 --- a/Scylla/PickDllGui.h +++ b/Scylla/PickDllGui.h @@ -1,85 +1,90 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls +#include // WTL dialog data exchange #include #include "ProcessAccessHelp.h" -class PickDllGui : public CDialogImpl +class PickDllGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_PICKDLL }; + BEGIN_DDX_MAP(PickDllGui) + DDX_CONTROL_HANDLE(IDC_LIST_DLLSELECT, ListDLLSelect) + END_DDX_MAP() + BEGIN_MSG_MAP(PickDllGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_SIZE(OnSize) NOTIFY_HANDLER_EX(IDC_LIST_DLLSELECT, LVN_COLUMNCLICK, OnListDllColumnClicked) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) END_MSG_MAP() PickDllGui(std::vector &moduleList); ModuleInfo* getSelectedModule() const { return selectedModule; } protected: // Variables std::vector &moduleList; ModuleInfo* selectedModule; // Controls CListViewCtrl ListDLLSelect; enum ListColumns { COL_NAME = 0, COL_IMAGEBASE, COL_IMAGESIZE, COL_PATH }; int prevColumn; bool ascending; CRect minDlgSize; CSize sizeOffset; // Handles CIcon hIcon; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); void OnSize(UINT nType, CSize size); LRESULT OnListDllColumnClicked(NMHDR* pnmh); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void addColumnsToModuleList(CListViewCtrl& list); void displayModuleList(CListViewCtrl& list); static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); };