diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp index b67fbb8..18f8ea9 100644 --- a/Scylla/MainGui.cpp +++ b/Scylla/MainGui.cpp @@ -1,918 +1,933 @@ #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 "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"; + 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) { MessageBox(L"Operating System is not supported", L"Error Operating System", MB_ICONERROR); 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)); EditOEPAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); EditIATAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); EditIATSize.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); enableDialogControls(FALSE); setIconAndDialogCaption(); GetWindowRect(&MinSize); return TRUE; } void MainGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { lpMMI->ptMinTrackSize.x = MinSize.right - MinSize.left; lpMMI->ptMinTrackSize.y = MinSize.bottom - MinSize.top; } void MainGui::OnSizing(UINT fwSide, RECT* pRect) { 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_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_IMPORTSOPTIONS, true, true, false, false}, {IDC_BTN_INVALIDIMPORTS, true, true, false, false}, {IDC_BTN_SUSPECTIMPORTS, true, true, false, false}, {IDC_BTN_CLEARIMPORTS, true, true, false, false}, {IDC_BTN_AUTOTRACE, true, true, false, false}, {IDC_BTN_SAVETREE, true, true, false, false}, {IDC_BTN_LOADTREE, true, true, false, false}, {IDC_GROUP_LOG, false, true, true, false}, {IDC_LIST_LOG, false, true, true, false}, {IDC_GROUP_MISC, true, false, false, true}, {IDC_BTN_DUMP, true, false, false, false}, {IDC_BTN_PEREBUILD, true, false, false, false}, {IDC_BTN_DLLINJECT, true, false, false, false}, {IDC_BTN_FIXDUMP, true, false, false, false} }; // Get size difference RECT rectOld; GetWindowRect(&rectOld); long deltaX = (pRect->right - pRect->left) - (rectOld.right - rectOld.left); long deltaY = (pRect->bottom - pRect->top) - (rectOld.bottom - rectOld.top); WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(deltaX, deltaY); } void MainGui::OnLButtonDown(UINT nFlags, CPoint point) { } void MainGui::OnContextMenu(CWindow wnd, CPoint point) { switch(wnd.GetDlgCtrlID()) { case IDC_TREE_IMPORTS: DisplayContextMenuImports(wnd, point); break; break; case IDC_LIST_LOG: DisplayContextMenuLog(wnd, point); break; //default: // DisplayContextMenu(wnd, point); // break; } } LRESULT MainGui::OnTreeImportsClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_CLICK"); return FALSE; } LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_DBLCLK"); return FALSE; } LRESULT MainGui::OnTreeImportsRightClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_RCLICK"); /* HTREEITEM selectedTreeNode = TreeImports.GetNextItem(NULL, TVGN_DROPHILITE); if(selectedTreeNode != NULL) { TreeImports.Select(selectedTreeNode, TVGN_CARET); } */ return FALSE; } LRESULT MainGui::OnTreeImportsRightDoubleClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_RDBLCLK"); 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::OnClearLog(UINT uNotifyCode, int nID, CWindow wndCtl) { clearOutputLog(); } 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) +{ + DWORD dwFlags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + if(!save) + dwFlags |= OFN_FILEMUSTEXIST; + else + dwFlags |= OFN_OVERWRITEPROMPT; + + CFileDialog dlgFile(!save, defExtension, defFileName, dwFlags, filter, m_hWnd); + if(dlgFile.DoModal() == IDOK) + { + wcscpy_s(selectedFile, MAX_PATH, dlgFile.m_szFileName); + return true; + } + return false; +} + void MainGui::setIconAndDialogCaption() { if(hIcon) { SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); } SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); } void MainGui::pickDllActionHandler() { 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) { DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode); if (address) { DisassemblerGui dlgDisassembler(address); dlgDisassembler.DoModal(); } } void MainGui::processSelectedActionHandler(int index) { std::vector& processList = processLister.getProcessList(); Process &process = processList.at(index); selectedProcess = &process; clearImportsActionHandler(); enableDialogControls(TRUE); Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath); if (processAccessHelp.hProcess != 0) { processAccessHelp.closeProcessHandle(); apiReader.clearAll(); } if (!processAccessHelp.openProcessHandle(process.PID)) { 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); selectedProcess->entryPoint = ProcessAccessHelp::getEntryPointFromFile(selectedProcess->fullPath); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),selectedProcess->entryPoint + selectedProcess->imageBase); EditOEPAddress.SetWindowText(stringBuffer); } 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(); } } 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(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 (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; // Get item under cursor CPoint client(pt); CWindow(GetDesktopWindow()).MapWindowPoints(TreeImports, &client, 1); // pt is screen, we need client UINT flags; CTreeItem over = TreeImports.HitTest(client, &flags); CTreeItem parent; if(over) { if(!(flags & TVHT_ONITEM)) { over = NULL; } else { parent = TreeImports.GetParentItem(over); } } 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) { 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__CLEAR: clearOutputLog(); break; } } } } /* void MainGui::DisplayContextMenu(CWindow hwnd, CPoint pt) { CMenu hmenu; // top-level menu CMenuHandle hmenuTrackPopup; // shortcut menu int menuItem; // selected menu item // Load the menu resource. if (!hmenu.LoadMenu(IDR_MENU_IMPORTS)) return; // TrackPopupMenu cannot display the menu bar so get // a handle to the first shortcut menu. hmenuTrackPopup = hmenu.GetSubMenu(0); // Display the shortcut menu. Track the right mouse // button. if (!hmenuTrackPopup) { MessageBox(L"hmenuTrackPopup == null", L"hmenuTrackPopup"); } menuItem = hmenuTrackPopup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { if (menuItem == ID_LISTCONTROL_SHOWEXPORTS) { //MessageBox(L"exports",L"dshhhhh"); } } } */ void MainGui::appendPluginListToMenu(CMenuHandle hMenuTrackPopup) { 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); } hMenuTrackPopup.AppendMenu(MF_MENUBARBREAK); hMenuTrackPopup.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); } hMenuTrackPopup.AppendMenu(MF_MENUBARBREAK); hMenuTrackPopup.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins"); } } void MainGui::dumpActionHandler() { if(!selectedProcess) return; - WCHAR * targetFile = 0; + WCHAR selectedFilePath[MAX_PATH]; + const WCHAR * fileFilter; + const WCHAR * defExtension; PeDump peDump; if (processAccessHelp.selectedModule) { - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileDll, true); + fileFilter = filterDll; + defExtension = L".dll"; } else { - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileExe, true); + fileFilter = filterExe; + defExtension = L".exe"; } - - - if (targetFile) + + 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(targetFile)) + if (peDump.dumpCompleteProcessToDisk(selectedFilePath)) { - Logger::printfDialog(TEXT("Dump success %s"),targetFile); + 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); } - - delete [] targetFile; } } DWORD_PTR MainGui::getOEPFromGui() { if (EditOEPAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { return stringToDwordPtr(stringBuffer); } else { return 0; } } void MainGui::peRebuildActionHandler() { DWORD newSize = 0; - WCHAR * targetFile = 0; + WCHAR selectedFilePath[MAX_PATH]; PeRebuild peRebuild; - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileExeDll, false); - - if (targetFile) + if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL)) { if (ConfigurationHolder::getConfigObject(CREATE_BACKUP)->isTrue()) { - if (!ProcessAccessHelp::createBackupFile(targetFile)) + if (!ProcessAccessHelp::createBackupFile(selectedFilePath)) { - Logger::printfDialog(TEXT("Creating backup file failed %s"), targetFile); + Logger::printfDialog(TEXT("Creating backup file failed %s"), selectedFilePath); } } - LONGLONG fileSize = ProcessAccessHelp::getFileSize(targetFile); - LPVOID mapped = peRebuild.createFileMappingViewFull(targetFile); + 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"), targetFile); + Logger::printfDialog(TEXT("Rebuild failed %s"), selectedFilePath); MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR); } else { - peRebuild.truncateFile(targetFile, newSize); + peRebuild.truncateFile(selectedFilePath, newSize); - Logger::printfDialog(TEXT("Rebuild success %s"), targetFile); + 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); } - - delete [] targetFile; } } void MainGui::dumpFixActionHandler() { if(!selectedProcess) return; - WCHAR * targetFile = 0; WCHAR newFilePath[MAX_PATH]; + WCHAR selectedFilePath[MAX_PATH]; + const WCHAR * fileFilter; + ImportRebuild importRebuild; if (TreeImports.GetCount() < 2) { Logger::printfDialog(TEXT("Nothing to rebuild")); return; } if (processAccessHelp.selectedModule) { - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileDll, false); + fileFilter = filterDll; } else { - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileExe, false); + fileFilter = filterExe; } - if (targetFile) + if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL)) { - wcscpy_s(newFilePath,MAX_PATH,targetFile); + 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'.'); } - if (processAccessHelp.selectedModule) - { - wcscat_s(newFilePath,MAX_PATH, L"_SCY.dll"); - } - else + wcscat_s(newFilePath, MAX_PATH, L"_SCY"); + + if(extension) { - wcscat_s(newFilePath,MAX_PATH, L"_SCY.exe"); + wcscat_s(newFilePath, MAX_PATH, extension); } - if (importRebuild.rebuildImportTable(targetFile,newFilePath,importsHandling.moduleList)) + 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"), targetFile); + Logger::printfDialog(TEXT("Import Rebuild failed, target %s"), selectedFilePath); MessageBox(L"Imports rebuilding failed", L"Failure", MB_ICONERROR); } - - delete [] targetFile; } - } void MainGui::enableDialogControls(BOOL value) { GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(value); GetDlgItem(IDC_BTN_DUMP).EnableWindow(value); GetDlgItem(IDC_BTN_DLLINJECT).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); //not yet implemented GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_SAVETREE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_LOADTREE).EnableWindow(FALSE); menu.EnableMenuItem(ID_MISC_SAVETREE, MF_GRAYED); menu.EnableMenuItem(ID_MISC_LOADTREE, MF_GRAYED); } void MainGui::showAboutDialog() { AboutGui dlgAbout; dlgAbout.DoModal(); } void MainGui::dllInjectActionHandler() { if(!selectedProcess) return; - WCHAR * targetFile = 0; + WCHAR selectedFilePath[MAX_PATH]; HMODULE hMod = 0; DllInjection dllInjection; - targetFile = ProcessAccessHelp::selectFile(ProcessAccessHelp::fileDll, false); - - if (targetFile) + if (showFileDialog(selectedFilePath, false, NULL, filterDll, NULL)) { - hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, targetFile); + 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"), targetFile); + Logger::printfDialog(TEXT("DLL unloading failed, target %s"), selectedFilePath); } } if (hMod) { - Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), targetFile); + Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), selectedFilePath); } else { - Logger::printfDialog(TEXT("DLL Injection failed, target %s"), targetFile); + Logger::printfDialog(TEXT("DLL Injection failed, target %s"), selectedFilePath); } - - delete [] targetFile; } - } 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 8a0b7a6..ecbe858 100644 --- a/Scylla/MainGui.h +++ b/Scylla/MainGui.h @@ -1,185 +1,193 @@ #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 //#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 { public: enum { IDD = IDD_DLG_MAIN }; BEGIN_MSG_MAP(MainGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_LBUTTONDOWN(OnLButtonDown) //MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove) //MSG_WM_EXITSIZEMOVE(OnExitSizeMove) 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_DLLINJECT, OnDLLInject) 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_MISC_DLLINJECTION, OnDLLInject) COMMAND_ID_HANDLER_EX(ID_MISC_PREFERENCES, OnOptions) COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) END_MSG_MAP() MainGui(); //Output Window 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[]; + // Controls CTreeViewCtrl TreeImports; CComboBox ComboProcessList; CEdit EditOEPAddress; CEdit EditIATAddress; CEdit EditIATSize; CListBox ListLog; RECT MinSize; // Handles CIcon hIcon; CMenu hMenuImports; CMenu hMenuLog; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); //void OnEnterSizeMove(); //void OnExitSizeMove(); void OnLButtonDown(UINT nFlags, CPoint point); void OnContextMenu(CWindow wnd, CPoint point); 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 OnClearLog(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, const WCHAR * defExtension); + void setIconAndDialogCaption(); void fillProcessListComboBox(CComboBox& hCombo); //static bool displayModuleList(HWND hWndDlg, HWND hList, LRESULT index); // Actions void pickDllActionHandler(); void processSelectedActionHandler(int index); void showInvalidImportsActionHandler(); void showSuspectImportsActionHandler(); void iatAutosearchActionHandler(); void getImportsActionHandler(); void appendPluginListToMenu(CMenuHandle hMenuTrackPopup); void dumpActionHandler(); DWORD_PTR getOEPFromGui(); void peRebuildActionHandler(); void startDisassemblerGui(CTreeItem selectedTreeNode); void dumpFixActionHandler(); void enableDialogControls(BOOL value); void showAboutDialog(); void dllInjectActionHandler(); void optionsActionHandler(); void clearImportsActionHandler(); void pluginActionHandler(int menuItem); // Popup menu functions //void DisplayContextMenu(CWindow, CPoint); void SetupImportsMenuItems(bool isItem, bool isThunk); void DisplayContextMenuImports(CWindow, CPoint); void DisplayContextMenuLog(CWindow, CPoint); // Misc void clearOutputLog();//Output Window static DWORD_PTR stringToDwordPtr(const WCHAR * hexString); }; diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp index 77abbea..ca72d10 100644 --- a/Scylla/ProcessAccessHelp.cpp +++ b/Scylla/ProcessAccessHelp.cpp @@ -1,798 +1,715 @@ #include "ProcessAccessHelp.h" -#include // base ATL classes -#include // base WTL classes -#include // ATL GUI classes -#include // WTL common dialogs - #include "Logger.h" #include "NativeWinApi.h" HANDLE ProcessAccessHelp::hProcess = 0; ModuleInfo * ProcessAccessHelp::selectedModule; DWORD_PTR ProcessAccessHelp::targetImageBase = 0; DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0; DWORD_PTR ProcessAccessHelp::maxValidAddress = 0; std::vector ProcessAccessHelp::moduleList; //target process module list std::vector ProcessAccessHelp::ownModuleList; //own module list _DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS]; unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0; _CodeInfo ProcessAccessHelp::decomposerCi = {0}; _DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS]; unsigned int ProcessAccessHelp::decodedInstructionsCount = 0; BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; //#define DEBUG_COMMENTS bool ProcessAccessHelp::openProcessHandle(DWORD dwPID) { if (dwPID > 0) { if (hProcess) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("openProcessHandle :: There is already a process handle, HANDLE %X\r\n"),hProcess); #endif return false; } else { //hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID); //if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid))) hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID); if (hProcess) { return true; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("openProcessHandle :: Failed to open handle, PID %X\r\n"),dwPID); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("openProcessHandle :: Wrong PID, PID %X \r\n"),dwPID); #endif return false; } } HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId) { HANDLE hProcess = 0; CLIENT_ID cid = {0}; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS ntStatus = 0; InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0); cid.UniqueProcess = (HANDLE)dwProcessId; ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid); if (NT_SUCCESS(ntStatus)) { return hProcess; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X\r\n"),dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus)); #endif return 0; } } void ProcessAccessHelp::closeProcessHandle() { CloseHandle(hProcess); hProcess = 0; moduleList.clear(); targetImageBase = 0; selectedModule = 0; } bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) { SIZE_T lpNumberOfBytesRead = 0; DWORD dwProtect = 0; bool returnValue = false; if (!hProcess) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromProcess :: hProcess == NULL\r\n")); #endif return returnValue; } if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) { if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u\r\n"),address,size,GetLastError()); #endif returnValue = false; } else { if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u\r\n"),address,size,GetLastError()); #endif returnValue = false; } else { returnValue = true; } VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect); } } else { returnValue = true; } if (returnValue) { if (size != lpNumberOfBytesRead) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes\r\n"), lpNumberOfBytesRead, size); #endif returnValue = false; } else { returnValue = true; } } return returnValue; } bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress) { ZeroMemory(&decomposerCi, sizeof(_CodeInfo)); decomposerCi.code = dataBuffer; decomposerCi.codeLen = (int)bufferSize; decomposerCi.dt = dt; decomposerCi.codeOffset = startAddress; decomposerInstructionsCount = 0; if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("decomposeMemory :: distorm_decompose == DECRES_INPUTERR\r\n")); #endif return false; } else { return true; } } bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset) { // Holds the result of the decoding. _DecodeResult res; // next is used for instruction's offset synchronization. // decodedInstructionsCount holds the count of filled instructions' array by the decoder. decodedInstructionsCount = 0; _OffsetType offset = startOffset; res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); /* for (unsigned int i = 0; i < decodedInstructionsCount; i++) { #ifdef SUPPORT_64BIT_OFFSET printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #else printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #endif }*/ if (res == DECRES_INPUTERR) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("disassembleMemory :: res == DECRES_INPUTERR\r\n")); #endif return false; } else if (res == DECRES_SUCCESS) { //printf("disassembleMemory :: res == DECRES_SUCCESS\n"); return true; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("disassembleMemory :: res == %d\r\n"),res); #endif return false; } } DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask) { DWORD pos = 0; size_t searchLen = strlen(mask) - 1; for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++) { if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' ) { if(mask[pos+1] == 0x00) { return (retAddress - searchLen); } pos++; } else { pos = 0; } } return 0; } bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath) { return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath); } LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath) { LONGLONG fileSize = 0; HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { fileSize = getFileSize(hFile); CloseHandle(hFile); hFile = 0; } return fileSize; } LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile) { LARGE_INTEGER lpFileSize = {0}; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { if (!GetFileSizeEx(hFile, &lpFileSize)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u\r\n"),GetLastError()); #endif return 0; } else { return lpFileSize.QuadPart; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize hFile invalid\r\n")); #endif return 0; } } bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer) { DWORD lpNumberOfBytesRead = 0; DWORD retValue = 0; DWORD dwError = 0; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); dwError = GetLastError(); if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromFile :: SetFilePointer failed error %u\r\n"),dwError); #endif return false; } else { if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0)) { return true; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromFile :: ReadFile failed - size %d - error %u\r\n"),size,GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readMemoryFromFile :: hFile invalid\r\n")); #endif return false; } } bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer) { DWORD lpNumberOfBytesWritten = 0; DWORD retValue = 0; DWORD dwError = 0; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); dwError = GetLastError(); if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("writeMemoryToFile :: SetFilePointer failed error %u\r\n"),dwError); #endif return false; } else { if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0)) { return true; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("writeMemoryToFile :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("writeMemoryToFile :: hFile invalid\r\n")); #endif return false; } } bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer) { DWORD lpNumberOfBytesWritten = 0; DWORD retValue = 0; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { SetFilePointer(hFile, 0, 0, FILE_END); if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0)) { return true; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("writeMemoryToFileEnd :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError()); #endif return false; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("writeMemoryToFileEnd :: hFile invalid\r\n")); #endif return false; } } bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath) { DWORD lpNumberOfBytesRead = 0; LONGLONG fileSize = 0; DWORD dwSize = 0; bool returnValue = 0; HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if( hFile == INVALID_HANDLE_VALUE ) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("readHeaderFromFile :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError()); #endif returnValue = false; } else { fileSize = getFileSize(hFile); if (fileSize > 0) { if (fileSize > bufferSize) { dwSize = bufferSize; } else { dwSize = (DWORD)(fileSize - 1); } returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer); } CloseHandle(hFile); } return returnValue; } LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath) { return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ); } LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath) { return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS); } LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap) { HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if( hFile == INVALID_HANDLE_VALUE ) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError()); #endif return NULL; } HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL); CloseHandle(hFile); if( hMappedFile == NULL ) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("createFileMappingView :: hMappedFile == NULL\r\n")); #endif return NULL; } if (GetLastError() == ERROR_ALREADY_EXISTS) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n")); #endif return NULL; } LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0); if( addrMappedDll == NULL ) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("createFileMappingView :: addrMappedDll == NULL\r\n")); #endif CloseHandle(hMappedFile); return NULL; } CloseHandle(hMappedFile); return addrMappedDll; } DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName) { DWORD dwPID = 0; HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32W pe32; pe32.dwSize = sizeof(PROCESSENTRY32W); if( !Process32FirstW( hProcessSnap, &pe32 ) ) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("getProcessByName :: Error getting first Process\r\n")); #endif CloseHandle( hProcessSnap ); return 0; } do { if(!_wcsicmp(pe32.szExeFile, processName)) { dwPID = pe32.th32ProcessID; break; } } while(Process32NextW(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); return dwPID; } bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector &moduleList) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; ModuleInfo module; // Take a snapshot of all modules in the specified process. hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); if( hModuleSnap == INVALID_HANDLE_VALUE ) { return false; } // Set the size of the structure before using it. me32.dwSize = sizeof( MODULEENTRY32 ); // Retrieve information about the first module, // and exit if unsuccessful if( !Module32First( hModuleSnap, &me32 ) ) { CloseHandle( hModuleSnap ); return false; } // Now walk the module list of the process, // and display information about each module //the first is always the .exe if (!Module32Next(hModuleSnap, &me32)) { CloseHandle( hModuleSnap ); return false; } moduleList.reserve(20); do { //printf(TEXT("\n MODULE NAME: %s"), me32.szModule); module.modBaseAddr = (DWORD_PTR)me32.modBaseAddr; module.modBaseSize = me32.modBaseSize; module.isAlreadyParsed = false; module.parsing = false; wcscpy_s(module.fullPath, MAX_PATH, me32.szExePath); moduleList.push_back(module); } while(Module32Next(hModuleSnap, &me32)); CloseHandle( hModuleSnap ); return true; } bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize) { MEMORY_BASIC_INFORMATION memBasic; if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("getMemoryRegionFromAddress :: VirtualQueryEx error %u\r\n"), GetLastError()); #endif return false; } else { *memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress; *memoryRegionSize = memBasic.RegionSize; return true; } } bool ProcessAccessHelp::getSizeOfImageCurrentProcess() { DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase); if (newSizeOfImage != 0) { ProcessAccessHelp::targetSizeOfImage = newSizeOfImage; return true; } else { return false; } } SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase) { SIZE_T sizeOfImage = 0; MEMORY_BASIC_INFORMATION lpBuffer = {0}; SIZE_T dwLength = sizeof(MEMORY_BASIC_INFORMATION); do { moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize); sizeOfImage += lpBuffer.RegionSize; //printf("Query 0x"PRINTF_DWORD_PTR_FULL" size 0x%08X\n",moduleBase,sizeOfImage); if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, dwLength)) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("getSizeOfImageProcess :: VirtualQuery failed %X\r\n"),GetLastError()); #endif lpBuffer.Type = 0; sizeOfImage = 0; } /*else { printf("\nAllocationBase %X\n",lpBuffer.AllocationBase); printf("AllocationProtect %X\n",lpBuffer.AllocationProtect); printf("BaseAddress %X\n",lpBuffer.BaseAddress); printf("Protect %X\n",lpBuffer.Protect); printf("RegionSize %X\n",lpBuffer.RegionSize); printf("State %X\n",lpBuffer.State); printf("Type %X\n",lpBuffer.Type); }*/ } while (lpBuffer.Type == MEM_IMAGE); //printf("Real sizeOfImage %X\n",sizeOfImage); return sizeOfImage; } -//OFN_FILEMUSTEXIST -WCHAR * ProcessAccessHelp::selectFile(fileFilter type, BOOL save, DWORD flags, HWND parent) -{ - DWORD dwFlags = flags | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING; - if(!save) - dwFlags |= OFN_FILEMUSTEXIST; - - const WCHAR* filter; - const WCHAR* defExt; - - switch (type) - { - case fileDll: - filter = TEXT("Dynamic Link Library (*.dll)\0*.dll\00"); - defExt = TEXT(".dll"); - break; - case fileExe: - filter = TEXT("Executable (*.exe)\0*.exe\00"); - defExt = TEXT(".exe"); - break; - case fileExeDll: - filter = TEXT("Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\00"); - defExt = 0; - break; - default: - filter = 0; - defExt = 0; - break; - } - - CFileDialog dlgFile(!save, defExt, NULL, dwFlags, filter, parent); - if(dlgFile.DoModal() == IDOK) - { - Logger::printfDialog(TEXT("Selected %s"), dlgFile.m_szFileName); - WCHAR * targetFile = new WCHAR[MAX_PATH]; - wcscpy_s(targetFile, MAX_PATH, dlgFile.m_szFileName); - return targetFile; - } - else - { -#ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("selectFileToSave :: CommDlgExtendedError 0x%X\r\n"), CommDlgExtendedError()); -#endif - return 0; - } - - /* - OPENFILENAME ofn = {0}; - WCHAR * targetFile = new WCHAR[MAX_PATH]; - targetFile[0] = 0; - - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = 0; - - ofn.lpstrCustomFilter = 0; - ofn.nFilterIndex = 1; - ofn.lpstrFile = targetFile; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFileTitle = 0; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = 0; - ofn.lpstrTitle = TEXT("Select a file"); - ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING | flags; - - if(GetOpenFileName(&ofn)) { - Logger::printfDialog(TEXT("Selected %s"),targetFile); - return targetFile; - } else { - delete [] targetFile; - -#ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("selectFileToSave :: CommDlgExtendedError 0x%X\r\n"), CommDlgExtendedError()); -#endif - return 0; - } - */ -} - DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath) { PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; readHeaderFromCurrentFile(filePath); pDosHeader = (PIMAGE_DOS_HEADER)fileHeaderFromDisk; if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileHeaderFromDisk + (DWORD_PTR)(pDosHeader->e_lfanew)); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; } return pNtHeader->OptionalHeader.AddressOfEntryPoint; } bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath) { size_t fileNameLength = wcslen(filePath) + 5; //.bak + null BOOL retValue = 0; WCHAR * backupFile = new WCHAR[fileNameLength]; wcscpy_s(backupFile, fileNameLength, filePath); wcscat_s(backupFile, fileNameLength, TEXT(".bak")); retValue = CopyFile(filePath, backupFile, FALSE); if (!retValue) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("createBackupFile :: CopyFile failed with error 0x%X\r\n"), GetLastError()); #endif } delete [] backupFile; return retValue != 0; } diff --git a/Scylla/ProcessAccessHelp.h b/Scylla/ProcessAccessHelp.h index 5f1c306..96fd6d0 100644 --- a/Scylla/ProcessAccessHelp.h +++ b/Scylla/ProcessAccessHelp.h @@ -1,223 +1,210 @@ #pragma once #include #include #include #include #include - /************************************************************************/ /* distorm */ /************************************************************************/ #include "distorm.h" /* #ifdef _WIN64 #pragma comment(lib, "distorm_x64.lib") #else #pragma comment(lib, "distorm_x86.lib") #endif */ // The number of the array of instructions the decoder function will use to return the disassembled instructions. // Play with this value for performance... #define MAX_INSTRUCTIONS (200) /************************************************************************/ class ApiInfo; class ModuleInfo { public: WCHAR fullPath[MAX_PATH]; DWORD_PTR modBaseAddr; DWORD modBaseSize; bool isAlreadyParsed; bool parsing; /* for iat rebuilding with duplicate entries: ntdll = low priority kernelbase = low priority SHLWAPI = low priority kernel32 = high priority priority = 1 -> normal/high priority priority = 0 -> low priority */ int priority; std::vector apiList; ModuleInfo() { modBaseAddr = 0; modBaseSize = 0; priority = 1; isAlreadyParsed = false; parsing = false; } const WCHAR * getFilename() const { const WCHAR* slash = wcsrchr(fullPath, L'\\'); if(slash) { return slash+1; } return fullPath; } }; class ApiInfo { public: char name[MAX_PATH]; DWORD hint; DWORD_PTR va; DWORD_PTR rva; DWORD_PTR ordinal; bool isForwarded; ModuleInfo * module; }; class ProcessAccessHelp { public: static HANDLE hProcess; //OpenProcess handle to target process static DWORD_PTR targetImageBase; static DWORD_PTR targetSizeOfImage; static DWORD_PTR maxValidAddress; static ModuleInfo * selectedModule; static std::vector moduleList; //target process module list static std::vector ownModuleList; //own module list static const int PE_HEADER_BYTES_COUNT = 2000; static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; //for decomposer static _DInst decomposerResult[MAX_INSTRUCTIONS]; static unsigned int decomposerInstructionsCount; static _CodeInfo decomposerCi; //distorm :: Decoded instruction information. static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; static unsigned int decodedInstructionsCount; #ifdef _WIN64 static const _DecodeType dt = Decode64Bits; #else static const _DecodeType dt = Decode32Bits; #endif - // for selectFile - enum fileFilter { - fileExe, - fileDll, - fileExeDll - }; - /* * Open a new process handle */ static bool openProcessHandle(DWORD dwPID); static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId); static void closeProcessHandle(); /* * Get all modules from a process */ static bool getProcessModules(DWORD dwPID, std::vector &moduleList); /* * file mapping view with different access level */ static LPVOID createFileMappingViewRead(const WCHAR * filePath); static LPVOID createFileMappingViewFull(const WCHAR * filePath); /* * Create a file mapping view of a file */ static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap); /* * Read memory from target process */ static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); /* * Read memory from file */ static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); /* * Write memory to file */ static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); /* * Write memory to file end */ static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer); /* * Disassemble Memory */ static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset); static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress); /* * Search for pattern */ static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask); /* * Get process ID by process name */ static DWORD getProcessByName(const WCHAR * processName); /* * Get memory region from address */ bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize); /* * Read PE Header from file */ static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath); static bool readHeaderFromCurrentFile(const WCHAR * filePath); /* * Get real sizeOfImage value */ static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase); /* * Get real sizeOfImage value current process */ static bool getSizeOfImageCurrentProcess(); - static LONGLONG getFileSize(HANDLE hFile); static LONGLONG getFileSize(const WCHAR * filePath); - static WCHAR * selectFile(fileFilter type, BOOL save, DWORD flags = 0, HWND parent = NULL); - - static DWORD getEntryPointFromFile(const WCHAR * filePath); - static bool createBackupFile(const WCHAR * filePath); };