diff --git a/Scylla/DumpMemoryGui.cpp b/Scylla/DumpMemoryGui.cpp index 33f7aae..39c8647 100644 --- a/Scylla/DumpMemoryGui.cpp +++ b/Scylla/DumpMemoryGui.cpp @@ -1,571 +1,573 @@ #include "DumpMemoryGui.h" #include "Architecture.h" #include "ProcessAccessHelp.h" #include #include "PeParser.h" WCHAR DumpMemoryGui::protectionString[100]; const WCHAR DumpMemoryGui::MemoryUndefined[] = L"UNDEF"; const WCHAR DumpMemoryGui::MemoryUnknown[] = L"UNKNOWN"; const WCHAR * DumpMemoryGui::MemoryStateValues[] = {L"COMMIT",L"FREE",L"RESERVE"}; const WCHAR * DumpMemoryGui::MemoryTypeValues[] = {L"IMAGE",L"MAPPED",L"PRIVATE"}; const WCHAR * DumpMemoryGui::MemoryProtectionValues[] = {L"EXECUTE",L"EXECUTE_READ",L"EXECUTE_READWRITE",L"EXECUTE_WRITECOPY",L"NOACCESS",L"READONLY",L"READWRITE",L"WRITECOPY",L"GUARD",L"NOCACHE",L"WRITECOMBINE"}; DumpMemoryGui::DumpMemoryGui() { dumpedMemory = 0; dumpedMemorySize = 0; deviceNameResolver = new DeviceNameResolver(); } DumpMemoryGui::~DumpMemoryGui() { if (dumpedMemory) { delete [] dumpedMemory; } if (deviceNameResolver) { delete deviceNameResolver; } + + memoryList.clear(); } BOOL DumpMemoryGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls DlgResize_Init(true, true); addColumnsToMemoryList(ListMemorySelect); displayMemoryList(ListMemorySelect); forceDump = false; DoDataExchange(DDX_LOAD); EditMemoryAddress.SetValue(ProcessAccessHelp::targetImageBase); EditMemorySize.SetValue((DWORD)ProcessAccessHelp::targetSizeOfImage); CenterWindow(); return TRUE; } void DumpMemoryGui::addColumnsToMemoryList(CListViewCtrl& list) { list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); list.InsertColumn(COL_ADDRESS, L"Address", LVCFMT_CENTER); list.InsertColumn(COL_SIZE, L"Size", LVCFMT_CENTER); list.InsertColumn(COL_FILENAME, L"File", LVCFMT_LEFT); list.InsertColumn(COL_PESECTION, L"PE Section", LVCFMT_LEFT); list.InsertColumn(COL_TYPE, L"Type", LVCFMT_CENTER); list.InsertColumn(COL_PROTECTION, L"Protection", LVCFMT_CENTER); list.InsertColumn(COL_STATE, L"State", LVCFMT_CENTER); list.InsertColumn(COL_MAPPED_FILE, L"Mapped File", LVCFMT_LEFT); } void DumpMemoryGui::displayMemoryList(CListViewCtrl& list) { int count = 0; WCHAR temp[20]; list.DeleteAllItems(); getMemoryList(); std::vector::const_iterator iter; for( iter = memoryList.begin(); iter != memoryList.end(); iter++ , count++) { swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->address); list.InsertItem(count,temp); swprintf_s(temp, L"%08X", iter->size); list.SetItemText(count, COL_SIZE, temp); list.SetItemText(count, COL_FILENAME, iter->filename); list.SetItemText(count, COL_PESECTION, iter->peSection); if (iter->state == MEM_FREE) { list.SetItemText(count, COL_TYPE, MemoryUndefined); } else { list.SetItemText(count, COL_TYPE, getMemoryTypeString(iter->type)); } if ( (iter->state == MEM_RESERVE) || (iter->state == MEM_FREE) ) { list.SetItemText(count, COL_PROTECTION, MemoryUndefined); } else { list.SetItemText(count, COL_PROTECTION, getMemoryProtectionString(iter->protect)); } list.SetItemText(count, COL_STATE, getMemoryStateString(iter->state)); list.SetItemText(count, COL_MAPPED_FILE, iter->mappedFilename); list.SetItemData(count, (DWORD_PTR)&(*iter)); } list.SetColumnWidth(COL_ADDRESS, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_SIZE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_FILENAME, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_PESECTION, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_TYPE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_PROTECTION, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_STATE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_MAPPED_FILE, LVSCW_AUTOSIZE_USEHEADER); } const WCHAR * DumpMemoryGui::getMemoryTypeString(DWORD value) { switch(value) { case MEM_IMAGE: return MemoryTypeValues[TYPE_IMAGE]; case MEM_MAPPED: return MemoryTypeValues[TYPE_MAPPED]; case MEM_PRIVATE: return MemoryTypeValues[TYPE_PRIVATE]; default: return MemoryUnknown; } } const WCHAR * DumpMemoryGui::getMemoryStateString(DWORD value) { switch(value) { case MEM_COMMIT: return MemoryStateValues[STATE_COMMIT]; case MEM_FREE: return MemoryStateValues[STATE_FREE]; case MEM_RESERVE: return MemoryStateValues[STATE_RESERVE]; default: return MemoryUnknown; } } WCHAR * DumpMemoryGui::getMemoryProtectionString(DWORD value) { protectionString[0] = 0; if (value & PAGE_GUARD) { wcscpy_s(protectionString, MemoryProtectionValues[PROT_GUARD]); wcscat_s(protectionString, L" | "); value ^= PAGE_GUARD; } if (value & PAGE_NOCACHE) { wcscpy_s(protectionString, MemoryProtectionValues[PROT_NOCACHE]); wcscat_s(protectionString, L" | "); value ^= PAGE_NOCACHE; } if (value & PAGE_WRITECOMBINE) { wcscpy_s(protectionString, MemoryProtectionValues[PROT_WRITECOMBINE]); wcscat_s(protectionString, L" | "); value ^= PAGE_WRITECOMBINE; } switch(value) { case PAGE_EXECUTE: { wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE]); break; } case PAGE_EXECUTE_READ: { wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_READ]); break; } case PAGE_EXECUTE_READWRITE: { wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_READWRITE]); break; } case PAGE_EXECUTE_WRITECOPY: { wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_WRITECOPY]); break; } case PAGE_NOACCESS: { wcscat_s(protectionString, MemoryProtectionValues[PROT_NOACCESS]); break; } case PAGE_READONLY: { wcscat_s(protectionString, MemoryProtectionValues[PROT_READONLY]); break; } case PAGE_READWRITE: { wcscat_s(protectionString, MemoryProtectionValues[PROT_READWRITE]); break; } case PAGE_WRITECOPY: { wcscat_s(protectionString, MemoryProtectionValues[PROT_WRITECOPY]); break; } default: { wcscat_s(protectionString, MemoryUnknown); } } return protectionString; } LRESULT DumpMemoryGui::OnListMemoryColumnClicked(NMHDR* pnmh) { NMLISTVIEW* list = (NMLISTVIEW*)pnmh; int column = list->iSubItem; if(column == prevColumn) { ascending = !ascending; } else { prevColumn = column; ascending = true; } // lo-byte: column, hi-byte: sort-order ListMemorySelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); return 0; } LRESULT DumpMemoryGui::OnListMemoryClick(NMHDR* pnmh) { int index = ListMemorySelect.GetSelectionMark(); if (index != -1) { selectedMemory = (Memory *)ListMemorySelect.GetItemData(index); if (selectedMemory) { updateAddressAndSize(selectedMemory); } } return 0; } void DumpMemoryGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { DoDataExchange(DDX_SAVE); if (EditMemoryAddress.GetValue() == 0 || EditMemorySize.GetValue() == 0) { wndCtl.MessageBoxW(L"Textbox is empty!",L"Error",MB_ICONERROR); } else { if (dumpMemory()) { EndDialog(1); } else { wndCtl.MessageBoxW(L"Reading memory from process failed",L"Error",MB_ICONERROR); } } } void DumpMemoryGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void DumpMemoryGui::updateAddressAndSize( Memory * selectedMemory ) { EditMemoryAddress.SetValue(selectedMemory->address); EditMemorySize.SetValue(selectedMemory->size); } int DumpMemoryGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { const Memory * module1 = (Memory *)lParam1; const Memory * module2 = (Memory *)lParam2; int column = LOBYTE(lParamSort); bool ascending = (HIBYTE(lParamSort) == TRUE); int diff = 0; switch(column) { case COL_ADDRESS: diff = module1->address < module2->address ? -1 : 1; break; case COL_SIZE: diff = module1->size < module2->size ? -1 : 1; break; case COL_FILENAME: diff = _wcsicmp(module1->filename, module2->filename); break; case COL_PESECTION: diff = _wcsicmp(module1->peSection, module2->peSection); break; case COL_TYPE: diff = module1->type < module2->type ? -1 : 1; break; case COL_PROTECTION: diff = module1->protect < module2->protect ? -1 : 1; break; case COL_STATE: diff = _wcsicmp(getMemoryStateString(module1->state), getMemoryStateString(module2->state)); //diff = module1->state < module2->state ? -1 : 1; break; case COL_MAPPED_FILE: diff = _wcsicmp(module1->mappedFilename, module2->mappedFilename); break; } return ascending ? diff : -diff; } void DumpMemoryGui::getMemoryList() { DWORD count = 0; DWORD_PTR address = 0; MEMORY_BASIC_INFORMATION memBasic = {0}; Memory memory; HMODULE * hMods = 0; DWORD cbNeeded = 0; bool notEnough = true; WCHAR target[MAX_PATH]; count = 100; hMods = new HMODULE[count]; if (memoryList.empty()) { memoryList.reserve(20); } else { memoryList.clear(); } memory.filename[0] = 0; memory.peSection[0] = 0; memory.mappedFilename[0] = 0; while(VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)address,&memBasic,sizeof(memBasic))) { memory.address = (DWORD_PTR)memBasic.BaseAddress; memory.type = memBasic.Type; memory.state = memBasic.State; memory.size = (DWORD)memBasic.RegionSize; memory.protect = memBasic.Protect; if (memory.type == MEM_MAPPED) { if (!getMappedFilename(&memory)) { memory.mappedFilename[0] = 0; } } memoryList.push_back(memory); memory.mappedFilename[0] = 0; address += memBasic.RegionSize; } do { if (!EnumProcessModules(ProcessAccessHelp::hProcess, hMods, count * sizeof(HMODULE), &cbNeeded)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"getMemoryList :: EnumProcessModules failed count %d", count); #endif delete [] hMods; return; } if ( (count * sizeof(HMODULE)) < cbNeeded ) { delete [] hMods; count += 100; hMods = new HMODULE[count]; } else { notEnough = false; } } while (notEnough); for (DWORD i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) { if (GetModuleFileNameExW(ProcessAccessHelp::hProcess, hMods[i], target, _countof(target))) { setModuleName((DWORD_PTR)hMods[i],target); setAllSectionNames((DWORD_PTR)hMods[i],target); } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"getMemoryList :: GetModuleFileNameExW failed 0x%X", GetLastError()); #endif } } delete [] hMods; } void DumpMemoryGui::setSectionName(DWORD_PTR sectionAddress, DWORD sectionSize, const WCHAR * sectionName) { bool found = false; std::vector::const_iterator iter; for( iter = memoryList.begin(); iter != memoryList.end(); iter++) { if (!found) { if ( (iter->address <= sectionAddress) && (sectionAddress < (iter->address + iter->size)) ) { if (wcslen(iter->peSection) == 0) { - wcscpy_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName); + wcscpy_s((WCHAR *)iter->peSection, _countof(iter->peSection), sectionName); } else { - wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, L"|"); - wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName); + wcscat_s((WCHAR *)iter->peSection, _countof(iter->peSection), L"|"); + wcscat_s((WCHAR *)iter->peSection, _countof(iter->peSection), sectionName); } found = true; } } else { if ((sectionSize+sectionAddress) < iter->address) { break; } if (wcslen(iter->peSection) == 0) { - wcscpy_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName); + wcscpy_s((WCHAR *)iter->peSection, _countof(iter->peSection), sectionName); } else { - wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, L"|"); - wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName); + wcscat_s((WCHAR *)iter->peSection, _countof(iter->peSection), L"|"); + wcscat_s((WCHAR *)iter->peSection, _countof(iter->peSection), sectionName); } } } } void DumpMemoryGui::setModuleName(DWORD_PTR moduleBase, const WCHAR * moduleName) { bool found = false; std::vector::const_iterator iter; //get filename const WCHAR* slash = wcsrchr(moduleName, L'\\'); if(slash) { moduleName = slash+1; } for( iter = memoryList.begin(); iter != memoryList.end(); iter++) { if (iter->address == moduleBase) { found = true; } if (found) { if (iter->type == MEM_IMAGE) { wcscpy_s((WCHAR *)iter->filename, MAX_PATH, moduleName); } else { break; } } } } void DumpMemoryGui::setAllSectionNames( DWORD_PTR moduleBase, WCHAR * moduleName ) { WCHAR sectionNameW[IMAGE_SIZEOF_SHORT_NAME + 1] = {0}; PeParser peFile(moduleName); if (peFile.isValidPeFile()) { std::vector & listSectionHeader = peFile.getSectionHeaderList(); for (WORD i = 0; i < peFile.getNumberOfSections(); i++) { peFile.getSectionNameUnicode(i, sectionNameW, _countof(sectionNameW)); setSectionName(moduleBase + listSectionHeader[i].sectionHeader.VirtualAddress, listSectionHeader[i].sectionHeader.Misc.VirtualSize, sectionNameW); } } else { MessageBox(moduleName,L"Not a valid PE -> This should never happen",MB_ICONERROR); } } bool DumpMemoryGui::dumpMemory() { DWORD_PTR address = EditMemoryAddress.GetValue(); dumpedMemorySize = EditMemorySize.GetValue(); swprintf_s(dumpFilename,TEXT("MEM_")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("_")TEXT("%08X"),address,dumpedMemorySize); dumpedMemory = new BYTE[dumpedMemorySize]; if (dumpedMemory) { if (forceDump) { return ProcessAccessHelp::readMemoryPartlyFromProcess(address,dumpedMemorySize,dumpedMemory); } else { return ProcessAccessHelp::readMemoryFromProcess(address,dumpedMemorySize,dumpedMemory); } } else { return false; } } bool DumpMemoryGui::getMappedFilename( Memory* memory ) { WCHAR filename[MAX_PATH] = {0}; //TODO replace with Nt direct syscall if (GetMappedFileNameW(ProcessAccessHelp::hProcess, (LPVOID)memory->address, filename, _countof(filename)) > 0) { return deviceNameResolver->resolveDeviceLongNameToShort(filename, memory->mappedFilename); } return false; } diff --git a/Scylla/DumpMemoryGui.h b/Scylla/DumpMemoryGui.h index 63eec66..1b13cf4 100644 --- a/Scylla/DumpMemoryGui.h +++ b/Scylla/DumpMemoryGui.h @@ -1,169 +1,169 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL window frame helpers #include // WTL utility classes #include // WTL enhanced msg map macros #include // WTL controls #include // WTL dialog data exchange #include #include "hexedit.h" #include "DeviceNameResolver.h" class Memory { public: DWORD_PTR address; DWORD size; WCHAR filename[MAX_PATH]; WCHAR mappedFilename[MAX_PATH]; - WCHAR peSection[IMAGE_SIZEOF_SHORT_NAME *4]; - DWORD state; - DWORD protect; - DWORD type; + WCHAR peSection[IMAGE_SIZEOF_SHORT_NAME * 20]; + DWORD state; + DWORD protect; + DWORD type; }; class DumpMemoryGui : public CDialogImpl, public CWinDataExchange, public CDialogResize { public: enum { IDD = IDD_DLG_DUMPMEMORY }; BEGIN_DDX_MAP(DumpMemoryGui) DDX_CONTROL_HANDLE(IDC_LIST_DUMPMEMORY, ListMemorySelect) DDX_CONTROL(IDC_EDIT_DUMPADDRESS, EditMemoryAddress) DDX_CONTROL(IDC_EDIT_DUMPSIZE, EditMemorySize) DDX_CHECK(IDC_CHECK_FORCEDUMP, forceDump) END_DDX_MAP() BEGIN_MSG_MAP(DumpMemoryGui) MSG_WM_INITDIALOG(OnInitDialog) NOTIFY_HANDLER_EX(IDC_LIST_DUMPMEMORY, LVN_COLUMNCLICK, OnListMemoryColumnClicked) NOTIFY_HANDLER_EX(IDC_LIST_DUMPMEMORY, NM_CLICK, OnListMemoryClick) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPMEMORY_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPMEMORY_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) CHAIN_MSG_MAP(CDialogResize) END_MSG_MAP() BEGIN_DLGRESIZE_MAP(DumpMemoryGui) DLGRESIZE_CONTROL(IDC_LIST_DUMPMEMORY, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMPMEMORY_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMPMEMORY_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_DUMPADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_DUMPSIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_SIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_ADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_CHECK_FORCEDUMP, DLSZ_MOVE_Y) END_DLGRESIZE_MAP() DumpMemoryGui(); ~DumpMemoryGui(); BYTE * dumpedMemory; DWORD dumpedMemorySize; WCHAR dumpFilename[39]; protected: CListViewCtrl ListMemorySelect; CHexEdit EditMemoryAddress; CHexEdit EditMemorySize; std::vector memoryList; Memory * selectedMemory; DeviceNameResolver * deviceNameResolver; enum ListColumns { COL_ADDRESS = 0, COL_SIZE, COL_FILENAME, COL_PESECTION, COL_TYPE, COL_PROTECTION, COL_STATE, COL_MAPPED_FILE }; int prevColumn; bool ascending; bool forceDump; // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); LRESULT OnListMemoryColumnClicked(NMHDR* pnmh); LRESULT OnListMemoryClick(NMHDR* pnmh); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void addColumnsToMemoryList(CListViewCtrl& list); void displayMemoryList(CListViewCtrl& list); static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); private: enum enumMemoryStateValues { STATE_COMMIT = 0, STATE_FREE, STATE_RESERVE }; //"IMAGE",L"MAPPED",L"PRIVATE" enum enumMemoryTypeValues { TYPE_IMAGE = 0, TYPE_MAPPED, TYPE_PRIVATE }; //"EXECUTE",L"EXECUTE_READ",L"EXECUTE_READWRITE",L"EXECUTE_WRITECOPY",L"NOACCESS",L"READONLY",L"READWRITE",L"WRITECOPY",L"GUARD",L"NOCACHE",L"WRITECOMBINE" enum enumMemoryProtectionValues { PROT_EXECUTE = 0, PROT_EXECUTE_READ, PROT_EXECUTE_READWRITE, PROT_EXECUTE_WRITECOPY, PROT_NOACCESS, PROT_READONLY, PROT_READWRITE, PROT_WRITECOPY, PROT_GUARD, PROT_NOCACHE, PROT_WRITECOMBINE }; static const WCHAR * MemoryStateValues[]; static const WCHAR * MemoryTypeValues[]; static const WCHAR * MemoryProtectionValues[]; static const WCHAR MemoryUnknown[]; static const WCHAR MemoryUndefined[]; static WCHAR protectionString[100]; static const WCHAR * getMemoryTypeString(DWORD value); static const WCHAR * getMemoryStateString(DWORD value); static WCHAR * getMemoryProtectionString(DWORD value); void updateAddressAndSize( Memory * selectedMemory ); void getMemoryList(); SIZE_T getSizeOfImage(DWORD_PTR moduleBase); void setModuleName(DWORD_PTR moduleBase, const WCHAR * moduleName); void setAllSectionNames( DWORD_PTR moduleBase, WCHAR * moduleName ); void setSectionName(DWORD_PTR sectionAddress, DWORD sectionSize, const WCHAR * sectionName); bool dumpMemory(); bool getMappedFilename( Memory* memory ); }; diff --git a/Scylla/DumpSectionGui.cpp b/Scylla/DumpSectionGui.cpp index 85785a9..7823f7c 100644 --- a/Scylla/DumpSectionGui.cpp +++ b/Scylla/DumpSectionGui.cpp @@ -1,382 +1,394 @@ #include "DumpSectionGui.h" #include "Architecture.h" #include "ProcessAccessHelp.h" #include "PeParser.h" bool PeSection::highlightVirtualSize() { //highlight big virtual sizes -> anti-dump protection return (virtualSize > 0x2000000); } std::vector & DumpSectionGui::getSectionList() { return sectionList; } +DumpSectionGui::DumpSectionGui() +{ + imageBase = 0; + entryPoint = 0; + fullpath[0] = 0; +} + +DumpSectionGui::~DumpSectionGui() +{ + sectionList.clear(); +} + BOOL DumpSectionGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls DlgResize_Init(true, true); addColumnsToSectionList(ListSectionSelect); displaySectionList(ListSectionSelect); selectOrDeselectAll(); isEditing = false; selectedSection = 0; CenterWindow(); return TRUE; } LRESULT DumpSectionGui::OnListSectionColumnClicked(NMHDR* pnmh) { NMLISTVIEW* list = (NMLISTVIEW*)pnmh; int column = list->iSubItem; if(column == prevColumn) { ascending = !ascending; } else { prevColumn = column; ascending = true; } // lo-byte: column, hi-byte: sort-order ListSectionSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); return 0; } LRESULT DumpSectionGui::OnListSectionClick(NMHDR* pnmh) { //int index = ListSectionSelect.GetSelectionMark(); //if (index != -1) //{ //} return 0; } LRESULT DumpSectionGui::OnListDoubleClick(NMHDR* pnmh) { LVHITTESTINFO hti; RECT rect, rect1, rect2; NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh; editingSubItem = ia->iSubItem; if (editingSubItem == COL_NAME || editingSubItem == COL_VA || editingSubItem == COL_RVA) { return 0; } hti.pt = ia->ptAction; int clicked = ListSectionSelect.HitTest(&hti); if(clicked != -1) { selectedSection = (PeSection *)ListSectionSelect.GetItemData(clicked); } ListSectionSelect.GetSubItemRect(ia->iItem,ia->iSubItem,LVIR_BOUNDS,&rect); //Get the Rectange of the listControl ListSectionSelect.GetWindowRect(&rect1); //Get the Rectange of the Dialog GetWindowRect(&rect2); int x = rect1.left - rect2.left; int y = rect1.top - rect2.top; isEditing = true; switch (editingSubItem) { case COL_VSize: valueBeforeEditing = selectedSection->virtualSize; break; case COL_RSize: valueBeforeEditing = selectedSection->rawSize; break; case COL_Characteristics: valueBeforeEditing = selectedSection->characteristics; break; default: valueBeforeEditing = 0; } EditListControl.SetValue(valueBeforeEditing); EditListControl.SetWindowPos(HWND_TOP,rect.left + 7, rect.top + 7, rect.right - rect.left, rect.bottom - rect.top, NULL); EditListControl.ShowWindow(SW_SHOW); EditListControl.SetFocus(); return 0; } void DumpSectionGui::OnSectionSelectAll(UINT uNotifyCode, int nID, CWindow wndCtl) { selectOrDeselectAll(); } void DumpSectionGui::OnEditList(UINT uNotifyCode, int nID, CWindow wndCtl) { switch (uNotifyCode) { case EN_KILLFOCUS: { isEditing = false; updateEditedItem(); EditListControl.ShowWindow(SW_HIDE); } break; } } void DumpSectionGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { if (isEditing) //EN_KILLFOCUS not sent? { updateEditedItem(); } updateCheckState(); EndDialog(1); } void DumpSectionGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } int DumpSectionGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { const PeSection * module1 = (PeSection *)lParam1; const PeSection * module2 = (PeSection *)lParam2; int column = LOBYTE(lParamSort); bool ascending = (HIBYTE(lParamSort) == TRUE); int diff = 0; switch(column) { case COL_NAME: diff = _wcsicmp(module1->name, module2->name); break; case COL_VA: diff = module1->virtualAddress < module2->virtualAddress ? -1 : 1; break; case COL_VSize: diff = module1->virtualSize < module2->virtualSize ? -1 : 1; break; case COL_RVA: diff = module1->rawAddress < module2->rawAddress ? -1 : 1; break; case COL_RSize: diff = module1->rawSize < module2->rawSize ? -1 : 1; break; case COL_Characteristics: diff = module1->characteristics < module2->characteristics ? -1 : 1; break; } return ascending ? diff : -diff; } void DumpSectionGui::addColumnsToSectionList(CListViewCtrl& list) { list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES|LVS_EX_GRIDLINES); list.InsertColumn(COL_NAME, L"Name", LVCFMT_CENTER); list.InsertColumn(COL_VA, L"Virtual Address", LVCFMT_CENTER); list.InsertColumn(COL_VSize, L"Virtual Size", LVCFMT_CENTER); list.InsertColumn(COL_RVA, L"Raw Address", LVCFMT_CENTER); list.InsertColumn(COL_RSize, L"Raw Size", LVCFMT_CENTER); list.InsertColumn(COL_Characteristics, L"Characteristics", LVCFMT_CENTER); } void DumpSectionGui::displaySectionList(CListViewCtrl& list) { int count = 0; WCHAR temp[20]; list.DeleteAllItems(); if (sectionList.empty()) { getAllSectionsFromFile(); } std::vector::const_iterator iter; for( iter = sectionList.begin(); iter != sectionList.end(); iter++ , count++) { list.InsertItem(count, iter->name); swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->virtualAddress); list.SetItemText(count, COL_VA, temp); swprintf_s(temp, L"%08X", iter->virtualSize); list.SetItemText(count, COL_VSize, temp); swprintf_s(temp, L"%08X", iter->rawAddress); list.SetItemText(count, COL_RVA, temp); swprintf_s(temp, L"%08X", iter->rawSize); list.SetItemText(count, COL_RSize, temp); swprintf_s(temp, L"%08X", iter->characteristics); list.SetItemText(count, COL_Characteristics, temp); list.SetItemData(count, (DWORD_PTR)&(*iter)); } list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_VA, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_VSize, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_RVA, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_RSize, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_Characteristics, LVSCW_AUTOSIZE_USEHEADER); } LRESULT DumpSectionGui::OnNMCustomdraw(NMHDR* pnmh) { LRESULT pResult = 0; unsigned int vectorIndex = 0; LPNMLVCUSTOMDRAW lpLVCustomDraw = (LPNMLVCUSTOMDRAW)(pnmh); switch(lpLVCustomDraw->nmcd.dwDrawStage) { case CDDS_ITEMPREPAINT: case CDDS_ITEMPREPAINT | CDDS_SUBITEM: { vectorIndex = (unsigned int)lpLVCustomDraw->nmcd.dwItemSpec; if (lpLVCustomDraw->iSubItem == COL_VSize) { if (sectionList[vectorIndex].highlightVirtualSize()) { lpLVCustomDraw->clrText = RGB(255,255,255); // white text lpLVCustomDraw->clrTextBk = RGB(255,0,0); // red background } } else { lpLVCustomDraw->clrText = CLR_DEFAULT; lpLVCustomDraw->clrTextBk = CLR_DEFAULT; } } break; default: break; } pResult |= CDRF_NOTIFYPOSTPAINT; pResult |= CDRF_NOTIFYITEMDRAW; pResult |= CDRF_NOTIFYSUBITEMDRAW; return pResult; } void DumpSectionGui::getAllSectionsFromFile() { PeSection peSection; if (sectionList.empty()) { sectionList.reserve(3); } else { sectionList.clear(); } PeParser peFile(fullpath); if (peFile.isValidPeFile()) { std::vector & listSectionHeader = peFile.getSectionHeaderList(); for (WORD i = 0; i < peFile.getNumberOfSections(); i++) { peFile.getSectionNameUnicode(i, peSection.name, _countof(peSection.name)); peSection.virtualAddress = imageBase + listSectionHeader[i].sectionHeader.VirtualAddress; peSection.virtualSize = listSectionHeader[i].sectionHeader.Misc.VirtualSize; peSection.rawAddress = listSectionHeader[i].sectionHeader.PointerToRawData; peSection.rawSize = listSectionHeader[i].sectionHeader.SizeOfRawData; peSection.characteristics = listSectionHeader[i].sectionHeader.Characteristics; peSection.isDumped = true; sectionList.push_back(peSection); } } else { MessageBox(fullpath, L"Not a valid PE -> This should never happen", MB_ICONERROR); } } void DumpSectionGui::updateEditedItem() { if (selectedSection) { DWORD newValue = EditListControl.GetValue(); if (valueBeforeEditing != newValue) { switch (editingSubItem) { case COL_VSize: selectedSection->virtualSize = newValue; break; case COL_RSize: selectedSection->rawSize = newValue; break; case COL_Characteristics: selectedSection->characteristics = newValue; break; } displaySectionList(ListSectionSelect); selectOrDeselectAll(); } } } void DumpSectionGui::updateCheckState() { PeSection * pesection; for (size_t i = 0; i < sectionList.size(); i++) { pesection = (PeSection *)ListSectionSelect.GetItemData((int)i); pesection->isDumped = ListSectionSelect.GetCheckState((int)i) == TRUE; } } void DumpSectionGui::selectOrDeselectAll() { BOOL checkState = ListSectionSelect.GetCheckState((int)0) ? FALSE : TRUE; for (size_t i = 0; i < sectionList.size(); i++) { ListSectionSelect.SetCheckState((int)i, checkState); } } \ No newline at end of file diff --git a/Scylla/DumpSectionGui.h b/Scylla/DumpSectionGui.h index cfc8412..17bfe02 100644 --- a/Scylla/DumpSectionGui.h +++ b/Scylla/DumpSectionGui.h @@ -1,132 +1,127 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL window frame helpers #include // WTL utility classes #include // WTL enhanced msg map macros #include // WTL controls #include // WTL dialog data exchange #include #include "hexedit.h" class PeSection { public: WCHAR name[IMAGE_SIZEOF_SHORT_NAME + 1]; DWORD_PTR virtualAddress; DWORD virtualSize; DWORD_PTR rawAddress; DWORD rawSize; DWORD characteristics; bool isDumped; bool highlightVirtualSize(); }; class DumpSectionGui : public CDialogImpl, public CWinDataExchange, public CDialogResize { public: enum { IDD = IDD_DLG_DUMPSECTION }; BEGIN_DDX_MAP(DumpSectionGui) DDX_CONTROL_HANDLE(IDC_LIST_DUMPSECTION, ListSectionSelect) DDX_CONTROL(IDC_EDIT_LISTCONTROL, EditListControl) END_DDX_MAP() BEGIN_MSG_MAP(DumpSectionGui) MSG_WM_INITDIALOG(OnInitDialog) NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, LVN_COLUMNCLICK, OnListSectionColumnClicked) NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_CLICK, OnListSectionClick) NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_CUSTOMDRAW, OnNMCustomdraw) NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_DBLCLK, OnListDoubleClick) COMMAND_ID_HANDLER_EX(IDC_BUTTON_SELECT_DESELECT, OnSectionSelectAll) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPSECTION_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_EDIT_LISTCONTROL, OnEditList) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPSECTION_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) CHAIN_MSG_MAP(CDialogResize) END_MSG_MAP() BEGIN_DLGRESIZE_MAP(DumpSectionGui) DLGRESIZE_CONTROL(IDC_LIST_DUMPSECTION, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMPSECTION_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMPSECTION_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BUTTON_SELECT_DESELECT, DLSZ_MOVE_Y) END_DLGRESIZE_MAP() - DumpSectionGui() - { - imageBase = 0; - entryPoint = 0; - fullpath[0] = 0; - } - //~DumpSectionGui(); + DumpSectionGui(); + ~DumpSectionGui(); DWORD_PTR imageBase; //VA DWORD_PTR entryPoint; WCHAR fullpath[MAX_PATH]; std::vector & getSectionList(); private: CListViewCtrl ListSectionSelect; CHexEdit EditListControl; std::vector sectionList; PeSection *selectedSection; bool isEditing; int editingSubItem; DWORD valueBeforeEditing; enum ListColumns { COL_NAME = 0, COL_VA, COL_VSize, COL_RVA, COL_RSize, COL_Characteristics }; int prevColumn; bool ascending; // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); LRESULT OnListSectionColumnClicked(NMHDR* pnmh); LRESULT OnListSectionClick(NMHDR* pnmh); LRESULT OnNMCustomdraw(NMHDR* pnmh); LRESULT OnListDoubleClick(NMHDR* pnmh); void OnSectionSelectAll(UINT uNotifyCode, int nID, CWindow wndCtl); void OnEditList(UINT uNotifyCode, int nID, CWindow wndCtl); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void addColumnsToSectionList(CListViewCtrl& list); void displaySectionList(CListViewCtrl& list); static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); WCHAR * getCharacteristicsString( DWORD characteristics ); void getAllSectionsFromFile(); void updateEditedItem(); void updateCheckState(); void selectOrDeselectAll(); }; \ No newline at end of file diff --git a/Scylla/Scylla.h b/Scylla/Scylla.h index a14486f..5478853 100644 --- a/Scylla/Scylla.h +++ b/Scylla/Scylla.h @@ -1,31 +1,31 @@ #pragma once #include "ConfigurationHolder.h" #include "PluginLoader.h" #include "ProcessLister.h" #include "Logger.h" #define APPNAME_S "Scylla" -#define APPVERSION_S "v0.6" +#define APPVERSION_S "v0.6a" #define APPNAME TEXT(APPNAME_S) #define APPVERSION TEXT(APPVERSION_S) class Scylla { public: static void init(); static ConfigurationHolder config; static PluginLoader plugins; static ProcessLister processLister; static FileLog debugLog; static ListboxLog windowLog; private: static const WCHAR DEBUG_LOG_FILENAME[]; };