diff --git a/Scylla/FunctionExport.cpp b/Scylla/FunctionExport.cpp index 63285fe..083643b 100644 --- a/Scylla/FunctionExport.cpp +++ b/Scylla/FunctionExport.cpp @@ -1,178 +1,176 @@ #include #include "PeParser.h" #include "ProcessAccessHelp.h" #include "Scylla.h" #include "Architecture.h" +#include "FunctionExport.h" -BOOL DumpProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); - -BOOL WINAPI ScyllaDumpCurrentProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); -BOOL WINAPI ScyllaDumpCurrentProcessA(const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); - -BOOL WINAPI ScyllaDumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); -BOOL WINAPI ScyllaDumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); - -BOOL WINAPI ScyllaRebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); -BOOL WINAPI ScyllaRebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); - -WCHAR * WINAPI ScyllaVersionInformationW(); -char * WINAPI ScyllaVersionInformationA(); -DWORD WINAPI ScyllaVersionInformationDword(); +extern HINSTANCE hDllModule; WCHAR * WINAPI ScyllaVersionInformationW() { return APPNAME L" " ARCHITECTURE L" " APPVERSION; } char * WINAPI ScyllaVersionInformationA() { return APPNAME_S " " ARCHITECTURE_S " " APPVERSION_S; } DWORD WINAPI ScyllaVersionInformationDword() { return APPVERSIONDWORD; } BOOL DumpProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult) { PeParser * peFile = 0; if (fileToDump) { peFile = new PeParser(fileToDump, true); } else { peFile = new PeParser(imagebase, true); } return peFile->dumpProcess(imagebase, entrypoint, fileResult); } BOOL WINAPI ScyllaRebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup) { if (createBackup) { if (!ProcessAccessHelp::createBackupFile(fileToRebuild)) { return FALSE; } } PeParser peFile(fileToRebuild, true); if (peFile.readPeSectionsFromFile()) { peFile.setDefaultFileAlignment(); if (removeDosStub) { peFile.removeDosStub(); } peFile.alignAllSectionHeaders(); peFile.fixPeHeader(); if (peFile.savePeFileToDisk(fileToRebuild)) { if (updatePeHeaderChecksum) { PeParser::updatePeHeaderChecksum(fileToRebuild, (DWORD)ProcessAccessHelp::getFileSize(fileToRebuild)); } return TRUE; } } return FALSE; } BOOL WINAPI ScyllaRebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup) { WCHAR fileToRebuildW[MAX_PATH]; if (MultiByteToWideChar(CP_ACP, 0, fileToRebuild, -1, fileToRebuildW, _countof(fileToRebuildW)) == 0) { return FALSE; } return ScyllaRebuildFileW(fileToRebuildW, removeDosStub, updatePeHeaderChecksum, createBackup); } BOOL WINAPI ScyllaDumpCurrentProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult) { ProcessAccessHelp::setCurrentProcessAsTarget(); return DumpProcessW(fileToDump, imagebase, entrypoint, fileResult); } BOOL WINAPI ScyllaDumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult) { if (ProcessAccessHelp::openProcessHandle((DWORD)pid)) { return DumpProcessW(fileToDump, imagebase, entrypoint, fileResult); } else { return FALSE; } } BOOL WINAPI ScyllaDumpCurrentProcessA(const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult) { WCHAR fileToDumpW[MAX_PATH]; WCHAR fileResultW[MAX_PATH]; if (fileResult == 0) { return FALSE; } if (MultiByteToWideChar(CP_ACP, 0, fileResult, -1, fileResultW, _countof(fileResultW)) == 0) { return FALSE; } if (fileToDump != 0) { if (MultiByteToWideChar(CP_ACP, 0, fileToDump, -1, fileToDumpW, _countof(fileToDumpW)) == 0) { return FALSE; } return ScyllaDumpCurrentProcessW(fileToDumpW, imagebase, entrypoint, fileResultW); } else { return ScyllaDumpCurrentProcessW(0, imagebase, entrypoint, fileResultW); } } BOOL WINAPI ScyllaDumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult) { WCHAR fileToDumpW[MAX_PATH]; WCHAR fileResultW[MAX_PATH]; if (fileResult == 0) { return FALSE; } if (MultiByteToWideChar(CP_ACP, 0, fileResult, -1, fileResultW, _countof(fileResultW)) == 0) { return FALSE; } if (fileToDump != 0) { if (MultiByteToWideChar(CP_ACP, 0, fileToDump, -1, fileToDumpW, _countof(fileToDumpW)) == 0) { return FALSE; } return ScyllaDumpProcessW(pid, fileToDumpW, imagebase, entrypoint, fileResultW); } else { return ScyllaDumpProcessW(pid, 0, imagebase, entrypoint, fileResultW); } } + + +INT WINAPI ScyllaStartGui(DWORD dwProcessId, HINSTANCE mod) +{ + GUI_DLL_PARAMETER guiParam; + guiParam.dwProcessId = dwProcessId; + guiParam.mod = mod; + + return InitializeGui(hDllModule, (LPARAM)&guiParam); +} \ No newline at end of file diff --git a/Scylla/IATSearch.cpp b/Scylla/IATSearch.cpp index 562350a..c49e7d5 100644 --- a/Scylla/IATSearch.cpp +++ b/Scylla/IATSearch.cpp @@ -1,532 +1,532 @@ #include "IATSearch.h" #include "Scylla.h" #include "Architecture.h" -#define DEBUG_COMMENTS +//#define DEBUG_COMMENTS bool IATSearch::searchImportAddressTableInProcess( DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT, bool advanced ) { DWORD_PTR addressInIAT = 0; *addressIAT = 0; *sizeIAT = 0; if (advanced) { return findIATAdvanced(startAddress, addressIAT, sizeIAT); } addressInIAT = findAPIAddressInIAT(startAddress); if(!addressInIAT) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"searchImportAddressTableInProcess :: addressInIAT not found, startAddress " PRINTF_DWORD_PTR_FULL, startAddress); #endif return false; } else { return findIATStartAndSize(addressInIAT, addressIAT,sizeIAT); } } bool IATSearch::findIATAdvanced( DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT ) { BYTE *dataBuffer; DWORD_PTR baseAddress; SIZE_T memorySize; findExecutableMemoryPagesByStartAddress(startAddress, &baseAddress, &memorySize); if (memorySize == 0) return false; dataBuffer = new BYTE[memorySize]; if (!readMemoryFromProcess((DWORD_PTR)baseAddress, memorySize,dataBuffer)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findAPIAddressInIAT2 :: error reading memory"); #endif return false; } std::set iatPointers; DWORD_PTR next; BYTE * tempBuf = dataBuffer; while(decomposeMemory(tempBuf, memorySize, (DWORD_PTR)baseAddress) && decomposerInstructionsCount != 0) { findIATPointers(iatPointers); next = (DWORD_PTR)(decomposerResult[decomposerInstructionsCount - 1].addr - baseAddress); next += decomposerResult[decomposerInstructionsCount - 1].size; // Advance ptr and recalc offset. tempBuf += next; if (memorySize <= next) { break; } memorySize -= next; baseAddress += next; } if (iatPointers.size() == 0) return false; filterIATPointersList(iatPointers); *addressIAT = *(iatPointers.begin()); - *sizeIAT = *(--iatPointers.end()) - *(iatPointers.begin()) + sizeof(DWORD_PTR); + *sizeIAT = (DWORD)(*(--iatPointers.end()) - *(iatPointers.begin()) + sizeof(DWORD_PTR)); Scylla::windowLog.log(L"IAT Search Advanced: Found %d (0x%X) possible IAT entries.", iatPointers.size(), iatPointers.size()); Scylla::windowLog.log(L"IAT Search Advanced: Possible IAT first " PRINTF_DWORD_PTR_FULL L" last " PRINTF_DWORD_PTR_FULL L" entry.", *(iatPointers.begin()), *(--iatPointers.end())); delete [] dataBuffer; return true; } DWORD_PTR IATSearch::findAPIAddressInIAT(DWORD_PTR startAddress) { const size_t MEMORY_READ_SIZE = 200; BYTE dataBuffer[MEMORY_READ_SIZE]; DWORD_PTR iatPointer = 0; int counter = 0; // to detect stolen api memoryAddress = 0; memorySize = 0; do { counter++; if (!readMemoryFromProcess(startAddress, sizeof(dataBuffer), dataBuffer)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findAPIAddressInIAT :: error reading memory " PRINTF_DWORD_PTR_FULL, startAddress); #endif return 0; } if (decomposeMemory(dataBuffer, sizeof(dataBuffer), startAddress)) { iatPointer = findIATPointer(); if (iatPointer) { if (isIATPointerValid(iatPointer)) { return iatPointer; } } } startAddress = findNextFunctionAddress(); //printf("startAddress %08X\n",startAddress); } while (startAddress != 0 && counter != 8); return 0; } DWORD_PTR IATSearch::findNextFunctionAddress() { #ifdef DEBUG_COMMENTS _DecodedInst inst; #endif for (unsigned int i = 0; i < decomposerInstructionsCount; i++) { if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) { if (decomposerResult[i].size >= 5) { if (decomposerResult[i].ops[0].type == O_PC) { #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_TARGET(&decomposerResult[i])); #endif return (DWORD_PTR)INSTRUCTION_GET_TARGET(&decomposerResult[i]); } } } } } return 0; } DWORD_PTR IATSearch::findIATPointer() { #ifdef DEBUG_COMMENTS _DecodedInst inst; #endif for (unsigned int i = 0; i < decomposerInstructionsCount; i++) { if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) { if (decomposerResult[i].size >= 5) { #ifdef _WIN64 if (decomposerResult[i].flags & FLAG_RIP_RELATIVE) { #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); #endif return INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i]); } #else if (decomposerResult[i].ops[0].type == O_DISP) { //jmp dword ptr || call dword ptr #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, decomposerResult[i].disp); #endif return (DWORD_PTR)decomposerResult[i].disp; } #endif } } } } return 0; } bool IATSearch::isIATPointerValid(DWORD_PTR iatPointer) { DWORD_PTR apiAddress = 0; if (!readMemoryFromProcess(iatPointer,sizeof(DWORD_PTR),&apiAddress)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"isIATPointerValid :: error reading memory"); #endif return false; } //printf("Win api ? %08X\n",apiAddress); if (isApiAddressValid(apiAddress) != 0) { return true; } else { //maybe redirected import? //if the address is 2 times inside a memory region it is possible a redirected api if (apiAddress > memoryAddress && apiAddress < (memoryAddress+memorySize)) { return true; } else { getMemoryRegionFromAddress(apiAddress, &memoryAddress, &memorySize); return false; } } } bool IATSearch::isPageExecutable(DWORD value) { if (value & PAGE_NOCACHE) value ^= PAGE_NOCACHE; if (value & PAGE_WRITECOMBINE) value ^= PAGE_WRITECOMBINE; switch(value) { case PAGE_EXECUTE: { return true; } case PAGE_EXECUTE_READ: { return true; } case PAGE_EXECUTE_READWRITE: { return true; } case PAGE_EXECUTE_WRITECOPY: { return true; } default: return false; } } bool IATSearch::findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT) { MEMORY_BASIC_INFORMATION memBasic = {0}; BYTE *dataBuffer = 0; if (VirtualQueryEx(hProcess,(LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findIATStartAddress :: VirtualQueryEx error %u", GetLastError()); #endif return false; } //(sizeof(DWORD_PTR) * 3) added to prevent buffer overflow dataBuffer = new BYTE[memBasic.RegionSize + (sizeof(DWORD_PTR) * 3)]; ZeroMemory(dataBuffer, memBasic.RegionSize + (sizeof(DWORD_PTR) * 3)); if (!readMemoryFromProcess((DWORD_PTR)memBasic.BaseAddress, memBasic.RegionSize, dataBuffer)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findIATStartAddress :: error reading memory"); #endif return false; } //printf("address %X memBasic.BaseAddress %X memBasic.RegionSize %X\n",address,memBasic.BaseAddress,memBasic.RegionSize); *addressIAT = findIATStartAddress((DWORD_PTR)memBasic.BaseAddress, address, dataBuffer); *sizeIAT = findIATSize((DWORD_PTR)memBasic.BaseAddress, *addressIAT, dataBuffer, (DWORD)memBasic.RegionSize); delete [] dataBuffer; return true; } DWORD_PTR IATSearch::findIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE * dataBuffer) { DWORD_PTR *pIATAddress = 0; pIATAddress = (DWORD_PTR *)((startAddress - baseAddress) + (DWORD_PTR)dataBuffer); while((DWORD_PTR)pIATAddress != (DWORD_PTR)dataBuffer) { if ( (*pIATAddress < 0xFFFF) || !isAddressAccessable(*pIATAddress) ) { if ( (*(pIATAddress - 1) < 0xFFFF) || !isAddressAccessable(*(pIATAddress - 1)) ) { //IAT end if ((DWORD_PTR)(pIATAddress - 2) >= (DWORD_PTR)dataBuffer) { if (!isApiAddressValid(*(pIATAddress - 2))) { return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress); } } else { return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress); } } } pIATAddress--; } return baseAddress; } DWORD IATSearch::findIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE * dataBuffer, DWORD bufferSize) { DWORD_PTR *pIATAddress = 0; pIATAddress = (DWORD_PTR *)((iatAddress - baseAddress) + (DWORD_PTR)dataBuffer); #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findIATSize :: baseAddress %X iatAddress %X dataBuffer %X pIATAddress %X", baseAddress, iatAddress, dataBuffer, pIATAddress); #endif while((DWORD_PTR)pIATAddress < ((DWORD_PTR)dataBuffer + bufferSize - 1)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findIATSize :: %X %X %X", pIATAddress, *pIATAddress, *(pIATAddress + 1)); #endif if ( (*pIATAddress < 0xFFFF) || !isAddressAccessable(*pIATAddress) ) //normal is 0 { if ( (*(pIATAddress + 1) < 0xFFFF) || !isAddressAccessable(*(pIATAddress + 1)) ) { //IAT end if (!isApiAddressValid(*(pIATAddress + 2))) { return (DWORD)((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer - (iatAddress - baseAddress)); } } } pIATAddress++; } return bufferSize; } bool IATSearch::isAddressAccessable(DWORD_PTR address) { BYTE junk[3]; SIZE_T numberOfBytesRead = 0; if (ReadProcessMemory(hProcess, (LPCVOID)address, junk, sizeof(junk), &numberOfBytesRead)) { if (numberOfBytesRead == sizeof(junk)) { if (junk[0] != 0x00) { return true; } } } return false; } void IATSearch::findIATPointers(std::set & iatPointers) { #ifdef DEBUG_COMMENTS _DecodedInst inst; #endif for (unsigned int i = 0; i < decomposerInstructionsCount; i++) { if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) { if (decomposerResult[i].size >= 5) { #ifdef _WIN64 if (decomposerResult[i].flags & FLAG_RIP_RELATIVE) { #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); #endif iatPointers.insert(INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); } #else if (decomposerResult[i].ops[0].type == O_DISP) { //jmp dword ptr || call dword ptr #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, decomposerResult[i].disp); #endif iatPointers.insert((DWORD_PTR)decomposerResult[i].disp); } #endif } } } } } void IATSearch::findExecutableMemoryPagesByStartAddress( DWORD_PTR startAddress, DWORD_PTR* baseAddress, SIZE_T* memorySize ) { MEMORY_BASIC_INFORMATION memBasic = {0}; DWORD_PTR tempAddress; *memorySize = 0; *baseAddress = 0; if (VirtualQueryEx(hProcess,(LPCVOID)startAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"findIATStartAddress :: VirtualQueryEx error %u", GetLastError()); #endif return; } //search down do { *memorySize = memBasic.RegionSize; *baseAddress = (DWORD_PTR)memBasic.BaseAddress; tempAddress = (DWORD_PTR)memBasic.BaseAddress - 1; if (VirtualQueryEx(hProcess, (LPCVOID)tempAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { break; } } while (isPageExecutable(memBasic.Protect)); tempAddress = *baseAddress; memBasic.RegionSize = *memorySize; *memorySize = 0; //search up do { tempAddress += memBasic.RegionSize; *memorySize += memBasic.RegionSize; if (VirtualQueryEx(hProcess, (LPCVOID)tempAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { break; } } while (isPageExecutable(memBasic.Protect)); } void IATSearch::filterIATPointersList( std::set & iatPointers ) { std::set::iterator iter; iter = iatPointers.begin(); std::advance(iter, iatPointers.size() / 2); //start in the middle, important! DWORD_PTR lastPointer = *iter; iter++; for (; iter != iatPointers.end(); iter++) { if ((*iter - lastPointer) > 0x100) //check difference { iatPointers.erase(iter, iatPointers.end()); break; } else { lastPointer = *iter; } } bool erased = true; while(erased) { iter = iatPointers.begin(); lastPointer = *iter; iter++; for (; iter != iatPointers.end(); iter++) { if ((*iter - lastPointer) > 0x100) //check difference { iter--; iatPointers.erase(iter); erased = true; break; } else { erased = false; lastPointer = *iter; } } } } diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp index b940197..446df17 100644 --- a/Scylla/MainGui.cpp +++ b/Scylla/MainGui.cpp @@ -1,1506 +1,1560 @@ #include "MainGui.h" #include "Architecture.h" //#include "PluginLoader.h" //#include "ConfigurationHolder.h" #include "PeParser.h" #include "DllInjectionPlugin.h" #include "DisassemblerGui.h" #include "PickApiGui.h" //#include "NativeWinApi.h" #include "ImportRebuilder.h" #include "SystemInformation.h" #include "Scylla.h" #include "AboutGui.h" #include "DonateGui.h" #include "OptionsGui.h" #include "TreeImportExport.h" extern CAppModule _Module; // o_O const WCHAR MainGui::filterExe[] = L"Executable (*.exe)\0*.exe\0All files\0*.*\0"; const WCHAR MainGui::filterDll[] = L"Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0"; const WCHAR MainGui::filterExeDll[] = L"Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0"; const WCHAR MainGui::filterTxt[] = L"Text file (*.txt)\0*.txt\0All files\0*.*\0"; const WCHAR MainGui::filterXml[] = L"XML file (*.xml)\0*.xml\0All files\0*.*\0"; const WCHAR MainGui::filterMem[] = L"MEM file (*.mem)\0*.mem\0All files\0*.*\0"; MainGui::MainGui() : selectedProcess(0), isProcessSuspended(false), importsHandling(TreeImports), TreeImportsSubclass(this, IDC_TREE_IMPORTS) { /* Logger::getDebugLogFilePath(); ConfigurationHolder::loadConfiguration(); PluginLoader::findAllPlugins(); NativeWinApi::initialize(); SystemInformation::getSystemInformation(); if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue()) { processLister.setDebugPrivileges(); } ProcessAccessHelp::getProcessModules(GetCurrentProcessId(), ProcessAccessHelp::ownModuleList); */ Scylla::init(); hIcon.LoadIcon(IDI_ICON_SCYLLA); hMenuImports.LoadMenu(IDR_MENU_IMPORTS); hMenuLog.LoadMenu(IDR_MENU_LOG); accelerators.LoadAccelerators(IDR_ACCELERATOR_MAIN); hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16); hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16); hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16); } BOOL MainGui::PreTranslateMessage(MSG* pMsg) { if(accelerators.TranslateAccelerator(m_hWnd, pMsg)) { return TRUE; // handled keyboard shortcuts } else if(IsDialogMessage(pMsg)) { return TRUE; // handled dialog messages } return FALSE; } +void MainGui::InitDllStartWithPreSelect( PGUI_DLL_PARAMETER guiParam ) +{ + ComboProcessList.ResetContent(); + std::vector& processList = Scylla::processLister.getProcessListSnapshot(); + int newSel = -1; + for (size_t i = 0; i < processList.size(); i++) + { + if (processList[i].PID == guiParam->dwProcessId) + newSel = (int)i; + swprintf_s(stringBuffer, L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath); + ComboProcessList.AddString(stringBuffer); + } + if (newSel != -1) + { + ComboProcessList.SetCurSel(newSel); + processSelectedActionHandler(newSel); + + if (guiParam->mod) //init mod + { + //select DLL + size_t len = ProcessAccessHelp::moduleList.size(); + newSel = -1; + for (size_t i = 0; i < len; i++) + { + if (ProcessAccessHelp::moduleList.at(i).modBaseAddr == (DWORD_PTR)guiParam->mod) + { + newSel = (int)i; + break; + } + } + if (newSel != -1) + { + //get selected module + ProcessAccessHelp::selectedModule = &ProcessAccessHelp::moduleList.at(newSel); + + ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr; + + DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath); + + EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase); + + Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename()); + Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint); + } + } + } +} + BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { if (SystemInformation::currenOS == UNKNOWN_OS) { if(IDCANCEL == MessageBox(L"Operating System is not supported\r\nContinue anyway?", L"Scylla", MB_ICONWARNING | MB_OKCANCEL)) { SendMessage(WM_CLOSE); return FALSE; } } // register ourselves to receive PreTranslateMessage CMessageLoop* pLoop = _Module.GetMessageLoop(); pLoop->AddMessageFilter(this); setupStatusBar(); DoDataExchange(); // attach controls DlgResize_Init(true, true); // init CDialogResize Scylla::windowLog.setWindow(ListLog); appendPluginListToMenu(hMenuImports.GetSubMenu(0)); appendPluginListToMenu(CMenuHandle(GetMenu()).GetSubMenu(MenuImportsOffsetTrace)); enableDialogControls(FALSE); setIconAndDialogCaption(); + + if (lInitParam) + { + InitDllStartWithPreSelect((PGUI_DLL_PARAMETER)lInitParam); + } return TRUE; } + void MainGui::OnDestroy() { PostQuitMessage(0); } void MainGui::OnSize(UINT nType, CSize size) { StatusBar.SendMessage(WM_SIZE); SetMsgHandled(FALSE); } void MainGui::OnContextMenu(CWindow wnd, CPoint point) { switch(wnd.GetDlgCtrlID()) { case IDC_TREE_IMPORTS: DisplayContextMenuImports(wnd, point); return; case IDC_LIST_LOG: DisplayContextMenuLog(wnd, point); return; } SetMsgHandled(FALSE); } void MainGui::OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl) { // Handle plugin trace menu selection if(uNotifyCode == 0 && !wndCtl.IsWindow()) // make sure it's a menu { if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { pluginActionHandler(nID); return; } } SetMsgHandled(FALSE); } LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh) { if(TreeImports.GetCount() < 1) return 0; // Get item under cursor CTreeItem over = findTreeItem(CPoint(GetMessagePos()), true); if(over && importsHandling.isImport(over)) { pickApiActionHandler(over); } return 0; } LRESULT MainGui::OnTreeImportsKeyDown(const NMHDR* pnmh) { const NMTVKEYDOWN * tkd = (NMTVKEYDOWN *)pnmh; switch(tkd->wVKey) { case VK_RETURN: { CTreeItem selected = TreeImports.GetFocusItem(); if(!selected.IsNull() && importsHandling.isImport(selected)) { pickApiActionHandler(selected); } } return 1; case VK_DELETE: deleteSelectedImportsActionHandler(); return 1; } SetMsgHandled(FALSE); return 0; } UINT MainGui::OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg) { if(lpMsg) { switch(lpMsg->wParam) { case VK_RETURN: return DLGC_WANTMESSAGE; } } SetMsgHandled(FALSE); return 0; } void MainGui::OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_RETURN: break; default: SetMsgHandled(FALSE); break; } } void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl) { fillProcessListComboBox(ComboProcessList); } void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { processSelectedActionHandler(ComboProcessList.GetCurSel()); } void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl) { pickDllActionHandler(); } void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl) { optionsActionHandler(); } void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpActionHandler(); } void MainGui::OnDumpMemory(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpMemoryActionHandler(); } void MainGui::OnDumpSection(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpSectionActionHandler(); } void MainGui::OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpFixActionHandler(); } void MainGui::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl) { peRebuildActionHandler(); } void MainGui::OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl) { dllInjectActionHandler(); } void MainGui::OnDisassembler(UINT uNotifyCode, int nID, CWindow wndCtl) { disassemblerActionHandler(); } void MainGui::OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl) { iatAutosearchActionHandler(); } void MainGui::OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl) { getImportsActionHandler(); } void MainGui::OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl) { showInvalidImportsActionHandler(); } void MainGui::OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl) { showSuspectImportsActionHandler(); } void MainGui::OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl) { clearImportsActionHandler(); } void MainGui::OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { invalidateSelectedImportsActionHandler(); } void MainGui::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { deleteSelectedImportsActionHandler(); } void MainGui::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl) { saveTreeActionHandler(); } void MainGui::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl) { loadTreeActionHandler(); } void MainGui::OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl) { // TODO } void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { if (isProcessSuspended) { int msgboxID = MessageBox(L"Process is suspended. Do you want to terminate the process?\r\n\r\nYES = Terminate Process\r\nNO = Try to resume the process\r\nCancel = Do nothing", L"Information", MB_YESNOCANCEL|MB_ICONINFORMATION); switch (msgboxID) { case IDYES: ProcessAccessHelp::terminateProcess(); break; case IDNO: ProcessAccessHelp::resumeProcess(); break; default: break; } } DestroyWindow(); } void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl) { showAboutDialog(); } void MainGui::OnDonate(UINT uNotifyCode, int nID, CWindow wndCtl) { showDonateDialog(); } void MainGui::setupStatusBar() { StatusBar.Create(m_hWnd, NULL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_TOOLTIPS, NULL, IDC_STATUS_BAR); CRect rcMain, rcStatus; GetClientRect(&rcMain); StatusBar.GetWindowRect(&rcStatus); const int PARTS = 4; int widths[PARTS]; widths[PART_COUNT] = rcMain.Width() / 5; widths[PART_INVALID] = widths[PART_COUNT] + rcMain.Width() / 5; widths[PART_IMAGEBASE] = widths[PART_INVALID] + rcMain.Width() / 3; widths[PART_MODULE] = -1; StatusBar.SetParts(PARTS, widths); ResizeClient(rcMain.Width(), rcMain.Height() + rcStatus.Height(), FALSE); } void MainGui::updateStatusBar() { // Rewrite ImportsHandling so we get these easily unsigned int totalImports = importsHandling.thunkCount(); unsigned int invalidImports = importsHandling.invalidThunkCount(); // \t = center, \t\t = right-align swprintf_s(stringBuffer, L"\tImports: %u", totalImports); StatusBar.SetText(PART_COUNT, stringBuffer); if(invalidImports > 0) { StatusBar.SetIcon(PART_INVALID, hIconError); } else { StatusBar.SetIcon(PART_INVALID, hIconCheck); } swprintf_s(stringBuffer, L"\tInvalid: %u", invalidImports); StatusBar.SetText(PART_INVALID, stringBuffer); if(selectedProcess) { DWORD_PTR imageBase = 0; const WCHAR * fileName = 0; if(ProcessAccessHelp::selectedModule) { imageBase = ProcessAccessHelp::selectedModule->modBaseAddr; fileName = ProcessAccessHelp::selectedModule->getFilename(); } else { imageBase = selectedProcess->imageBase; fileName = selectedProcess->filename; } swprintf_s(stringBuffer, L"\tImagebase: " PRINTF_DWORD_PTR_FULL, imageBase); StatusBar.SetText(PART_IMAGEBASE, stringBuffer); StatusBar.SetText(PART_MODULE, fileName); StatusBar.SetTipText(PART_MODULE, fileName); } else { StatusBar.SetText(PART_IMAGEBASE, L""); StatusBar.SetText(PART_MODULE, L""); } } bool MainGui::showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter, const WCHAR * defExtension, const WCHAR * directory) { OPENFILENAME ofn = {0}; // WTL doesn't support new explorer styles on Vista and up // This is because it uses a custom hook, we could remove it or derive // from CFileDialog but this solution is easier and allows more control anyway (e.g. initial dir) if(defFileName) { wcscpy_s(selectedFile, MAX_PATH, defFileName); } else { selectedFile[0] = L'\0'; } ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = m_hWnd; ofn.lpstrFilter = filter; ofn.lpstrDefExt = defExtension; // only first 3 chars are used, no dots! ofn.lpstrFile = selectedFile; ofn.lpstrInitialDir = directory; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; /* *OFN_EXPLORER is automatically used, it only has to be specified *if using a custom hook *OFN_LONGNAMES is automatically used by explorer-style dialogs */ if(save) ofn.Flags |= OFN_OVERWRITEPROMPT; else ofn.Flags |= OFN_FILEMUSTEXIST; if(save) return 0 != GetSaveFileName(&ofn); else return 0 != GetOpenFileName(&ofn); } void MainGui::setIconAndDialogCaption() { SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION); } void MainGui::pickDllActionHandler() { if(!selectedProcess) return; PickDllGui dlgPickDll(ProcessAccessHelp::moduleList); if(dlgPickDll.DoModal()) { //get selected module ProcessAccessHelp::selectedModule = dlgPickDll.getSelectedModule(); ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr; DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath); EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase); Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename()); Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint); } else { ProcessAccessHelp::selectedModule = 0; } updateStatusBar(); } void MainGui::pickApiActionHandler(CTreeItem item) { if(!importsHandling.isImport(item)) return; // TODO: new node when user picked an API from another DLL? PickApiGui dlgPickApi(ProcessAccessHelp::moduleList); if(dlgPickApi.DoModal()) { const ApiInfo* api = dlgPickApi.getSelectedApi(); if(api && api->module) { importsHandling.setImport(item, api->module->getFilename(), api->name, api->ordinal, api->hint, true, api->isForwarded); } } updateStatusBar(); } void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode) { if(!selectedProcess) return; DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode); if (address) { BYTE test; if(!ProcessAccessHelp::readMemoryFromProcess(address, sizeof(test), &test)) { swprintf_s(stringBuffer, L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address); MessageBox(stringBuffer, L"Failure", MB_ICONERROR); } else { DisassemblerGui dlgDisassembler(address, &apiReader); dlgDisassembler.DoModal(); } } } void MainGui::processSelectedActionHandler(int index) { std::vector& processList = Scylla::processLister.getProcessList(); Process &process = processList.at(index); selectedProcess = 0; clearImportsActionHandler(); Scylla::windowLog.log(L"Analyzing %s", process.fullPath); if (ProcessAccessHelp::hProcess != 0) { ProcessAccessHelp::closeProcessHandle(); apiReader.clearAll(); } if (!ProcessAccessHelp::openProcessHandle(process.PID)) { enableDialogControls(FALSE); Scylla::windowLog.log(L"Error: Cannot open process handle."); updateStatusBar(); return; } ProcessAccessHelp::getProcessModules(process.PID, ProcessAccessHelp::moduleList); apiReader.readApisFromModuleList(); Scylla::windowLog.log(L"Loading modules done."); //TODO improve ProcessAccessHelp::selectedModule = 0; ProcessAccessHelp::targetSizeOfImage = process.imageSize; ProcessAccessHelp::targetImageBase = process.imageBase; ProcessAccessHelp::getSizeOfImageCurrentProcess(); process.imageSize = (DWORD)ProcessAccessHelp::targetSizeOfImage; Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", process.imageBase, process.imageSize); process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath); EditOEPAddress.SetValue(process.entryPoint + process.imageBase); selectedProcess = &process; enableDialogControls(TRUE); updateStatusBar(); } void MainGui::fillProcessListComboBox(CComboBox& hCombo) { hCombo.ResetContent(); std::vector& processList = Scylla::processLister.getProcessListSnapshot(); for (size_t i = 0; i < processList.size(); i++) { swprintf_s(stringBuffer, L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath); hCombo.AddString(stringBuffer); } } /* void MainGui::addTextToOutputLog(const WCHAR * text) { if (m_hWnd) { ListLog.SetCurSel(ListLog.AddString(text)); } } */ void MainGui::clearOutputLog() { if (m_hWnd) { ListLog.ResetContent(); } } bool MainGui::saveLogToFile(const WCHAR * file) { const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian const WCHAR newLine[] = L"\r\n"; bool success = true; HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile != INVALID_HANDLE_VALUE) { ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM); WCHAR * buffer = 0; size_t bufsize = 0; for(int i = 0; i < ListLog.GetCount(); i++) { size_t size = ListLog.GetTextLen(i); size += _countof(newLine)-1; if(size+1 > bufsize) { bufsize = size+1; delete[] buffer; try { buffer = new WCHAR[bufsize]; } catch(std::bad_alloc&) { buffer = 0; success = false; break; } } ListLog.GetText(i, buffer); wcscat_s(buffer, bufsize, newLine); ProcessAccessHelp::writeMemoryToFileEnd(hFile, (DWORD)(size * sizeof(WCHAR)), buffer); } delete[] buffer; CloseHandle(hFile); } return success; } void MainGui::showInvalidImportsActionHandler() { importsHandling.selectImports(true, false); GotoDlgCtrl(TreeImports); } void MainGui::showSuspectImportsActionHandler() { importsHandling.selectImports(false, true); GotoDlgCtrl(TreeImports); } void MainGui::deleteSelectedImportsActionHandler() { CTreeItem selected = TreeImports.GetFirstSelectedItem(); while(!selected.IsNull()) { if(importsHandling.isModule(selected)) { importsHandling.cutModule(selected); } else { importsHandling.cutImport(selected); } selected = TreeImports.GetNextSelectedItem(selected); } updateStatusBar(); } void MainGui::invalidateSelectedImportsActionHandler() { CTreeItem selected = TreeImports.GetFirstSelectedItem(); while(!selected.IsNull()) { if(importsHandling.isImport(selected)) { importsHandling.invalidateImport(selected); } selected = TreeImports.GetNextSelectedItem(selected); } updateStatusBar(); } void MainGui::loadTreeActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, false, NULL, filterXml, NULL, stringBuffer)) { TreeImportExport treeIO(selectedFilePath); DWORD_PTR addrOEP = 0; DWORD_PTR addrIAT = 0; DWORD sizeIAT = 0; if(!treeIO.importTreeList(importsHandling.moduleList, &addrOEP, &addrIAT, &sizeIAT)) { Scylla::windowLog.log(L"Loading tree file failed %s", selectedFilePath); MessageBox(L"Loading tree file failed.", L"Failure", MB_ICONERROR); } else { EditOEPAddress.SetValue(addrOEP); EditIATAddress.SetValue(addrIAT); EditIATSize.SetValue(sizeIAT); importsHandling.displayAllImports(); updateStatusBar(); Scylla::windowLog.log(L"Loaded tree file %s", selectedFilePath); Scylla::windowLog.log(L"-> OEP: " PRINTF_DWORD_PTR_FULL, addrOEP); Scylla::windowLog.log(L"-> IAT: " PRINTF_DWORD_PTR_FULL L" Size: " PRINTF_DWORD_PTR, addrIAT, sizeIAT); } } } void MainGui::saveTreeActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, filterXml, L"xml", stringBuffer)) { TreeImportExport treeIO(selectedFilePath); DWORD_PTR addrOEP = EditOEPAddress.GetValue(); DWORD_PTR addrIAT = EditIATAddress.GetValue(); DWORD sizeIAT = EditIATSize.GetValue(); if(!treeIO.exportTreeList(importsHandling.moduleList, selectedProcess, addrOEP, addrIAT, sizeIAT)) { Scylla::windowLog.log(L"Saving tree file failed %s", selectedFilePath); MessageBox(L"Saving tree file failed.", L"Failure", MB_ICONERROR); } else { Scylla::windowLog.log(L"Saved tree file %s", selectedFilePath); } } } void MainGui::iatAutosearchActionHandler() { DWORD_PTR searchAddress = 0; DWORD_PTR addressIAT = 0, addressIATAdv = 0; DWORD sizeIAT = 0, sizeIATAdv = 0; IATSearch iatSearch; if(!selectedProcess) return; if(EditOEPAddress.GetWindowTextLength() > 0) { searchAddress = EditOEPAddress.GetValue(); if (searchAddress) { if (Scylla::config[USE_ADVANCED_IAT_SEARCH].isTrue()) { if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIATAdv, &sizeIATAdv, true)) { Scylla::windowLog.log(L"IAT Search Advanced: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIATAdv, addressIATAdv - ProcessAccessHelp::targetImageBase, sizeIATAdv, sizeIATAdv); } else { Scylla::windowLog.log(L"IAT Search Advanced: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress); } } if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT, false)) { Scylla::windowLog.log(L"IAT Search Normal: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT); } else { Scylla::windowLog.log(L"IAT Search Normal: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress); } if (addressIAT != 0 && addressIATAdv == 0) { setDialogIATAddressAndSize(addressIAT, sizeIAT); } else if (addressIAT == 0 && addressIATAdv != 0) { setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv); } else if (addressIAT != 0 && addressIATAdv != 0) { if (addressIATAdv != addressIAT || sizeIAT != sizeIATAdv) { int msgboxID = MessageBox(L"Result of advanced and normal search is different. Do you want to use the IAT Search Advanced result?", L"Information", MB_YESNO|MB_ICONINFORMATION); if (msgboxID == IDYES) { setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv); } else { setDialogIATAddressAndSize(addressIAT, sizeIAT); } } else { setDialogIATAddressAndSize(addressIAT, sizeIAT); } } } } } void MainGui::getImportsActionHandler() { if(!selectedProcess) return; DWORD_PTR addressIAT = EditIATAddress.GetValue(); DWORD sizeIAT = EditIATSize.GetValue(); if (addressIAT && sizeIAT) { apiReader.readAndParseIAT(addressIAT, sizeIAT, importsHandling.moduleList); importsHandling.displayAllImports(); updateStatusBar(); } } void MainGui::SetupImportsMenuItems(CTreeItem item) { bool isItem, isImport = false; isItem = !item.IsNull(); if(isItem) { isImport = importsHandling.isImport(item); } CMenuHandle hSub = hMenuImports.GetSubMenu(0); UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED; UINT importOnly = isImport ? MF_ENABLED : MF_GRAYED; hSub.EnableMenuItem(ID__INVALIDATE, itemOnly); hSub.EnableMenuItem(ID__DISASSEMBLE, importOnly); hSub.EnableMenuItem(ID__CUTTHUNK, importOnly); hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly); } void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt) { if(TreeImports.GetCount() < 1) return; CTreeItem over, parent; if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; over = TreeImports.GetFocusItem(); if(over) { over.EnsureVisible(); over.GetRect(&pos, TRUE); TreeImports.ClientToScreen(&pos); } else { TreeImports.GetWindowRect(&pos); } pt = pos.TopLeft(); } else { // Get item under cursor over = findTreeItem(pt, true); } SetupImportsMenuItems(over); CMenuHandle hSub = hMenuImports.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { //wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName); //MessageBox(stringBuffer, L"plugin selection"); pluginActionHandler(menuItem); return; } switch (menuItem) { case ID__INVALIDATE: if(importsHandling.isModule(over)) importsHandling.invalidateModule(over); else importsHandling.invalidateImport(over); break; case ID__DISASSEMBLE: startDisassemblerGui(over); break; case ID__EXPANDALLNODES: importsHandling.expandAllTreeNodes(); break; case ID__COLLAPSEALLNODES: importsHandling.collapseAllTreeNodes(); break; case ID__CUTTHUNK: importsHandling.cutImport(over); break; case ID__DELETETREENODE: importsHandling.cutModule(importsHandling.isImport(over) ? over.GetParent() : over); break; } } updateStatusBar(); } void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt) { if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; ListLog.GetWindowRect(&pos); pt = pos.TopLeft(); } CMenuHandle hSub = hMenuLog.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { switch (menuItem) { case ID__SAVE: WCHAR selectedFilePath[MAX_PATH]; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt", stringBuffer)) { saveLogToFile(selectedFilePath); } break; case ID__CLEAR: clearOutputLog(); break; } } } void MainGui::appendPluginListToMenu(CMenuHandle hMenu) { std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList(); std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList(); if (scyllaPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < scyllaPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins"); } if (imprecPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < imprecPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins"); } } void MainGui::dumpMemoryActionHandler() { WCHAR selectedFilePath[MAX_PATH]; DumpMemoryGui dlgDumpMemory; if(dlgDumpMemory.DoModal()) { getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, dlgDumpMemory.dumpFilename, filterMem, L"mem", stringBuffer)) { if (ProcessAccessHelp::writeMemoryToNewFile(selectedFilePath,dlgDumpMemory.dumpedMemorySize,dlgDumpMemory.dumpedMemory)) { Scylla::windowLog.log(L"Memory dump saved %s", selectedFilePath); } else { Scylla::windowLog.log(L"Error! Cannot write memory dump to disk"); } } } } void MainGui::dumpSectionActionHandler() { WCHAR selectedFilePath[MAX_PATH]; DumpSectionGui dlgDumpSection; const WCHAR * fileFilter; const WCHAR * defExtension; PeParser * peFile = 0; dlgDumpSection.entryPoint = EditOEPAddress.GetValue(); if (ProcessAccessHelp::selectedModule) { //dump DLL fileFilter = filterDll; defExtension = L"dll"; dlgDumpSection.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr; //get it from gui wcscpy_s(dlgDumpSection.fullpath, ProcessAccessHelp::selectedModule->fullPath); } else { fileFilter = filterExe; defExtension = L"exe"; dlgDumpSection.imageBase = ProcessAccessHelp::targetImageBase; //get it from gui wcscpy_s(dlgDumpSection.fullpath, selectedProcess->fullPath); } if(dlgDumpSection.DoModal()) { getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer)) { checkSuspendProcess(); if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue()) { peFile = new PeParser(dlgDumpSection.fullpath, true); } else { peFile = new PeParser(dlgDumpSection.imageBase, true); } std::vector & sectionList = dlgDumpSection.getSectionList(); if (peFile->dumpProcess(dlgDumpSection.imageBase, dlgDumpSection.entryPoint, selectedFilePath, sectionList)) { Scylla::windowLog.log(L"Dump success %s", selectedFilePath); } else { Scylla::windowLog.log(L"Error: Cannot dump image."); MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR); } delete peFile; } } } void MainGui::dumpActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; const WCHAR * defExtension; DWORD_PTR modBase = 0; DWORD_PTR entrypoint = 0; WCHAR * filename = 0; PeParser * peFile = 0; if (ProcessAccessHelp::selectedModule) { fileFilter = filterDll; defExtension = L"dll"; } else { fileFilter = filterExe; defExtension = L"exe"; } getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer)) { entrypoint = EditOEPAddress.GetValue(); checkSuspendProcess(); if (ProcessAccessHelp::selectedModule) { //dump DLL modBase = ProcessAccessHelp::selectedModule->modBaseAddr; filename = ProcessAccessHelp::selectedModule->fullPath; } else { //dump exe modBase = ProcessAccessHelp::targetImageBase; filename = selectedProcess->fullPath; } if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue()) { peFile = new PeParser(filename, true); } else { peFile = new PeParser(modBase, true); } if (peFile->dumpProcess(modBase, entrypoint, selectedFilePath)) { Scylla::windowLog.log(L"Dump success %s", selectedFilePath); } else { Scylla::windowLog.log(L"Error: Cannot dump image."); MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR); } delete peFile; } } void MainGui::peRebuildActionHandler() { DWORD newSize = 0; WCHAR selectedFilePath[MAX_PATH]; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL, stringBuffer)) { if (Scylla::config[CREATE_BACKUP].isTrue()) { if (!ProcessAccessHelp::createBackupFile(selectedFilePath)) { Scylla::windowLog.log(L"Creating backup file failed %s", selectedFilePath); } } DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath); PeParser peFile(selectedFilePath, true); if (!peFile.isValidPeFile()) { Scylla::windowLog.log(L"This is not a valid PE file %s", selectedFilePath); MessageBox(L"Not a valid PE file.", L"Failure", MB_ICONERROR); return; } if (peFile.readPeSectionsFromFile()) { peFile.setDefaultFileAlignment(); if (Scylla::config[REMOVE_DOS_HEADER_STUB].isTrue()) { peFile.removeDosStub(); } peFile.alignAllSectionHeaders(); peFile.fixPeHeader(); if (peFile.savePeFileToDisk(selectedFilePath)) { newSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath); if (Scylla::config[UPDATE_HEADER_CHECKSUM].isTrue()) { Scylla::windowLog.log(L"Generating PE header checksum"); if (!PeParser::updatePeHeaderChecksum(selectedFilePath, newSize)) { Scylla::windowLog.log(L"Generating PE header checksum FAILED!"); } } Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath); Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", fileSize, newSize, ((newSize * 100) / fileSize) ); } else { Scylla::windowLog.log(L"Rebuild failed, cannot save file %s", selectedFilePath); MessageBox(L"Rebuild failed. Cannot save file.", L"Failure", MB_ICONERROR); } } else { Scylla::windowLog.log(L"Rebuild failed, cannot read file %s", selectedFilePath); MessageBox(L"Rebuild failed. Cannot read file.", L"Failure", MB_ICONERROR); } } } void MainGui::dumpFixActionHandler() { if(!selectedProcess) return; if (TreeImports.GetCount() < 2) { Scylla::windowLog.log(L"Nothing to rebuild"); return; } WCHAR newFilePath[MAX_PATH]; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; DWORD_PTR modBase = 0; DWORD_PTR entrypoint = EditOEPAddress.GetValue(); if (ProcessAccessHelp::selectedModule) { modBase = ProcessAccessHelp::selectedModule->modBaseAddr; fileFilter = filterDll; } else { modBase = ProcessAccessHelp::targetImageBase; fileFilter = filterExe; } getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL, stringBuffer)) { wcscpy_s(newFilePath, selectedFilePath); const WCHAR * extension = 0; WCHAR* dot = wcsrchr(newFilePath, L'.'); if (dot) { *dot = L'\0'; extension = selectedFilePath + (dot - newFilePath); //wcsrchr(selectedFilePath, L'.'); } wcscat_s(newFilePath, L"_SCY"); if(extension) { wcscat_s(newFilePath, extension); } ImportRebuilder importRebuild(selectedFilePath); if (Scylla::config[IAT_FIX_AND_OEP_FIX].isTrue()) { importRebuild.setEntryPointRva((DWORD)(entrypoint - modBase)); } if (Scylla::config[OriginalFirstThunk_SUPPORT].isTrue()) { importRebuild.enableOFTSupport(); } if (importRebuild.rebuildImportTable(newFilePath, importsHandling.moduleList)) { Scylla::windowLog.log(L"Import Rebuild success %s", newFilePath); } else { Scylla::windowLog.log(L"Import Rebuild failed %s", selectedFilePath); MessageBox(L"Import Rebuild failed", L"Failure", MB_ICONERROR); } } } void MainGui::enableDialogControls(BOOL value) { BOOL valButton = value ? TRUE : FALSE; GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(valButton); GetDlgItem(IDC_BTN_DUMP).EnableWindow(valButton); GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(valButton); GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(valButton); GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(valButton); GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(valButton); GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(valButton); GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(valButton); CMenuHandle menu = GetMenu(); UINT valMenu = value ? MF_ENABLED : MF_GRAYED; menu.EnableMenuItem(ID_FILE_DUMP, valMenu); menu.EnableMenuItem(ID_FILE_DUMPMEMORY, valMenu); menu.EnableMenuItem(ID_FILE_DUMPSECTION, valMenu); menu.EnableMenuItem(ID_FILE_FIXDUMP, valMenu); menu.EnableMenuItem(ID_IMPORTS_INVALIDATESELECTED, valMenu); menu.EnableMenuItem(ID_IMPORTS_CUTSELECTED, valMenu); menu.EnableMenuItem(ID_IMPORTS_SAVETREE, valMenu); menu.EnableMenuItem(ID_IMPORTS_LOADTREE, valMenu); menu.EnableMenuItem(ID_MISC_DLLINJECTION, valMenu); menu.EnableMenuItem(ID_MISC_DISASSEMBLER, valMenu); menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetScylla, MF_BYPOSITION | valMenu); menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetImpRec, MF_BYPOSITION | valMenu); //not yet implemented GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE); menu.EnableMenuItem(ID_TRACE_AUTOTRACE, MF_GRAYED); } CTreeItem MainGui::findTreeItem(CPoint pt, bool screenCoordinates) { if(screenCoordinates) { TreeImports.ScreenToClient(&pt); } UINT flags; CTreeItem over = TreeImports.HitTest(pt, &flags); if(over) { if(!(flags & TVHT_ONITEM)) { over.m_hTreeItem = NULL; } } return over; } void MainGui::showAboutDialog() { AboutGui dlgAbout; dlgAbout.DoModal(); } void MainGui::showDonateDialog() { DonateGui dlgDonate; dlgDonate.DoModal(); } void MainGui::dllInjectActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; HMODULE hMod = 0; DllInjection dllInjection; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if (showFileDialog(selectedFilePath, false, NULL, filterDll, NULL, stringBuffer)) { hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, selectedFilePath); if (hMod && Scylla::config[DLL_INJECTION_AUTO_UNLOAD].isTrue()) { if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod)) { Scylla::windowLog.log(L"DLL unloading failed, target %s", selectedFilePath); } } if (hMod) { Scylla::windowLog.log(L"DLL Injection was successful, target %s", selectedFilePath); } else { Scylla::windowLog.log(L"DLL Injection failed, target %s", selectedFilePath); } } } void MainGui::disassemblerActionHandler() { DWORD_PTR oep = EditOEPAddress.GetValue(); DisassemblerGui disGuiDlg(oep, &apiReader); disGuiDlg.DoModal(); } void MainGui::optionsActionHandler() { OptionsGui dlgOptions; dlgOptions.DoModal(); } void MainGui::clearImportsActionHandler() { importsHandling.clearAllImports(); updateStatusBar(); } void MainGui::pluginActionHandler( int menuItem ) { if(!selectedProcess) return; DllInjectionPlugin dllInjectionPlugin; std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList(); std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList(); menuItem -= PLUGIN_MENU_BASE_ID; dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess; dllInjectionPlugin.apiReader = &apiReader; if (menuItem < (int)scyllaPluginList.size()) { //scylla plugin dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); } else { #ifndef _WIN64 menuItem -= (int)scyllaPluginList.size(); //imprec plugin dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); #endif } importsHandling.scanAndFixModuleList(); importsHandling.displayAllImports(); updateStatusBar(); } bool MainGui::getCurrentModulePath(WCHAR * buffer, size_t bufferSize) { if(!selectedProcess) return false; if(ProcessAccessHelp::selectedModule) { wcscpy_s(buffer, bufferSize, ProcessAccessHelp::selectedModule->fullPath); } else { wcscpy_s(buffer, bufferSize, selectedProcess->fullPath); } WCHAR * slash = wcsrchr(buffer, L'\\'); if(slash) { *(slash+1) = L'\0'; } return true; } void MainGui::checkSuspendProcess() { if (Scylla::config[SUSPEND_PROCESS_FOR_DUMPING].isTrue()) { if (!ProcessAccessHelp::suspendProcess()) { Scylla::windowLog.log(L"Error: Cannot suspend process."); } else { isProcessSuspended = true; Scylla::windowLog.log(L"Suspending process successful, please resume manually."); } } } void MainGui::setDialogIATAddressAndSize( DWORD_PTR addressIAT, DWORD sizeIAT ) { EditIATAddress.SetValue(addressIAT); EditIATSize.SetValue(sizeIAT); swprintf_s(stringBuffer, L"IAT found:\r\n\r\nStart: " PRINTF_DWORD_PTR_FULL L"\r\nSize: 0x%04X (%d) ", addressIAT, sizeIAT, sizeIAT); MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION); } diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h index 507e829..16d4e68 100644 --- a/Scylla/MainGui.h +++ b/Scylla/MainGui.h @@ -1,312 +1,314 @@ #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 "multitree.h" #include "hexedit.h" #include "Logger.h" #include "ProcessLister.h" #include "IATSearch.h" #include "PickDllGui.h" #include "DumpMemoryGui.h" #include "DumpSectionGui.h" #include "ImportsHandling.h" +#include "FunctionExport.h" class MainGui : public CDialogImpl, public CWinDataExchange, public CDialogResize, public CMessageFilter { public: enum { IDD = IDD_DLG_MAIN }; // Dialog Data eXchange, attaches/subclasses child controls to wrappers // DDX_CONTROL : subclass // DDX_CONTROL_HANDLE : attach BEGIN_DDX_MAP(MainGui) DDX_CONTROL(IDC_TREE_IMPORTS, TreeImportsSubclass) // needed for message reflection DDX_CONTROL(IDC_TREE_IMPORTS, TreeImports) DDX_CONTROL_HANDLE(IDC_CBO_PROCESSLIST, ComboProcessList) DDX_CONTROL_HANDLE(IDC_LIST_LOG, ListLog) DDX_CONTROL(IDC_EDIT_OEPADDRESS, EditOEPAddress) DDX_CONTROL(IDC_EDIT_IATADDRESS, EditIATAddress) DDX_CONTROL(IDC_EDIT_IATSIZE, EditIATSize) END_DDX_MAP() // Our message map // Messages are passed from top to bottom // The first handler that doesn't call SetMsgHandled(FALSE) aborts the chain // If none signals the message as handled, it will be passed to mixins (CHAIN_MSG_MAP) // or ultimately passed to DefWindowProc BEGIN_MSG_MAP_EX(MainGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_DESTROY(OnDestroy) MSG_WM_SIZE(OnSize) MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_COMMAND(OnCommand) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_DBLCLK, OnTreeImportsDoubleClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, TVN_KEYDOWN, OnTreeImportsKeyDown) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_DROPDOWN, OnProcessListDrop) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_SELENDOK, OnProcessListSelected) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL, OnPickDLL) COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMP, OnDump) COMMAND_ID_HANDLER_EX(IDC_BTN_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(IDC_BTN_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(IDC_BTN_IATAUTOSEARCH, OnIATAutoSearch) COMMAND_ID_HANDLER_EX(IDC_BTN_GETIMPORTS, OnGetImports) COMMAND_ID_HANDLER_EX(IDC_BTN_INVALIDIMPORTS, OnInvalidImports) COMMAND_ID_HANDLER_EX(IDC_BTN_SUSPECTIMPORTS, OnSuspectImports) COMMAND_ID_HANDLER_EX(IDC_BTN_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_FILE_DUMP, OnDump) COMMAND_ID_HANDLER_EX(ID_FILE_DUMPMEMORY, OnDumpMemory) COMMAND_ID_HANDLER_EX(ID_FILE_DUMPSECTION, OnDumpSection) COMMAND_ID_HANDLER_EX(ID_FILE_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(ID_FILE_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(ID_FILE_EXIT, OnExit) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWINVALID, OnInvalidImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWSUSPECT, OnSuspectImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_INVALIDATESELECTED, OnInvalidateSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CUTSELECTED, OnCutSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SAVETREE, OnSaveTree) COMMAND_ID_HANDLER_EX(ID_IMPORTS_LOADTREE, OnLoadTree) COMMAND_ID_HANDLER_EX(ID_TRACE_AUTOTRACE, OnAutotrace) COMMAND_ID_HANDLER_EX(ID_MISC_DLLINJECTION, OnDLLInject) COMMAND_ID_HANDLER_EX(ID_MISC_DISASSEMBLER, OnDisassembler) COMMAND_ID_HANDLER_EX(ID_MISC_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout) COMMAND_ID_HANDLER_EX(ID_HELP_DONATE, OnDonate) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) REFLECT_NOTIFY_ID(IDC_TREE_IMPORTS) // pass WM_NOTIFY to child control CHAIN_MSG_MAP(CDialogResize) // Message map for subclassed treeview // CContainedWindow forwards all messages to this map ALT_MSG_MAP(IDC_TREE_IMPORTS) MSG_WM_GETDLGCODE(OnTreeImportsSubclassGetDlgCode) MSG_WM_CHAR(OnTreeImportsSubclassChar) END_MSG_MAP() // Dialog resize 'table' // States if child controls move or resize or center in a specific direction // when the parent dialog is resized BEGIN_DLGRESIZE_MAP(MainGui) DLGRESIZE_CONTROL(IDC_GROUP_ATTACH, DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_CBO_PROCESSLIST, DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_BTN_PICKDLL, DLSZ_MOVE_X) DLGRESIZE_CONTROL(IDC_GROUP_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_TREE_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_BTN_INVALIDIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_SUSPECTIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_CLEARIMPORTS, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_IATINFO, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_OEPADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_IATADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_IATSIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_OEPADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_IATADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_IATSIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_IATAUTOSEARCH, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_GETIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_ACTIONS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_AUTOTRACE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_DUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_PEREBUILD, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_FIXDUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_LIST_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X) END_DLGRESIZE_MAP() MainGui(); //void addTextToOutputLog(const WCHAR * text); //CWindow getLogListboxHandle() const { return ListLog; } protected: // Variables WCHAR stringBuffer[600]; ImportsHandling importsHandling; //ProcessAccessHelp processAccessHelp; ApiReader apiReader; Process * selectedProcess; bool isProcessSuspended; // File selection filters static const WCHAR filterExe[]; static const WCHAR filterDll[]; static const WCHAR filterExeDll[]; static const WCHAR filterTxt[]; static const WCHAR filterXml[]; static const WCHAR filterMem[]; // Controls CMultiSelectTreeViewCtrl TreeImports; CComboBox ComboProcessList; CHexEdit EditOEPAddress; CHexEdit EditIATAddress; CHexEdit EditIATSize; CListBox ListLog; CStatusBarCtrl StatusBar; enum StatusParts { PART_COUNT = 0, PART_INVALID, PART_IMAGEBASE, PART_MODULE }; CContainedWindow TreeImportsSubclass; // Handles CIcon hIcon; CMenu hMenuImports; CMenu hMenuLog; CAccelerator accelerators; CIcon hIconCheck; CIcon hIconWarning; CIcon hIconError; static const int MenuImportsOffsetTrace = 2; static const int MenuImportsTraceOffsetScylla = 2; static const int MenuImportsTraceOffsetImpRec = 4; static const int PLUGIN_MENU_BASE_ID = 0x10; protected: virtual BOOL PreTranslateMessage(MSG* pMsg); // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnDestroy(); void OnSize(UINT nType, CSize size); void OnContextMenu(CWindow wnd, CPoint point); void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl); // WM_NOTIFY handlers LRESULT OnTreeImportsDoubleClick(const NMHDR* pnmh); LRESULT OnTreeImportsKeyDown(const NMHDR* pnmh); // Forwarded messages from subclassed treeview UINT OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg); void OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags); // WM_COMMAND handlers void OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl); void OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl); void OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDumpMemory(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDumpSection(UINT uNotifyCode, int nID, CWindow wndCtl); void OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDisassembler(UINT uNotifyCode, int nID, CWindow wndCtl); void OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl); void OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDonate(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions bool showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter = NULL, const WCHAR * defExtension = NULL, const WCHAR * directory = NULL); void setupStatusBar(); void updateStatusBar(); void fillProcessListComboBox(CComboBox& hCombo); void setIconAndDialogCaption(); void enableDialogControls(BOOL value); CTreeItem findTreeItem(CPoint pt, bool screenCoordinates); // Actions void pickDllActionHandler(); void pickApiActionHandler(CTreeItem item); void processSelectedActionHandler(int index); void showInvalidImportsActionHandler(); void showSuspectImportsActionHandler(); void deleteSelectedImportsActionHandler(); void invalidateSelectedImportsActionHandler(); void loadTreeActionHandler(); void saveTreeActionHandler(); void iatAutosearchActionHandler(); void getImportsActionHandler(); void dumpActionHandler(); void dumpMemoryActionHandler(); void dumpSectionActionHandler(); void peRebuildActionHandler(); void startDisassemblerGui(CTreeItem selectedTreeNode); void dumpFixActionHandler(); void showAboutDialog(); void showDonateDialog(); void dllInjectActionHandler(); void disassemblerActionHandler(); void optionsActionHandler(); void clearImportsActionHandler(); void pluginActionHandler(int menuItem); // Popup menu functions void SetupImportsMenuItems(CTreeItem item); void appendPluginListToMenu(CMenuHandle hMenuTrackPopup); void DisplayContextMenuImports(CWindow, CPoint); void DisplayContextMenuLog(CWindow, CPoint); // Log void clearOutputLog(); bool saveLogToFile(const WCHAR * file); // Misc bool getCurrentModulePath(WCHAR * buffer, size_t bufferSize); void checkSuspendProcess(); void setDialogIATAddressAndSize( DWORD_PTR addressIAT, DWORD sizeIAT ); + void InitDllStartWithPreSelect( PGUI_DLL_PARAMETER guiParam ); }; diff --git a/Scylla/Scylla.vcxproj b/Scylla/Scylla.vcxproj index 0df4ca4..9c9b80d 100644 --- a/Scylla/Scylla.vcxproj +++ b/Scylla/Scylla.vcxproj @@ -1,263 +1,264 @@  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 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)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) Windows true $(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)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) Windows true $(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)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) true Speed Windows false true true $(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 Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded $(SolutionDir)tinyxml;$(SolutionDir)diStorm\include;%(AdditionalIncludeDirectories) true Windows false true true $(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 + \ No newline at end of file diff --git a/Scylla/Scylla.vcxproj.filters b/Scylla/Scylla.vcxproj.filters index 70b9aab..2bc855a 100644 --- a/Scylla/Scylla.vcxproj.filters +++ b/Scylla/Scylla.vcxproj.filters @@ -1,235 +1,247 @@  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {e037d0d5-35ad-4034-83db-746a56a4fee7} {6f76186f-b79c-41e2-8939-05d9de028aad} + + {94d7cf3b-0d27-4bd6-b08f-e5894e02ef30} + + + {bbdfcdb4-3526-43c4-8984-da0f635cc93b} + Quelldateien Quelldateien\GUI + + Quelldateien\GUI + Quelldateien Quelldateien\GUI Quelldateien\GUI Quelldateien Quelldateien Quelldateien - - Quelldateien - - - Quelldateien - - - Quelldateien - Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien\GUI Quelldateien Quelldateien Quelldateien\GUI Quelldateien\GUI Quelldateien\GUI Quelldateien - Quelldateien - - - Quelldateien + Quelldateien\GUI Quelldateien - - Quelldateien - Quelldateien + + Quelldateien\GUI + - Quelldateien + Quelldateien\Helper - + Quelldateien + Quelldateien\GUI + + + Quelldateien + + Quelldateien + + Quelldateien + + + Quelldateien\GUI + Headerdateien Headerdateien\GUI + + Headerdateien\GUI + Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien Headerdateien Headerdateien Headerdateien\GUI - - Headerdateien - - - Headerdateien - - - Headerdateien - Headerdateien Headerdateien Headerdateien Headerdateien Headerdateien\GUI Headerdateien Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien\GUI Headerdateien\GUI Headerdateien - + Headerdateien\GUI - + Headerdateien - + Headerdateien - - Headerdateien + + Headerdateien\GUI - + Headerdateien - + + Headerdateien\Helper + + Headerdateien - + + Headerdateien\GUI + + Headerdateien - + Headerdateien - + + Headerdateien\GUI + + Headerdateien Ressourcendateien Ressourcendateien Ressourcendateien Ressourcendateien Ressourcendateien \ No newline at end of file diff --git a/Scylla/main.cpp b/Scylla/main.cpp index 4ef3366..7b7716c 100644 --- a/Scylla/main.cpp +++ b/Scylla/main.cpp @@ -1,115 +1,140 @@ //#include // Visual Leak Detector #include // base ATL classes #include // base WTL classes #include "Architecture.h" CAppModule _Module; #include "MainGui.h" MainGui* pMainGui = NULL; // for Logger +HINSTANCE hDllModule = 0; LONG WINAPI HandleUnknownException(struct _EXCEPTION_POINTERS *ExceptionInfo); +void AddExceptionHandler(); +void RemoveExceptionHandler(); +int InitializeGui(HINSTANCE hInstance, LPARAM param); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) +{ + AddExceptionHandler(); + + return InitializeGui(hInstance, (LPARAM)0); +} + +int InitializeGui(HINSTANCE hInstance, LPARAM param) { CoInitialize(NULL); - SetUnhandledExceptionFilter(HandleUnknownException); AtlInitCommonControls(ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES); HRESULT hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); int nRet = 0; // BLOCK: Run application { MainGui dlgMain; pMainGui = &dlgMain; // o_O CMessageLoop loop; _Module.AddMessageLoop(&loop); - dlgMain.Create(GetDesktopWindow()); + dlgMain.Create(GetDesktopWindow(), param); + dlgMain.ShowWindow(SW_SHOW); loop.Run(); } _Module.Term(); CoUninitialize(); return nRet; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { // Perform actions based on the reason for calling. switch(fdwReason) { case DLL_PROCESS_ATTACH: // Initialize once for each new process. // Return FALSE to fail DLL load. + AddExceptionHandler(); + hDllModule = hinstDLL; break; case DLL_THREAD_ATTACH: // Do thread-specific initialization. break; case DLL_THREAD_DETACH: // Do thread-specific cleanup. break; case DLL_PROCESS_DETACH: // Perform any necessary cleanup. + RemoveExceptionHandler(); break; } return TRUE; // Successful DLL_PROCESS_ATTACH. } +LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; + +void AddExceptionHandler() +{ + oldFilter = SetUnhandledExceptionFilter(HandleUnknownException); +} +void RemoveExceptionHandler() +{ + SetUnhandledExceptionFilter(oldFilter); +} + LONG WINAPI HandleUnknownException(struct _EXCEPTION_POINTERS *ExceptionInfo) { WCHAR registerInfo[220]; WCHAR message[159 + _countof(registerInfo)]; DWORD_PTR address = (DWORD_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress; swprintf_s(message, _countof(message), TEXT("ExceptionCode %08X\r\nExceptionFlags %08X\r\nNumberParameters %08X\r\nExceptionAddress VA ")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("\r\nExceptionAddress RVA ")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("\r\n\r\n"), ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionFlags, ExceptionInfo->ExceptionRecord->NumberParameters, address, address - (DWORD_PTR)GetModuleHandle(NULL)); #ifdef _WIN64 swprintf_s(registerInfo, _countof(registerInfo),TEXT("rax=0x%p, rbx=0x%p, rdx=0x%p, rcx=0x%p, rsi=0x%p, rdi=0x%p, rbp=0x%p, rsp=0x%p, rip=0x%p"), ExceptionInfo->ContextRecord->Rax, ExceptionInfo->ContextRecord->Rbx, ExceptionInfo->ContextRecord->Rdx, ExceptionInfo->ContextRecord->Rcx, ExceptionInfo->ContextRecord->Rsi, ExceptionInfo->ContextRecord->Rdi, ExceptionInfo->ContextRecord->Rbp, ExceptionInfo->ContextRecord->Rsp, ExceptionInfo->ContextRecord->Rip ); #else swprintf_s(registerInfo, _countof(registerInfo),TEXT("eax=0x%p, ebx=0x%p, edx=0x%p, ecx=0x%p, esi=0x%p, edi=0x%p, ebp=0x%p, esp=0x%p, eip=0x%p"), ExceptionInfo->ContextRecord->Eax, ExceptionInfo->ContextRecord->Ebx, ExceptionInfo->ContextRecord->Edx, ExceptionInfo->ContextRecord->Ecx, ExceptionInfo->ContextRecord->Esi, ExceptionInfo->ContextRecord->Edi, ExceptionInfo->ContextRecord->Ebp, ExceptionInfo->ContextRecord->Esp, ExceptionInfo->ContextRecord->Eip ); #endif wcscat_s(message, _countof(message), registerInfo); MessageBox(0, message, TEXT("Exception! Please report it!"), MB_ICONERROR); return EXCEPTION_EXECUTE_HANDLER; } diff --git a/Scylla/scylla_export_functions.def b/Scylla/scylla_export_functions.def index 2695344..fe5cb89 100644 --- a/Scylla/scylla_export_functions.def +++ b/Scylla/scylla_export_functions.def @@ -1,10 +1,11 @@ EXPORTS ScyllaDumpCurrentProcessW @1 ScyllaDumpCurrentProcessA @2 ScyllaDumpProcessW @3 ScyllaDumpProcessA @4 ScyllaRebuildFileW @5 ScyllaRebuildFileA @6 ScyllaVersionInformationW @7 ScyllaVersionInformationA @8 ScyllaVersionInformationDword @9 + ScyllaStartGui @10