diff --git a/Scylla/DeviceNameResolver.cpp b/Scylla/DeviceNameResolver.cpp new file mode 100644 index 0000000..c0d1787 --- /dev/null +++ b/Scylla/DeviceNameResolver.cpp @@ -0,0 +1,55 @@ + +#include "DeviceNameResolver.h" + +DeviceNameResolver::DeviceNameResolver() +{ + initDeviceNameList(); +} + +DeviceNameResolver::~DeviceNameResolver() +{ + deviceNameList.clear(); +} + +void DeviceNameResolver::initDeviceNameList() +{ + TCHAR shortName[3] = {0}; + TCHAR longName[MAX_PATH] = {0}; + HardDisk hardDisk; + + shortName[1] = L':'; + + deviceNameList.reserve(3); + + for ( TCHAR shortD = TEXT('a'); shortD < TEXT('z'); shortD++ ) + { + shortName[0] = shortD; + if (QueryDosDevice( shortName, longName, MAX_PATH ) > 0) + { + hardDisk.shortName[0] = _totupper(shortD); + hardDisk.shortName[1] = TEXT(':'); + hardDisk.shortName[2] = 0; + + hardDisk.longNameLength = _tcslen(longName); + + + _tcscpy_s(hardDisk.longName, longName); + deviceNameList.push_back(hardDisk); + } + } +} + +bool DeviceNameResolver::resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ) +{ + for (unsigned int i = 0; i < deviceNameList.size(); i++) + { + if (!_tcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength)) + { + _tcscpy_s(targetPath, MAX_PATH, deviceNameList[i].shortName); + _tcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength); + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/Scylla/DeviceNameResolver.h b/Scylla/DeviceNameResolver.h new file mode 100644 index 0000000..32ba924 --- /dev/null +++ b/Scylla/DeviceNameResolver.h @@ -0,0 +1,27 @@ +#include + + +#pragma once + +#include +#include +#include + +class HardDisk { +public: + WCHAR shortName[3]; + WCHAR longName[MAX_PATH]; + size_t longNameLength; +}; + +class DeviceNameResolver +{ +public: + DeviceNameResolver(); + ~DeviceNameResolver(); + bool resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ); +private: + std::vector deviceNameList; + + void initDeviceNameList(); +}; \ No newline at end of file diff --git a/Scylla/DumpMemoryGui.cpp b/Scylla/DumpMemoryGui.cpp index a15443e..142db46 100644 --- a/Scylla/DumpMemoryGui.cpp +++ b/Scylla/DumpMemoryGui.cpp @@ -1,540 +1,604 @@ #include "DumpMemoryGui.h" -#include "definitions.h" +#include "Architecture.h" #include "ProcessAccessHelp.h" #include 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", L"NONE"}; +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; + } } 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, TEXT(PRINTF_DWORD_PTR_FULL), iter->address); + 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); - list.SetItemText(count, COL_TYPE, getMemoryTypeString(iter->type)); - list.SetItemText(count, COL_PROTECTION, getMemoryProtectionString(iter->protect)); + + 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 0: - return MemoryTypeValues[TYPE_NONE]; 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,_countof(protectionString), MemoryProtectionValues[PROT_GUARD]); wcscat_s(protectionString,_countof(protectionString), L" | "); value ^= PAGE_GUARD; } if (value & PAGE_NOCACHE) { wcscpy_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_NOCACHE]); wcscat_s(protectionString,_countof(protectionString), L" | "); value ^= PAGE_NOCACHE; } if (value & PAGE_WRITECOMBINE) { wcscpy_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_WRITECOMBINE]); wcscat_s(protectionString,_countof(protectionString), L" | "); value ^= PAGE_WRITECOMBINE; } switch(value) { - case 0: - { - wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_NOACCESS]); - break; - } case PAGE_EXECUTE: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_EXECUTE]); break; } case PAGE_EXECUTE_READ: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_EXECUTE_READ]); break; } case PAGE_EXECUTE_READWRITE: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_EXECUTE_READWRITE]); break; } case PAGE_EXECUTE_WRITECOPY: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_EXECUTE_WRITECOPY]); break; } case PAGE_NOACCESS: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_NOACCESS]); break; } case PAGE_READONLY: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_READONLY]); break; } case PAGE_READWRITE: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_READWRITE]); break; } case PAGE_WRITECOPY: { wcscat_s(protectionString,_countof(protectionString), MemoryProtectionValues[PROT_WRITECOPY]); break; } default: { wcscat_s(protectionString,_countof(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"Read 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 = 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 + 1, sectionName); } else { wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME *4,L"|"); wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME *4,sectionName); } found = true; } } else { if ((sectionSize+sectionAddress) < iter->address) { break; } if (wcslen(iter->peSection) == 0) { wcscpy_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME + 1, sectionName); } else { wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME *4,L"|"); wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME *4,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 ) { WORD numSections = 0; PIMAGE_DOS_HEADER pDos = 0; PIMAGE_NT_HEADERS pNT = 0; PIMAGE_SECTION_HEADER pSec = 0; DWORD size = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 200; DWORD correctSize = 0; WCHAR sectionNameW[IMAGE_SIZEOF_SHORT_NAME + 1] = {0}; CHAR sectionNameA[IMAGE_SIZEOF_SHORT_NAME + 1] = {0}; BYTE * buffer = new BYTE[size]; if (ProcessAccessHelp::readMemoryFromProcess(moduleBase,size,buffer)) { pDos = (PIMAGE_DOS_HEADER)buffer; if (pDos->e_magic == IMAGE_DOS_SIGNATURE) { pNT = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew); if (pNT->Signature == IMAGE_NT_SIGNATURE) { numSections = pNT->FileHeader.NumberOfSections; correctSize = (numSections*sizeof(IMAGE_SECTION_HEADER)) + sizeof(IMAGE_NT_HEADERS) + pDos->e_lfanew; if (size < correctSize) { size = correctSize; delete [] buffer; buffer = new BYTE[size]; if (!ProcessAccessHelp::readMemoryFromProcess(moduleBase,size,buffer)) { delete [] buffer; return; } pDos = (PIMAGE_DOS_HEADER)buffer; pNT = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew); } pSec = IMAGE_FIRST_SECTION(pNT); for (WORD i = 0; i < numSections; i++) { memcpy(sectionNameA,pSec->Name,8); swprintf_s(sectionNameW,_countof(sectionNameW),L"%S",sectionNameA); setSectionName(moduleBase + pSec->VirtualAddress, pSec->Misc.VirtualSize,sectionNameW); pSec++; } } } } delete [] buffer; } bool DumpMemoryGui::dumpMemory() { DWORD_PTR address = EditMemoryAddress.GetValue(); dumpedMemorySize = EditMemorySize.GetValue(); - swprintf_s(dumpFilename,_countof(dumpFilename),TEXT("MEM_")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("_")TEXT("%08X"),address,dumpedMemorySize); + swprintf_s(dumpFilename,_countof(dumpFilename),TEXT("MEM_")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("_")TEXT("%08X"),address,dumpedMemorySize); dumpedMemory = new BYTE[dumpedMemorySize]; if (dumpedMemory) { - return ProcessAccessHelp::readMemoryFromProcess(address,dumpedMemorySize,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 5c24147..f841e16 100644 --- a/Scylla/DumpMemoryGui.h +++ b/Scylla/DumpMemoryGui.h @@ -1,159 +1,168 @@ #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; }; 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_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, - TYPE_NONE + 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]; const WCHAR * getMemoryTypeString(DWORD value); const WCHAR * getMemoryStateString(DWORD value); 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/MainGui.rc b/Scylla/MainGui.rc index 91abd3c..3806cec 100644 Binary files a/Scylla/MainGui.rc and b/Scylla/MainGui.rc differ diff --git a/Scylla/NativeWinApi.cpp b/Scylla/NativeWinApi.cpp index b4e1779..c1da6ba 100644 --- a/Scylla/NativeWinApi.cpp +++ b/Scylla/NativeWinApi.cpp @@ -1,66 +1,68 @@ #include "NativeWinApi.h" def_NtCreateThreadEx NativeWinApi::NtCreateThreadEx = 0; def_NtDuplicateObject NativeWinApi::NtDuplicateObject = 0; def_NtOpenProcess NativeWinApi::NtOpenProcess = 0; def_NtOpenThread NativeWinApi::NtOpenThread = 0; def_NtQueryObject NativeWinApi::NtQueryObject = 0; def_NtQueryInformationFile NativeWinApi::NtQueryInformationFile = 0; def_NtQueryInformationProcess NativeWinApi::NtQueryInformationProcess = 0; def_NtQueryInformationThread NativeWinApi::NtQueryInformationThread = 0; def_NtQuerySystemInformation NativeWinApi::NtQuerySystemInformation = 0; +def_NtQueryVirtualMemory NativeWinApi::NtQueryVirtualMemory = 0; def_NtResumeThread NativeWinApi::NtResumeThread = 0; def_NtSetInformationThread NativeWinApi::NtSetInformationThread = 0; def_NtTerminateProcess NativeWinApi::NtTerminateProcess = 0; def_RtlNtStatusToDosError NativeWinApi::RtlNtStatusToDosError = 0; void NativeWinApi::initialize() { HMODULE hModuleNtdll = GetModuleHandle(L"ntdll.dll"); if (!hModuleNtdll) { return; } NtCreateThreadEx = (def_NtCreateThreadEx)GetProcAddress(hModuleNtdll, "NtCreateThreadEx"); NtDuplicateObject = (def_NtDuplicateObject)GetProcAddress(hModuleNtdll, "NtDuplicateObject"); NtOpenProcess = (def_NtOpenProcess)GetProcAddress(hModuleNtdll, "NtOpenProcess"); NtOpenThread = (def_NtOpenThread)GetProcAddress(hModuleNtdll, "NtOpenThread"); NtQueryObject = (def_NtQueryObject)GetProcAddress(hModuleNtdll, "NtQueryObject"); NtQueryInformationFile = (def_NtQueryInformationFile)GetProcAddress(hModuleNtdll, "NtQueryInformationFile"); NtQueryInformationProcess = (def_NtQueryInformationProcess)GetProcAddress(hModuleNtdll, "NtQueryInformationProcess"); NtQueryInformationThread = (def_NtQueryInformationThread)GetProcAddress(hModuleNtdll, "NtQueryInformationThread"); NtQuerySystemInformation = (def_NtQuerySystemInformation)GetProcAddress(hModuleNtdll, "NtQuerySystemInformation"); + NtQueryVirtualMemory = (def_NtQueryVirtualMemory)GetProcAddress(hModuleNtdll, "NtQueryVirtualMemory"); NtResumeThread = (def_NtResumeThread)GetProcAddress(hModuleNtdll, "NtResumeThread"); NtSetInformationThread = (def_NtSetInformationThread)GetProcAddress(hModuleNtdll, "NtSetInformationThread"); NtTerminateProcess = (def_NtTerminateProcess)GetProcAddress(hModuleNtdll, "NtTerminateProcess"); RtlNtStatusToDosError = (def_RtlNtStatusToDosError)GetProcAddress(hModuleNtdll, "RtlNtStatusToDosError"); } PPEB NativeWinApi::getCurrentProcessEnvironmentBlock() { return getProcessEnvironmentBlockAddress(GetCurrentProcess()); } PPEB NativeWinApi::getProcessEnvironmentBlockAddress(HANDLE processHandle) { ULONG lReturnLength = 0; PROCESS_BASIC_INFORMATION processBasicInformation; if ((NtQueryInformationProcess(processHandle,ProcessBasicInformation,&processBasicInformation,sizeof(PROCESS_BASIC_INFORMATION),&lReturnLength) >= 0) && (lReturnLength == sizeof(PROCESS_BASIC_INFORMATION))) { //printf("NtQueryInformationProcess success %d\n",sizeof(PROCESS_BASIC_INFORMATION)); return processBasicInformation.PebBaseAddress; } else { //printf("NtQueryInformationProcess failed %d vs %d\n",lReturnLength,sizeof(PROCESS_BASIC_INFORMATION)); return 0; } } \ No newline at end of file diff --git a/Scylla/NativeWinApi.h b/Scylla/NativeWinApi.h index d356994..d53d4ec 100644 --- a/Scylla/NativeWinApi.h +++ b/Scylla/NativeWinApi.h @@ -1,261 +1,284 @@ #pragma once #include #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define DUPLICATE_SAME_ATTRIBUTES 0x00000004 #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemNextEventIdInformation, SystemEventIdsInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemPlugPlayBusInformation, SystemDockInformation, SystemPowerInformation2, SystemProcessorSpeedInformation, SystemCurrentTimeZoneInformation, SystemLookasideInformation } SYSTEM_INFORMATION_CLASS; typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; typedef struct _FILE_NAME_INFORMATION { // Information Classes 9 and 21 ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAME_INFORMATION; typedef enum _FILE_INFORMATION_CLASS { FileNameInformation=9, } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _CLIENT_ID{ HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; #define InitializeObjectAttributes(p,n,a,r,s) \ { \ (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ (p)->ObjectName = n; \ (p)->Attributes = a; \ (p)->RootDirectory = r; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } typedef struct _OBJECT_ATTRIBUTES { ULONG Length; PVOID RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef enum _OBJECT_INFORMATION_CLASS { ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectAllInformation, ObjectDataInformation } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; typedef enum _THREADINFOCLASS { ThreadBasicInformation, ThreadTimes, ThreadPriority, ThreadBasePriority, ThreadAffinityMask, ThreadImpersonationToken, ThreadDescriptorTableEntry, ThreadEnableAlignmentFaultFixup, ThreadEventPair_Reusable, ThreadQuerySetWin32StartAddress, ThreadZeroTlsCell, ThreadPerformanceCount, ThreadAmILastThread, ThreadIdealProcessor, ThreadPriorityBoost, ThreadSetTlsArrayAddress, ThreadIsIoPending, ThreadHideFromDebugger, ThreadBreakOnTermination, MaxThreadInfoClass } THREADINFOCLASS; +// +// Memory Information Classes for NtQueryVirtualMemory +// +typedef enum _MEMORY_INFORMATION_CLASS { + MemoryBasicInformation, + MemoryWorkingSetList, + MemorySectionName, + MemoryBasicVlmInformation +} MEMORY_INFORMATION_CLASS; + typedef enum _PROCESSINFOCLASS { ProcessBasicInformation, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters, ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, ProcessEnableAlignmentFaultFixup, ProcessPriorityClass, ProcessWx86Information, ProcessHandleCount, ProcessAffinityMask, ProcessPriorityBoost, ProcessDeviceMap, ProcessSessionInformation, ProcessForegroundInformation, ProcessWow64Information, ProcessImageFileName, ProcessLUIDDeviceMapsEnabled, ProcessBreakOnTermination, ProcessDebugObjectHandle, ProcessDebugFlags, ProcessHandleTracing, ProcessIoPriority, ProcessExecuteFlags, ProcessResourceManagement, ProcessCookie, ProcessImageInformation, MaxProcessInfoClass } PROCESSINFOCLASS; typedef struct _PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; PVOID Reserved2[10]; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; BYTE Reserved4[104]; PVOID Reserved5[52]; PVOID PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1]; ULONG SessionId; } PEB, *PPEB; typedef struct _PROCESS_BASIC_INFORMATION { PVOID Reserved1; PPEB PebBaseAddress; PVOID Reserved2[2]; ULONG_PTR UniqueProcessId; PVOID Reserved3; } PROCESS_BASIC_INFORMATION; +typedef struct _MEMORY_WORKING_SET_LIST +{ + ULONG NumberOfPages; + ULONG WorkingSetList[1]; +} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; + +typedef struct _MEMORY_SECTION_NAME +{ + UNICODE_STRING SectionFileName; +} MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME; + + typedef NTSTATUS (WINAPI *def_NtTerminateProcess)(HANDLE ProcessHandle, NTSTATUS ExitStatus); typedef NTSTATUS (WINAPI *def_NtQueryObject)(HANDLE Handle,OBJECT_INFORMATION_CLASS ObjectInformationClass,PVOID ObjectInformation,ULONG ObjectInformationLength,PULONG ReturnLength); typedef NTSTATUS (WINAPI *def_NtDuplicateObject)(HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, PHANDLE TargetHandle, ACCESS_MASK DesiredAccess, BOOLEAN InheritHandle, ULONG Options ); typedef NTSTATUS (WINAPI *def_NtQueryInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); typedef NTSTATUS (WINAPI *def_NtQueryInformationThread)(HANDLE ThreadHandle,THREADINFOCLASS ThreadInformationClass,PVOID ThreadInformation,ULONG ThreadInformationLength,PULONG ReturnLength); typedef NTSTATUS (WINAPI *def_NtQueryInformationProcess)(HANDLE ProcessHandle,PROCESSINFOCLASS ProcessInformationClass,PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength); typedef NTSTATUS (WINAPI *def_NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength, PULONG ReturnLength); +typedef NTSTATUS (WINAPI *def_NtQueryVirtualMemory)(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, ULONG Length, PULONG ResultLength); typedef NTSTATUS (WINAPI *def_NtOpenProcess)(PHANDLE ProcessHandle, ACCESS_MASK AccessMask, PVOID ObjectAttributes, PCLIENT_ID ClientId ); typedef NTSTATUS (WINAPI *def_NtOpenThread)(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId); typedef NTSTATUS (WINAPI *def_NtResumeThread)(HANDLE ThreadHandle, PULONG SuspendCount); typedef NTSTATUS (WINAPI *def_NtSetInformationThread)(HANDLE ThreadHandle,THREADINFOCLASS ThreadInformationClass,PVOID ThreadInformation,ULONG ThreadInformationLength); typedef NTSTATUS (WINAPI *def_NtCreateThreadEx)(PHANDLE hThread,ACCESS_MASK DesiredAccess,LPVOID ObjectAttributes,HANDLE ProcessHandle,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,BOOL CreateSuspended,ULONG StackZeroBits,LPVOID SizeOfStackCommit,LPVOID SizeOfStackReserve,LPVOID lpBytesBuffer); - typedef ULONG (WINAPI *def_RtlNtStatusToDosError)(NTSTATUS Status); class NativeWinApi { public: static def_NtCreateThreadEx NtCreateThreadEx; static def_NtDuplicateObject NtDuplicateObject; static def_NtOpenProcess NtOpenProcess; static def_NtOpenThread NtOpenThread; static def_NtQueryObject NtQueryObject; static def_NtQueryInformationFile NtQueryInformationFile; static def_NtQueryInformationProcess NtQueryInformationProcess; static def_NtQueryInformationThread NtQueryInformationThread; static def_NtQuerySystemInformation NtQuerySystemInformation; + static def_NtQueryVirtualMemory NtQueryVirtualMemory; static def_NtResumeThread NtResumeThread; static def_NtSetInformationThread NtSetInformationThread; static def_NtTerminateProcess NtTerminateProcess; static def_RtlNtStatusToDosError RtlNtStatusToDosError; static void initialize(); static PPEB getCurrentProcessEnvironmentBlock(); static PPEB getProcessEnvironmentBlockAddress(HANDLE processHandle); }; diff --git a/Scylla/PeDump.cpp b/Scylla/PeDump.cpp index 27aab73..86d9fb7 100644 --- a/Scylla/PeDump.cpp +++ b/Scylla/PeDump.cpp @@ -1,437 +1,437 @@ #include "PeDump.h" #include "ProcessAccessHelp.h" #include "Scylla.h" #include "Architecture.h" bool PeDump::useHeaderFromDisk = true; bool PeDump::appendOverlayData = true; //#define DEBUG_COMMENTS bool PeDump::fillPeHeaderStructs(bool fromDisk) { DWORD dwSize = ProcessAccessHelp::PE_HEADER_BYTES_COUNT; if (dwSize > sizeOfImage) { dwSize = (DWORD)sizeOfImage; } headerData = new BYTE[dwSize]; if (!headerData) return false; if (fromDisk) { //from disk if (!ProcessAccessHelp::readHeaderFromFile(headerData, dwSize, fullpath)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readHeaderFromFile failed - %X %s", dwSize, fullpath); #endif return false; } } else { //from memory if (!ProcessAccessHelp::readMemoryFromProcess(imageBase, dwSize, headerData)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readMemoryFromProcess failed - " PRINTF_DWORD_PTR_FULL L" %X " PRINTF_DWORD_PTR_FULL, imageBase, dwSize, headerData); #endif return false; } } pDOSHeader = (PIMAGE_DOS_HEADER)headerData; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)headerData + (DWORD_PTR)pDOSHeader->e_lfanew); pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader); return true; } bool PeDump::validateHeaders() { if ((pDOSHeader != 0) && (pDOSHeader->e_magic == IMAGE_DOS_SIGNATURE) && (pNTHeader->Signature == IMAGE_NT_SIGNATURE)) { #ifdef _WIN64 if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) #else if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) #endif { return true; } else { return false; } } else { return false; } } bool PeDump::dumpCompleteProcessToDisk(const WCHAR * dumpFilePath) { if (!fillPeHeaderStructs(useHeaderFromDisk)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> fillPeHeaderStructs failed"); #endif return false; } if (!validateHeaders()) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> validateHeaders failed"); #endif return false; } dumpData = new BYTE[sizeOfImage]; if (dumpData) { - if (!ProcessAccessHelp::readMemoryFromProcess(imageBase,sizeOfImage,dumpData)) + if (!ProcessAccessHelp::readMemoryPartlyFromProcess(imageBase,sizeOfImage,dumpData)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> readMemoryFromProcess failed"); #endif return false; } else { fixDump(dumpData); if (saveDumpToDisk(dumpFilePath, dumpData, (DWORD)sizeOfImage)) { if (appendOverlayData) { appendOverlayDataToDump(dumpFilePath); } //printf("dump success\n"); return true; } else { return false; } } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> new BYTE[sizeOfImage] failed %X", sizeOfImage); #endif return false; } } bool PeDump::appendOverlayDataToDump(const WCHAR *dumpFilePath) { DWORD_PTR offset = 0; DWORD size = 0; if (getOverlayData(fullpath,&offset,&size)) { if (offset == 0) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"appendOverlayDataToDump :: No overlay exists"); #endif return true; } else { if (copyFileDataFromOffset(fullpath, dumpFilePath, offset, size)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay success"); #endif return true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay failed"); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"appendOverlayDataToDump :: getOverlayData failed"); #endif return false; } } bool PeDump::copyFileDataFromOffset(const WCHAR * sourceFile, const WCHAR * destFile, DWORD_PTR fileOffset, DWORD dwSize) { HANDLE hSourceFile, hDestFile; BYTE * dataBuffer = 0; bool retValue = false; hSourceFile = CreateFile(sourceFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hSourceFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open source file"); #endif return false; } hDestFile = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(hSourceFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open destination file"); #endif CloseHandle(hSourceFile); return false; } dataBuffer = new BYTE[dwSize]; if (ProcessAccessHelp::readMemoryFromFile(hSourceFile, (LONG)fileOffset, dwSize, dataBuffer)) { if (ProcessAccessHelp::writeMemoryToFileEnd(hDestFile,dwSize,dataBuffer)) { retValue = true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"copyFileDataFromOffset :: writeMemoryToFileEnd failed"); #endif retValue = false; } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"copyFileDataFromOffset :: readMemoryFromFile failed to read from source file"); #endif retValue = false; } delete [] dataBuffer; CloseHandle(hSourceFile); CloseHandle(hDestFile); return retValue; } void PeDump::fixDump(BYTE * dumpBuffer) { int counter = 0; PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)dumpBuffer; PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD_PTR)dumpBuffer + pDos->e_lfanew); PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(pNt); fixNtHeaderForDump(pNt, pNTHeader); do { fixSectionHeaderForDump(pSec, pSectionHeader); pSectionHeader++; pSec++; counter++; } while (counter < pNt->FileHeader.NumberOfSections); } void PeDump::fixBadNtHeaderValues(PIMAGE_NT_HEADERS pNtHead) { //maybe imagebase in process is not real imagebase pNtHead->OptionalHeader.ImageBase = imageBase; pNtHead->OptionalHeader.AddressOfEntryPoint = (DWORD)(entryPoint - imageBase); pNtHead->OptionalHeader.SizeOfImage = sizeOfImage; } void PeDump::fixSectionHeaderForDump(PIMAGE_SECTION_HEADER oldSecHead, PIMAGE_SECTION_HEADER newSecHead) { memcpy_s(oldSecHead->Name, IMAGE_SIZEOF_SHORT_NAME, newSecHead->Name, IMAGE_SIZEOF_SHORT_NAME); oldSecHead->Characteristics = newSecHead->Characteristics; oldSecHead->Misc.VirtualSize = newSecHead->Misc.VirtualSize; oldSecHead->VirtualAddress = newSecHead->VirtualAddress; oldSecHead->SizeOfRawData = newSecHead->Misc.VirtualSize; oldSecHead->PointerToRawData = newSecHead->VirtualAddress; } void PeDump::fixNtHeaderForDump(PIMAGE_NT_HEADERS oldNtHead, PIMAGE_NT_HEADERS newNtHead) { //some special fixBadNtHeaderValues(newNtHead); //fix FileHeader oldNtHead->FileHeader.NumberOfSections = newNtHead->FileHeader.NumberOfSections; //fix OptionalHeader oldNtHead->OptionalHeader.ImageBase = newNtHead->OptionalHeader.ImageBase; oldNtHead->OptionalHeader.SizeOfImage = newNtHead->OptionalHeader.SizeOfImage; oldNtHead->OptionalHeader.BaseOfCode = newNtHead->OptionalHeader.BaseOfCode; oldNtHead->OptionalHeader.AddressOfEntryPoint = newNtHead->OptionalHeader.AddressOfEntryPoint; oldNtHead->OptionalHeader.SectionAlignment = newNtHead->OptionalHeader.SectionAlignment; oldNtHead->OptionalHeader.FileAlignment = newNtHead->OptionalHeader.SectionAlignment; //deleted in x64 PE #ifndef _WIN64 oldNtHead->OptionalHeader.BaseOfData = newNtHead->OptionalHeader.BaseOfData; #endif } bool PeDump::saveDumpToDisk(const WCHAR * dumpFilePath, BYTE *dumpBuffer, DWORD dumpSize) { DWORD lpNumberOfBytesWritten = 0; bool retValue = false; HANDLE hFile = CreateFile(dumpFilePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"saveDumpToDisk :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif retValue = false; } else { if (WriteFile(hFile, dumpBuffer, dumpSize, &lpNumberOfBytesWritten, 0)) { if (lpNumberOfBytesWritten != dumpSize) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"saveDumpToDisk :: lpNumberOfBytesWritten != dumpSize %d %d", lpNumberOfBytesWritten,dumpSize); #endif retValue = false; } else { retValue = true; } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"saveDumpToDisk :: WriteFile failed %u",GetLastError()); #endif retValue = false; } CloseHandle(hFile); } return retValue; } bool PeDump::getOverlayData(const WCHAR * filepath, DWORD_PTR * overlayFileOffset, DWORD * overlaySize) { LONGLONG fileSize = 0; DWORD dwSize = 0; DWORD bufferSize = 1000; BYTE *buffer = 0; bool returnValue = 0; PIMAGE_DOS_HEADER pDOSh = 0; PIMAGE_NT_HEADERS pNTh = 0; PIMAGE_SECTION_HEADER pSech = 0; int counter = 0; DWORD calcSize = 0; HANDLE hFile = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if( hFile == INVALID_HANDLE_VALUE ) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"getOverlayData :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif returnValue = false; } else { fileSize = ProcessAccessHelp::getFileSize(hFile); if (fileSize > 0) { if (fileSize > bufferSize) { dwSize = bufferSize; } else { dwSize = (DWORD)(fileSize - 1); } buffer = new BYTE[dwSize]; if (ProcessAccessHelp::readMemoryFromFile(hFile, 0, dwSize, buffer)) { pDOSh = (PIMAGE_DOS_HEADER)buffer; pNTh = (PIMAGE_NT_HEADERS)((DWORD_PTR)buffer + pDOSh->e_lfanew); //first section pSech = IMAGE_FIRST_SECTION(pNTh); counter = 1; //get last section while(counter < pNTh->FileHeader.NumberOfSections) { counter++; pSech++; } //printf("PointerToRawData %X\nSizeOfRawData %X\nfile size %X\n",pSech->PointerToRawData,pSech->SizeOfRawData,pSech->PointerToRawData+pSech->SizeOfRawData); calcSize = pSech->PointerToRawData + pSech->SizeOfRawData; if (calcSize < fileSize) { //overlay found *overlayFileOffset = calcSize; *overlaySize = (DWORD)(fileSize - calcSize); } else { *overlayFileOffset = 0; *overlaySize = 0; } returnValue = true; } else { returnValue = false; } delete [] buffer; } else { returnValue = false; } CloseHandle(hFile); } return returnValue; } \ No newline at end of file diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp index 75616c3..81a41b2 100644 --- a/Scylla/PickDllGui.cpp +++ b/Scylla/PickDllGui.cpp @@ -1,144 +1,144 @@ #include "PickDllGui.h" -#include "definitions.h" +#include "Architecture.h" PickDllGui::PickDllGui(std::vector &moduleList) : moduleList(moduleList) { selectedModule = 0; prevColumn = -1; ascending = true; } BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls DlgResize_Init(true, true); addColumnsToModuleList(ListDLLSelect); displayModuleList(ListDLLSelect); CenterWindow(); return TRUE; } LRESULT PickDllGui::OnListDllColumnClicked(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 ListDLLSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); return 0; } LRESULT PickDllGui::OnListDllDoubleClick(NMHDR* pnmh) { NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh; LVHITTESTINFO hti; hti.pt = ia->ptAction; int clicked = ListDLLSelect.HitTest(&hti); if(clicked != -1) { selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(clicked); EndDialog(1); } 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()); - swprintf_s(temp, TEXT(PRINTF_DWORD_PTR_FULL), iter->modBaseAddr); + swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->modBaseAddr); list.SetItemText(count, COL_IMAGEBASE, temp); swprintf_s(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/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp index 00ca738..7ba0070 100644 --- a/Scylla/ProcessAccessHelp.cpp +++ b/Scylla/ProcessAccessHelp.cpp @@ -1,729 +1,803 @@ #include "ProcessAccessHelp.h" #include "Scylla.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 Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", 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 Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"openProcessHandle :: Wrong PID, PID %X", 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 Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus)); #endif return 0; } } void ProcessAccessHelp::closeProcessHandle() { CloseHandle(hProcess); hProcess = 0; moduleList.clear(); targetImageBase = 0; selectedModule = 0; } +bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) +{ + SIZE_T lpNumberOfBytesRead = 0; + DWORD_PTR addressPart = 0; + DWORD_PTR readBytes = 0; + DWORD_PTR bytesToRead = 0; + MEMORY_BASIC_INFORMATION memBasic = {0}; + bool returnValue = false; + + if (!hProcess) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL"); +#endif + return returnValue; + } + + if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) + { + addressPart = address; + + do + { + if (!VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)addressPart,&memBasic,sizeof(memBasic))) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart,size, GetLastError()); +#endif + break; + } + + bytesToRead = memBasic.RegionSize; + + if ( (readBytes+bytesToRead) > size) + { + bytesToRead = size - readBytes; + } + + if (memBasic.State != MEM_FREE && memBasic.State != MEM_RESERVE) + { + if (!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes)) ) + { + break; + } + } + else + { + ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes),bytesToRead); + } + + + readBytes += bytesToRead; + + addressPart += memBasic.RegionSize; + + } while (readBytes < size); + + if (readBytes == size) + { + returnValue = true; + } + + } + else + { + returnValue = true; + } + + return returnValue; +} + 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 Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL"); #endif return returnValue; } if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError()); +#endif if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u", address,size, GetLastError()); #endif returnValue = false; } else { if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", 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 Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes", 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 Scylla::debugLog.log(L"decomposeMemory :: distorm_decompose == DECRES_INPUTERR"); #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 Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR"); #endif return false; } else if (res == DECRES_SUCCESS) { //printf("disassembleMemory :: res == DECRES_SUCCESS\n"); return true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"disassembleMemory :: res == %d", 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 Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError()); #endif return 0; } else { return lpFileSize.QuadPart; } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid"); #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 Scylla::debugLog.log(L"readMemoryFromFile :: SetFilePointer failed error %u", dwError); #endif return false; } else { if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0)) { return true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid"); #endif return false; } } bool ProcessAccessHelp::writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer) { HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { return writeMemoryToFile(hFile,0,size,dataBuffer); } else { return false; } } bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID 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 Scylla::debugLog.log(L"writeMemoryToFile :: SetFilePointer failed error %u", dwError); #endif return false; } else { if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0)) { return true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"writeMemoryToFile :: hFile invalid"); #endif return false; } } bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID 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 Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"writeMemoryToFileEnd :: hFile invalid"); #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 Scylla::debugLog.log(L"readHeaderFromFile :: INVALID_HANDLE_VALUE %u", 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 Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif return NULL; } HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL); CloseHandle(hFile); if( hMappedFile == NULL ) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL"); #endif return NULL; } if (GetLastError() == ERROR_ALREADY_EXISTS) { #ifdef DEBUG_COMMENTS - Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS); + Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS"); #endif return NULL; } LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0); if( addrMappedDll == NULL ) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL"); #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 Scylla::debugLog.log(L"getProcessByName :: Error getting first Process"); #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(L"\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, 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 Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", 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 Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", 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; } 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, L".bak"); retValue = CopyFile(filePath, backupFile, FALSE); if (!retValue) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError()); #endif } delete [] backupFile; return retValue != 0; } diff --git a/Scylla/ProcessAccessHelp.h b/Scylla/ProcessAccessHelp.h index 5b49e29..c5fc3c0 100644 --- a/Scylla/ProcessAccessHelp.h +++ b/Scylla/ProcessAccessHelp.h @@ -1,212 +1,217 @@ #pragma once #include #include #include /************************************************************************/ /* distorm */ /************************************************************************/ #include // 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]; WORD hint; DWORD_PTR va; DWORD_PTR rva; WORD 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 size_t 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 /* * 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 target process and ignore no data pages + */ + static bool readMemoryPartlyFromProcess(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, LPCVOID dataBuffer); /* * Write memory to new file */ static bool writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer); /* * Write memory to file end */ static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID 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 */ static 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 DWORD getEntryPointFromFile(const WCHAR * filePath); static bool createBackupFile(const WCHAR * filePath); }; diff --git a/Scylla/ProcessLister.cpp b/Scylla/ProcessLister.cpp index c793ae1..1bb5c13 100644 --- a/Scylla/ProcessLister.cpp +++ b/Scylla/ProcessLister.cpp @@ -1,372 +1,331 @@ #include "ProcessLister.h" #include "SystemInformation.h" #include "Logger.h" #include "ProcessAccessHelp.h" #include //#define DEBUG_COMMENTS def_IsWow64Process ProcessLister::_IsWow64Process = 0; std::vector& ProcessLister::getProcessList() { return processList; } bool ProcessLister::isWindows64() { #ifdef _WIN64 //compiled 64bit application return true; #else //32bit exe, check wow64 BOOL bIsWow64 = FALSE; //not available in all windows operating systems //Minimum supported client: Windows Vista, Windows XP with SP2 //Minimum supported server: Windows Server 2008, Windows Server 2003 with SP1 if (_IsWow64Process) { _IsWow64Process(GetCurrentProcess(), &bIsWow64); if (bIsWow64 == TRUE) { return true; } else { return false; } } else { return false; } #endif } - -void ProcessLister::initDeviceNameList() -{ - TCHAR shortName[3] = {0}; - TCHAR longName[MAX_PATH] = {0}; - HardDisk hardDisk; - - shortName[1] = L':'; - - for ( WCHAR shortD = L'a'; shortD < L'z'; shortD++ ) - { - shortName[0] = shortD; - if (QueryDosDeviceW( shortName, longName, MAX_PATH ) > 0) - { - hardDisk.shortName[0] = towupper(shortD); - hardDisk.shortName[1] = L':'; - hardDisk.shortName[2] = 0; - - hardDisk.longNameLength = wcslen(longName); - - wcscpy_s(hardDisk.longName, longName); - deviceNameList.push_back(hardDisk); - } - } -} - //only needed in windows xp DWORD ProcessLister::setDebugPrivileges() { DWORD err = 0; HANDLE hToken = 0; TOKEN_PRIVILEGES Debug_Privileges = {0}; if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Debug_Privileges.Privileges[0].Luid)) { return GetLastError(); } if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { err = GetLastError(); if(hToken) CloseHandle(hToken); return err; } Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Debug_Privileges.PrivilegeCount = 1; AdjustTokenPrivileges(hToken, false, &Debug_Privileges, 0, NULL, NULL); CloseHandle(hToken); return GetLastError(); } /************************************************************************/ /* Check if a process is 32 or 64bit */ /************************************************************************/ ProcessType ProcessLister::checkIsProcess64(DWORD dwPID) { HANDLE hProcess; BOOL bIsWow64 = FALSE; if (dwPID == 0) { //unknown return PROCESS_UNKNOWN; } //hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, NULL, dwPID); hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, dwPID); if(!hProcess) { //missing rights return PROCESS_MISSING_RIGHTS; } if (!isWindows64()) { //32bit win can only run 32bit process CloseHandle(hProcess); return PROCESS_32; } _IsWow64Process(hProcess, &bIsWow64); CloseHandle(hProcess); if (bIsWow64 == FALSE) { //process not running under wow return PROCESS_64; } else { //process running under wow -> 32bit return PROCESS_32; } } bool ProcessLister::getAbsoluteFilePath(Process * process) { WCHAR processPath[MAX_PATH]; HANDLE hProcess; //hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, NULL, process->PID); hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION, process->PID); if(!hProcess) { //missing rights return false; } if (GetProcessImageFileName(hProcess, processPath, _countof(processPath)) > 0) { CloseHandle(hProcess); - if (!resolveDeviceLongNameToShort(processPath, process->fullPath)) + if (!deviceNameResolver->resolveDeviceLongNameToShort(processPath, process->fullPath)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s", processPath); #endif } return true; } else { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"getAbsoluteFilePath :: GetProcessImageFileName failed %u", GetLastError()); #endif CloseHandle(hProcess); return false; } } std::vector& ProcessLister::getProcessListSnapshot() { HANDLE hProcessSnap; ProcessType processType; PROCESSENTRY32 pe32; HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32 = {0}; Process process; if (!processList.empty()) { //clear elements, but keep reversed memory processList.clear(); } else { //first time, reserve memory processList.reserve(34); } hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { return processList; } pe32.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap); return processList; } do { //filter process list if (pe32.th32ProcessID > 4) { processType = checkIsProcess64(pe32.th32ProcessID); if (processType != PROCESS_MISSING_RIGHTS) { #ifdef _WIN64 if (processType == PROCESS_64) #else if (processType == PROCESS_32) #endif { process.PID = pe32.th32ProcessID; hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process.PID); if(hModuleSnap != INVALID_HANDLE_VALUE) { me32.dwSize = sizeof(MODULEENTRY32); Module32First(hModuleSnap, &me32); process.imageBase = (DWORD_PTR)me32.hModule; process.imageSize = me32.modBaseSize; CloseHandle(hModuleSnap); } wcscpy_s(process.filename, pe32.szExeFile); getAbsoluteFilePath(&process); processList.push_back(process); } } } } while(Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); //reverse process list std::reverse(processList.begin(), processList.end()); return processList; } void ProcessLister::getAllModuleInformation() { /*for (std::size_t i = 0; i < processList.size(); i++) { getModuleInformationByProcess(&processList[i]); }*/ } void ProcessLister::getModuleInformationByProcess(Process *process) { /* MODULEENTRY32 me32 = {0}; HANDLE hModuleSnap = INVALID_HANDLE_VALUE; char temp[111]; if (process->PID == 0) { MessageBox(0, "PID == NULL","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); return; } #ifdef _WIN64 if (!process->is64BitProcess) { //MessageBox(hWndDlg, "I'm a x64 process and you're trying to access a 32-bit process!","displayModuleList", MB_OK); return; } #else if (process->is64BitProcess) { //MessageBox(hWndDlg, "I'm a 32-bit process and you're trying to access a x64 process!","displayModuleList", MB_OK); return; } #endif hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process->PID); if(hModuleSnap == INVALID_HANDLE_VALUE) { sprintf_s(temp, "GetLastError %d",GetLastError()); MessageBox(0, temp,"ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); return; } me32.dwSize = sizeof(MODULEENTRY32); if(!Module32First(hModuleSnap, &me32)) { MessageBox(0, "Module32First error","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); CloseHandle(hModuleSnap); return; } do { ModuleInfo moduleInfo; if (!_strnicmp(me32.szExePath,"\\Systemroot",11)) { char * path = (char *)malloc(MAX_PATH); sprintf_s(path"%s\\%s",getenv("SystemRoot"),(me32.szExePath + 12)); strcpy_s(moduleInfo.fullPath,MAX_PATH, path); free(path); } else if(!_strnicmp(me32.szExePath,"\\??\\",4)) { strcpy_s(moduleInfo.fullPath,MAX_PATH, (me32.szExePath + 4)); } else { strcpy_s(moduleInfo.fullPath,MAX_PATH,me32.szExePath); } moduleInfo.hModule = (DWORD_PTR)me32.hModule; moduleInfo.modBaseSize = me32.modBaseSize; moduleInfo.modBaseAddr = (DWORD_PTR)me32.modBaseAddr; process->moduleList[moduleInfo.hModule] = moduleInfo; } while(Module32Next(hModuleSnap, &me32)); CloseHandle(hModuleSnap);*/ } - -bool ProcessLister::resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ) -{ - for (unsigned int i = 0; i < deviceNameList.size(); i++) - { - if (!_wcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength)) - { - wcscpy_s(targetPath, MAX_PATH,deviceNameList[i].shortName); - wcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength); - return true; - } - } - - return false; -} diff --git a/Scylla/ProcessLister.h b/Scylla/ProcessLister.h index a93630e..1664084 100644 --- a/Scylla/ProcessLister.h +++ b/Scylla/ProcessLister.h @@ -1,70 +1,65 @@ #pragma once #include #include #include #include +#include "DeviceNameResolver.h" + typedef BOOL (WINAPI *def_IsWow64Process)(HANDLE hProcess,PBOOL Wow64Process); class Process { public: DWORD PID; DWORD_PTR imageBase; DWORD entryPoint; //without imagebase DWORD imageSize; WCHAR filename[MAX_PATH]; WCHAR fullPath[MAX_PATH]; Process() { PID = 0; } }; -class HardDisk { -public: - WCHAR shortName[3]; - WCHAR longName[MAX_PATH]; - size_t longNameLength; -}; - enum ProcessType { PROCESS_UNKNOWN, PROCESS_MISSING_RIGHTS, PROCESS_32, PROCESS_64 }; class ProcessLister { public: static def_IsWow64Process _IsWow64Process; ProcessLister() { - initDeviceNameList(); + deviceNameResolver = new DeviceNameResolver(); _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"); } + ~ProcessLister() + { + delete deviceNameResolver; + } std::vector& getProcessList(); static bool isWindows64(); static DWORD setDebugPrivileges(); std::vector& ProcessLister::getProcessListSnapshot(); private: std::vector processList; - std::vector deviceNameList; + DeviceNameResolver * deviceNameResolver; ProcessType checkIsProcess64(DWORD dwPID); - void initDeviceNameList(); - - bool getAbsoluteFilePath(Process * process); void getAllModuleInformation(); void getModuleInformationByProcess(Process *process); - bool resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ); }; \ No newline at end of file diff --git a/Scylla/Scylla.h b/Scylla/Scylla.h index bf02bc6..aff4d13 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 Beta" +#define APPVERSION_S "v0.6 Beta 2" #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[]; }; diff --git a/Scylla/Scylla.vcxproj b/Scylla/Scylla.vcxproj index 8b449d0..7238499 100644 --- a/Scylla/Scylla.vcxproj +++ b/Scylla/Scylla.vcxproj @@ -1,236 +1,248 @@  Debug Win32 Debug x64 Release Win32 Release x64 {710434C9-FC4B-4F1D-B318-E10ADC78499F} Win32Proj Scylla Application true Unicode + v90 Application true Unicode Application false true Unicode - v100 + v90 Application false true Unicode true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ + $(SolutionDir)WTL81_9127_Include;$(IncludePath) true + $(SolutionDir)WTL81_9127_Include;$(IncludePath) false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ + $(SolutionDir)WTL81_9127_Include;$(IncludePath) false + $(SolutionDir)WTL81_9127_Include;$(IncludePath) Level3 Disabled WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) + $(SolutionDir)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) Windows true - $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;psapi.lib;imagehlp.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' + true + $(TargetDir)$(TargetName).map Level3 Disabled WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) + $(SolutionDir)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) Windows true - $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;psapi.lib;imagehlp.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded - $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) + $(SolutionDir)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) true + Speed Windows false true true - $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;psapi.lib;imagehlp.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded - $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) + $(SolutionDir)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) true Windows false true true - $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;psapi.lib;imagehlp.lib;%(AdditionalDependencies) + $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' + + + + \ No newline at end of file diff --git a/Scylla/resource.h b/Scylla/resource.h index 2420cac..aeddc30 100644 Binary files a/Scylla/resource.h and b/Scylla/resource.h differ