Page MenuHomedesp's stash

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Scylla.sln b/Scylla.sln
new file mode 100644
index 0000000..cca0ab2
--- /dev/null
+++ b/Scylla.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scylla", "Scylla\Scylla.vcxproj", "{710434C9-FC4B-4F1D-B318-E10ADC78499F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|Win32.Build.0 = Debug|Win32
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|x64.ActiveCfg = Debug|x64
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|x64.Build.0 = Debug|x64
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|Win32.ActiveCfg = Release|Win32
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|Win32.Build.0 = Release|Win32
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|x64.ActiveCfg = Release|x64
+ {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Scylla/AboutGui.cpp b/Scylla/AboutGui.cpp
new file mode 100644
index 0000000..0a87d51
--- /dev/null
+++ b/Scylla/AboutGui.cpp
@@ -0,0 +1,25 @@
+#include "AboutGui.h"
+#include "definitions.h"
+
+INT_PTR AboutGui::initDialog(HINSTANCE hInstance, HWND hWndParent)
+{
+ return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT),hWndParent, (DLGPROC)aboutDlgProc);
+}
+
+LRESULT CALLBACK AboutGui::aboutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ SetDlgItemText(hWnd,IDC_STATIC_ABOUT, TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)TEXT("\n\n")TEXT(DEVELOPED)TEXT("\n\n\n")TEXT(CREDIT_DISTORM)TEXT("\n")TEXT(CREDIT_YODA)TEXT("\n\n")TEXT(GREETINGS)TEXT("\n\n\n")TEXT(VISIT));
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_ABOUT_OK:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
\ No newline at end of file
diff --git a/Scylla/AboutGui.h b/Scylla/AboutGui.h
new file mode 100644
index 0000000..2fcd9d8
--- /dev/null
+++ b/Scylla/AboutGui.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "MainGui.h"
+
+
+class AboutGui {
+public:
+
+ static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent);
+
+private:
+ static LRESULT CALLBACK aboutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+};
\ No newline at end of file
diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp
new file mode 100644
index 0000000..7586b48
--- /dev/null
+++ b/Scylla/ApiReader.cpp
@@ -0,0 +1,1103 @@
+
+#include "ApiReader.h"
+
+#include "Logger.h"
+#include "definitions.h"
+#include "SystemInformation.h"
+
+stdext::hash_multimap<DWORD_PTR, ApiInfo *> ApiReader::apiList; //api look up table
+std::map<DWORD_PTR, ImportModuleThunk> * ApiReader::moduleThunkList; //store found apis
+
+DWORD_PTR ApiReader::minApiAddress = 0xFFFFFFFF;
+DWORD_PTR ApiReader::maxApiAddress = 0;
+
+//#define DEBUG_COMMENTS
+
+void ApiReader::readApisFromModuleList()
+{
+ for (unsigned int i = 0; i < moduleList.size();i++)
+ {
+ setModulePriority(&moduleList[i]);
+
+ if (moduleList[i].modBaseAddr + moduleList[i].modBaseSize > maxValidAddress)
+ {
+ maxValidAddress = moduleList[i].modBaseAddr + moduleList[i].modBaseSize;
+ }
+
+ Logger::printfDialog(TEXT("Module parsing: %s"),moduleList[i].fullPath);
+
+ if (!moduleList[i].isAlreadyParsed)
+ {
+ parseModule(&moduleList[i]);
+ }
+ }
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Address Min ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Max ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\nimagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" maxValidAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),minApiAddress,maxApiAddress,targetImageBase,maxValidAddress);
+#endif
+}
+
+void ApiReader::parseModule(ModuleInfo *module)
+{
+ module->parsing = true;
+
+ if (isWinSxSModule(module))
+ {
+ parseModuleWithMapping(module);
+ }
+ else if (isModuleLoadedInOwnProcess(module))
+ {
+ parseModuleWithOwnProcess(module);
+ }
+ else
+ {
+ parseModuleWithProcess(module);
+ }
+
+
+ module->isAlreadyParsed = true;
+}
+
+void ApiReader::parseModuleWithMapping(ModuleInfo *moduleInfo)
+{
+ LPVOID fileMapping = 0;
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+
+ fileMapping = createFileMappingViewRead(moduleInfo->fullPath);
+
+ if (fileMapping == 0)
+ return;
+
+ pDosHeader = (PIMAGE_DOS_HEADER)fileMapping;
+ pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew));
+
+ if (isPeAndExportTableValid(pNtHeader))
+ {
+ parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping);
+ }
+
+
+ UnmapViewOfFile(fileMapping);
+
+}
+
+inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader)
+{
+ if ((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer,char * functionNameParent, DWORD_PTR rvaParent, DWORD_PTR ordinalParent, ModuleInfo *moduleParent)
+{
+ size_t dllNameLength = 0;
+ DWORD_PTR ordinal = 0;
+ ModuleInfo *module = 0;
+ DWORD_PTR vaApi = 0;
+ DWORD_PTR rvaApi = 0;
+ char dllName[100] = {0};
+ WCHAR dllNameW[100] = {0};
+ char *fordwardedString = (char *)vaStringPointer;
+ char *searchFunctionName = strchr(fordwardedString, '.');
+
+
+ if (!searchFunctionName)
+ return;
+
+ dllNameLength = searchFunctionName - fordwardedString;
+
+ if (dllNameLength >= 99)
+ {
+ return;
+ }
+ else
+ {
+ strncpy_s(dllName,sizeof(dllName),fordwardedString,dllNameLength);
+ }
+
+ searchFunctionName++;
+
+ //Windows 7
+ if (!strncmp(dllName,"api-ms-win-", 11))
+ {
+ /*
+ Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html
+ */
+
+ FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName);
+
+ if (addy != 0)
+ {
+ addApi(functionNameParent,0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent);
+ }
+
+ return;
+ }
+
+ strcat_s(dllName,sizeof(dllName),".dll");
+
+ size_t convertedChars = 0;
+ mbstowcs_s(&convertedChars, dllNameW, strlen(dllName) + 1, dllName, _TRUNCATE);
+
+ if (!_wcsicmp(dllNameW, moduleParent->getFilename()))
+ {
+ module = moduleParent;
+ }
+ else
+ {
+ module = findModuleByName(dllNameW);
+ }
+
+ if (module != 0) // module == 0 -> can be ignored
+ {
+ /*if ((module->isAlreadyParsed == false) && (module != moduleParent))
+ {
+ //do API extract
+
+ if (module->parsing == true)
+ {
+ //some stupid circle dependency
+ printf("stupid circle dependency %s\n",module->getFilename());
+ }
+ else
+ {
+ parseModule(module);
+ }
+ }*/
+
+ if (strchr(searchFunctionName,'#'))
+ {
+ //forwarding by ordinal
+ searchFunctionName++;
+ ordinal = atoi(searchFunctionName);
+ findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi);
+ }
+ else
+ {
+ findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi);
+ }
+
+ if (rvaApi == 0)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"handleForwardedApi :: Api not found, this is really BAD! %S\r\n",fordwardedString);
+#endif
+ }
+ else
+ {
+ addApi(functionNameParent,0, ordinalParent, vaApi, rvaApi, true, moduleParent);
+ }
+ }
+
+}
+
+ModuleInfo * ApiReader::findModuleByName(WCHAR *name)
+{
+ for (unsigned int i = 0; i < moduleList.size(); i++) {
+ if (!_wcsicmp(moduleList[i].getFilename(), name))
+ {
+ return &moduleList[i];
+ }
+ }
+
+ return 0;
+}
+
+void ApiReader::addApiWithoutName(DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo)
+{
+ addApi(0, 0, ordinal, va, rva, isForwarded, moduleInfo);
+}
+
+void ApiReader::addApi(char *functionName, WORD hint, DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo)
+{
+ ApiInfo *apiInfo = new ApiInfo();
+
+ if ((functionName != 0) && (strlen(functionName) < MAX_PATH))
+ {
+ strcpy_s(apiInfo->name, MAX_PATH, functionName);
+ }
+ else
+ {
+ apiInfo->name[0] = 0x00;
+ }
+
+ apiInfo->ordinal = ordinal;
+ apiInfo->isForwarded = isForwarded;
+ apiInfo->module = moduleInfo;
+ apiInfo->rva = rva;
+ apiInfo->va = va;
+ apiInfo->hint = hint;
+
+ setMinMaxApiAddress(va);
+
+ moduleInfo->apiList.push_back(apiInfo);
+
+ apiList.insert(API_Pair(va, apiInfo));
+}
+
+BYTE * ApiReader::getHeaderFromProcess(ModuleInfo * module)
+{
+ BYTE *bufferHeader = 0;
+ DWORD readSize = 0;
+
+ if (module->modBaseSize < PE_HEADER_BYTES_COUNT)
+ {
+ readSize = module->modBaseSize;
+ }
+ else
+ {
+ readSize = PE_HEADER_BYTES_COUNT;
+ }
+
+ bufferHeader = new BYTE[readSize];
+
+ if(!readMemoryFromProcess(module->modBaseAddr, readSize, bufferHeader))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"getHeaderFromProcess :: Error reading header\r\n");
+#endif
+ delete[] bufferHeader;
+ return 0;
+ }
+ else
+ {
+ return bufferHeader;
+ }
+}
+
+BYTE * ApiReader::getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader)
+{
+ DWORD readSize = 0;
+ BYTE *bufferExportTable = 0;
+
+ readSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
+
+ if (readSize < (sizeof(IMAGE_EXPORT_DIRECTORY) + 8))
+ {
+ //Something is wrong with the PE Header
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"Something is wrong with the PE Header here Export table size %d\r\n",readSize);
+#endif
+ readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100;
+ }
+
+ if (readSize)
+ {
+ bufferExportTable = new BYTE[readSize];
+
+ if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"getExportTableFromProcess :: Error reading export table from process\r\n");
+#endif
+ delete[] bufferExportTable;
+ return 0;
+ }
+ else
+ {
+ return bufferExportTable;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void ApiReader::parseModuleWithProcess(ModuleInfo * module)
+{
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+ BYTE *bufferHeader = 0;
+ BYTE *bufferExportTable = 0;
+
+
+ bufferHeader = getHeaderFromProcess(module);
+
+ if (bufferHeader == 0)
+ return;
+
+ pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
+ pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
+
+ if (isPeAndExportTableValid(pNtHeader))
+ {
+ bufferExportTable = getExportTableFromProcess(module, pNtHeader);
+
+ if(bufferExportTable)
+ {
+ parseExportTable(module,pNtHeader,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+ delete[] bufferExportTable;
+ }
+ }
+
+ delete[] bufferHeader;
+}
+
+void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress)
+{
+ DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
+ WORD *addressOfNameOrdinalsArray = 0;
+ char *functionName = 0;
+ DWORD_PTR RVA = 0, VA = 0, ordinal = 0;
+ DWORD i = 0, j = 0;
+ bool withoutName;
+
+
+ addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
+ addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
+ addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"parseExportTable :: module %s NumberOfNames %X\r\n",module->fullPath,pExportDir->NumberOfNames);
+#endif
+
+ for (i = 0; i < pExportDir->NumberOfNames; i++)
+ {
+ functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
+ ordinal = (addressOfNameOrdinalsArray[i] + pExportDir->Base);
+ RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
+ VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("parseExportTable :: api %S ")TEXT(" ordinal %d imagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),functionName,ordinal,module->modBaseAddr,RVA,VA);
+#endif
+ if (!isApiBlacklisted(functionName))
+ {
+ if (!isApiForwarded(RVA,pNtHeader))
+ {
+ addApi(functionName, (WORD)i, ordinal,VA,RVA,false,module);
+ }
+ else
+ {
+ //printf("Forwarded: %s\n",functionName);
+ handleForwardedApi(RVA + deltaAddress,functionName,RVA,ordinal,module);
+ }
+ }
+
+ }
+
+ /*Exports without name*/
+ if (pExportDir->NumberOfNames != pExportDir->NumberOfFunctions)
+ {
+ for (i = 0; i < pExportDir->NumberOfFunctions; i++)
+ {
+ withoutName = true;
+ for (j = 0; j < pExportDir->NumberOfNames; j++)
+ {
+ if(addressOfNameOrdinalsArray[j] == i)
+ {
+ withoutName = false;
+ break;
+ }
+ }
+ if (withoutName && addressOfFunctionsArray[i] != 0)
+ {
+ ordinal = (i+pExportDir->Base);
+ RVA = addressOfFunctionsArray[i];
+ VA = (addressOfFunctionsArray[i] + module->modBaseAddr);
+
+
+ if (!isApiForwarded(RVA,pNtHeader))
+ {
+ addApiWithoutName(ordinal,VA,RVA,false,module);
+ }
+ else
+ {
+ handleForwardedApi(RVA + deltaAddress,0,RVA,ordinal,module);
+ }
+
+ }
+ }
+ }
+}
+
+void ApiReader::findApiByModuleAndOrdinal(ModuleInfo * module, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
+{
+ findApiByModule(module,0,ordinal,vaApi,rvaApi);
+}
+
+void ApiReader::findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
+{
+ findApiByModule(module,searchFunctionName,0,vaApi,rvaApi);
+}
+
+void ApiReader::findApiByModule(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
+{
+ if (isModuleLoadedInOwnProcess(module))
+ {
+ HMODULE hModule = GetModuleHandle(module->getFilename());
+
+ if (hModule)
+ {
+ if (ordinal)
+ {
+ *vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal);
+ }
+ else
+ {
+ *vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName);
+ }
+
+
+ if (vaApi)
+ {
+ *rvaApi = (*vaApi) - (DWORD_PTR)hModule;
+ *vaApi = (*rvaApi) + module->modBaseAddr;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("findApiByModule :: vaApi == NULL, should never happen %S\r\n"),searchFunctionName);
+#endif
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("findApiByModule :: hModule == NULL, should never happen %s\r\n"),module->getFilename());
+#endif
+ }
+ }
+ else
+ {
+ //search api in extern process
+ findApiInProcess(module,searchFunctionName,ordinal,vaApi,rvaApi);
+ }
+}
+
+bool ApiReader::isModuleLoadedInOwnProcess(ModuleInfo * module)
+{
+ for (unsigned int i = 0; i < ownModuleList.size(); i++)
+ {
+ if (!_wcsicmp(module->fullPath, ownModuleList[i].fullPath))
+ {
+ //printf("isModuleLoadedInOwnProcess :: %s %s\n",module->fullPath,ownModuleList[i].fullPath);
+ return true;
+ }
+ }
+ return false;
+}
+
+void ApiReader::parseModuleWithOwnProcess( ModuleInfo * module )
+{
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+ HMODULE hModule = GetModuleHandle(module->getFilename());
+
+ if (hModule)
+ {
+ pDosHeader = (PIMAGE_DOS_HEADER)hModule;
+ pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + (DWORD_PTR)(pDosHeader->e_lfanew));
+
+ if (isPeAndExportTableValid(pNtHeader))
+ {
+ parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)hModule);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("parseModuleWithOwnProcess :: hModule is NULL\r\n"));
+#endif
+ }
+}
+
+bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader)
+{
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ Logger::printfDialog(TEXT("-> IMAGE_NT_SIGNATURE doesn't match."));
+ return false;
+ }
+ else if ((pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) || (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0))
+ {
+ Logger::printfDialog(TEXT("-> No export table."));
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void ApiReader::findApiInProcess(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
+{
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+ BYTE *bufferHeader = 0;
+ BYTE *bufferExportTable = 0;
+
+
+ bufferHeader = getHeaderFromProcess(module);
+
+ if (bufferHeader == 0)
+ return;
+
+ pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
+ pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
+
+ if (isPeAndExportTableValid(pNtHeader))
+ {
+ bufferExportTable = getExportTableFromProcess(module, pNtHeader);
+
+ if(bufferExportTable)
+ {
+ findApiInExportTable(module,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,searchFunctionName,ordinal,vaApi,rvaApi);
+ delete[] bufferExportTable;
+ }
+ }
+
+ delete[] bufferHeader;
+}
+
+bool ApiReader::findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
+{
+ DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
+ WORD *addressOfNameOrdinalsArray = 0;
+ char *functionName = 0;
+ DWORD i = 0, j = 0;
+
+ addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
+ addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
+ addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
+
+ if (searchFunctionName)
+ {
+ for (i = 0; i < pExportDir->NumberOfNames; i++)
+ {
+ functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
+
+ if (!strcmp(functionName,searchFunctionName))
+ {
+ *rvaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
+ *vaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < pExportDir->NumberOfFunctions; i++)
+ {
+ if (ordinal == (i+pExportDir->Base))
+ {
+ *rvaApi = addressOfFunctionsArray[i];
+ *vaApi = (addressOfFunctionsArray[i] + module->modBaseAddr);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+void ApiReader::setModulePriority(ModuleInfo * module)
+{
+ WCHAR *moduleFileName = module->getFilename();
+
+ if (!_wcsicmp(moduleFileName, TEXT("kernelbase.dll")))
+ {
+ module->priority = 0;
+ }
+ else if (!_wcsicmp(moduleFileName, TEXT("ntdll.dll")))
+ {
+ module->priority = 0;
+ }
+ else if (!_wcsicmp(moduleFileName, TEXT("shlwapi.dll")))
+ {
+ module->priority = 0;
+ }
+ else if (!_wcsicmp(moduleFileName, TEXT("kernel32.dll")))
+ {
+ module->priority = 2;
+ }
+ else
+ {
+ module->priority = 1;
+ }
+}
+
+bool ApiReader::isApiAddressValid(DWORD_PTR virtualAddress)
+{
+ return apiList.count(virtualAddress) > 0;
+}
+
+ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect)
+{
+ stdext::hash_multimap<DWORD_PTR, ApiInfo *>::iterator it1, it2;
+ size_t c = 0;
+ size_t countDuplicates = apiList.count(virtualAddress);
+ int countHighPriority = 0;
+ ApiInfo *apiFound = 0;
+
+
+ if (countDuplicates == 0)
+ {
+ Logger::printfDialog(TEXT("getApiByVirtualAddress :: No Api found ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress);
+ return 0;
+ }
+ else if (countDuplicates == 1)
+ {
+ //API is 100% correct
+ *isSuspect = false;
+ it1 = apiList.find(virtualAddress); // Find first match.
+ return (ApiInfo *)((*it1).second);
+ }
+ else
+ {
+ it1 = apiList.find(virtualAddress); // Find first match.
+ it2 = it1;
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+
+ if (apiFound->module->priority >= 1) //1 == high priority
+ {
+ countHighPriority++;
+ }
+ }
+
+ it1 = it2;
+
+ if (countHighPriority == 0)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == 0 ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),virtualAddress);
+#endif
+ *isSuspect = true;
+ return (ApiInfo *)((*it1).second);
+ }
+ else if (countHighPriority == 1)
+ {
+ //API is 100% correct if countHighPriority == 1
+
+ *isSuspect = false;
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+
+ if (apiFound->module->priority >= 1) //1 == high priority
+ {
+ return apiFound;
+ }
+ }
+ }
+ else
+ {
+ //API not 100% correct
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == %d ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),countHighPriority,virtualAddress);
+#endif
+ *isSuspect = true;
+ /*for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+ Logger::printfDialog("%s - %s %X %X\n",apiFound->name,apiFound->module->getFilename(),apiFound->rva, apiFound->ordinal);
+ }
+ it1 = it2;*/
+
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+
+ //prefer APIs with a name
+ if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority
+ {
+ //prefer ANSI/UNICODE APIs
+ if (strrchr(apiFound->name,TEXT('W')) || strrchr(apiFound->name,TEXT('A')))
+ {
+ return apiFound;
+ }
+ }
+ }
+
+ it1 = it2;
+
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+
+ //prefer APIs with a name
+ if (apiFound->module->priority == 2 && !strrchr(apiFound->name,TEXT('_'))) //1 == high priority
+ {
+ return apiFound;
+ }
+ }
+
+ it1 = it2;
+
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+ if (apiFound->module->priority == 1 && apiFound->name[0] != 0x00) //1 == high priority
+ {
+ return apiFound;
+ }
+ }
+
+ it1 = it2;
+
+ for (c = 0; c < countDuplicates; c++, it1++)
+ {
+ apiFound = (ApiInfo *)((*it1).second);
+
+ if (apiFound->module->priority == 1) //1 == high priority
+ {
+ return apiFound;
+ }
+ }
+ }
+ }
+
+ //is never reached
+ Logger::printfDialog(TEXT("getApiByVirtualAddress :: There is a big bug\n"));
+ return (ApiInfo *) 1;
+}
+
+void ApiReader::setMinMaxApiAddress(DWORD_PTR virtualAddress)
+{
+ if (virtualAddress < minApiAddress)
+ {
+ minApiAddress = virtualAddress - 1;
+ }
+ if (virtualAddress > maxApiAddress)
+ {
+ maxApiAddress = virtualAddress + 1;
+ }
+}
+
+void ApiReader::readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map<DWORD_PTR, ImportModuleThunk> &moduleListNew)
+{
+ moduleThunkList = &moduleListNew;
+ BYTE *dataIat = new BYTE[sizeIAT];
+ if (readMemoryFromProcess(addressIAT,sizeIAT,dataIat))
+ {
+ parseIAT(addressIAT,dataIat,sizeIAT);
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ApiReader::readAndParseIAT :: error reading iat ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),addressIAT);
+#endif
+ }
+
+ delete[] dataIat;
+}
+
+void ApiReader::parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size)
+{
+ ApiInfo *apiFound = 0;
+ ModuleInfo *module = 0;
+ bool isSuspect = false;
+ int countApiFound = 0, countApiNotFound = 0;
+ DWORD_PTR * pIATAddress = (DWORD_PTR *)iatBuffer;
+ SIZE_T sizeIAT = size / sizeof(DWORD_PTR);
+
+ bool foundModuleBreak = false;
+
+ for (SIZE_T i = 0; i < sizeIAT; i++)
+ {
+ //Logger::printfDialog("%08X %08X %d von %d",addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer,pIATAddress[i],i,sizeIAT);
+
+
+ if (pIATAddress[i] == 0 || pIATAddress[i] == -1)
+ {
+ /*if (pIATAddress[i+1] != 0)
+ {
+ printf("parseIAT :: Module break\n");
+ }*/
+ /*else
+ {
+ printf("parseIAT :: IAT finished\n");
+ break;
+ }*/
+ foundModuleBreak = true;
+ }
+ else if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) )
+ {
+
+ apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect);
+ if (apiFound == (ApiInfo *)1)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("apiFound == (ApiInfo *)1 -> ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),pIATAddress[i]);
+#endif
+ }
+ else if (apiFound)
+ {
+ countApiFound++;
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %s %d %s\r\n"),apiFound->va, apiFound->module->getFilename(), apiFound->ordinal,apiFound->name);
+#endif
+ if (module != apiFound->module)
+ {
+ module = apiFound->module;
+ addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, true, isSuspect);
+ }
+ else
+ {
+ addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, false, isSuspect);
+ }
+
+ }
+ else
+ {
+ countApiNotFound++;
+ addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
+ //printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
+ }
+ }
+ else
+ {
+ //printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
+ countApiNotFound++;
+ addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
+ }
+ }
+
+ Logger::printfDialog(TEXT("IAT parsing finished, found %d valid APIs, missed %d APIs"),countApiFound,countApiNotFound);
+}
+
+void ApiReader::addFoundApiToModuleList(DWORD_PTR iatAddressVA, ApiInfo * apiFound, bool isNewModule, bool isSuspect)
+{
+ if (isNewModule)
+ {
+ addModuleToModuleList(apiFound->module->getFilename(), iatAddressVA - targetImageBase);
+ }
+ addFunctionToModuleList(apiFound, iatAddressVA, iatAddressVA - targetImageBase, apiFound->ordinal, true, isSuspect);
+}
+
+bool ApiReader::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
+{
+ ImportModuleThunk module;
+
+ module.firstThunk = firstThunk;
+ wcscpy_s(module.moduleName, MAX_PATH, moduleName);
+
+ (*moduleThunkList).insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
+
+ return true;
+}
+
+void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
+{
+ ImportModuleThunk module;
+
+ module.firstThunk = firstThunk;
+ wcscpy_s(module.moduleName, MAX_PATH, TEXT("?"));
+
+ (*moduleThunkList).insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
+}
+
+bool ApiReader::addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect)
+{
+ ImportThunk import;
+ ImportModuleThunk * module = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+
+ if ((*moduleThunkList).size() > 1)
+ {
+ iterator1 = (*moduleThunkList).begin();
+ while (iterator1 != (*moduleThunkList).end())
+ {
+ if (rva >= iterator1->second.firstThunk)
+ {
+ iterator1++;
+ if (iterator1 == (*moduleThunkList).end())
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ else if (rva < iterator1->second.firstThunk)
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n"));
+#endif
+ break;
+ }
+ }
+ }
+ else
+ {
+ iterator1 = (*moduleThunkList).begin();
+ module = &(iterator1->second);
+ }
+
+ if (!module)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
+#endif
+ return false;
+ }
+
+
+ import.suspect = suspect;
+ import.valid = valid;
+ import.va = va;
+ import.rva = rva;
+ import.apiAddressVA = apiFound->va;
+ import.ordinal = ordinal;
+ import.hint = (WORD)apiFound->hint;
+
+ wcscpy_s(import.moduleName, MAX_PATH, apiFound->module->getFilename());
+ strcpy_s(import.name, MAX_PATH, apiFound->name);
+
+ module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
+
+ return true;
+}
+
+void ApiReader::clearAll()
+{
+ minApiAddress = -1;
+ maxApiAddress = 0;
+
+ for ( stdext::hash_multimap<DWORD_PTR, ApiInfo *>::iterator it = apiList.begin(); it != apiList.end(); ++it )
+ {
+ delete it->second;
+ }
+ apiList.clear();
+
+ if (moduleThunkList != 0)
+ {
+ (*moduleThunkList).clear();
+ }
+}
+
+bool ApiReader::addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress)
+{
+ ImportThunk import;
+ ImportModuleThunk * module = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ DWORD_PTR rva = iatAddressVA - targetImageBase;
+
+ if ((*moduleThunkList).size() > 0)
+ {
+ iterator1 = (*moduleThunkList).begin();
+ while (iterator1 != (*moduleThunkList).end())
+ {
+ if (rva >= iterator1->second.firstThunk)
+ {
+ iterator1++;
+ if (iterator1 == (*moduleThunkList).end())
+ {
+ iterator1--;
+ //new unknown module
+ if (iterator1->second.moduleName[0] == L'?')
+ {
+ module = &(iterator1->second);
+ }
+ else
+ {
+ addUnknownModuleToModuleList(rva);
+ module = &((*moduleThunkList).find(rva)->second);
+ }
+
+ break;
+ }
+ else if (rva < iterator1->second.firstThunk)
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n"));
+#endif
+ break;
+ }
+ }
+ }
+ else
+ {
+ //new unknown module
+ addUnknownModuleToModuleList(rva);
+ module = &((*moduleThunkList).find(rva)->second);
+ }
+
+ if (!module)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
+#endif
+ return false;
+ }
+
+
+ import.suspect = true;
+ import.valid = false;
+ import.va = iatAddressVA;
+ import.rva = rva;
+ import.apiAddressVA = apiAddress;
+ import.ordinal = 0;
+
+ wcscpy_s(import.moduleName, MAX_PATH, TEXT("?"));
+ strcpy_s(import.name, MAX_PATH, "?");
+
+ module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
+
+ return true;
+}
+
+bool ApiReader::isApiBlacklisted( const char * functionName )
+{
+ if (SystemInformation::currenOS < WIN_VISTA_32)
+ {
+ if (!strcmp(functionName, "RestoreLastError"))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+
+ /*#ifdef _WIN64
+ else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer"))
+ {
+ return true;
+ }
+#endif*/
+}
+
+bool ApiReader::isWinSxSModule( ModuleInfo * module )
+{
+ if (wcsstr(module->fullPath, TEXT("\\WinSxS\\")))
+ {
+ return true;
+ }
+ else if (wcsstr(module->fullPath, TEXT("\\winsxs\\")))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/Scylla/ApiReader.h b/Scylla/ApiReader.h
new file mode 100644
index 0000000..de09da2
--- /dev/null
+++ b/Scylla/ApiReader.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "ProcessAccessHelp.h"
+#include "Thunks.h"
+
+typedef std::pair<DWORD_PTR, ApiInfo *> API_Pair;
+
+class ApiReader : public ProcessAccessHelp {
+public:
+ static stdext::hash_multimap<DWORD_PTR, ApiInfo *> apiList; //api look up table
+
+ static std::map<DWORD_PTR, ImportModuleThunk> * moduleThunkList; //store found apis
+
+ static DWORD_PTR minApiAddress;
+ static DWORD_PTR maxApiAddress;
+
+ /*
+ * Read all APIs from target process
+ */
+ void readApisFromModuleList();
+
+
+ bool isApiAddressValid(DWORD_PTR virtualAddress);
+ ApiInfo * getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect);
+ void readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT,std::map<DWORD_PTR, ImportModuleThunk> &moduleListNew );
+
+ void clearAll();
+
+private:
+ void parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size);
+
+ void addApi(char *functionName, WORD hint, DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo);
+ void addApiWithoutName(DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo);
+ inline bool isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader);
+ void handleForwardedApi(DWORD_PTR vaStringPointer,char *functionNameParent,DWORD_PTR rvaParent, DWORD_PTR ordinalParent, ModuleInfo *moduleParent);
+ void parseModule(ModuleInfo *module);
+ void parseModuleWithProcess(ModuleInfo * module);
+
+
+ void parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress);
+
+ ModuleInfo * findModuleByName(WCHAR *name);
+
+ void findApiByModuleAndOrdinal(ModuleInfo * module, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
+ void findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
+ void findApiByModule(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
+
+ bool isModuleLoadedInOwnProcess( ModuleInfo * module );
+ void parseModuleWithOwnProcess( ModuleInfo * module );
+ bool isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader);
+ void findApiInProcess( ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi );
+ bool findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
+
+ BYTE * getHeaderFromProcess(ModuleInfo * module);
+ BYTE * getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader);
+
+ void setModulePriority(ModuleInfo * module);
+ void setMinMaxApiAddress(DWORD_PTR virtualAddress);
+
+
+ void parseModuleWithMapping(ModuleInfo *moduleInfo); //not used
+ void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo * apiFound, bool isNewModule, bool isSuspect);
+ bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk);
+ bool addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect);
+ bool addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress);
+
+ void addUnknownModuleToModuleList(DWORD_PTR firstThunk);
+ bool isApiBlacklisted( const char * functionName );
+ bool isWinSxSModule( ModuleInfo * module );
+};
\ No newline at end of file
diff --git a/Scylla/ConfigurationHolder.cpp b/Scylla/ConfigurationHolder.cpp
new file mode 100644
index 0000000..d7af60b
--- /dev/null
+++ b/Scylla/ConfigurationHolder.cpp
@@ -0,0 +1,266 @@
+
+#include "ConfigurationHolder.h"
+#include "resource.h"
+
+WCHAR ConfigurationHolder::configPath[MAX_PATH];
+ConfigurationInitializer ConfigurationHolder::config;
+
+//#define DEBUG_COMMENTS
+
+ConfigurationInitializer::ConfigurationInitializer()
+{
+ ConfigObject configObject;
+
+ mapConfig[USE_PE_HEADER_FROM_DISK] = configObject.newValues(L"USE_PE_HEADER_FROM_DISK", Boolean, IDC_CHECK_PE_HEADER_FROM_DISK);
+ mapConfig[DEBUG_PRIVILEGE] = configObject.newValues(L"DEBUG_PRIVILEGE", Boolean, IDC_CHECK_DEBUG_PRIVILEGES);
+ mapConfig[CREATE_BACKUP] = configObject.newValues(L"CREATE_BACKUP", Boolean, IDC_CHECK_CREATE_BACKUP);
+ mapConfig[DLL_INJECTION_AUTO_UNLOAD] = configObject.newValues(L"DLL_INJECTION_AUTO_UNLOAD", Boolean, IDC_CHECK_UNLOAD_DLL);
+ mapConfig[UPDATE_HEADER_CHECKSUM] = configObject.newValues(L"UPDATE_HEADER_CHECKSUM", Boolean, IDC_CHECK_HEADER_CHECKSUM);
+
+ mapConfig[IAT_SECTION_NAME] = configObject.newValues(L"IAT_SECTION_NAME", String, IDC_OPTIONS_SECTIONNAME);
+}
+
+
+bool ConfigurationHolder::loadConfiguration()
+{
+ std::map<Configuration, ConfigObject>::iterator mapIter;
+
+ if (!buildConfigFilePath())
+ {
+ return false;
+ }
+
+ for (mapIter = config.mapConfig.begin() ; mapIter != config.mapConfig.end(); mapIter++)
+ {
+ if (!loadConfig((*mapIter).second))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ConfigurationHolder::saveConfiguration()
+{
+ std::map<Configuration, ConfigObject>::iterator mapIter;
+
+ if (!buildConfigFilePath())
+ {
+ return false;
+ }
+
+ for (mapIter = config.mapConfig.begin() ; mapIter != config.mapConfig.end(); mapIter++)
+ {
+ if (!saveConfig((*mapIter).second))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ConfigurationHolder::saveNumericToConfigFile(ConfigObject & configObject, int nBase)
+{
+
+ if (nBase == 16)
+ {
+#ifdef _WIN64
+ swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%016I64X"),configObject.valueNumeric);
+#else
+ swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%08X"),configObject.valueNumeric);
+#endif
+ }
+ else
+ {
+#ifdef _WIN64
+ swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%I64u"),configObject.valueNumeric);
+#else
+ swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%u"),configObject.valueNumeric);
+#endif
+ }
+
+
+ if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, configObject.valueString, configPath))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ConfigurationHolder::readNumericFromConfigFile(ConfigObject & configObject, int nBase)
+{
+ GetPrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME),configObject.name,TEXT(""),configObject.valueString, 100, configPath);
+
+ if (wcslen(configObject.valueString) > 0)
+ {
+
+#ifdef _WIN64
+ configObject.valueNumeric = _wcstoui64(configObject.valueString, NULL, nBase);
+#else
+ configObject.valueNumeric = wcstoul(configObject.valueString, NULL, nBase);
+#endif
+
+ if (configObject.valueNumeric)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool ConfigurationHolder::saveStringToConfigFile(ConfigObject & configObject)
+{
+ if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, configObject.valueString, configPath))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ConfigurationHolder::readStringFromConfigFile(ConfigObject & configObject)
+{
+ GetPrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME),configObject.name,TEXT(""),configObject.valueString, 100, configPath);
+
+ if (wcslen(configObject.valueString) > 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ConfigurationHolder::readBooleanFromConfigFile(ConfigObject & configObject)
+{
+ if (GetPrivateProfileInt(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, 0, configPath) != 0)
+ {
+ configObject.valueNumeric = 1;
+ }
+ else
+ {
+ configObject.valueNumeric = 0;
+ }
+
+ return true;
+}
+
+bool ConfigurationHolder::saveBooleanToConfigFile(ConfigObject & configObject)
+{
+ WCHAR *boolValue = 0;
+
+ if (configObject.valueNumeric == 0)
+ {
+ boolValue = L"0";
+ }
+ else
+ {
+ boolValue = L"1";
+ }
+
+ if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, boolValue, configPath))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ConfigurationHolder::loadConfig(ConfigObject & configObject)
+{
+ switch (configObject.configType)
+ {
+ case String:
+ return readStringFromConfigFile(configObject);
+ break;
+ case Boolean:
+ return readBooleanFromConfigFile(configObject);
+ break;
+ case Decimal:
+ return readNumericFromConfigFile(configObject, 10);
+ break;
+ case Hexadecimal:
+ return readNumericFromConfigFile(configObject, 16);
+ break;
+ default:
+ return false;
+ }
+}
+
+bool ConfigurationHolder::saveConfig(ConfigObject & configObject)
+{
+ switch (configObject.configType)
+ {
+ case String:
+ return saveStringToConfigFile(configObject);
+ break;
+ case Boolean:
+ return saveBooleanToConfigFile(configObject);
+ break;
+ case Decimal:
+ return saveNumericToConfigFile(configObject, 10);
+ break;
+ case Hexadecimal:
+ return saveNumericToConfigFile(configObject, 16);
+ break;
+ default:
+ return false;
+ }
+}
+
+ConfigObject * ConfigurationHolder::getConfigObject(Configuration configuration)
+{
+ return &(config.mapConfig[configuration]);
+}
+
+bool ConfigurationHolder::buildConfigFilePath()
+{
+ ZeroMemory(configPath, sizeof(configPath));
+
+ if (!GetModuleFileName(0, configPath, _countof(configPath)))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("buildConfigFilePath :: GetModuleFileName failed %d\r\n",GetLastError());
+#endif
+ return false;
+ }
+
+ //remove exe file name
+ for (size_t i = wcslen(configPath) - 1; i >= 0; i--)
+ {
+ if (configPath[i] == L'\\')
+ {
+ configPath[i + 1] = 0;
+ break;
+ }
+ }
+
+ wcscat_s(configPath, _countof(configPath), TEXT(CONFIG_FILE_NAME) );
+
+ //wprintf(L"configPath %s\n\n", configPath);
+
+ return true;
+}
+
+std::map<Configuration, ConfigObject> & ConfigurationHolder::getConfigList()
+{
+ return config.mapConfig;
+}
\ No newline at end of file
diff --git a/Scylla/ConfigurationHolder.h b/Scylla/ConfigurationHolder.h
new file mode 100644
index 0000000..c617832
--- /dev/null
+++ b/Scylla/ConfigurationHolder.h
@@ -0,0 +1,100 @@
+
+#pragma once
+
+#include <windows.h>
+#include <stdio.h>
+#include <map>
+
+#define CONFIG_FILE_NAME "Scylla.ini"
+#define CONFIG_FILE_SECTION_NAME "SCYLLA_CONFIG"
+
+enum ConfigType {
+ String,
+ Decimal,
+ Hexadecimal,
+ Boolean
+};
+
+enum Configuration {
+ USE_PE_HEADER_FROM_DISK,
+ DEBUG_PRIVILEGE,
+ CREATE_BACKUP,
+ DLL_INJECTION_AUTO_UNLOAD,
+ IAT_SECTION_NAME,
+ UPDATE_HEADER_CHECKSUM,
+};
+
+#define CONFIG_OPTIONS_STRING_LENGTH 100
+
+class ConfigObject {
+public:
+ WCHAR name[MAX_PATH];
+ ConfigType configType;
+
+ DWORD_PTR valueNumeric;
+ WCHAR valueString[CONFIG_OPTIONS_STRING_LENGTH];
+
+ int dialogItemValue;
+
+ ConfigObject& newValues(WCHAR * configname, ConfigType config, int dlgValue)
+ {
+ wcscpy_s(name, MAX_PATH, configname);
+ configType = config;
+ valueNumeric = 0;
+ ZeroMemory(valueString, sizeof(valueString));
+ dialogItemValue = dlgValue;
+
+ return *this;
+ }
+
+ bool isTrue()
+ {
+ return (valueNumeric == 1);
+ }
+
+ void setTrue()
+ {
+ valueNumeric = 1;
+ }
+
+ void setFalse()
+ {
+ valueNumeric = 0;
+ }
+};
+
+class ConfigurationInitializer {
+public:
+ std::map<Configuration, ConfigObject> mapConfig;
+
+ ConfigurationInitializer();
+};
+
+class ConfigurationHolder {
+public:
+
+ static bool loadConfiguration();
+ static bool saveConfiguration();
+
+ static ConfigObject * getConfigObject(Configuration configuration);
+ static std::map<Configuration, ConfigObject> & getConfigList();
+
+private:
+ static ConfigurationInitializer config;
+ static WCHAR configPath[MAX_PATH];
+
+ static bool buildConfigFilePath();
+
+
+
+ static bool readStringFromConfigFile(ConfigObject & configObject);
+ static bool readBooleanFromConfigFile(ConfigObject & configObject);
+ static bool readNumericFromConfigFile(ConfigObject & configObject, int nBase);
+
+ static bool saveStringToConfigFile(ConfigObject & configObject);
+ static bool saveBooleanToConfigFile(ConfigObject & configObject);
+ static bool saveNumericToConfigFile(ConfigObject & configObject, int nBase);
+
+ static bool loadConfig(ConfigObject & configObject);
+ static bool saveConfig(ConfigObject & configObject);
+};
\ No newline at end of file
diff --git a/Scylla/DisassemblerGui.cpp b/Scylla/DisassemblerGui.cpp
new file mode 100644
index 0000000..c1331ef
--- /dev/null
+++ b/Scylla/DisassemblerGui.cpp
@@ -0,0 +1,262 @@
+#include "DisassemblerGui.h"
+#include "ProcessAccessHelp.h"
+
+HWND DisassemblerGui::hWndDlg = 0;
+HINSTANCE DisassemblerGui::hInstance = 0;
+DWORD_PTR DisassemblerGui::startAddress = 0;
+WCHAR DisassemblerGui::tempBuffer[100];
+
+INT_PTR DisassemblerGui::initDialog(HINSTANCE hInst, HWND hWndParent, DWORD_PTR address)
+{
+ hInstance = hInst;
+ startAddress = address;
+ return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_DISASSEMBLER),hWndParent, (DLGPROC)disassemblerDlgProc);
+}
+
+LRESULT CALLBACK DisassemblerGui::disassemblerDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ hWndDlg = hWnd;
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ addColumnsToDisassembler(GetDlgItem(hWnd, IDC_LIST_DISASSEMBLER));
+ displayDisassembly();
+ break;
+
+ case WM_CONTEXTMENU:
+ OnContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_PICKDLL_OK:
+ /*index = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_DLLSELECT));
+ if (index != -1)
+ {
+ selectedModule = &(*moduleList).at(index);
+ EndDialog(hWnd, 1);
+ }*/
+
+ return TRUE;
+ case IDC_BTN_PICKDLL_CANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void DisassemblerGui::addColumnsToDisassembler( HWND list )
+{
+ if (list)
+ {
+ LVCOLUMN * lvc = (LVCOLUMN*)malloc(sizeof(LVCOLUMN));
+
+ ListView_SetExtendedListViewStyleEx(list,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);
+
+ lvc->mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_LEFT;
+ lvc->cx = 105;
+ lvc->pszText = L"Address";
+ ListView_InsertColumn(list, COL_ADDRESS, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_CENTER;
+ lvc->cx = 40;
+ lvc->pszText = L"Size";
+ ListView_InsertColumn(list, COL_INSTRUCTION_SIZE, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_LEFT;
+ lvc->cx = 130;
+ lvc->pszText = L"OpCodes";
+ ListView_InsertColumn(list, COL_OPCODES, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_LEFT;
+ lvc->cx = 200;
+ lvc->pszText = L"Instructions";
+ ListView_InsertColumn(list, COL_INSTRUCTION, lvc);
+
+
+ free(lvc);
+ }
+}
+
+void DisassemblerGui::displayDisassembly()
+{
+ LVITEM item;
+ HWND hList = GetDlgItem(hWndDlg, IDC_LIST_DISASSEMBLER);
+
+ ListView_DeleteAllItems(hList);
+
+ item.mask = LVIF_TEXT;
+
+ BYTE * data = new BYTE[DISASSEMBLER_GUI_MEMORY_SIZE];
+
+ ProcessAccessHelp::readMemoryFromProcess(startAddress,DISASSEMBLER_GUI_MEMORY_SIZE, data);
+
+ ProcessAccessHelp::disassembleMemory(data,DISASSEMBLER_GUI_MEMORY_SIZE, startAddress);
+
+ for (unsigned int i = 0; i < ProcessAccessHelp::decodedInstructionsCount; i++)
+ {
+
+#ifdef _WIN64
+ swprintf_s(tempBuffer, _countof(tempBuffer),L"%016I64X",ProcessAccessHelp::decodedInstructions[i].offset);
+#else
+ swprintf_s(tempBuffer, _countof(tempBuffer),L"%08X",ProcessAccessHelp::decodedInstructions[i].offset);
+#endif
+
+ item.iItem = i;
+ item.iSubItem = COL_ADDRESS;
+ item.pszText = tempBuffer;
+ item.iItem = ListView_InsertItem(hList, &item);
+
+ swprintf_s(tempBuffer, _countof(tempBuffer),L"%02d",ProcessAccessHelp::decodedInstructions[i].size);
+
+ item.iSubItem = COL_INSTRUCTION_SIZE;
+ item.pszText = tempBuffer;
+ ListView_SetItem(hList, &item);
+
+ swprintf_s(tempBuffer, _countof(tempBuffer),L"%-24S",(char *)ProcessAccessHelp::decodedInstructions[i].instructionHex.p);
+
+ item.iSubItem = COL_OPCODES;
+ item.pszText = tempBuffer;
+ ListView_SetItem(hList, &item);
+
+ swprintf_s(tempBuffer, _countof(tempBuffer),L"%S%S%S",(char*)ProcessAccessHelp::decodedInstructions[i].mnemonic.p, ProcessAccessHelp::decodedInstructions[i].operands.length != 0 ? " " : "", (char*)ProcessAccessHelp::decodedInstructions[i].operands.p);
+
+ item.iSubItem = COL_INSTRUCTION;
+ item.pszText = tempBuffer;
+ ListView_SetItem(hList, &item);
+ }
+
+ delete [] data;
+}
+
+void DisassemblerGui::OnContextMenu(int x, int y)
+{
+ HWND hwnd = 0;
+ int selection;
+ POINT pt = { x, y }; // location of mouse click
+ HTREEITEM selectedTreeNode = 0;
+
+ if ((hwnd = mouseInDialogItem(IDC_LIST_DISASSEMBLER, pt)) != NULL)
+ {
+ HMENU hmenuTrackPopup = getCorrectSubMenu(IDR_MENU_DISASSEMBLER, 0);
+
+ BOOL menuItem = TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, 0);
+
+ if (menuItem)
+ {
+ selection = ListView_GetSelectionMark(hwnd);
+ if (selection != -1) //valid selection?
+ {
+ switch (menuItem)
+ {
+ case ID__DIS_ADDRESS:
+ getModuleListItem(COL_ADDRESS,selection,tempBuffer);
+ copyToClipboard();
+ break;
+ case ID__DIS_SIZE:
+ getModuleListItem(COL_INSTRUCTION_SIZE,selection,tempBuffer);
+ copyToClipboard();
+ break;
+ case ID__DIS_OPCODES:
+ getModuleListItem(COL_OPCODES,selection,tempBuffer);
+ copyToClipboard();
+ break;
+ case ID__DIS_INSTRUCTIONS:
+ getModuleListItem(COL_INSTRUCTION,selection,tempBuffer);
+ copyToClipboard();
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+void DisassemblerGui::copyToClipboard()
+{
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(tempBuffer));
+ LPVOID lock = GlobalLock(hMem);
+
+ CopyMemory(lock,tempBuffer, sizeof(tempBuffer));
+
+ if (!OpenClipboard(hWndDlg))
+ return;
+
+ EmptyClipboard();
+
+ GlobalUnlock(hMem);
+
+ SetClipboardData(CF_UNICODETEXT, hMem);
+ CloseClipboard();
+
+ GlobalFree(hMem);
+}
+
+void DisassemblerGui::getModuleListItem(int column, int iItem, WCHAR * buffer)
+{
+ LVITEM pitem = {0};
+ pitem.iItem = iItem;
+ pitem.iSubItem = column;
+ pitem.mask = LVIF_TEXT;
+ pitem.cchTextMax = 256;
+ pitem.pszText = buffer;
+ ListView_GetItem(GetDlgItem(hWndDlg, IDC_LIST_DISASSEMBLER),&pitem);
+}
+
+
+HMENU DisassemblerGui::getCorrectSubMenu(int menuItem, int subMenuItem)
+{
+ HMENU hmenu; // top-level menu
+ HMENU hmenuTrackPopup; // shortcut menu
+ // Load the menu resource.
+ if ((hmenu = LoadMenu(hInstance, MAKEINTRESOURCE(menuItem))) == NULL)
+ return 0;
+
+ hmenuTrackPopup = GetSubMenu(hmenu, subMenuItem);
+
+ if (hmenuTrackPopup)
+ {
+ return hmenuTrackPopup;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+HWND DisassemblerGui::mouseInDialogItem(int dlgItem, POINT pt)
+{
+ RECT rc;
+ HWND hwnd = GetDlgItem(hWndDlg, dlgItem);
+ if (hwnd)
+ {
+ // Get the bounding rectangle of the client area.
+ GetClientRect(hwnd, &rc);
+
+ // Convert the mouse position to client coordinates.
+ ScreenToClient(hwnd, &pt);
+
+ // If the position is in the client area, display a
+ // shortcut menu.
+ if (PtInRect(&rc, pt))
+ {
+ return hwnd;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
diff --git a/Scylla/DisassemblerGui.h b/Scylla/DisassemblerGui.h
new file mode 100644
index 0000000..13dd93c
--- /dev/null
+++ b/Scylla/DisassemblerGui.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "MainGui.h"
+
+static const enum DisassemblerColumns {
+ COL_ADDRESS,
+ COL_INSTRUCTION_SIZE,
+ COL_OPCODES,
+ COL_INSTRUCTION
+};
+
+#define DISASSEMBLER_GUI_MEMORY_SIZE 0x100
+
+class DisassemblerGui {
+public:
+ static WCHAR tempBuffer[100];
+ static HWND hWndDlg;
+ static HINSTANCE hInstance;
+ static DWORD_PTR startAddress;
+
+ static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent, DWORD_PTR address);
+ static void addColumnsToDisassembler( HWND list );
+ static void displayDisassembly();
+private:
+ static LRESULT CALLBACK disassemblerDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static HWND mouseInDialogItem(int dlgItem, POINT pt);
+ static void OnContextMenu(int x, int y);
+ static HMENU getCorrectSubMenu(int menuItem, int subMenuItem);
+ static void getModuleListItem(int column, int iItem, WCHAR * buffer);
+ static void copyToClipboard();
+};
\ No newline at end of file
diff --git a/Scylla/DllInjection.cpp b/Scylla/DllInjection.cpp
new file mode 100644
index 0000000..bdd8d38
--- /dev/null
+++ b/Scylla/DllInjection.cpp
@@ -0,0 +1,246 @@
+#include "DllInjection.h"
+#include "Logger.h"
+#include <Psapi.h>
+
+#include "NativeWinApi.h"
+
+//#define DEBUG_COMMENTS
+
+ HMODULE DllInjection::dllInjection(HANDLE hProcess, const WCHAR * filename)
+ {
+ LPVOID remoteMemory = 0;
+ SIZE_T memorySize = 0;
+ HANDLE hThread = 0;
+ HMODULE hModule = 0;
+
+ memorySize = (wcslen(filename) + 1) * sizeof(WCHAR);
+
+ if (memorySize < 7)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dllInjection :: memorySize invalid\r\n");
+#endif
+ return 0;
+ }
+
+ remoteMemory = VirtualAllocEx(hProcess, NULL, memorySize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ if (remoteMemory == 0)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dllInjection :: VirtualAllocEx failed 0x%X\r\n",GetLastError());
+#endif
+ return 0;
+ }
+
+ if (WriteProcessMemory(hProcess, remoteMemory, filename, memorySize, &memorySize))
+ {
+ hThread = startRemoteThread(hProcess,LoadLibraryW,remoteMemory);
+
+ if (hThread)
+ {
+ WaitForSingleObject(hThread, INFINITE);
+
+#ifdef _WIN64
+
+ hModule = getModuleHandleByFilename(hProcess, filename);
+
+#else
+ //returns only 32 bit values -> design bug by microsoft
+ if (!GetExitCodeThread(hThread, (LPDWORD) &hModule))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dllInjection :: GetExitCodeThread failed 0x%X\r\n",GetLastError());
+#endif
+ hModule = 0;
+ }
+#endif
+
+ CloseHandle(hThread);
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dllInjection :: CreateRemoteThread failed 0x%X\r\n",GetLastError());
+#endif
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dllInjection :: WriteProcessMemory failed 0x%X\r\n",GetLastError());
+#endif
+ }
+
+
+ VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
+
+ return hModule;
+ }
+
+ bool DllInjection::unloadDllInProcess(HANDLE hProcess, HMODULE hModule)
+ {
+ HANDLE hThread = 0;
+ DWORD lpThreadId = 0;
+ BOOL freeLibraryRet = 0;
+
+
+ hThread = startRemoteThread(hProcess,FreeLibrary,hModule);
+
+ if (hThread)
+ {
+ WaitForSingleObject(hThread, INFINITE);
+
+ if (!GetExitCodeThread(hThread, (LPDWORD) &freeLibraryRet))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"unloadDllInProcess :: GetExitCodeThread failed 0x%X\r\n",GetLastError());
+#endif
+ freeLibraryRet = 0;
+ }
+
+ CloseHandle(hThread);
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"unloadDllInProcess :: CreateRemoteThread failed 0x%X\r\n",GetLastError());
+#endif
+ }
+
+ return freeLibraryRet != 0;
+ }
+
+ HMODULE DllInjection::getModuleHandleByFilename( HANDLE hProcess, const WCHAR * filename )
+ {
+ HMODULE * hMods = 0;
+ HMODULE hModResult = 0;
+ DWORD count = 0;
+ WCHAR target[MAX_PATH];
+ DWORD cbNeeded = 0;
+ bool notEnough = true;
+
+ count = 100;
+ hMods = new HMODULE[count];
+
+ do
+ {
+ if (!EnumProcessModules(hProcess, hMods, count * sizeof(HMODULE), &cbNeeded))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"DllInjection::getModuleHandle :: EnumProcessModules failed count %d\r\n",count);
+#endif
+ delete [] hMods;
+ return 0;
+ }
+
+ 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(hProcess, hMods[i], target, _countof(target)))
+ {
+ if (!_wcsicmp(target,filename))
+ {
+ hModResult = hMods[i];
+ break;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"DllInjection::getModuleHandle :: GetModuleFileNameExW failed 0x%X\r\n", GetLastError());
+#endif
+ }
+ }
+
+ if (!hModResult)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"DllInjection::getModuleHandle :: Handle not found\r\n");
+#endif
+ }
+
+ delete [] hMods;
+
+ return hModResult;
+ }
+
+ void DllInjection::specialThreadSettings( HANDLE hThread )
+ {
+ if (hThread)
+ {
+ if (!SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"specialThreadSettings :: SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL) failed 0x%X\r\n",GetLastError());
+#endif
+ }
+
+ if (NativeWinApi::NtSetInformationThread)
+ {
+ if (NativeWinApi::NtSetInformationThread(hThread, ThreadHideFromDebugger, 0, 0) != STATUS_SUCCESS)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"specialThreadSettings :: NtSetInformationThread ThreadHideFromDebugger failed\r\n");
+#endif
+ }
+ }
+ }
+ }
+
+ HANDLE DllInjection::startRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)
+ {
+ HANDLE hThread = 0;
+
+ hThread = customCreateRemoteThread(hProcess, lpStartAddress, lpParameter);
+
+ if (hThread)
+ {
+ specialThreadSettings(hThread);
+ ResumeThread(hThread);
+ }
+
+ return hThread;
+ }
+
+ HANDLE DllInjection::customCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)
+ {
+ DWORD lpThreadId = 0;
+ HANDLE hThread = 0;
+ NTSTATUS ntStatus = 0;
+
+ if (NativeWinApi::NtCreateThreadEx)
+ {
+ #define THREAD_ALL_ACCESS_VISTA_7 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
+
+ //for windows vista/7
+ ntStatus = NativeWinApi::NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS_VISTA_7, 0, hProcess, (LPTHREAD_START_ROUTINE)lpStartAddress, (LPVOID)lpParameter, TRUE, 0, 0, 0, 0);
+ if (NT_SUCCESS(ntStatus))
+ {
+ return hThread;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"customCreateRemoteThread :: NtCreateThreadEx failed 0x%X\r\n",NativeWinApi::RtlNtStatusToDosError(ntStatus));
+#endif
+ return 0;
+ }
+ }
+ else
+ {
+ return CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)lpStartAddress,lpParameter,CREATE_SUSPENDED,&lpThreadId);
+ }
+ }
diff --git a/Scylla/DllInjection.h b/Scylla/DllInjection.h
new file mode 100644
index 0000000..fd84662
--- /dev/null
+++ b/Scylla/DllInjection.h
@@ -0,0 +1,18 @@
+#include <windows.h>
+#include <Commctrl.h>
+#include <stdio.h>
+#include <map>
+#include <Windowsx.h>
+
+
+class DllInjection {
+public:
+ HMODULE dllInjection(HANDLE hProcess, const WCHAR * filename);
+ bool unloadDllInProcess(HANDLE hProcess, HMODULE hModule);
+ HANDLE startRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter);
+
+private:
+ HANDLE customCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter);
+ void specialThreadSettings( HANDLE hThread );
+ HMODULE getModuleHandleByFilename( HANDLE hProcess, const WCHAR * filename );
+};
\ No newline at end of file
diff --git a/Scylla/DllInjectionPlugin.cpp b/Scylla/DllInjectionPlugin.cpp
new file mode 100644
index 0000000..097a81a
--- /dev/null
+++ b/Scylla/DllInjectionPlugin.cpp
@@ -0,0 +1,264 @@
+#include "DllInjectionPlugin.h"
+#include "Logger.h"
+
+const WCHAR * DllInjectionPlugin::FILE_MAPPING_NAME = L"ScyllaPluginExchange";
+
+HANDLE DllInjectionPlugin::hProcess = 0;
+
+//#define DEBUG_COMMENTS
+
+void DllInjectionPlugin::injectPlugin(Plugin & plugin, std::map<DWORD_PTR, ImportModuleThunk> & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize)
+{
+ PSCYLLA_EXCHANGE scyllaExchange = 0;
+ PUNRESOLVED_IMPORT unresImp = 0;
+
+ BYTE * dataBuffer = 0;
+ DWORD_PTR numberOfUnresolvedImports = getNumberOfUnresolvedImports(moduleList);
+
+ if (numberOfUnresolvedImports == 0)
+ {
+ Logger::printfDialog(L"No unresolved Imports");
+ return;
+ }
+
+ if (!createFileMapping((DWORD)(sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports))))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"injectPlugin :: createFileMapping %X failed\r\n",sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports));
+#endif
+ return;
+ }
+
+ scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
+ scyllaExchange->status = 0xFF;
+ scyllaExchange->imageBase = imageBase;
+ scyllaExchange->imageSize = imageSize;
+ scyllaExchange->numberOfUnresolvedImports = numberOfUnresolvedImports;
+ scyllaExchange->offsetUnresolvedImportsArray = sizeof(SCYLLA_EXCHANGE);
+
+ unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)lpViewOfFile + sizeof(SCYLLA_EXCHANGE));
+
+ addUnresolvedImports(unresImp, moduleList);
+
+ UnmapViewOfFile(lpViewOfFile);
+ lpViewOfFile = 0;
+
+ HMODULE hDll = dllInjection(hProcess, plugin.fullpath);
+ if (hDll)
+ {
+ Logger::printfDialog(L"Plugin injection was successful");
+ if (!unloadDllInProcess(hProcess,hDll))
+ {
+ Logger::printfDialog(L"Plugin unloading failed");
+ }
+ lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+ if (lpViewOfFile)
+ {
+ scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
+ handlePluginResults(scyllaExchange, moduleList);
+ }
+
+ }
+ else
+ {
+ Logger::printfDialog(L"Plugin injection failed");
+ }
+
+ closeAllHandles();
+}
+
+
+
+bool DllInjectionPlugin::createFileMapping(DWORD mappingSize)
+{
+ hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, mappingSize, FILE_MAPPING_NAME);
+
+ if (hMapFile == NULL)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMapping :: CreateFileMapping failed 0x%X\r\n",GetLastError());
+#endif
+ return false;
+ }
+
+ lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+ if (lpViewOfFile == NULL)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMapping :: MapViewOfFile failed 0x%X\r\n",GetLastError());
+#endif
+ CloseHandle(hMapFile);
+ hMapFile = 0;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void DllInjectionPlugin::closeAllHandles()
+{
+ if (lpViewOfFile)
+ {
+ UnmapViewOfFile(lpViewOfFile);
+ lpViewOfFile = 0;
+ }
+ if (hMapFile)
+ {
+ CloseHandle(hMapFile);
+ hMapFile = 0;
+ }
+}
+
+DWORD_PTR DllInjectionPlugin::getNumberOfUnresolvedImports( std::map<DWORD_PTR, ImportModuleThunk> & moduleList )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk = 0;
+ ImportThunk * importThunk = 0;
+ DWORD_PTR dwNumber = 0;
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->valid == false)
+ {
+ dwNumber++;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+
+ return dwNumber;
+}
+
+void DllInjectionPlugin::addUnresolvedImports( PUNRESOLVED_IMPORT firstUnresImp, std::map<DWORD_PTR, ImportModuleThunk> & moduleList )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk = 0;
+ ImportThunk * importThunk = 0;
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->valid == false)
+ {
+ firstUnresImp->InvalidApiAddress = importThunk->apiAddressVA;
+ firstUnresImp->ImportTableAddressPointer = importThunk->va;
+ firstUnresImp++;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+
+ firstUnresImp->InvalidApiAddress = 0;
+ firstUnresImp->ImportTableAddressPointer = 0;
+}
+
+void DllInjectionPlugin::handlePluginResults( PSCYLLA_EXCHANGE scyllaExchange, std::map<DWORD_PTR, ImportModuleThunk> & moduleList )
+{
+ PUNRESOLVED_IMPORT unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray);;
+
+ switch (scyllaExchange->status)
+ {
+ case SCYLLA_STATUS_SUCCESS:
+ Logger::printfDialog(L"Plugin was successful");
+ updateImportsWithPluginResult(unresImp, moduleList);
+ break;
+ case SCYLLA_STATUS_UNKNOWN_ERROR:
+ Logger::printfDialog(L"Plugin reported Unknown Error");
+ break;
+ case SCYLLA_STATUS_UNSUPPORTED_PROTECTION:
+ Logger::printfDialog(L"Plugin detected unknown protection");
+ updateImportsWithPluginResult(unresImp, moduleList);
+ break;
+ case SCYLLA_STATUS_IMPORT_RESOLVING_FAILED:
+ Logger::printfDialog(L"Plugin import resolving failed");
+ updateImportsWithPluginResult(unresImp, moduleList);
+ break;
+ case SCYLLA_STATUS_MAPPING_FAILED:
+ Logger::printfDialog(L"Plugin file mapping failed");
+ break;
+ default:
+ Logger::printfDialog(L"Plugin failed without reason");
+ }
+}
+
+void DllInjectionPlugin::updateImportsWithPluginResult( PUNRESOLVED_IMPORT firstUnresImp, std::map<DWORD_PTR, ImportModuleThunk> & moduleList )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk = 0;
+ ImportThunk * importThunk = 0;
+ ApiInfo * apiInfo = 0;
+ bool isSuspect = 0;
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->valid == false)
+ {
+ if (apiReader->isApiAddressValid(firstUnresImp->InvalidApiAddress))
+ {
+ apiInfo = apiReader->getApiByVirtualAddress(firstUnresImp->InvalidApiAddress,&isSuspect);
+
+ importThunk->suspect = isSuspect;
+ importThunk->valid = true;
+ importThunk->apiAddressVA = firstUnresImp->InvalidApiAddress;
+ importThunk->hint = (WORD)apiInfo->hint;
+ importThunk->ordinal = apiInfo->ordinal;
+ strcpy_s(importThunk->name, MAX_PATH,apiInfo->name);
+ wcscpy_s(importThunk->moduleName, MAX_PATH, apiInfo->module->getFilename());
+
+ if (moduleThunk->moduleName[0] == TEXT('?'))
+ {
+ wcscpy_s(moduleThunk->moduleName, MAX_PATH, apiInfo->module->getFilename());
+ }
+ }
+
+ firstUnresImp++;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+}
diff --git a/Scylla/DllInjectionPlugin.h b/Scylla/DllInjectionPlugin.h
new file mode 100644
index 0000000..9f8fb14
--- /dev/null
+++ b/Scylla/DllInjectionPlugin.h
@@ -0,0 +1,61 @@
+#include "DllInjection.h"
+#include "PluginLoader.h"
+#include "Thunks.h"
+#include "ApiReader.h"
+
+#define SCYLLA_STATUS_SUCCESS 0
+#define SCYLLA_STATUS_UNKNOWN_ERROR 1
+#define SCYLLA_STATUS_UNSUPPORTED_PROTECTION 2
+#define SCYLLA_STATUS_IMPORT_RESOLVING_FAILED 3
+#define SCYLLA_STATUS_MAPPING_FAILED 0xFF
+
+/* Important note:
+ *
+ * If you write a plugin for the x86 (32-Bit) edition: DWORD_PTR address has 32 bit (4 byte)
+ * If you write a plugin for the x64 (64-Bit) edition: DWORD_PTR address has 64 bit (8 byte)
+ */
+typedef struct _UNRESOLVED_IMPORT { // Scylla Plugin exchange format
+ DWORD_PTR ImportTableAddressPointer; //in VA, address in IAT which points to an invalid api address
+ DWORD_PTR InvalidApiAddress; //in VA, invalid api address that needs to be resolved
+} UNRESOLVED_IMPORT, *PUNRESOLVED_IMPORT;
+
+typedef struct _SCYLLA_EXCHANGE {
+ BYTE status; //return a status, default 0xFF
+ DWORD_PTR imageBase; //image base
+ DWORD_PTR imageSize; //size of the image
+ DWORD_PTR numberOfUnresolvedImports; //number of unresolved imports in this structure
+ BYTE offsetUnresolvedImportsArray;
+} SCYLLA_EXCHANGE, *PSCYLLA_EXCHANGE;
+
+class DllInjectionPlugin : public DllInjection {
+
+public:
+ static const WCHAR * FILE_MAPPING_NAME;
+ static HANDLE hProcess;
+
+ ApiReader * apiReader;
+ HANDLE hMapFile;
+ LPVOID lpViewOfFile;
+
+ DllInjectionPlugin()
+ {
+ hMapFile = 0;
+ lpViewOfFile = 0;
+ apiReader = 0;
+ }
+
+ ~DllInjectionPlugin()
+ {
+ closeAllHandles();
+ }
+
+ void injectPlugin(Plugin & plugin, std::map<DWORD_PTR, ImportModuleThunk> & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize);
+
+private:
+ bool createFileMapping(DWORD mappingSize);
+ void closeAllHandles();
+ DWORD_PTR getNumberOfUnresolvedImports( std::map<DWORD_PTR, ImportModuleThunk> & moduleList );
+ void addUnresolvedImports( PUNRESOLVED_IMPORT firstUnresImp, std::map<DWORD_PTR, ImportModuleThunk> & moduleList );
+ void handlePluginResults( PSCYLLA_EXCHANGE scyllaExchange, std::map<DWORD_PTR, ImportModuleThunk> & moduleList );
+ void updateImportsWithPluginResult( PUNRESOLVED_IMPORT firstUnresImp, std::map<DWORD_PTR, ImportModuleThunk> & moduleList );
+};
\ No newline at end of file
diff --git a/Scylla/IATSearch.cpp b/Scylla/IATSearch.cpp
new file mode 100644
index 0000000..a1f978b
--- /dev/null
+++ b/Scylla/IATSearch.cpp
@@ -0,0 +1,342 @@
+#include "IATSearch.h"
+#include "Logger.h"
+#include "definitions.h"
+
+//#define DEBUG_COMMENTS
+
+
+bool IATSearch::searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT)
+{
+ DWORD_PTR addressInIAT = 0;
+
+ addressInIAT = findAPIAddressInIAT(startAddress);
+
+ if(!addressInIAT)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("searchImportAddressTableInProcess :: addressInIAT not found, startAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),startAddress);
+#endif
+ return false;
+ }
+ else
+ {
+ return findIATStartAndSize(addressInIAT, addressIAT,sizeIAT);
+ }
+}
+
+DWORD_PTR IATSearch::findAPIAddressInIAT(DWORD_PTR startAddress)
+{
+ static const int MEMORY_READ_SIZE = 200;
+ BYTE *dataBuffer = new BYTE[MEMORY_READ_SIZE];
+ DWORD_PTR iatPointer = 0;
+ int counter = 0;
+
+ // to detect stolen api
+ memoryAddress = 0;
+ memorySize = 0;
+
+ do
+ {
+ counter++;
+
+ if (!readMemoryFromProcess(startAddress,MEMORY_READ_SIZE,dataBuffer))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("findAPIAddressInIAT :: error reading memory ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), startAddress);
+#endif
+ return 0;
+ }
+
+ if (decomposeMemory(dataBuffer,MEMORY_READ_SIZE,startAddress))
+ {
+ iatPointer = findIATPointer();
+ if (iatPointer)
+ {
+ if (isIATPointerValid(iatPointer))
+ {
+ delete[] dataBuffer;
+ return iatPointer;
+ }
+ }
+ }
+
+ startAddress = findNextFunctionAddress();
+ //printf("startAddress %08X\n",startAddress);
+ } while (startAddress != 0 && counter != 8);
+
+
+ delete[] dataBuffer;
+ 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);
+ Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), 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);
+ Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), 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);
+ Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), 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;
+}
+
+DWORD_PTR IATSearch::findAddressFromWORDString(char * stringBuffer)
+{
+ char * pAddress = 0;
+ char * pTemp = 0;
+ DWORD_PTR address = 0;
+
+ //string split it e.g. DWORD [0x40f0fc], QWORD [RIP+0x40f0]
+ pAddress = strchr(stringBuffer, 'x');
+
+ if (pAddress)
+ {
+ pAddress++;
+
+ pTemp = strchr(pAddress, ']');
+ *pTemp = 0x00;
+
+ address = strtoul(pAddress, 0, 16);
+
+ //printf("findAddressFromWORDString :: %08X\n",address);
+
+ if (address == ULONG_MAX)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findAddressFromDWORDString :: strtoul ULONG_MAX\r\n");
+#endif
+ return 0;
+ }
+ else
+ {
+ return address;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+DWORD_PTR IATSearch::findAddressFromNormalCALLString(char * stringBuffer)
+{
+ char * pAddress = 0;
+ DWORD_PTR address = 0;
+
+ //e.g. CALL 0x7238
+ pAddress = strchr(stringBuffer, 'x');
+
+ if (pAddress)
+ {
+ pAddress++;
+
+ address = strtoul(pAddress, 0, 16);
+
+ //printf("findAddressFromNormalCALLString :: %08X\n",address);
+
+ if (address == ULONG_MAX)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findAddressFromNormalCALLString :: strtoul ULONG_MAX\r\n");
+#endif
+ return 0;
+ }
+ else
+ {
+ return address;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool IATSearch::isIATPointerValid(DWORD_PTR iatPointer)
+{
+ DWORD_PTR apiAddress = 0;
+
+ if (!readMemoryFromProcess(iatPointer,sizeof(DWORD_PTR),&apiAddress))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("isIATPointerValid :: error reading memory\r\n");
+#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::findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT)
+{
+ MEMORY_BASIC_INFORMATION memBasic;
+ BYTE *dataBuffer = 0;
+
+ if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findIATStartAddress :: VirtualQueryEx error %u\r\n",GetLastError());
+#endif
+ return false;
+ }
+
+ dataBuffer = new BYTE[memBasic.RegionSize];
+
+ if (!readMemoryFromProcess((DWORD_PTR)memBasic.BaseAddress,memBasic.RegionSize,dataBuffer))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findIATStartAddress :: error reading memory\r\n");
+#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);
+
+ 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 == 0 && *(pIATAddress - 1) == 0)
+ {
+ if (((DWORD_PTR)(pIATAddress - 2) >= (DWORD_PTR)dataBuffer) && isApiAddressValid(*(pIATAddress - 2)))
+ {
+
+ }
+ else
+ {
+ return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress);
+ }
+ }
+ else if (*pIATAddress < 0xFFFF && *(pIATAddress - 1) < 0xFFFF)
+ {
+ //IAT end
+ 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
+ Logger::debugLog("findIATSize :: baseAddress %X iatAddress %X dataBuffer %X\r\n",baseAddress,iatAddress, dataBuffer);
+#endif
+
+ while((DWORD_PTR)pIATAddress < ((DWORD_PTR)dataBuffer + bufferSize - 1))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findIATSize :: %X %X %X\r\n",pIATAddress,*pIATAddress, *(pIATAddress + 1));
+#endif
+ if (*pIATAddress < 0xFFFF && *(pIATAddress + 1) < 0xFFFF) //normal is 0
+ {
+
+ //IAT end
+ return (DWORD)((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer);
+ }
+
+ pIATAddress++;
+ }
+
+ return bufferSize;
+}
\ No newline at end of file
diff --git a/Scylla/IATSearch.h b/Scylla/IATSearch.h
new file mode 100644
index 0000000..1def25f
--- /dev/null
+++ b/Scylla/IATSearch.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "ApiReader.h"
+
+
+class IATSearch : protected ApiReader {
+public:
+
+ DWORD_PTR memoryAddress;
+ SIZE_T memorySize;
+
+ bool searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT);
+
+private:
+
+ DWORD_PTR findAPIAddressInIAT(DWORD_PTR startAddress);
+ DWORD_PTR findNextFunctionAddress();
+ DWORD_PTR findIATPointer();
+ DWORD_PTR findAddressFromWORDString(char * stringBuffer);
+ DWORD_PTR findAddressFromNormalCALLString(char * stringBuffer);
+ bool isIATPointerValid(DWORD_PTR iatPointer);
+
+ bool findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT);
+
+ DWORD_PTR findIATStartAddress( DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE * dataBuffer );
+ DWORD findIATSize( DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE * dataBuffer, DWORD bufferSize );
+};
\ No newline at end of file
diff --git a/Scylla/ImportRebuild.cpp b/Scylla/ImportRebuild.cpp
new file mode 100644
index 0000000..2af8670
--- /dev/null
+++ b/Scylla/ImportRebuild.cpp
@@ -0,0 +1,578 @@
+#include "ImportRebuild.h"
+
+#include "Logger.h"
+#include "ConfigurationHolder.h"
+//#define DEBUG_COMMENTS
+
+
+bool ImportRebuild::splitTargetFile()
+{
+ PIMAGE_SECTION_HEADER pSecHeader = 0;
+ WORD i = 0;
+ BYTE * data = 0;
+ DWORD alignment = 0;
+ DWORD dwSize = 0;
+
+ pDosHeader = new IMAGE_DOS_HEADER;
+ CopyMemory(pDosHeader, imageData, sizeof(IMAGE_DOS_HEADER));
+
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ return false;
+ }
+
+ pNTHeader = new IMAGE_NT_HEADERS;
+ CopyMemory(pNTHeader, (PVOID)((DWORD_PTR)imageData + pDosHeader->e_lfanew), sizeof(IMAGE_NT_HEADERS));
+
+ if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ return false;
+ }
+
+ if (pDosHeader->e_lfanew > sizeof(IMAGE_DOS_HEADER))
+ {
+ dwSize = pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER);
+ pDosStub = new BYTE[dwSize];
+ CopyMemory(pDosStub, (PVOID)((DWORD_PTR)imageData + sizeof(IMAGE_DOS_HEADER)), dwSize);
+ }
+ else
+ {
+ pDosStub = 0;
+ }
+
+ pSecHeader = IMAGE_FIRST_SECTION((PIMAGE_NT_HEADERS)((DWORD_PTR)imageData + pDosHeader->e_lfanew));
+
+ for (i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++)
+ {
+ dwSize = pSecHeader->SizeOfRawData;
+
+ if (dwSize > 300000000)
+ {
+ dwSize = 300000000;
+ }
+
+ alignment = alignValue(dwSize, pNTHeader->OptionalHeader.FileAlignment);
+ data = new BYTE[alignment];
+
+ ZeroMemory(data, alignment);
+ CopyMemory(data, (PVOID)((DWORD_PTR)imageData + pSecHeader->PointerToRawData), dwSize);
+
+ vecSectionData.push_back(data);
+ vecSectionHeaders.push_back(*pSecHeader);
+
+ pSecHeader++;
+ }
+
+ delete [] imageData;
+ imageData = 0;
+
+ return true;
+}
+
+bool ImportRebuild::alignSectionHeaders()
+{
+ for (WORD i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ vecSectionHeaders[i].VirtualAddress = alignValue(vecSectionHeaders[i].VirtualAddress, pNTHeader->OptionalHeader.SectionAlignment);
+ vecSectionHeaders[i].Misc.VirtualSize = alignValue(vecSectionHeaders[i].Misc.VirtualSize, pNTHeader->OptionalHeader.SectionAlignment);
+
+ vecSectionHeaders[i].PointerToRawData = alignValue(vecSectionHeaders[i].PointerToRawData, pNTHeader->OptionalHeader.FileAlignment);
+ vecSectionHeaders[i].SizeOfRawData = alignValue(vecSectionHeaders[i].SizeOfRawData, pNTHeader->OptionalHeader.FileAlignment);
+ }
+
+ return true;
+}
+
+bool ImportRebuild::saveNewFile(const WCHAR * filepath)
+{
+ DWORD fileOffset = 0;
+ DWORD dwWriteSize = 0;
+ size_t i = 0;
+
+ if (vecSectionHeaders.size() != vecSectionData.size())
+ {
+ return false;
+ }
+
+ HANDLE hFile = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("saveNewFile :: INVALID_HANDLE_VALUE %u\r\n",GetLastError());
+#endif
+
+ return false;
+ }
+
+ //alignSectionHeaders();
+ updatePeHeader();
+
+ fileOffset = 0;
+ dwWriteSize = sizeof(IMAGE_DOS_HEADER);
+ ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pDosHeader);
+
+ fileOffset += dwWriteSize;
+ dwWriteSize = pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER);
+ ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pDosStub);
+
+ fileOffset += dwWriteSize;
+ dwWriteSize = sizeof(IMAGE_NT_HEADERS);
+ ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pNTHeader);
+
+ fileOffset += dwWriteSize;
+ dwWriteSize = sizeof(IMAGE_SECTION_HEADER);
+
+ for (i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if (!ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &vecSectionHeaders[i]))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("saveNewFile :: writeMemoryToFile failed offset %X size %X\r\n"),fileOffset,dwWriteSize);
+#endif
+ CloseHandle(hFile);
+ return false;
+ }
+ fileOffset += dwWriteSize;
+ }
+
+ for (i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ dwWriteSize = vecSectionHeaders[i].PointerToRawData - fileOffset;
+
+ if (dwWriteSize)
+ {
+ if (!writeZeroMemoryToFile(hFile, fileOffset, dwWriteSize))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("saveNewFile :: writeZeroMemoryToFile failed offset %X size %X\r\n"),fileOffset,dwWriteSize);
+#endif
+ CloseHandle(hFile);
+ return false;
+ }
+ fileOffset += dwWriteSize;
+ }
+
+ dwWriteSize = vecSectionHeaders[i].SizeOfRawData;
+
+ ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, vecSectionData[i]);
+ fileOffset += dwWriteSize;
+ }
+
+
+ CloseHandle(hFile);
+
+ return true;
+}
+
+bool ImportRebuild::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size)
+{
+ bool retValue = false;
+ PVOID zeromemory = calloc(size, 1);
+
+ if (zeromemory)
+ {
+ retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory);
+ free(zeromemory);
+ }
+ else
+ {
+ retValue = false;
+ }
+
+ return retValue;
+}
+
+void ImportRebuild::clearAllData()
+{
+ if (pDosStub)
+ {
+ delete [] pDosStub;
+ pDosStub = 0;
+ }
+
+ if (imageData)
+ {
+ delete [] imageData;
+ imageData = 0;
+ }
+
+ delete pDosHeader;
+ pDosHeader = 0;
+
+ delete pNTHeader;
+ pNTHeader = 0;
+
+ vecSectionHeaders.clear();
+
+ for (size_t i = 0; i < vecSectionData.size(); i++)
+ {
+ delete [] vecSectionData[i];
+ }
+
+ vecSectionData.clear();
+}
+
+bool ImportRebuild::addNewSection(char * sectionName, DWORD sectionSize, BYTE * sectionData)
+{
+ BYTE * newBuffer = 0;
+ IMAGE_SECTION_HEADER pNewSection = {0};
+ size_t lastSectionIndex = vecSectionHeaders.size() - 1;
+ size_t nameLength = strlen(sectionName);
+
+ if (nameLength > IMAGE_SIZEOF_SHORT_NAME)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("addNewSection :: sectionname is too long %d\r\n"),nameLength);
+#endif
+ return false;
+ }
+
+ memcpy_s(pNewSection.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength);
+
+ pNewSection.SizeOfRawData = alignValue(sectionSize, pNTHeader->OptionalHeader.FileAlignment);
+ pNewSection.Misc.VirtualSize = alignValue(sectionSize, pNTHeader->OptionalHeader.SectionAlignment);
+
+ pNewSection.PointerToRawData = alignValue(vecSectionHeaders[lastSectionIndex].PointerToRawData + vecSectionHeaders[lastSectionIndex].SizeOfRawData, pNTHeader->OptionalHeader.FileAlignment);
+ pNewSection.VirtualAddress = alignValue(vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize, pNTHeader->OptionalHeader.SectionAlignment);
+
+ pNewSection.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA;
+
+ vecSectionHeaders.push_back(pNewSection);
+
+ if ( (sectionSize != pNewSection.SizeOfRawData) || (sectionData == 0) )
+ {
+ newBuffer = new BYTE[pNewSection.SizeOfRawData];
+ ZeroMemory(newBuffer, pNewSection.SizeOfRawData);
+
+ if (sectionData)
+ {
+ CopyMemory(newBuffer, sectionData, sectionSize);
+ }
+
+ }
+ else
+ {
+ newBuffer = sectionData;
+ }
+
+ vecSectionData.push_back(newBuffer);
+
+ return true;
+}
+
+bool ImportRebuild::loadTargetFile(const WCHAR * filepath)
+{
+ HANDLE hTargetFile = INVALID_HANDLE_VALUE;
+ DWORD fileSize = 0;
+ bool retValue = false;
+
+ hTargetFile = CreateFile(filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if(hTargetFile == INVALID_HANDLE_VALUE)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("loadTargetFile :: INVALID_HANDLE_VALUE %u\r\n",GetLastError());
+#endif
+
+ return false;
+ }
+
+ fileSize = (DWORD)ProcessAccessHelp::getFileSize(hTargetFile);
+
+ if (!fileSize)
+ {
+ CloseHandle(hTargetFile);
+ hTargetFile = 0;
+ return false;
+ }
+
+ imageData = new BYTE[fileSize];
+
+ if (!imageData)
+ {
+ retValue = false;
+ }
+ else
+ {
+ retValue = ProcessAccessHelp::readMemoryFromFile(hTargetFile, 0, fileSize, imageData);
+ }
+
+ CloseHandle(hTargetFile);
+ hTargetFile = 0;
+
+ return retValue;
+}
+
+DWORD ImportRebuild::alignValue(DWORD badValue, DWORD alignTo)
+{
+ return (((badValue + alignTo - 1) / alignTo) * alignTo);
+}
+
+DWORD ImportRebuild::convertRVAToOffsetVector(DWORD dwRVA)
+{
+ for (size_t i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if ((vecSectionHeaders[i].VirtualAddress <= dwRVA) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > dwRVA))
+ {
+ return ((dwRVA - vecSectionHeaders[i].VirtualAddress) + vecSectionHeaders[i].PointerToRawData);
+ }
+ }
+
+ return 0;
+}
+
+DWORD ImportRebuild::convertRVAToOffset(DWORD dwRVA)
+{
+ PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);
+
+ for (WORD i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++)
+ {
+ if ((pSectionHeader->VirtualAddress <= dwRVA) && ((pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize) > dwRVA))
+ {
+ return ((dwRVA - pSectionHeader->VirtualAddress) + pSectionHeader->PointerToRawData);
+ }
+ pSectionHeader++;
+ }
+
+ return 0;
+}
+
+DWORD_PTR ImportRebuild::convertOffsetToRVAVector(DWORD dwOffset)
+{
+ for (size_t i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if ((vecSectionHeaders[i].PointerToRawData <= dwOffset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > dwOffset))
+ {
+ return ((dwOffset - vecSectionHeaders[i].PointerToRawData) + vecSectionHeaders[i].VirtualAddress);
+ }
+ }
+
+ return 0;
+}
+
+DWORD ImportRebuild::convertOffsetToRVA(DWORD dwOffset)
+{
+ PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);
+
+ for (WORD i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++)
+ {
+ if ((pSectionHeader->PointerToRawData <= dwOffset) && ((pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData) > dwOffset))
+ {
+ return ((dwOffset - pSectionHeader->PointerToRawData) + pSectionHeader->VirtualAddress);
+ }
+ pSectionHeader++;
+ }
+
+ return 0;
+}
+
+void ImportRebuild::updatePeHeader()
+{
+ size_t lastSectionIndex = vecSectionHeaders.size() - 1;
+
+ pNTHeader->FileHeader.NumberOfSections = (WORD)(lastSectionIndex + 1);
+ pNTHeader->OptionalHeader.SizeOfImage = vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize;
+
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
+
+ if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress)
+ {
+ for (size_t i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if ((vecSectionHeaders[i].VirtualAddress <= pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress))
+ {
+ //section must be read and writeable
+ vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
+ }
+ }
+
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
+ }
+
+
+ pNTHeader->OptionalHeader.NumberOfRvaAndSizes = 0x10;
+
+ pNTHeader->OptionalHeader.SizeOfHeaders = alignValue(pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pNTHeader->FileHeader.SizeOfOptionalHeader + (pNTHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), pNTHeader->OptionalHeader.FileAlignment);
+
+}
+
+
+
+bool ImportRebuild::buildNewImportTable(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
+{
+ size_t lastSectionIndex = 0;
+
+ createNewImportSection(moduleList);
+
+ lastSectionIndex = vecSectionHeaders.size() - 1;
+
+ DWORD dwSize = fillImportSection(moduleList, lastSectionIndex);
+
+ setFlagToIATSection((*moduleList.begin()).second.firstThunk);
+
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vecSectionHeaders[lastSectionIndex].VirtualAddress;
+ pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(moduleList.size() * sizeof(IMAGE_IMPORT_DESCRIPTOR));
+ return true;
+}
+
+bool ImportRebuild::createNewImportSection(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
+{
+ char sectionName[9] = {0};
+ size_t i = 0;
+
+ DWORD sectionSize = calculateMinSize(moduleList);
+
+ if (wcslen(ConfigurationHolder::getConfigObject(IAT_SECTION_NAME)->valueString) > IMAGE_SIZEOF_SHORT_NAME)
+ {
+ strcpy_s(sectionName, sizeof(sectionName), ".SCY");
+ }
+ else
+ {
+ wcstombs_s(&i, sectionName, sizeof(sectionName), ConfigurationHolder::getConfigObject(IAT_SECTION_NAME)->valueString, _TRUNCATE);
+ }
+
+
+ return addNewSection(sectionName,sectionSize,0);
+}
+
+DWORD ImportRebuild::calculateMinSize(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
+{
+ DWORD dwSize = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
+ std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
+
+ dwSize = (DWORD)((moduleList.size() + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)); //last is zero'ed
+
+ for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
+ {
+ dwSize += (DWORD)((*mapIt).second.thunkList.size() + sizeof(IMAGE_IMPORT_BY_NAME));
+ dwSize += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
+
+ for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
+ {
+ dwSize += (DWORD)(strlen((*mapIt2).second.name) + 1);
+ }
+ }
+
+ return dwSize;
+}
+
+BYTE * ImportRebuild::getMemoryPointerFromRVA(DWORD_PTR dwRVA)
+{
+ DWORD_PTR offset = convertRVAToOffsetVector((DWORD)dwRVA);
+
+ for (size_t i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if ((vecSectionHeaders[i].PointerToRawData <= offset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > offset))
+ {
+ return (BYTE *)((DWORD_PTR)vecSectionData[i] + (offset - vecSectionHeaders[i].PointerToRawData));
+ }
+ }
+
+ return 0;
+}
+
+DWORD ImportRebuild::fillImportSection( std::map<DWORD_PTR, ImportModuleThunk> & moduleList, size_t importSectionIndex )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
+ std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
+ PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
+ PIMAGE_IMPORT_BY_NAME pImportByName = 0;
+ PIMAGE_THUNK_DATA pThunk = 0;
+
+ char dllName[MAX_PATH];
+ size_t stringLength = 0;
+
+ BYTE * data = vecSectionData[importSectionIndex];
+ DWORD offset = 0;
+
+ pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(data);
+
+ //skip the IMAGE_IMPORT_DESCRIPTOR
+ offset += (DWORD)((moduleList.size() + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR));
+
+ for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
+ {
+ wcstombs_s(&stringLength, dllName, (size_t)MAX_PATH, (*mapIt).second.moduleName, (size_t)MAX_PATH);
+
+ memcpy((data + offset), dllName, stringLength); //copy module name to section
+
+ pImportDesc->FirstThunk = (DWORD)(*mapIt).second.firstThunk;
+ pImportDesc->Name = (DWORD)convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + offset);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("fillImportSection :: importDesc.Name %X\r\n", pImportDesc->Name);
+#endif
+
+ offset += (DWORD)stringLength; //stringLength has null termination char
+
+ pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)data + offset);
+
+ pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA((*mapIt).second.firstThunk));
+
+ for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
+ {
+ pImportByName->Hint = (*mapIt2).second.hint;
+
+ stringLength = strlen((*mapIt2).second.name) + 1;
+ memcpy(pImportByName->Name, (*mapIt2).second.name, stringLength);
+
+ //pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA((*mapIt2).second.rva));
+
+ pThunk->u1.AddressOfData = convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + offset);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("pThunk->u1.AddressOfData %X %X %X\n",pThunk->u1.AddressOfData, pThunk, vecSectionHeaders[importSectionIndex].PointerToRawData + offset);
+#endif
+ offset += (DWORD)(sizeof(WORD) + stringLength);
+ pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + (sizeof(WORD) + stringLength));
+ pThunk++;
+ }
+
+ pThunk->u1.AddressOfData = 0;
+
+ pImportDesc++;
+ }
+
+ return offset;
+}
+
+bool ImportRebuild::rebuildImportTable(const WCHAR * targetFilePath, const WCHAR * newFilePath, std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
+{
+ bool retValue = false;
+
+ if (loadTargetFile(targetFilePath))
+ {
+ splitTargetFile();
+
+ buildNewImportTable(moduleList);
+
+ retValue = saveNewFile(newFilePath);
+
+ clearAllData();
+
+ return retValue;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("rebuildImportTable ::Failed to load target %s\n"), targetFilePath);
+#endif
+ return true;
+ }
+}
+
+void ImportRebuild::setFlagToIATSection(DWORD_PTR iatAddress)
+{
+ for (size_t i = 0; i < vecSectionHeaders.size(); i++)
+ {
+ if ((vecSectionHeaders[i].VirtualAddress <= iatAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > iatAddress))
+ {
+ //section must be read and writeable
+ vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
+ }
+ }
+}
diff --git a/Scylla/ImportRebuild.h b/Scylla/ImportRebuild.h
new file mode 100644
index 0000000..14239c4
--- /dev/null
+++ b/Scylla/ImportRebuild.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "ProcessAccessHelp.h"
+#include "Thunks.h"
+
+class ImportRebuild {
+public:
+
+ bool rebuildImportTable(const WCHAR * targetFilePath, const WCHAR * newFilePath, std::map<DWORD_PTR, ImportModuleThunk> & moduleList);
+
+ DWORD convertRVAToOffset(DWORD dwRVA);
+ DWORD convertOffsetToRVA(DWORD dwOffset);
+
+ bool addNewSection(char * sectionName, DWORD sectionSize, BYTE * sectionData);
+
+ bool writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size);
+
+private:
+ std::vector<IMAGE_SECTION_HEADER> vecSectionHeaders;
+ std::vector<BYTE *> vecSectionData;
+
+ BYTE * imageData;
+ BYTE * pDosStub;
+ PIMAGE_DOS_HEADER pDosHeader;
+ PIMAGE_NT_HEADERS pNTHeader;
+
+ PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
+ PIMAGE_THUNK_DATA pThunkData;
+ PIMAGE_IMPORT_BY_NAME pImportByName;
+
+ DWORD getOffsetLastSection();
+
+ void clearAllData();
+ void updatePeHeader();
+ DWORD fillImportSection( std::map<DWORD_PTR, ImportModuleThunk> & moduleList, size_t lastSectionIndex );
+ bool splitTargetFile();
+ DWORD calculateMinSize(std::map<DWORD_PTR, ImportModuleThunk> & moduleList);
+
+ DWORD convertRVAToOffsetVector(DWORD dwRVA);
+ DWORD_PTR convertOffsetToRVAVector(DWORD dwOffset);
+
+ BYTE * getMemoryPointerFromRVA(DWORD_PTR dwRVA);
+
+ DWORD alignValue(DWORD badValue, DWORD alignTo);
+
+ bool alignSectionHeaders();
+
+ bool saveNewFile(const WCHAR * filepath);
+ bool loadTargetFile(const WCHAR * filepath);
+
+ bool createNewImportSection(std::map<DWORD_PTR, ImportModuleThunk> & moduleList);
+ bool buildNewImportTable(std::map<DWORD_PTR, ImportModuleThunk> & moduleList);
+ void setFlagToIATSection( DWORD_PTR iatAddress );
+};
\ No newline at end of file
diff --git a/Scylla/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp
new file mode 100644
index 0000000..c94a798
--- /dev/null
+++ b/Scylla/ImportsHandling.cpp
@@ -0,0 +1,825 @@
+
+#include "ImportsHandling.h"
+#include "definitions.h"
+
+//#define DEBUG_COMMENTS
+
+bool ImportModuleThunk::isValid()
+{
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator = thunkList.begin();
+ while (iterator != thunkList.end())
+ {
+ if (iterator->second.valid == false)
+ {
+ return false;
+ }
+ iterator++;
+ }
+
+ return true;
+}
+
+DWORD_PTR ImportModuleThunk::getFirstThunk()
+{
+ if (thunkList.size() > 0)
+ {
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator = thunkList.begin();
+ return iterator->first;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*bool ImportsHandling::addModule(WCHAR * moduleName, DWORD_PTR firstThunk)
+{
+ ImportModuleThunk module;
+
+ module.firstThunk = firstThunk;
+ wcscpy_s(module.moduleName, MAX_PATH, moduleName);
+
+ moduleList.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
+
+ return true;
+}*/
+
+/*bool ImportsHandling::addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect)
+{
+ ImportThunk import;
+ ImportModuleThunk * module = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+
+ if (moduleList.size() > 1)
+ {
+ iterator1 = moduleList.begin();
+ while (iterator1 != moduleList.end())
+ {
+ if (rva >= iterator1->second.firstThunk)
+ {
+ iterator1++;
+ if (iterator1 == moduleList.end())
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ else if (rva < iterator1->second.firstThunk)
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ iterator1 = moduleList.begin();
+ module = &(iterator1->second);
+ }
+
+ if (!module)
+ {
+ Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(""),rva);
+ return false;
+ }
+
+ //TODO
+ import.suspect = true;
+ import.valid = false;
+ import.va = va;
+ import.rva = rva;
+ import.ordinal = ordinal;
+
+ wcscpy_s(import.moduleName, MAX_PATH, moduleName);
+ strcpy_s(import.name, MAX_PATH, name);
+
+ module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
+
+ return true;
+}*/
+
+void ImportsHandling::displayAllImports()
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+ HTREEITEM module;
+ HTREEITEM apiFunction;
+ HWND idTreeView = GetDlgItem(hWndMainDlg, IDC_TREE_IMPORTS);
+
+ TreeView_DeleteAllItems(idTreeView);
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ module = addDllToTreeView(idTreeView,moduleThunk->moduleName,moduleThunk->firstThunk,moduleThunk->thunkList.size(),moduleThunk->isValid());
+
+ moduleThunk->hTreeItem = module;
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+ apiFunction = addApiToTreeView(idTreeView,module,importThunk);
+ importThunk->hTreeItem = apiFunction;
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+
+}
+
+HTREEITEM ImportsHandling::addDllToTreeView(HWND idTreeView, const WCHAR * dllName, DWORD_PTR firstThunk, size_t numberOfFunctions, bool valid)
+{
+ WCHAR validString[4];
+
+ if (valid)
+ {
+ wcscpy_s(validString,_countof(validString),TEXT("YES"));
+ }
+ else
+ {
+ wcscpy_s(validString,_countof(validString),TEXT("NO"));
+ }
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" NbThunk: %02X (dec: %02d) valid: %s"),dllName,firstThunk,numberOfFunctions,numberOfFunctions,validString);
+
+ tvInsert.hParent = NULL;
+ tvInsert.hInsertAfter = TVI_ROOT;
+ tvInsert.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = stringBuffer;
+ return TreeView_InsertItem(idTreeView, &tvInsert);
+}
+
+HTREEITEM ImportsHandling::addApiToTreeView(HWND idTreeView, HTREEITEM parentDll, ImportThunk * importThunk)
+{
+ if (importThunk->ordinal != 0)
+ {
+ if (importThunk->name[0] != 0x00)
+ {
+ swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name);
+ }
+ else
+ {
+ swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal);
+ }
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->va,importThunk->rva,importThunk->moduleName,tempString);
+ }
+ else
+ {
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" prt: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(""),importThunk->va,importThunk->rva,importThunk->apiAddressVA);
+ }
+
+
+ tvInsert.hParent = parentDll;
+ tvInsert.hInsertAfter = TVI_LAST;
+ tvInsert.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = stringBuffer;
+ return TreeView_InsertItem(idTreeView, &tvInsert);
+}
+
+void ImportsHandling::showImports(bool invalid, bool suspect)
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+ HWND idTreeView = GetDlgItem(hWndMainDlg, IDC_TREE_IMPORTS);
+
+ SetFocus(idTreeView);
+ TreeView_SelectItem(idTreeView,0); //remove selection
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (invalid && !importThunk->valid)
+ {
+ selectItem(idTreeView, importThunk->hTreeItem);
+ setFocus(idTreeView,importThunk->hTreeItem);
+ }
+ else if (suspect && importThunk->suspect)
+ {
+ selectItem(idTreeView, importThunk->hTreeItem);
+ setFocus(idTreeView,importThunk->hTreeItem);
+ }
+ else
+ {
+ unselectItem(idTreeView, importThunk->hTreeItem);
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+}
+
+bool ImportsHandling::isItemSelected(HWND hwndTV, HTREEITEM hItem)
+{
+ TV_ITEM tvi;
+ tvi.mask = TVIF_STATE | TVIF_HANDLE;
+ tvi.stateMask = TVIS_SELECTED;
+ tvi.hItem = hItem;
+
+ TreeView_GetItem(hwndTV, &tvi);
+
+ return (tvi.state & TVIS_SELECTED) != 0;
+}
+
+void ImportsHandling::unselectItem(HWND hwndTV, HTREEITEM htItem)
+{
+ selectItem(hwndTV, htItem, false);
+}
+
+bool ImportsHandling::selectItem(HWND hwndTV, HTREEITEM hItem, bool select)
+{
+ TV_ITEM tvi;
+ tvi.mask = TVIF_STATE | TVIF_HANDLE;
+ tvi.stateMask = TVIS_SELECTED;
+ tvi.state = select ? TVIS_SELECTED : 0;
+ tvi.hItem = hItem;
+
+
+ if ( TreeView_SetItem(hwndTV, &tvi) == -1 )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void ImportsHandling::setFocus(HWND hwndTV, HTREEITEM htItem)
+{
+ // the current focus
+ HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(hwndTV);
+
+ if ( htItem )
+ {
+ // set the focus
+ if ( htItem != htFocus )
+ {
+ // remember the selection state of the item
+ bool wasSelected = isItemSelected(hwndTV, htItem);
+
+ if ( htFocus && isItemSelected(hwndTV, htFocus) )
+ {
+ // prevent the tree from unselecting the old focus which it
+ // would do by default (TreeView_SelectItem unselects the
+ // focused item)
+ TreeView_SelectItem(hwndTV, 0);
+ selectItem(hwndTV, htFocus);
+ }
+
+ TreeView_SelectItem(hwndTV, htItem);
+
+ if ( !wasSelected )
+ {
+ // need to clear the selection which TreeView_SelectItem() gave
+ // us
+ unselectItem(hwndTV, htItem);
+ }
+ //else: was selected, still selected - ok
+ }
+ //else: nothing to do, focus already there
+ }
+ else
+ {
+ if ( htFocus )
+ {
+ bool wasFocusSelected = isItemSelected(hwndTV, htFocus);
+
+ // just clear the focus
+ TreeView_SelectItem(hwndTV, 0);
+
+ if ( wasFocusSelected )
+ {
+ // restore the selection state
+ selectItem(hwndTV, htFocus);
+ }
+ }
+ //else: nothing to do, no focus already
+ }
+}
+
+bool ImportsHandling::invalidateFunction( HTREEITEM selectedTreeNode )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+ TV_ITEM tvi = {0};
+
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->hTreeItem == selectedTreeNode)
+ {
+ importThunk->ordinal = 0;
+ importThunk->hint = 0;
+ importThunk->valid = false;
+ importThunk->suspect = false;
+ importThunk->moduleName[0] = 0;
+ importThunk->name[0] = 0;
+
+ updateImportInTreeView(importThunk);
+ updateModuleInTreeView(moduleThunk);
+ return true;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+
+ return false;
+}
+
+void ImportsHandling::updateImportInTreeView(ImportThunk * importThunk)
+{
+ TV_ITEM tvi = {0};
+ HWND treeControl = GetDlgItem(hWndMainDlg,IDC_TREE_IMPORTS);
+
+ if (importThunk->ordinal != 0)
+ {
+ if (importThunk->name[0] != 0x00)
+ {
+ swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name);
+ }
+ else
+ {
+ swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal);
+ }
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->va,importThunk->rva,importThunk->moduleName,tempString);
+ }
+ else
+ {
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" prt: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(""),importThunk->va,importThunk->rva,importThunk->apiAddressVA);
+ }
+
+ tvi.pszText = stringBuffer;
+ tvi.cchTextMax = 260;
+ tvi.hItem = importThunk->hTreeItem;
+ tvi.mask = TVIF_TEXT;
+ TreeView_SetItem(treeControl,&tvi);
+}
+
+void ImportsHandling::updateModuleInTreeView(ImportModuleThunk * importThunk)
+{
+ TV_ITEM tvi = {0};
+ HWND treeControl = GetDlgItem(hWndMainDlg,IDC_TREE_IMPORTS);
+
+ WCHAR validString[4];
+
+ if (importThunk->isValid())
+ {
+ wcscpy_s(validString,_countof(validString),TEXT("YES"));
+ }
+ else
+ {
+ wcscpy_s(validString,_countof(validString),TEXT("NO"));
+ }
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" NbThunk: %02X (dec: %02d) valid: %s"),importThunk->moduleName,importThunk->firstThunk,importThunk->thunkList.size(),importThunk->thunkList.size(),validString);
+
+
+ tvi.pszText = stringBuffer;
+ tvi.cchTextMax = 260;
+ tvi.hItem = importThunk->hTreeItem;
+ tvi.mask = TVIF_TEXT;
+ TreeView_SetItem(treeControl,&tvi);
+}
+
+bool ImportsHandling::cutThunk( HTREEITEM selectedTreeNode )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+ TV_ITEM tvi = {0};
+ HWND treeControl = GetDlgItem(hWndMainDlg,IDC_TREE_IMPORTS);
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->hTreeItem == selectedTreeNode)
+ {
+
+ TreeView_DeleteItem(treeControl,importThunk->hTreeItem);
+ moduleThunk->thunkList.erase(iterator2);
+
+ if (moduleThunk->thunkList.empty())
+ {
+ TreeView_DeleteItem(treeControl,moduleThunk->hTreeItem);
+ moduleList.erase(iterator1);
+ }
+ else
+ {
+ updateModuleInTreeView(moduleThunk);
+ }
+ return true;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+
+ return false;
+}
+
+bool ImportsHandling::deleteTreeNode( HTREEITEM selectedTreeNode )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+ TV_ITEM tvi = {0};
+ HWND treeControl = GetDlgItem(hWndMainDlg,IDC_TREE_IMPORTS);
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+
+
+ if (moduleThunk->hTreeItem == selectedTreeNode)
+ {
+ TreeView_DeleteItem(treeControl,moduleThunk->hTreeItem);
+ moduleThunk->thunkList.clear();
+ moduleList.erase(iterator1);
+ return true;
+ }
+ else
+ {
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->hTreeItem == selectedTreeNode)
+ {
+ TreeView_DeleteItem(treeControl,moduleThunk->hTreeItem);
+ moduleThunk->thunkList.clear();
+ moduleList.erase(iterator1);
+ return true;
+ }
+
+ iterator2++;
+ }
+ }
+
+
+
+ iterator1++;
+ }
+
+ return false;
+}
+
+DWORD_PTR ImportsHandling::getApiAddressByNode( HTREEITEM selectedTreeNode )
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->hTreeItem == selectedTreeNode)
+ {
+ return importThunk->apiAddressVA;
+ }
+
+ iterator2++;
+ }
+
+ iterator1++;
+ }
+ return 0;
+}
+
+
+void ImportsHandling::scanAndFixModuleList()
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
+ ImportModuleThunk * moduleThunk;
+ ImportThunk * importThunk;
+
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ iterator2 = moduleThunk->thunkList.begin();
+
+ while (iterator2 != moduleThunk->thunkList.end())
+ {
+ importThunk = &(iterator2->second);
+
+ if (importThunk->moduleName[0] == 0 || importThunk->moduleName[0] == L'?')
+ {
+ addNotFoundApiToModuleList(importThunk);
+ }
+ else
+ {
+ if (isNewModule(importThunk->moduleName))
+ {
+ addModuleToModuleList(importThunk->moduleName, importThunk->rva);
+ }
+
+ addFunctionToModuleList(importThunk);
+ }
+
+ iterator2++;
+ }
+
+ moduleThunk->thunkList.clear();
+
+ iterator1++;
+ }
+
+ moduleList.clear();
+ moduleList.insert(moduleListNew.begin(), moduleListNew.end());
+ moduleListNew.clear();
+}
+
+bool ImportsHandling::findNewModules( std::map<DWORD_PTR, ImportThunk> & thunkList )
+{
+ throw std::exception("The method or operation is not implemented.");
+}
+
+bool ImportsHandling::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
+{
+ ImportModuleThunk module;
+
+ module.firstThunk = firstThunk;
+ wcscpy_s(module.moduleName, MAX_PATH, moduleName);
+
+ moduleListNew.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
+
+ return true;
+}
+
+bool ImportsHandling::isNewModule(const WCHAR * moduleName)
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+
+ iterator1 = moduleListNew.begin();
+
+ while (iterator1 != moduleListNew.end())
+ {
+ if (!_wcsicmp(iterator1->second.moduleName, moduleName))
+ {
+ return false;
+ }
+
+ iterator1++;
+ }
+
+ return true;
+}
+
+void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
+{
+ ImportModuleThunk module;
+
+ module.firstThunk = firstThunk;
+ wcscpy_s(module.moduleName, MAX_PATH, TEXT("?"));
+
+ moduleListNew.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
+}
+
+bool ImportsHandling::addNotFoundApiToModuleList(ImportThunk * apiNotFound)
+{
+ ImportThunk import;
+ ImportModuleThunk * module = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ DWORD_PTR rva = apiNotFound->rva;
+
+ if (moduleListNew.size() > 0)
+ {
+ iterator1 = moduleListNew.begin();
+ while (iterator1 != moduleListNew.end())
+ {
+ if (rva >= iterator1->second.firstThunk)
+ {
+ iterator1++;
+ if (iterator1 == moduleListNew.end())
+ {
+ iterator1--;
+ //new unknown module
+ if (iterator1->second.moduleName[0] == L'?')
+ {
+ module = &(iterator1->second);
+ }
+ else
+ {
+ addUnknownModuleToModuleList(apiNotFound->rva);
+ module = &(moduleListNew.find(rva)->second);
+ }
+
+ break;
+ }
+ else if (rva < iterator1->second.firstThunk)
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("Error iterator1 != (*moduleThunkList).end()\r\n");
+#endif
+ break;
+ }
+ }
+ }
+ else
+ {
+ //new unknown module
+ addUnknownModuleToModuleList(apiNotFound->rva);
+ module = &(moduleListNew.find(rva)->second);
+ }
+
+ if (!module)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
+#endif
+ return false;
+ }
+
+
+ import.suspect = true;
+ import.valid = false;
+ import.va = apiNotFound->va;
+ import.rva = apiNotFound->rva;
+ import.apiAddressVA = apiNotFound->apiAddressVA;
+ import.ordinal = 0;
+
+ wcscpy_s(import.moduleName, MAX_PATH, TEXT("?"));
+ strcpy_s(import.name, MAX_PATH, "?");
+
+ module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
+
+ return true;
+}
+
+bool ImportsHandling::addFunctionToModuleList(ImportThunk * apiFound)
+{
+ ImportThunk import;
+ ImportModuleThunk * module = 0;
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+
+ if (moduleListNew.size() > 1)
+ {
+ iterator1 = moduleListNew.begin();
+ while (iterator1 != moduleListNew.end())
+ {
+ if (apiFound->rva >= iterator1->second.firstThunk)
+ {
+ iterator1++;
+ if (iterator1 == moduleListNew.end())
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ else if (apiFound->rva < iterator1->second.firstThunk)
+ {
+ iterator1--;
+ module = &(iterator1->second);
+ break;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Error iterator1 != moduleListNew.end()\r\n"));
+#endif
+ break;
+ }
+ }
+ }
+ else
+ {
+ iterator1 = moduleListNew.begin();
+ module = &(iterator1->second);
+ }
+
+ if (!module)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),apiFound->rva);
+#endif
+ return false;
+ }
+
+
+ import.suspect = apiFound->suspect;
+ import.valid = apiFound->valid;
+ import.va = apiFound->va;
+ import.rva = apiFound->rva;
+ import.apiAddressVA = apiFound->apiAddressVA;
+ import.ordinal = apiFound->ordinal;
+ import.hint = apiFound->hint;
+
+ wcscpy_s(import.moduleName, MAX_PATH, apiFound->moduleName);
+ strcpy_s(import.name, MAX_PATH, apiFound->name);
+
+ module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
+
+ return true;
+}
+
+void ImportsHandling::expandAllTreeNodes()
+{
+ changeExpandStateOfTreeNodes(TVE_EXPAND);
+}
+
+void ImportsHandling::collapseAllTreeNodes()
+{
+ changeExpandStateOfTreeNodes(TVE_COLLAPSE);
+}
+
+void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag)
+{
+ std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
+ ImportModuleThunk * moduleThunk;
+
+ HWND treeControl = GetDlgItem(hWndMainDlg,IDC_TREE_IMPORTS);
+
+ iterator1 = moduleList.begin();
+
+ while (iterator1 != moduleList.end())
+ {
+ moduleThunk = &(iterator1->second);
+
+ TreeView_Expand(treeControl, moduleThunk->hTreeItem, flag);
+
+ iterator1++;
+ }
+}
diff --git a/Scylla/ImportsHandling.h b/Scylla/ImportsHandling.h
new file mode 100644
index 0000000..31aff46
--- /dev/null
+++ b/Scylla/ImportsHandling.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "Thunks.h"
+#include "MainGui.h"
+
+class ImportsHandling : public MainGui {
+public:
+ std::map<DWORD_PTR, ImportModuleThunk> moduleList;
+ std::map<DWORD_PTR, ImportModuleThunk> moduleListNew;
+
+ //bool addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect);
+ //bool addModule(WCHAR * moduleName, DWORD_PTR firstThunk);
+
+ void displayAllImports();
+ void showImports(bool invalid, bool suspect);
+ bool invalidateFunction(HTREEITEM selectedTreeNode);
+ bool cutThunk( HTREEITEM selectedTreeNode );
+ bool deleteTreeNode( HTREEITEM selectedTreeNode );
+
+ void updateImportInTreeView(ImportThunk * importThunk);
+ void updateModuleInTreeView(ImportModuleThunk * importThunk);
+ DWORD_PTR getApiAddressByNode( HTREEITEM selectedTreeNode );
+ void scanAndFixModuleList();
+ void expandAllTreeNodes();
+ void collapseAllTreeNodes();
+
+private:
+ DWORD numberOfFunctions;
+
+ WCHAR tempString[100];
+
+ TV_INSERTSTRUCT tvInsert;
+ HTREEITEM m_hItemFirstSel;
+
+ HTREEITEM addDllToTreeView(HWND idTreeView, const WCHAR * dllName, DWORD_PTR firstThunk, size_t numberOfFunctions, bool valid);
+ HTREEITEM addApiToTreeView(HWND idTreeView, HTREEITEM parentDll, ImportThunk * importThunk);
+
+
+ bool isItemSelected(HWND hwndTV, HTREEITEM hItem);
+ void unselectItem(HWND hwndTV, HTREEITEM htItem);
+ bool selectItem(HWND hwndTV, HTREEITEM hItem, bool select = true);
+ void setFocus(HWND hwndTV, HTREEITEM htItem);
+ bool findNewModules( std::map<DWORD_PTR, ImportThunk> & thunkList );
+
+ bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk);
+ void addUnknownModuleToModuleList(DWORD_PTR firstThunk);
+ bool addNotFoundApiToModuleList(ImportThunk * apiNotFound);
+ bool addFunctionToModuleList(ImportThunk * apiFound);
+ bool isNewModule(const WCHAR * moduleName);
+
+ void changeExpandStateOfTreeNodes(UINT flag);
+
+
+};
\ No newline at end of file
diff --git a/Scylla/Logger.cpp b/Scylla/Logger.cpp
new file mode 100644
index 0000000..0b08567
--- /dev/null
+++ b/Scylla/Logger.cpp
@@ -0,0 +1,90 @@
+#include "Logger.h"
+
+#include "MainGui.h"
+
+WCHAR Logger::debugLogFile[MAX_PATH];
+WCHAR Logger::logbuf[300];
+char Logger::logbufChar[300];
+
+void Logger::getDebugLogFilePath()
+{
+ GetModuleFileName(0, debugLogFile, MAX_PATH);
+
+ for(size_t i = wcslen(debugLogFile); i > 0; i--)
+ {
+ if(debugLogFile[i] == L'\\')
+ {
+ debugLogFile[i+1] = 0x00;
+ break;
+ }
+ }
+
+ wcscat_s(debugLogFile, _countof(debugLogFile), TEXT(DEBUG_LOG_FILENAME));
+}
+
+
+void Logger::debugLog(const WCHAR * format, ...)
+{
+ FILE * pFile;
+ va_list va_alist;
+
+ if (!format)
+ {
+ return;
+ }
+
+ ZeroMemory(logbuf, sizeof(logbuf));
+
+ va_start (va_alist, format);
+ _vsnwprintf_s(logbuf, _countof(logbuf), _countof(logbuf) - 1, format, va_alist);
+ va_end (va_alist);
+
+ if (_wfopen_s(&pFile,debugLogFile,L"a") == NULL)
+ {
+ fputws(logbuf,pFile);
+ fclose (pFile);
+ }
+}
+
+void Logger::debugLog(const char * format, ...)
+{
+ FILE * pFile;
+ va_list va_alist;
+
+ if (!format)
+ {
+ return;
+ }
+
+ ZeroMemory(logbufChar, sizeof(logbufChar));
+
+ va_start (va_alist, format);
+ _vsnprintf_s(logbufChar, _countof(logbufChar), _countof(logbufChar) - 1, format, va_alist);
+ va_end (va_alist);
+
+ if (_wfopen_s(&pFile,debugLogFile,L"a") == NULL)
+ {
+ fputs(logbufChar,pFile);
+ fclose (pFile);
+ }
+}
+
+void Logger::printfDialog(const WCHAR * format, ...)
+{
+ va_list va_alist;
+
+ if (!format)
+ {
+ return;
+ }
+
+ ZeroMemory(logbuf, sizeof(logbuf));
+
+ va_start (va_alist, format);
+ _vsnwprintf_s(logbuf, _countof(logbuf), _countof(logbuf) - 1, format, va_alist);
+ va_end (va_alist);
+
+
+ MainGui::addTextToOutputLog(logbuf);
+ UpdateWindow(MainGui::hWndMainDlg);
+}
\ No newline at end of file
diff --git a/Scylla/Logger.h b/Scylla/Logger.h
new file mode 100644
index 0000000..2ff6a97
--- /dev/null
+++ b/Scylla/Logger.h
@@ -0,0 +1,20 @@
+
+#pragma once
+
+#include <windows.h>
+
+#define DEBUG_LOG_FILENAME "Scylla_debug.log"
+
+class Logger {
+public:
+ static void debugLog(const WCHAR * format, ...);
+ static void debugLog(const CHAR * format, ...);
+ static void printfDialog(const WCHAR * format, ...);
+
+ static void getDebugLogFilePath();
+
+private:
+ static WCHAR debugLogFile[MAX_PATH];
+ static WCHAR logbuf[300];
+ static char logbufChar[300];
+};
\ No newline at end of file
diff --git a/Scylla/MainGui.aps b/Scylla/MainGui.aps
new file mode 100644
index 0000000..d559401
Binary files /dev/null and b/Scylla/MainGui.aps differ
diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp
new file mode 100644
index 0000000..567fd08
--- /dev/null
+++ b/Scylla/MainGui.cpp
@@ -0,0 +1,880 @@
+#include "MainGui.h"
+#include "ImportsHandling.h"
+#include "definitions.h"
+#include "PluginLoader.h"
+#include "ConfigurationHolder.h"
+#include "PeDump.h"
+#include "PeRebuild.h"
+#include "DllInjectionPlugin.h"
+#include "DisassemblerGui.h"
+#include "NativeWinApi.h"
+#include "ImportRebuild.h"
+#include "SystemInformation.h"
+#include "AboutGui.h"
+#include "OptionsGui.h"
+
+HINSTANCE MainGui::hInstance = 0;
+HWND MainGui::hWndParent = 0;
+HWND MainGui::hWndMainDlg = 0;
+Process * MainGui::selectedProcess = 0;
+
+WCHAR MainGui::stringBuffer[300] = {0};
+
+ProcessLister MainGui::processLister;
+ImportsHandling MainGui::importsHandling;
+ProcessAccessHelp MainGui::processAccessHelp;
+ApiReader MainGui::apiReader;
+
+void MainGui::initDialog(HINSTANCE hInstance)
+{
+ hInstance = hInstance;
+ Logger::getDebugLogFilePath();
+ ConfigurationHolder::loadConfiguration();
+ PluginLoader::findAllPlugins();
+ NativeWinApi::initialize();
+ SystemInformation::getSystemInformation();
+
+
+ if (SystemInformation::currenOS == UNKNOWN_OS)
+ {
+ MessageBox(0, TEXT("Operating System is not supported"), TEXT("Error Operating System"),MB_OK);
+ return;
+ }
+
+
+ processAccessHelp.getProcessModules(GetCurrentProcessId(), processAccessHelp.ownModuleList);
+
+ //Register controls, required for Windows XP
+ InitCommonControls();
+ return;
+ DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_MAIN),hWndParent, (DLGPROC)mainDlgProc);
+
+ //ConfigurationHolder::saveConfiguration();
+}
+
+LRESULT CALLBACK MainGui::mainDlgProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ hWndMainDlg = hWndDlg;
+ HTREEITEM selectedTreeNode = 0;
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ //init dialog elements
+ dialogInitActionHandler();
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch(LOWORD(wParam))
+ {
+ case IDC_TREE_IMPORTS:
+ {
+ if(((LPNMHDR)lParam)->code == NM_CLICK)
+ {
+ //Logger::printfDialog(L"NM_CLICK");
+ }
+ if(((LPNMHDR)lParam)->code == NM_DBLCLK)
+ {
+ //Logger::printfDialog(L"NM_DBLCLK");
+ }
+ if(((LPNMHDR)lParam)->code == NM_RCLICK)
+ {
+ //Logger::printfDialog(L"NM_RCLICK");
+
+ selectedTreeNode=(HTREEITEM)SendDlgItemMessage (hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETNEXTITEM,TVGN_DROPHILITE,0);
+ if(selectedTreeNode != NULL)
+ {
+ SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_SELECTITEM,TVGN_CARET,(LPARAM)selectedTreeNode);
+ }
+ }
+ if(((LPNMHDR)lParam)->code == NM_RDBLCLK)
+ {
+ //Logger::printfDialog(L"NM_RDBLCLK");
+ }
+ }
+ break;
+ /*case IDC_MODULELIST:
+ LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
+ if (pnmv->uChanged & LVIF_STATE)
+ {
+ if ((pnmv->uNewState & LVIS_SELECTED) && (!(pnmv->uOldState & LVIS_SELECTED)) && (pnmv->hdr.code == LVN_ITEMCHANGED))
+ {
+
+ //sprintf(stringBuffer,"%X",i);
+ //MessageBox(hWndDlg, text,"Display Notification", MB_OK);
+ break;
+ }
+ }*/
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_CBO_PROCESSLIST:
+ switch(HIWORD(wParam))
+ {
+ case CBN_DROPDOWN: //list is about to display
+ fillProcessListComboBox(GetDlgItem(hWndDlg, IDC_CBO_PROCESSLIST));
+ break;
+ case CBN_SELENDOK: //item selected
+ processSelectedActionHandler(SendMessage(GetDlgItem(hWndDlg, IDC_CBO_PROCESSLIST),CB_GETCURSEL,0,0));
+ break;
+ }
+
+ return TRUE;
+
+ case IDC_BTN_PICKDLL:
+ pickDllActionHandler();
+ return TRUE;
+ case IDC_BTN_OPTIONS:
+ optionsActionHandler();
+ return TRUE;
+ case IDC_BTN_DUMP:
+ dumpActionHandler();
+ return TRUE;
+ case IDC_BTN_FIXDUMP:
+ dumpFixActionHandler();
+ return TRUE;
+ case IDC_BTN_PEREBUILD:
+ peRebuildActionHandler();
+ return TRUE;
+ case IDC_BTN_DLLINJECT:
+ dllInjectActionHandler();
+ return TRUE;
+ case ID_MISC_DLLINJECTION:
+ dllInjectActionHandler();
+ return TRUE;
+ case ID_MISC_PREFERENCES:
+ optionsActionHandler();
+ return TRUE;
+ case IDC_BTN_IATAUTOSEARCH:
+ iatAutosearchActionHandler();
+ return TRUE;
+ case IDC_BTN_GETIMPORTS:
+ getImportsActionHandler();
+ return TRUE;
+ case IDC_BTN_INVALIDIMPORTS:
+ showInvalidImportsActionHandler();
+ return TRUE;
+ case IDC_BTN_SUSPECTIMPORTS:
+ showSuspectImportsActionHandler();
+ return TRUE;
+ case IDC_BTN_CLEARIMPORTS:
+ TreeView_DeleteAllItems(GetDlgItem(hWndDlg, IDC_TREE_IMPORTS));
+ importsHandling.moduleList.clear();
+ return TRUE;
+ case IDC_BTN_CLEARLOG:
+ clearOutputLog();
+ return TRUE;
+ case IDC_BTN_ABOUT:
+ showAboutDialog();
+ return TRUE;
+ case ID_HELP_ABOUT:
+ showAboutDialog();
+ return TRUE;
+ case IDC_BTN_EXIT:
+ PostQuitMessage(0);
+ EndDialog(hWndDlg, 0);
+ return TRUE;
+ case ID_FILE_EXIT:
+ PostQuitMessage(0);
+ EndDialog(hWndDlg, 0);
+ return TRUE;
+ case IDCANCEL:
+ PostQuitMessage(0);
+ EndDialog(hWndDlg, 0);
+ return TRUE;
+ }
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ //leftButtonDownActionHandler();
+ //return TRUE;
+
+ case WM_CONTEXTMENU:
+ return OnContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ default:
+ return FALSE;
+ }
+}
+
+void MainGui::setIconAndDialogCaption()
+{
+ if (hWndMainDlg)
+ {
+ HICON hicon = LoadIcon(GetModuleHandle(0),MAKEINTRESOURCE(IDI_ICON_SCYLLA1));
+ SendMessage(hWndMainDlg, WM_SETICON, ICON_BIG, (LPARAM)hicon);
+ SendMessage(hWndMainDlg, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)TEXT(" "));
+ SetWindowText(hWndMainDlg,stringBuffer);
+ }
+}
+
+
+void MainGui::leftButtonDownActionHandler(WPARAM wParam, LPARAM lParam)
+{
+ if(wParam & MK_CONTROL)
+ {
+
+ }
+ else if(wParam & MK_SHIFT)
+ {
+
+ }
+ else
+ {
+
+ }
+}
+
+void MainGui::dialogInitActionHandler()
+{
+ setIconAndDialogCaption();
+
+ if (ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue())
+ {
+ processLister.setDebugPrivileges();
+ }
+
+
+ enableDialogButtons(FALSE);
+
+ Edit_LimitText(GetDlgItem(hWndMainDlg,IDC_EDIT_OEPADDRESS), MAX_HEX_VALUE_EDIT_LENGTH);
+ Edit_LimitText(GetDlgItem(hWndMainDlg,IDC_EDIT_IATADDRESS), MAX_HEX_VALUE_EDIT_LENGTH);
+ Edit_LimitText(GetDlgItem(hWndMainDlg,IDC_EDIT_IATSIZE), MAX_HEX_VALUE_EDIT_LENGTH);
+}
+
+void MainGui::pickDllActionHandler()
+{
+ if (PickDllGui::initDialog(hInstance,hWndMainDlg, processAccessHelp.moduleList))
+ {
+ //get selected module
+ processAccessHelp.selectedModule = PickDllGui::selectedModule;
+ Logger::printfDialog(TEXT("->>> Module %s selected."), processAccessHelp.selectedModule->getFilename());
+ Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),processAccessHelp.selectedModule->modBaseAddr,processAccessHelp.selectedModule->modBaseSize);
+ }
+ else
+ {
+ processAccessHelp.selectedModule = 0;
+ }
+}
+
+void MainGui::startDisassemblerGui(HTREEITEM selectedTreeNode)
+{
+ DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode);
+ if (address)
+ {
+ DisassemblerGui::initDialog(hInstance,hWndMainDlg,address);
+ }
+
+}
+
+void MainGui::processSelectedActionHandler(LRESULT index)
+{
+ std::vector<Process>& processList = processLister.getProcessList();
+ Process &process = processList.at(index);
+ selectedProcess = &process;
+
+ enableDialogButtons(TRUE);
+
+ Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath);
+
+ if (processAccessHelp.hProcess != 0)
+ {
+ processAccessHelp.closeProcessHandle();
+ apiReader.clearAll();
+ }
+
+ if (!processAccessHelp.openProcessHandle(process.PID))
+ {
+ Logger::printfDialog(TEXT("Error: Cannot open process handle."));
+ return;
+ }
+
+ processAccessHelp.getProcessModules(process.PID, processAccessHelp.moduleList);
+
+ apiReader.readApisFromModuleList();
+
+ Logger::printfDialog(TEXT("Loading modules done."));
+
+ //TODO improve
+ processAccessHelp.selectedModule = 0;
+ processAccessHelp.targetSizeOfImage = process.imageSize;
+ processAccessHelp.targetImageBase = process.imageBase;
+
+ ProcessAccessHelp::getSizeOfImageCurrentProcess();
+
+ process.imageSize = (DWORD)processAccessHelp.targetSizeOfImage;
+
+
+ Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),process.imageBase, process.imageSize);
+
+ selectedProcess->entryPoint = ProcessAccessHelp::getEntryPointFromFile(selectedProcess->fullPath);
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),selectedProcess->entryPoint + selectedProcess->imageBase);
+ SetDlgItemText(hWndMainDlg, IDC_EDIT_OEPADDRESS, stringBuffer);
+}
+
+
+
+void MainGui::fillProcessListComboBox(HWND hCombo)
+{
+ if (hCombo)
+ {
+ SendMessage(hCombo,CB_RESETCONTENT,0,0);
+
+ std::vector<Process>& processList = processLister.getProcessListSnapshot();
+
+ for (size_t i = 0; i < processList.size(); i++)
+ {
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("0x%04X - %s - %s"),processList[i].PID,processList[i].filename,processList[i].fullPath);
+ SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)stringBuffer);
+ }
+ }
+}
+
+void MainGui::addTextToOutputLog(const WCHAR * text)
+{
+ if (hWndMainDlg)
+ {
+ HWND hList = GetDlgItem(hWndMainDlg,IDC_LIST_LOG);
+
+ ListBox_SetCurSel(hList, ListBox_AddString(hList,text));
+ }
+}
+
+void MainGui::clearOutputLog()
+{
+ if (hWndMainDlg)
+ {
+ SendDlgItemMessage(hWndMainDlg, IDC_LIST_LOG, LB_RESETCONTENT, 0, 0);
+ }
+}
+
+void MainGui::showInvalidImportsActionHandler()
+{
+ importsHandling.showImports(true, false);
+}
+
+void MainGui::showSuspectImportsActionHandler()
+{
+ importsHandling.showImports(false, true);
+}
+
+void MainGui::iatAutosearchActionHandler()
+{
+ DWORD_PTR searchAddress = 0;
+ DWORD_PTR addressIAT = 0;
+ DWORD sizeIAT = 0;
+ IATSearch iatSearch;
+
+ GetDlgItemText(hWndMainDlg, IDC_EDIT_OEPADDRESS, stringBuffer, _countof(stringBuffer));
+
+ if (wcslen(stringBuffer) > 1)
+ {
+ searchAddress = stringToDwordPtr(stringBuffer);
+ if (searchAddress)
+ {
+ if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT))
+ {
+ Logger::printfDialog(TEXT("IAT found at VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d)"),addressIAT, addressIAT - processAccessHelp.targetImageBase,sizeIAT,sizeIAT);
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),addressIAT);
+ SetDlgItemText(hWndMainDlg,IDC_EDIT_IATADDRESS,stringBuffer);
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%08X"),sizeIAT);
+ SetDlgItemText(hWndMainDlg,IDC_EDIT_IATSIZE,stringBuffer);
+
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("IAT found! Start Address ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d) "),addressIAT,sizeIAT,sizeIAT);
+ MessageBox(hWndMainDlg,stringBuffer, TEXT("IAT found"), MB_OK);
+
+ }
+ else
+ {
+ Logger::printfDialog(TEXT("IAT not found at OEP ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("!"),searchAddress);
+ }
+ }
+
+ }
+}
+
+void MainGui::getImportsActionHandler()
+{
+ DWORD_PTR addressIAT = 0;
+ DWORD sizeIAT = 0;
+
+ GetDlgItemText(hWndMainDlg, IDC_EDIT_IATADDRESS, stringBuffer, sizeof(stringBuffer));
+ addressIAT = stringToDwordPtr(stringBuffer);
+
+ GetDlgItemText(hWndMainDlg, IDC_EDIT_IATSIZE, stringBuffer, sizeof(stringBuffer));
+ sizeIAT = wcstoul(stringBuffer, NULL, 16);
+
+ if (addressIAT && sizeIAT)
+ {
+ apiReader.readAndParseIAT(addressIAT, sizeIAT,importsHandling.moduleList);
+ importsHandling.displayAllImports();
+ }
+}
+
+
+DWORD_PTR MainGui::stringToDwordPtr(WCHAR * hexString)
+{
+ DWORD_PTR address = 0;
+
+#ifdef _WIN64
+ address = _wcstoui64(hexString, NULL, 16);
+#else
+ address = wcstoul(hexString, NULL, 16);
+#endif
+
+ if (address == 0)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"stringToDwordPtr :: address == 0, %s",hexString);
+#endif
+ return 0;
+ }
+ else
+ {
+ return address;
+ }
+}
+
+bool MainGui::OnContextMenu(int x, int y)
+{
+ HWND hwnd = 0;
+ POINT pt = { x, y }; // location of mouse click
+ //TV_ITEM tvi;
+ //WCHAR ttt[260] = {0};
+ //HTREEITEM selectedTreeNode = 0;
+
+ if ((hwnd = mouseInDialogItem(IDC_TREE_IMPORTS, pt)) != NULL)
+ {
+ if (TreeView_GetCount(hwnd)) //module list should not be empty
+ {
+ /*selectedTreeNode = (HTREEITEM)SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETNEXTITEM,TVGN_CARET,(LPARAM)selectedTreeNode);
+ tvi.mask=TVIF_TEXT; // item text attrivute
+
+ tvi.pszText=ttt; // Text is the pointer to the text
+
+ tvi.cchTextMax=260; // size of text to retrieve.
+
+ tvi.hItem=selectedTreeNode; // the selected item
+
+ SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETITEM,TVGN_CARET,(LPARAM)&tvi);
+ Logger::printfDialog(L"selected %s",tvi.pszText);*/
+ DisplayContextMenuImports(hwnd, pt);
+ }
+ return true;
+ }
+ //if (PtInRect(&rc, pt))
+ //{
+ // ClientToScreen(hwnd, &pt);
+ // DisplayContextMenu(hwnd, pt);
+ // return TRUE;
+ //}
+
+ // Return FALSE if no menu is displayed.
+
+ return false;
+}
+
+void MainGui::DisplayContextMenuImports(HWND hwnd, POINT pt)
+{
+ BOOL menuItem = 0;
+ HTREEITEM selectedTreeNode = 0;
+ std::vector<Plugin> &pluginList = PluginLoader::getPluginList();
+ HMENU hmenuTrackPopup = getCorrectSubMenu(IDR_MENU_IMPORTS, 0);
+
+ appendPluginListToMenu(hmenuTrackPopup);
+
+ if (hmenuTrackPopup)
+ {
+ menuItem = TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, 0);
+ if (menuItem)
+ {
+
+ if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(pluginList.size() + PLUGIN_MENU_BASE_ID)))
+ {
+ //wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName);
+ //MessageBox(0,stringBuffer,L"plugin selection",0);
+
+ DllInjectionPlugin dllInjectionPlugin;
+ dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
+ dllInjectionPlugin.apiReader = &apiReader;
+ dllInjectionPlugin.injectPlugin(pluginList[menuItem - PLUGIN_MENU_BASE_ID], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
+
+ importsHandling.scanAndFixModuleList();
+ importsHandling.displayAllImports();
+ return;
+ }
+
+ selectedTreeNode = (HTREEITEM)SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETNEXTITEM,TVGN_CARET,(LPARAM)selectedTreeNode);
+
+ switch (menuItem)
+ {
+ case ID__INVALIDATEFUNCTION:
+ {
+ importsHandling.invalidateFunction(selectedTreeNode);
+ }
+
+ break;
+ case ID__DISASSEMBLE:
+ {
+ startDisassemblerGui(selectedTreeNode);
+ }
+ break;
+ case ID__CUTTHUNK:
+ {
+ importsHandling.cutThunk(selectedTreeNode);
+ }
+ break;
+ case ID__DELETETREENODE:
+ {
+ importsHandling.deleteTreeNode(selectedTreeNode);
+ }
+ break;
+ case ID__EXPANDALLNODES:
+ {
+ importsHandling.expandAllTreeNodes();
+ }
+ break;
+ case ID__COLLAPSEALLNODES:
+ {
+ importsHandling.collapseAllTreeNodes();
+ }
+ break;
+ }
+
+
+ }
+ }
+}
+
+HWND MainGui::mouseInDialogItem(int dlgItem, POINT pt)
+{
+ RECT rc;
+ HWND hwnd = GetDlgItem(hWndMainDlg, dlgItem);
+ if (hwnd)
+ {
+ // Get the bounding rectangle of the client area.
+ GetClientRect(hwnd, &rc);
+
+ // Convert the mouse position to client coordinates.
+ ScreenToClient(hwnd, &pt);
+
+ // If the position is in the client area, display a
+ // shortcut menu.
+ if (PtInRect(&rc, pt))
+ {
+ return hwnd;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+HMENU MainGui::getCorrectSubMenu(int menuItem, int subMenuItem)
+{
+ HMENU hmenu; // top-level menu
+ HMENU hmenuTrackPopup; // shortcut menu
+ // Load the menu resource.
+ if ((hmenu = LoadMenu(hInstance, MAKEINTRESOURCE(menuItem))) == NULL)
+ return 0;
+
+ hmenuTrackPopup = GetSubMenu(hmenu, subMenuItem);
+
+ if (hmenuTrackPopup)
+ {
+ return hmenuTrackPopup;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void MainGui::DisplayContextMenu(HWND hwnd, POINT pt)
+{
+ HMENU hmenu; // top-level menu
+ HMENU hmenuTrackPopup; // shortcut menu
+ int menuItem; // selected menu item
+
+ // Load the menu resource.
+ if ((hmenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_IMPORTS))) == NULL)
+ return;
+
+ // TrackPopupMenu cannot display the menu bar so get
+ // a handle to the first shortcut menu.
+
+ hmenuTrackPopup = GetSubMenu(hmenu, 0);
+
+ // Display the shortcut menu. Track the right mouse
+ // button.
+ if (!hmenuTrackPopup)
+ {
+ MessageBoxA(0,"hmenuTrackPopup == null","hmenuTrackPopup",0);
+ }
+
+ menuItem = TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+
+ if (menuItem)
+ {
+ /*if (menuItem == ID_LISTCONTROL_SHOWEXPORTS)
+ {
+ MessageBox(0,"exports","dshhhhh",0);
+ }*/
+ }
+
+ // Destroy the menu.
+
+ DestroyMenu(hmenu);
+}
+
+void MainGui::appendPluginListToMenu(HMENU hMenuTrackPopup)
+{
+ HMENU newMenu = CreatePopupMenu();
+
+ std::vector<Plugin> &pluginList = PluginLoader::getPluginList();
+
+ if (pluginList.size() > 0)
+ {
+ for (size_t i = 0; i < pluginList.size(); i++)
+ {
+ AppendMenu(newMenu, MF_STRING, i + PLUGIN_MENU_BASE_ID, pluginList[i].pluginName);
+ }
+
+ AppendMenu(hMenuTrackPopup,MF_MENUBARBREAK,0,0);
+ AppendMenu(hMenuTrackPopup,MF_POPUP,(UINT_PTR)newMenu,TEXT("Plugins"));
+ }
+
+}
+
+void MainGui::dumpActionHandler()
+{
+ WCHAR * targetFile = 0;
+ PeDump peDump;
+
+ if (processAccessHelp.selectedModule)
+ {
+ targetFile = ProcessAccessHelp::selectFileToSave(0, 0);
+ }
+ else
+ {
+ targetFile = ProcessAccessHelp::selectFileToSave(0, 1);
+ }
+
+
+ if (targetFile)
+ {
+ if (processAccessHelp.selectedModule)
+ {
+ //dump DLL
+
+ peDump.imageBase = processAccessHelp.selectedModule->modBaseAddr;
+ peDump.sizeOfImage = processAccessHelp.selectedModule->modBaseSize;
+ //get it from gui
+ peDump.entryPoint = getOEPFromGui();
+ wcscpy_s(peDump.fullpath, MAX_PATH, processAccessHelp.selectedModule->fullPath);
+ }
+ else
+ {
+ peDump.imageBase = ProcessAccessHelp::targetImageBase;
+ peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage;
+ //get it from gui
+ peDump.entryPoint = getOEPFromGui();
+ wcscpy_s(peDump.fullpath, MAX_PATH, selectedProcess->fullPath);
+ }
+
+ peDump.useHeaderFromDisk = ConfigurationHolder::getConfigObject(USE_PE_HEADER_FROM_DISK)->isTrue();
+ if (peDump.dumpCompleteProcessToDisk(targetFile))
+ {
+ Logger::printfDialog(TEXT("Dump success %s"),targetFile);
+ //MessageBox(hWndMainDlg,TEXT("Image dumped successfully."),TEXT("Success"),MB_OK);
+ }
+ else
+ {
+ Logger::printfDialog(TEXT("Error: Cannot dump image."));
+ MessageBox(hWndMainDlg,TEXT("Cannot dump image."),TEXT("Failure"),MB_OK);
+ }
+
+ delete [] targetFile;
+ }
+}
+
+DWORD_PTR MainGui::getOEPFromGui()
+{
+ if (GetDlgItemText(hWndMainDlg, IDC_EDIT_OEPADDRESS, stringBuffer, _countof(stringBuffer)))
+ {
+ return stringToDwordPtr(stringBuffer);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void MainGui::peRebuildActionHandler()
+{
+ DWORD newSize = 0;
+ WCHAR * targetFile = 0;
+ PeRebuild peRebuild;
+
+ targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 2);
+
+ if (targetFile)
+ {
+ if (ConfigurationHolder::getConfigObject(CREATE_BACKUP)->isTrue())
+ {
+ if (!ProcessAccessHelp::createBackupFile(targetFile))
+ {
+ Logger::printfDialog(TEXT("Creating backup file failed %s"), targetFile);
+ }
+ }
+
+ LONGLONG fileSize = ProcessAccessHelp::getFileSize(targetFile);
+ LPVOID mapped = peRebuild.createFileMappingViewFull(targetFile);
+
+ newSize = peRebuild.realignPE(mapped, (DWORD)fileSize);
+ peRebuild.closeAllMappingHandles();
+
+ if (newSize < 10)
+ {
+ Logger::printfDialog(TEXT("Rebuild failed %s"), targetFile);
+ MessageBox(hWndMainDlg,TEXT("Rebuild failed."),TEXT("Failure"),MB_OK);
+ }
+ else
+ {
+ peRebuild.truncateFile(targetFile, newSize);
+
+ Logger::printfDialog(TEXT("Rebuild success %s"), targetFile);
+ Logger::printfDialog(TEXT("-> Old file size 0x%08X new file size 0x%08X (%d %%)"), (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) );
+ //MessageBox(hWndMainDlg,TEXT("Image rebuilded successfully."),TEXT("Success"),MB_OK);
+ }
+
+
+ delete [] targetFile;
+ }
+}
+
+void MainGui::dumpFixActionHandler()
+{
+ WCHAR * targetFile = 0;
+ WCHAR newFilePath[MAX_PATH];
+ ImportRebuild importRebuild;
+
+ if (TreeView_GetCount(GetDlgItem(hWndMainDlg, IDC_TREE_IMPORTS)) < 2)
+ {
+ Logger::printfDialog(TEXT("Nothing to rebuild"));
+ return;
+ }
+
+ if (processAccessHelp.selectedModule)
+ {
+ targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 0);
+ }
+ else
+ {
+ targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 1);
+ }
+
+ if (targetFile)
+ {
+ wcscpy_s(newFilePath,MAX_PATH,targetFile);
+
+ for (size_t i = wcslen(newFilePath) - 1; i >= 0; i--)
+ {
+ if (newFilePath[i] == L'.')
+ {
+ newFilePath[i] = 0;
+ break;
+ }
+ }
+
+ wcscat_s(newFilePath,MAX_PATH, L"_SCY.exe");
+
+ if (importRebuild.rebuildImportTable(targetFile,newFilePath,importsHandling.moduleList))
+ {
+ //MessageBox(hWndMainDlg,L"Imports rebuilding successful",L"Success",MB_OK);
+
+ Logger::printfDialog(TEXT("Import Rebuild success %s"), newFilePath);
+ }
+ else
+ {
+ Logger::printfDialog(TEXT("Import Rebuild failed, target %s"), targetFile);
+ MessageBox(hWndMainDlg,L"Imports rebuilding failed",L"Failure",MB_OK);
+ }
+
+ delete [] targetFile;
+ }
+
+}
+
+void MainGui::enableDialogButtons(BOOL value)
+{
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_PICKDLL), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_DUMP), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_DLLINJECT), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_FIXDUMP), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_IATAUTOSEARCH), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_GETIMPORTS), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_SUSPECTIMPORTS), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_INVALIDIMPORTS), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_CLEARIMPORTS), value);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_OPTIONS), TRUE);
+
+ //not yet implemented
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_AUTOTRACE), FALSE);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_SAVETREE), FALSE);
+ EnableWindow(GetDlgItem(hWndMainDlg, IDC_BTN_LOADTREE), FALSE);
+
+}
+
+void MainGui::showAboutDialog()
+{
+ AboutGui::initDialog(hInstance,hWndMainDlg);
+}
+
+void MainGui::dllInjectActionHandler()
+{
+ WCHAR * targetFile = 0;
+ HMODULE hMod = 0;
+ DllInjection dllInjection;
+
+ targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 0);
+
+ if (targetFile)
+ {
+ hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, targetFile);
+ if (hMod && ConfigurationHolder::getConfigObject(DLL_INJECTION_AUTO_UNLOAD)->isTrue())
+ {
+ if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod))
+ {
+ Logger::printfDialog(TEXT("DLL unloading failed, target %s"), targetFile);
+ }
+ }
+
+ if (hMod)
+ {
+ Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), targetFile);
+ }
+ else
+ {
+ Logger::printfDialog(TEXT("DLL Injection failed, target %s"), targetFile);
+ }
+
+ delete [] targetFile;
+ }
+
+}
+
+void MainGui::optionsActionHandler()
+{
+ OptionsGui::initOptionsDialog(hInstance, hWndMainDlg);
+}
diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h
new file mode 100644
index 0000000..e086863
--- /dev/null
+++ b/Scylla/MainGui.h
@@ -0,0 +1,95 @@
+#pragma once
+
+//#define _CRTDBG_MAP_ALLOC
+//#include <stdlib.h>
+//#include <crtdbg.h>
+
+#include <windows.h>
+#include <Commctrl.h>
+#include <stdio.h>
+#include <map>
+#include <Windowsx.h>
+
+#include "resource.h"
+#include "Logger.h"
+#include "ProcessLister.h"
+#include "IATSearch.h"
+#include "PickDllGui.h"
+
+
+#pragma comment(lib, "comctl32.lib")
+
+
+#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+
+class ImportsHandling;
+
+class MainGui
+{
+public:
+ static HWND hWndMainDlg;
+ static Process * selectedProcess;
+
+ static void initDialog(HINSTANCE hInstance);
+
+ //Output Window
+ static void addTextToOutputLog(const WCHAR * text);
+
+ static DWORD_PTR stringToDwordPtr(WCHAR * hexString);
+
+protected:
+ static HWND hWndParent;
+
+ static HINSTANCE hInstance;
+ static ProcessLister processLister;
+ static WCHAR stringBuffer[300];
+
+ static ImportsHandling importsHandling;
+ static ProcessAccessHelp processAccessHelp;
+ static ApiReader apiReader;
+
+private:
+
+ static LRESULT CALLBACK mainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ static void setIconAndDialogCaption();
+
+
+ static void fillProcessListComboBox(HWND hCombo);
+ static void getModuleListItem(int column, int iItem, char * buffer);
+
+
+ static void leftButtonDownActionHandler(WPARAM wParam, LPARAM lParam);
+ static void dialogInitActionHandler();
+ static void pickDllActionHandler();
+ static void processSelectedActionHandler(LRESULT index);
+
+ //static bool displayModuleList(HWND hWndDlg, HWND hList, LRESULT index);
+
+
+ // POPUP MENU Prototypes
+ static bool OnContextMenu(int, int);
+ static void DisplayContextMenu(HWND, POINT);
+ static HWND mouseInDialogItem(int, POINT);
+ static void DisplayContextMenuImports(HWND, POINT);
+ static HMENU getCorrectSubMenu(int, int);
+
+
+ static void clearOutputLog();//Output Window
+ static void showInvalidImportsActionHandler();
+ static void showSuspectImportsActionHandler();
+ static void iatAutosearchActionHandler();
+ static void getImportsActionHandler();
+ static void appendPluginListToMenu( HMENU hMenuTrackPopup );
+ static void dumpActionHandler();
+ static DWORD_PTR getOEPFromGui();
+ static void peRebuildActionHandler();
+
+ static void startDisassemblerGui(HTREEITEM selectedTreeNode);
+ static void dumpFixActionHandler();
+ static void enableDialogButtons( BOOL value );
+ static void showAboutDialog();
+ static void dllInjectActionHandler();
+ static void optionsActionHandler();
+};
\ No newline at end of file
diff --git a/Scylla/MainGui.rc b/Scylla/MainGui.rc
new file mode 100644
index 0000000..3e25378
Binary files /dev/null and b/Scylla/MainGui.rc differ
diff --git a/Scylla/NativeWinApi.cpp b/Scylla/NativeWinApi.cpp
new file mode 100644
index 0000000..42cda73
--- /dev/null
+++ b/Scylla/NativeWinApi.cpp
@@ -0,0 +1,66 @@
+#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_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(TEXT("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");
+ 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
new file mode 100644
index 0000000..262f776
--- /dev/null
+++ b/Scylla/NativeWinApi.h
@@ -0,0 +1,261 @@
+#pragma once
+
+#include <windows.h>
+
+#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;
+
+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 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 ULONG (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_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_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/OptionsGui.cpp b/Scylla/OptionsGui.cpp
new file mode 100644
index 0000000..13fbb19
--- /dev/null
+++ b/Scylla/OptionsGui.cpp
@@ -0,0 +1,186 @@
+#include "OptionsGui.h"
+#include "ConfigurationHolder.h"
+
+HWND OptionsGui::hWndDlg = 0;
+
+INT_PTR OptionsGui::initOptionsDialog(HINSTANCE hInstance, HWND hWndParent)
+{
+ return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_OPTIONS),hWndParent, (DLGPROC)optionsDlgProc);
+}
+
+LRESULT CALLBACK OptionsGui::optionsDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ hWndDlg = hWnd;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ Edit_LimitText(GetDlgItem(hWndDlg,IDC_OPTIONS_SECTIONNAME), IMAGE_SIZEOF_SHORT_NAME);
+ loadOptions();
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_OPTIONS_OK:
+ {
+ saveOptions();
+ ConfigurationHolder::saveConfiguration();
+ EndDialog(hWnd, 0);
+ }
+ return TRUE;
+ case IDC_BTN_OPTIONS_CANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void OptionsGui::saveOptions()
+{
+ std::map<Configuration, ConfigObject>::iterator mapIter;
+
+ for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++)
+ {
+ getConfigOptionsFromDlg((*mapIter).second);
+ }
+}
+
+void OptionsGui::loadOptions()
+{
+ std::map<Configuration, ConfigObject>::iterator mapIter;
+
+ for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++)
+ {
+ displayConfigInDlg((*mapIter).second);
+ }
+}
+
+void OptionsGui::setCheckBox( int nIDDlgItem, bool bValue )
+{
+ if (bValue)
+ {
+ Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_CHECKED);
+ }
+ else
+ {
+ Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_UNCHECKED);
+ }
+}
+
+void OptionsGui::displayConfigInDlg( ConfigObject & config )
+{
+ switch (config.configType)
+ {
+ case String:
+ {
+ setEditControl(config.dialogItemValue, config.valueString);
+ }
+ break;
+ case Boolean:
+ {
+ setCheckBox(config.dialogItemValue, config.isTrue());
+ }
+ break;
+ case Decimal:
+ {
+#ifdef _WIN64
+ swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%I64u"),config.valueNumeric);
+#else
+ swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%u"),config.valueNumeric);
+#endif
+ setEditControl(config.dialogItemValue, config.valueString);
+ }
+ break;
+ case Hexadecimal:
+ {
+#ifdef _WIN64
+ swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%016I64X"),config.valueNumeric);
+#else
+ swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%08X"),config.valueNumeric);
+#endif
+ setEditControl(config.dialogItemValue, config.valueString);
+ }
+ break;
+ }
+}
+
+void OptionsGui::setEditControl( int nIDDlgItem, const WCHAR * valueString )
+{
+ SetDlgItemText(hWndDlg,nIDDlgItem,valueString);
+}
+
+void OptionsGui::getConfigOptionsFromDlg( ConfigObject & config )
+{
+ switch (config.configType)
+ {
+ case String:
+ {
+ getEditControl(config.dialogItemValue, config.valueString);
+ }
+ break;
+ case Boolean:
+ {
+ getCheckBox(config.dialogItemValue, &config.valueNumeric);
+ }
+ break;
+ case Decimal:
+ {
+ getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 10);
+ }
+ break;
+ case Hexadecimal:
+ {
+ getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 16);
+ }
+ break;
+ }
+}
+
+bool OptionsGui::getEditControl( int nIDDlgItem, WCHAR * valueString )
+{
+ if (GetDlgItemText(hWndDlg, nIDDlgItem, valueString, CONFIG_OPTIONS_STRING_LENGTH))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void OptionsGui::getCheckBox( int nIDDlgItem, DWORD_PTR * valueNumeric )
+{
+ switch (Button_GetCheck(GetDlgItem(hWndDlg, nIDDlgItem)))
+ {
+ case BST_CHECKED:
+ *valueNumeric = 1;
+ return;
+ case BST_UNCHECKED:
+ *valueNumeric = 0;
+ return;
+ default:
+ *valueNumeric = 0;
+ }
+}
+
+void OptionsGui::getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase )
+{
+ WCHAR temp[CONFIG_OPTIONS_STRING_LENGTH] = {0};
+
+ if (getEditControl(nIDDlgItem, temp))
+ {
+#ifdef _WIN64
+ *valueNumeric = _wcstoui64(temp, NULL, nBase);
+#else
+ *valueNumeric = wcstoul(temp, NULL, nBase);
+#endif
+ }
+ else
+ {
+ *valueNumeric = 0;
+ }
+}
diff --git a/Scylla/OptionsGui.h b/Scylla/OptionsGui.h
new file mode 100644
index 0000000..21a32cb
--- /dev/null
+++ b/Scylla/OptionsGui.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "MainGui.h"
+
+class ConfigObject;
+
+class OptionsGui {
+public:
+ static HWND hWndDlg;
+ static INT_PTR initOptionsDialog(HINSTANCE hInstance, HWND hWndParent);
+private:
+ static LRESULT CALLBACK optionsDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static void saveOptions();
+ static void loadOptions();
+ static void setCheckBox( int nIDDlgItem, bool bValue );
+ static void displayConfigInDlg( ConfigObject & config );
+ static void setEditControl( int nIDDlgItem, const WCHAR * valueString );
+ static void getConfigOptionsFromDlg( ConfigObject & config );
+
+ static bool getEditControl( int nIDDlgItem, WCHAR * valueString );
+ static void getCheckBox( int dialogItemValue, DWORD_PTR * valueNumeric );
+ static void getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase );
+};
\ No newline at end of file
diff --git a/Scylla/PeDump.cpp b/Scylla/PeDump.cpp
new file mode 100644
index 0000000..77f7f80
--- /dev/null
+++ b/Scylla/PeDump.cpp
@@ -0,0 +1,436 @@
+#include "PeDump.h"
+#include "ProcessAccessHelp.h"
+
+#include "Logger.h"
+#include "definitions.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
+ Logger::debugLog(L"fillPeHeaderStructs -> ProcessAccessHelp::readHeaderFromFile failed - %X %s\r\n", dwSize, fullpath);
+#endif
+ return false;
+ }
+ }
+ else
+ {
+ //from memory
+ if (!ProcessAccessHelp::readMemoryFromProcess(imageBase, dwSize, headerData))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("fillPeHeaderStructs -> ProcessAccessHelp::readMemoryFromProcess failed - ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %X ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),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
+ Logger::debugLog("dumpCompleteProcessToDisk -> fillPeHeaderStructs failed\r\n");
+#endif
+ return false;
+ }
+
+ if (!validateHeaders())
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("dumpCompleteProcessToDisk -> validateHeaders failed\r\n");
+#endif
+ return false;
+ }
+
+ dumpData = new BYTE[sizeOfImage];
+
+ if (dumpData)
+ {
+ if (!ProcessAccessHelp::readMemoryFromProcess(imageBase,sizeOfImage,dumpData))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("dumpCompleteProcessToDisk -> readMemoryFromProcess failed\r\n");
+#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
+ Logger::debugLog("dumpCompleteProcessToDisk -> new BYTE[sizeOfImage] failed %X\r\n",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
+ Logger::debugLog("appendOverlayDataToDump :: No overlay exists\r\n");
+#endif
+ return true;
+ }
+ else
+ {
+ if (copyFileDataFromOffset(fullpath, dumpFilePath, offset, size))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("appendOverlayDataToDump :: appending overlay success\r\n");
+#endif
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("appendOverlayDataToDump :: appending overlay failed\r\n");
+#endif
+ return false;
+ }
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("appendOverlayDataToDump :: getOverlayData failed\r\n");
+#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
+ Logger::debugLog("copyFileDataFromOffset :: failed to open source file\r\n");
+#endif
+ return false;
+ }
+
+ hDestFile = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+
+ if(hSourceFile == INVALID_HANDLE_VALUE)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("copyFileDataFromOffset :: failed to open destination file\r\n");
+#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
+ Logger::debugLog("copyFileDataFromOffset :: writeMemoryToFileEnd failed\r\n");
+#endif
+ retValue = false;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("copyFileDataFromOffset :: readMemoryFromFile failed to read from source file\r\n");
+#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.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
+ Logger::debugLog("saveDumpToDisk :: INVALID_HANDLE_VALUE %u\r\n",GetLastError());
+#endif
+ retValue = false;
+ }
+ else
+ {
+ if (WriteFile(hFile, dumpBuffer, dumpSize, &lpNumberOfBytesWritten, 0))
+ {
+ if (lpNumberOfBytesWritten != dumpSize)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("saveDumpToDisk :: lpNumberOfBytesWritten != dumpSize %d %d\r\n",lpNumberOfBytesWritten,dumpSize);
+#endif
+ retValue = false;
+ }
+ else
+ {
+ retValue = true;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("saveDumpToDisk :: WriteFile failed %u\r\n",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
+ Logger::debugLog("getOverlayData :: INVALID_HANDLE_VALUE %u\r\n",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/PeDump.h b/Scylla/PeDump.h
new file mode 100644
index 0000000..6f0bcfd
--- /dev/null
+++ b/Scylla/PeDump.h
@@ -0,0 +1,63 @@
+
+#include <windows.h>
+
+class PeDump {
+public:
+ DWORD_PTR entryPoint; //VA
+ DWORD_PTR imageBase; //VA
+ DWORD sizeOfImage;
+ WCHAR fullpath[MAX_PATH];
+
+ //Settings
+ static bool useHeaderFromDisk;
+ static bool appendOverlayData;
+
+ PeDump()
+ {
+ imageBase = 0;
+ sizeOfImage = 0;
+ dumpData = 0;
+ headerData = 0;
+ pNTHeader = 0;
+ pDOSHeader = 0;
+ pSectionHeader = 0;
+ }
+
+ ~PeDump()
+ {
+ if (dumpData != 0)
+ {
+ delete [] dumpData;
+ }
+
+ if (headerData != 0)
+ {
+ delete [] headerData;
+ }
+ }
+
+ bool dumpCompleteProcessToDisk(const WCHAR * dumpFilePath);
+
+ bool saveDumpToDisk(const WCHAR * dumpFilePath, BYTE *dumpBuffer, DWORD dumpSize);
+
+
+ bool copyFileDataFromOffset(const WCHAR * sourceFile, const WCHAR * destFile, DWORD_PTR fileOffset, DWORD dwSize);
+ bool appendOverlayDataToDump(const WCHAR * dumpFilePath);
+ bool getOverlayData(const WCHAR * filepath, DWORD_PTR * overlayFileOffset, DWORD * overlaySize);
+
+private:
+ BYTE * dumpData;
+ BYTE * headerData;
+
+ PIMAGE_DOS_HEADER pDOSHeader;
+ PIMAGE_NT_HEADERS pNTHeader;
+ PIMAGE_SECTION_HEADER pSectionHeader;
+
+ bool validateHeaders();
+ bool fillPeHeaderStructs(bool fromDisk);
+
+ void fixDump(BYTE * dumpBuffer);
+ void fixBadNtHeaderValues(PIMAGE_NT_HEADERS pNtHead);
+ void fixSectionHeaderForDump(PIMAGE_SECTION_HEADER oldSecHead, PIMAGE_SECTION_HEADER newSecHead);
+ void fixNtHeaderForDump(PIMAGE_NT_HEADERS oldNtHead, PIMAGE_NT_HEADERS newNtHead);
+};
\ No newline at end of file
diff --git a/Scylla/PeRebuild.cpp b/Scylla/PeRebuild.cpp
new file mode 100644
index 0000000..09e4922
--- /dev/null
+++ b/Scylla/PeRebuild.cpp
@@ -0,0 +1,732 @@
+#include "PeRebuild.h"
+
+#include <imagehlp.h>
+#pragma comment(lib,"imagehlp.lib")
+
+#include "ProcessAccessHelp.h"
+
+#include "Logger.h"
+#include "ConfigurationHolder.h"
+
+//#define DEBUG_COMMENTS
+
+bool PeRebuild::truncateFile(WCHAR * szFilePath, DWORD dwNewFsize)
+{
+ bool retValue = true;
+ HANDLE hFile = CreateFile(szFilePath,GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ if (SetFilePointer(hFile, dwNewFsize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ {
+ if (GetLastError() == NO_ERROR)
+ {
+ retValue = true;
+ }
+ else
+ {
+ retValue = false;
+ }
+ }
+ else
+ {
+ retValue = true;
+ }
+
+ if (!SetEndOfFile(hFile))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("SetEndOfFile failed error %d\r\n", GetLastError());
+#endif
+ retValue = false;
+ }
+
+ CloseHandle(hFile);
+
+ return retValue;
+}
+
+DWORD PeRebuild::validAlignment(DWORD BadSize)
+{
+ div_t DivRes;
+
+ DivRes = div(BadSize, FileAlignmentConstant);
+ if (DivRes.rem == 0)
+ return BadSize;
+ return ((DivRes.quot+1) * FileAlignmentConstant);
+}
+
+DWORD PeRebuild::validAlignmentNew(DWORD badAddress)
+{
+ DWORD moduloResult = badAddress % FileAlignmentConstant;
+
+ if (moduloResult)
+ {
+ return (FileAlignmentConstant - moduloResult);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool PeRebuild::isRoundedTo(DWORD_PTR dwTarNum, DWORD_PTR dwRoundNum)
+{
+#ifdef _WIN64
+ lldiv_t d;
+
+ d = div((__int64)dwTarNum, (__int64)dwRoundNum);
+#else
+ ldiv_t d;
+
+ d = div((long)dwTarNum, (long)dwRoundNum);
+#endif
+
+ return (d.rem == 0);
+}
+
+void PeRebuild::cleanSectionPointer()
+{
+ if (pSections)
+ {
+ for (int j = 0; j < MAX_SEC_NUM; j++)
+ {
+ if (pSections[j])
+ {
+ free(pSections[j]);
+ pSections[j] = 0;
+ }
+ }
+ }
+}
+
+DWORD PeRebuild::realignPE(LPVOID AddressOfMapFile, DWORD dwFsize)
+{
+ PIMAGE_DOS_HEADER pDosh = 0;
+ PIMAGE_NT_HEADERS pPeh = 0;
+ PIMAGE_SECTION_HEADER pSectionh = 0;
+ int i = 0;
+ DWORD extraAlign = 0;
+
+ ZeroMemory(&pSections, sizeof(pSections));
+
+ // get the other parameters
+ pMap = AddressOfMapFile;
+ dwMapBase = (DWORD_PTR)pMap;
+
+ if (dwFsize == 0 || pMap == NULL)
+ return 1;
+
+ // access the PE Header and check whether it's a valid one
+ pDosh = (PIMAGE_DOS_HEADER)(pMap);
+ pPeh = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh+pDosh->e_lfanew);
+
+ if (!validatePeHeaders(pDosh))
+ {
+ return 0;
+ }
+
+ if (pPeh->FileHeader.NumberOfSections > MAX_SEC_NUM)
+ {
+ return 3;
+ }
+
+ __try
+ {
+ /* START */
+ pPeh->OptionalHeader.FileAlignment = FileAlignmentConstant;
+
+ /* Realign the PE Header */
+ // get the size of all headers
+ dwTmpNum = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pPeh->FileHeader.SizeOfOptionalHeader + (pPeh->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
+
+
+ // kill room between the "win32 pls" message and the PE signature
+ // find the end of the message
+ pW = (WORD*)(dwMapBase + ScanStartDS);
+ while (*pW != 0 || (!isRoundedTo((DWORD_PTR)pW, 0x10)))
+ {
+ pW = (WORD*)((DWORD_PTR)pW + 1);
+ }
+
+ wTmpNum = (WORD)((DWORD_PTR)pW - dwMapBase);
+ if (wTmpNum < pDosh->e_lfanew)
+ {
+ CopyMemory((LPVOID)pW,(VOID*)pPeh,dwTmpNum); // copy the Header to the right place
+ pDosh->e_lfanew = wTmpNum;
+ }
+
+ dwSectionBase = validAlignment(dwTmpNum + pDosh->e_lfanew);
+ pPeh = (PIMAGE_NT_HEADERS)(dwMapBase + pDosh->e_lfanew); // because the NT header moved
+ // correct the SizeOfHeaders
+ pPeh->OptionalHeader.SizeOfHeaders = dwSectionBase;
+
+ /* Realign all sections */
+ // make a copy of all sections
+ // this is needed if the sections aren't sorted by their RawOffset (e.g. Petite)
+ pSectionh = IMAGE_FIRST_SECTION(pPeh);
+
+ for (i=0; i<pPeh->FileHeader.NumberOfSections; i++)
+ {
+ if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0)
+ {
+ ++pSectionh;
+ continue;
+ }
+ // get a valid size
+ dwTmpNum = pSectionh->SizeOfRawData;
+ if ((pSectionh->SizeOfRawData + pSectionh->PointerToRawData) > dwFsize)
+ {
+ dwTmpNum = dwFsize - pSectionh->PointerToRawData;
+ }
+
+ //dwTmpNum -= 1;
+
+ // copy the section into some memory
+ // limit max section size to 300 MB = 300000 KB = 300000000 B
+ if (dwTmpNum > 300000000)
+ {
+ dwTmpNum = 300000000;
+ }
+
+ //because of validAlignment we need some extra space, max 0x200 extra
+ extraAlign = validAlignmentNew(dwTmpNum);
+
+ pSections[i] = malloc(dwTmpNum + extraAlign);
+ ZeroMemory(pSections[i], dwTmpNum + extraAlign);
+
+ if (pSections[i] == NULL) // fatal error !!!
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("realignPE :: malloc failed with dwTmpNum %08X %08X\r\n", dwTmpNum, extraAlign);
+#endif
+
+ cleanSectionPointer();
+
+ return 4;
+ }
+ CopyMemory(pSections[i],(LPVOID)(pSectionh->PointerToRawData+dwMapBase),dwTmpNum);
+ ++pSectionh;
+ }
+
+ // start realigning the sections
+ pSectionh = IMAGE_FIRST_SECTION(pPeh);
+
+ for (i=0;i<pPeh->FileHeader.NumberOfSections;i++)
+ {
+ // some anti crash code :P
+ if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0)
+ {
+ ++pSectionh;
+ if (pSectionh->PointerToRawData == 0)
+ {
+ continue;
+ }
+ pSectionh->PointerToRawData = dwSectionBase;
+ continue;
+ }
+ // let pCH point to the end of the current section
+ if ((pSectionh->PointerToRawData+pSectionh->SizeOfRawData) <= dwFsize)
+ {
+ pCH = (char*)(dwMapBase+pSectionh->PointerToRawData+pSectionh->SizeOfRawData-1);
+ }
+ else
+ {
+ pCH = (char*)(dwMapBase+dwFsize-1);
+ }
+ // look for the end of this section
+ while (*pCH == 0)
+ {
+ --pCH;
+ }
+ // calculate the new RawSize
+ dwTmpNum = (DWORD)(((DWORD_PTR)pCH - dwMapBase) + MinSectionTerm - pSectionh->PointerToRawData);
+ if (dwTmpNum < pSectionh->SizeOfRawData)
+ {
+ pSectionh->SizeOfRawData = dwTmpNum;
+ }
+ else // the new size is too BIG
+ {
+ dwTmpNum = pSectionh->SizeOfRawData;
+ }
+ // copy the section to the new place
+ if (i != pPeh->FileHeader.NumberOfSections-1)
+ {
+ dwTmpNum = validAlignment(dwTmpNum);
+ }
+
+ CopyMemory((LPVOID)(dwMapBase+dwSectionBase), pSections[i], dwTmpNum);
+ // set the RawOffset
+ pSectionh->PointerToRawData = dwSectionBase;
+ // get the RawOffset for the next section
+ dwSectionBase = dwTmpNum+dwSectionBase; // the last section doesn't need to be aligned
+ // go to the next section
+ ++pSectionh;
+ }
+
+ // delete bound import directories because it is destroyed if present
+ pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
+ pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
+
+ // clean up
+ cleanSectionPointer();
+ }
+ __except(1)
+ {
+ // clean up
+ cleanSectionPointer();
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("realignPE :: Exception occured\r\n");
+#endif
+ return 0;
+ }
+
+ if (ConfigurationHolder::getConfigObject(UPDATE_HEADER_CHECKSUM)->isTrue())
+ {
+ updatePeHeaderChecksum(AddressOfMapFile, dwSectionBase);
+ }
+
+ return dwSectionBase; // return the new filesize
+}
+
+
+// returns:
+// -1 - access violation
+// -2 - no relocation found
+// -3 - no own section
+// -4 - dll characteristics found
+// -5 - invalid PE file
+// else the new raw size
+DWORD PeRebuild::wipeReloc(void* pMap, DWORD dwFsize)
+{
+ PIMAGE_DOS_HEADER pDosH;
+ PIMAGE_NT_HEADERS pNTH;
+ PIMAGE_SECTION_HEADER pSecH;
+ PIMAGE_SECTION_HEADER pSH, pSH2;
+ DWORD dwRelocRVA, i;
+ BOOL bOwnSec = FALSE;
+ DWORD dwNewFsize;
+
+ __try // =)
+ {
+ // get pe header pointers
+ pDosH = (PIMAGE_DOS_HEADER)pMap;
+
+ if (pDosH->e_magic != IMAGE_DOS_SIGNATURE)
+ return -5;
+
+ pNTH = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosH + pDosH->e_lfanew);
+
+ if (pNTH->Signature != IMAGE_NT_SIGNATURE)
+ return -5;
+
+ pSecH = IMAGE_FIRST_SECTION(pNTH);
+
+ // has PE dll characteristics ?
+ if (pNTH->FileHeader.Characteristics & IMAGE_FILE_DLL)
+ return -4;
+
+ // is there a reloc section ?
+ dwRelocRVA = pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+
+ if (!dwRelocRVA)
+ return -2;
+
+ // check whether the relocation has an own section
+ pSH = pSecH;
+ for (i=0; i < pNTH->FileHeader.NumberOfSections; i++)
+ {
+ if (pSH->VirtualAddress == dwRelocRVA)
+ {
+ bOwnSec = TRUE;
+ break; // pSH -> reloc section header and i == section index
+ }
+ ++pSH;
+ }
+ if (!bOwnSec)
+ return -3;
+
+ if (i+1 == pNTH->FileHeader.NumberOfSections)
+ {
+ //--- relocation is the last section ---
+ // truncate at the start of the reloc section
+ dwNewFsize = pSH->PointerToRawData;
+ }
+ else
+ {
+ //--- relocation isn't the last section ---
+ dwNewFsize = dwFsize - pSH->SizeOfRawData;
+
+ //-> copy the section(s) after the relocation to the start of the relocation
+ pSH2 = pSH;
+ ++pSH2; // pSH2 -> pointer to first section after relocation
+ memcpy(
+ (void*)(pSH->PointerToRawData + (DWORD)pMap),
+ (const void*)(pSH2->PointerToRawData + (DWORD)pMap),
+ dwFsize - pSH2->PointerToRawData);
+
+ //-> fix the section headers
+ // (pSH -> reloc section header)
+ // (pSH2 -> first section after reloc section)
+ for (++i; i < pNTH->FileHeader.NumberOfSections; i++)
+ {
+ // apply important values
+ pSH->SizeOfRawData = pSH2->SizeOfRawData;
+ pSH->VirtualAddress = pSH2->VirtualAddress;
+ pSH->Misc.VirtualSize = pSH2->Misc.VirtualSize;
+
+ // apply section name
+ memcpy(
+ (void*)(pSH->Name),
+ (const void*)(pSH2->Name),
+ sizeof(pSH2->Name));
+ ++pSH;
+ ++pSH2;
+ }
+ }
+
+ // dec section number
+ --pNTH->FileHeader.NumberOfSections;
+
+ // kill reloc directory entry
+ pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
+ pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
+
+ // fix virtual parts of the PE Header (a must for win2k)
+ pSH2 = pSH = pSecH;
+ ++pSH2;
+ for (i=0; i < (DWORD)pNTH->FileHeader.NumberOfSections-1; i++)
+ {
+ pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress;
+ ++pSH;
+ ++pSH2;
+ }
+ // (pSH -> pointer to last section)
+ if (pSH->Misc.PhysicalAddress)
+ pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->Misc.VirtualSize;
+ else // WATCOM is always a bit special >:-)
+ pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->SizeOfRawData;
+ }
+ __except(1)
+ {
+ // an access violation occurred :(
+ return -1;
+ }
+
+ return dwNewFsize;
+}
+
+bool PeRebuild::validatePE(void* pPEImage, DWORD dwFileSize)
+{
+ PIMAGE_NT_HEADERS pNTh;
+ PIMAGE_SECTION_HEADER pSech,pSH, pSH2, pLastSH;
+ UINT i;
+ DWORD dwHeaderSize;
+
+ // get PE base information
+ pNTh = ImageNtHeader(pPEImage);
+
+ if (!pNTh)
+ return FALSE;
+
+
+ pSech = IMAGE_FIRST_SECTION(pNTh);
+
+ // FIX:
+ // ... the SizeOfHeaders
+ pSH = pSech;
+ dwHeaderSize = 0xFFFFFFFF;
+ for(i=0; i < pNTh->FileHeader.NumberOfSections; i++)
+ {
+ if (pSH->PointerToRawData && pSH->PointerToRawData < dwHeaderSize)
+ {
+ dwHeaderSize = pSH->PointerToRawData;
+ }
+ ++pSH;
+ }
+ pNTh->OptionalHeader.SizeOfHeaders = dwHeaderSize;
+
+ // ...Virtual Sizes
+ pSH2 = pSH = pSech;
+ ++pSH2;
+ for (i=0; i < (DWORD)pNTh->FileHeader.NumberOfSections-1; i++)
+ {
+ pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress;
+ ++pSH;
+ ++pSH2;
+ }
+
+ // (pSH -> pointer to last section)
+ pLastSH = pSH;
+
+ // ...RawSize of the last section
+ pLastSH->SizeOfRawData = dwFileSize - pLastSH->PointerToRawData;
+
+ // ...SizeOfImage
+ if (pLastSH->Misc.PhysicalAddress)
+ {
+ pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->Misc.VirtualSize;
+ }
+ else // WATCOM is always a bit special >:-)
+ {
+ pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->SizeOfRawData;
+ }
+
+ return true;
+}
+
+ReBaseErr PeRebuild::reBasePEImage(void* pPE, DWORD_PTR dwNewBase)
+{
+ PIMAGE_NT_HEADERS pNT;
+ PIMAGE_RELOCATION pR;
+ ReBaseErr ret;
+ DWORD_PTR dwDelta;
+ DWORD *pdwAddr, dwRva, dwType;
+ UINT iItems, i;
+ WORD *pW;
+
+ // dwNewBase valid ?
+ if (dwNewBase & 0xFFFF)
+ {
+ ret = RB_INVALIDNEWBASE;
+ goto Exit; // ERR
+ }
+
+ //
+ // get relocation dir ptr
+ //
+ pNT = ImageNtHeader(pPE);
+ if (!pNT)
+ {
+ ret = RB_INVALIDPE;
+ goto Exit; // ERR
+ }
+ // new base = old base ?
+ if (pNT->OptionalHeader.ImageBase == dwNewBase)
+ {
+ ret = RB_OK;
+ goto Exit; // OK
+ }
+ if (!pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
+ {
+ ret = RB_NORELOCATIONINFO;
+ goto Exit; // ERR
+ }
+
+ pR = (PIMAGE_RELOCATION)ImageRvaToVa(
+ pNT,
+ pPE,
+ pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
+ NULL);
+
+ if (!pR)
+ {
+ ret = RB_INVALIDRVA;
+ goto Exit; // ERR
+ }
+
+ //
+ // add delta to relocation items
+ //
+ dwDelta = dwNewBase - pNT->OptionalHeader.ImageBase;
+ __try
+ {
+ do
+ {
+ // get number of items
+ if (pR->SymbolTableIndex)
+ iItems = (pR->SymbolTableIndex - 8) / 2;
+ else
+ break; // no items in this block
+
+ // trace/list block items...
+ pW = (WORD*)((DWORD_PTR)pR + 8);
+
+ for (i = 0; i < iItems; i++)
+ {
+ dwRva = (*pW & 0xFFF) + pR->VirtualAddress;
+ dwType = *pW >> 12;
+ if (dwType != 0) // fully compatible ???
+ {
+ // add delta
+ pdwAddr = (PDWORD)ImageRvaToVa(
+ pNT,
+ pPE,
+ dwRva,
+ NULL);
+ if (!pdwAddr)
+ {
+ ret = RB_INVALIDRVA;
+ goto Exit; // ERR
+ }
+ *pdwAddr += dwDelta;
+ }
+ // next item
+ ++pW;
+ }
+
+ pR = (PIMAGE_RELOCATION)pW; // pR -> next block header
+ } while ( *(DWORD*)pW );
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret = RB_ACCESSVIOLATION;
+ goto Exit; // ERR
+ }
+
+ // apply new base to header
+ pNT->OptionalHeader.ImageBase = dwNewBase;
+
+ ret = RB_OK; // OK
+
+Exit:
+ return ret;
+}
+
+
+bool PeRebuild::updatePeHeaderChecksum(LPVOID AddressOfMapFile, DWORD dwFsize)
+{
+ PIMAGE_NT_HEADERS32 pNTHeader32 = 0;
+ PIMAGE_NT_HEADERS64 pNTHeader64 = 0;
+ DWORD headerSum = 0;
+ DWORD checkSum = 0;
+
+ pNTHeader32 = (PIMAGE_NT_HEADERS32)CheckSumMappedFile(AddressOfMapFile, dwFsize, &headerSum, &checkSum);
+
+ if (!pNTHeader32)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("updatePeHeaderChecksum :: CheckSumMappedFile failed error %X\r\n", GetLastError());
+#endif
+ return false;
+ }
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("Old checksum %08X new checksum %08X\r\n",headerSum,checkSum);
+#endif
+
+ if (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader32;
+ pNTHeader64->OptionalHeader.CheckSum = checkSum;
+ }
+ else
+ {
+ pNTHeader32->OptionalHeader.CheckSum = checkSum;
+ }
+
+ return true;
+}
+
+LPVOID PeRebuild::createFileMappingViewFull(const WCHAR * filePath)
+{
+ hFileToMap = CreateFile(filePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if( hFileToMap == INVALID_HANDLE_VALUE )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n",GetLastError());
+#endif
+ hMappedFile = 0;
+ hFileToMap = 0;
+ addrMappedDll = 0;
+ return NULL;
+ }
+
+ hMappedFile = CreateFileMapping(hFileToMap, 0, PAGE_READWRITE, 0, 0, NULL);
+
+ if( hMappedFile == NULL )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMappingViewFull :: hMappedFile == NULL\r\n");
+#endif
+ CloseHandle(hFileToMap);
+ hMappedFile = 0;
+ hFileToMap = 0;
+ addrMappedDll = 0;
+ return NULL;
+ }
+
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n");
+#endif
+ CloseHandle(hFileToMap);
+ hMappedFile = 0;
+ hFileToMap = 0;
+ addrMappedDll = 0;
+ return NULL;
+ }
+
+ addrMappedDll = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+ if(!addrMappedDll)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("createFileMappingView :: addrMappedDll == NULL\r\n");
+#endif
+ CloseHandle(hFileToMap);
+ CloseHandle(hMappedFile);
+ hMappedFile = 0;
+ hFileToMap = 0;
+ return NULL;
+ }
+
+ return addrMappedDll;
+}
+
+void PeRebuild::closeAllMappingHandles()
+{
+ if (addrMappedDll)
+ {
+ if (!FlushViewOfFile(addrMappedDll, 0))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("closeAllMappingHandles :: Could not flush memory to disk (%d)\r\n", GetLastError());
+#endif
+ }
+
+ UnmapViewOfFile(addrMappedDll);
+ addrMappedDll = 0;
+ }
+ if (hMappedFile)
+ {
+ CloseHandle(hMappedFile);
+ hMappedFile = 0;
+ }
+ if (hFileToMap)
+ {
+ CloseHandle(hFileToMap);
+ hFileToMap = 0;
+ }
+}
+
+bool PeRebuild::validatePeHeaders( PIMAGE_DOS_HEADER pDosh )
+{
+ PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh + pDosh->e_lfanew);
+
+ if ((pDosh != 0) && (pDosh->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;
+ }
+}
diff --git a/Scylla/PeRebuild.h b/Scylla/PeRebuild.h
new file mode 100644
index 0000000..a180cf4
--- /dev/null
+++ b/Scylla/PeRebuild.h
@@ -0,0 +1,62 @@
+#include <Windows.h>
+#include <stdlib.h>
+
+typedef enum _ReBaseErr
+{
+ RB_OK = 0,
+ RB_INVALIDPE,
+ RB_NORELOCATIONINFO,
+ RB_INVALIDRVA,
+ RB_INVALIDNEWBASE,
+ RB_ACCESSVIOLATION
+} ReBaseErr;
+
+class PeRebuild {
+
+/*****************************************************************************
+ Improved Realign DLL version 1.5 by yoda
+*****************************************************************************/
+public:
+ bool truncateFile(WCHAR * szFilePath, DWORD dwNewFsize);
+ DWORD realignPE(LPVOID AddressOfMapFile,DWORD dwFsize);
+ DWORD wipeReloc(void* pMap, DWORD dwFsize);
+ bool validatePE(void* pPEImage, DWORD dwFileSize);
+ ReBaseErr reBasePEImage(void* pPE, DWORD_PTR dwNewBase);
+
+ bool updatePeHeaderChecksum(LPVOID AddressOfMapFile, DWORD dwFsize);
+
+ LPVOID createFileMappingViewFull(const WCHAR * filePath);
+ void closeAllMappingHandles();
+
+
+private:
+ // constants
+#define MAX_SEC_NUM 30
+
+ const static DWORD ScanStartDS = 0x40;
+ const static int MinSectionTerm = 5;
+ const static int FileAlignmentConstant = 0x200;
+
+ // variables
+ DWORD_PTR dwMapBase;
+ LPVOID pMap;
+ DWORD dwTmpNum,dwSectionBase;
+ WORD wTmpNum;
+ CHAR * pCH;
+ WORD * pW;
+ DWORD * pDW;
+ LPVOID pSections[MAX_SEC_NUM];
+
+ //my vars
+ HANDLE hFileToMap;
+ HANDLE hMappedFile;
+ LPVOID addrMappedDll;
+
+
+ DWORD validAlignment(DWORD BadSize);
+ DWORD validAlignmentNew(DWORD badAddress);
+ bool isRoundedTo(DWORD_PTR dwTarNum, DWORD_PTR dwRoundNum);
+
+ void cleanSectionPointer();
+ bool validatePeHeaders( PIMAGE_DOS_HEADER pDosh );
+};
\ No newline at end of file
diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp
new file mode 100644
index 0000000..1d749e4
--- /dev/null
+++ b/Scylla/PickDllGui.cpp
@@ -0,0 +1,131 @@
+#include "PickDllGui.h"
+
+
+HWND PickDllGui::hWndDlg;
+std::vector<ModuleInfo> * PickDllGui::moduleList = 0;
+ModuleInfo * PickDllGui::selectedModule = 0;
+
+INT_PTR PickDllGui::initDialog(HINSTANCE hInstance, HWND hWndParent, std::vector<ModuleInfo> &moduleListNew)
+{
+ moduleList = &moduleListNew;
+ return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_PICKDLL),hWndParent, (DLGPROC)pickDllDlgProc);
+}
+
+LRESULT CALLBACK PickDllGui::pickDllDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int index;
+ hWndDlg = hWnd;
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ addColumnsToModuleList(GetDlgItem(hWnd, IDC_LIST_DLLSELECT));
+ displayModuleList();
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_PICKDLL_OK:
+ index = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_DLLSELECT));
+ if (index != -1)
+ {
+ selectedModule = &(*moduleList).at(index);
+ EndDialog(hWnd, 1);
+ }
+
+ return TRUE;
+ case IDC_BTN_PICKDLL_CANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hWnd, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void PickDllGui::addColumnsToModuleList(HWND hList)
+{
+ if (hList)
+ {
+ LVCOLUMN * lvc = (LVCOLUMN*)malloc(sizeof(LVCOLUMN));
+
+ ListView_SetExtendedListViewStyleEx(hList,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);
+
+ lvc->mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc->cx = 210;
+ lvc->pszText = L"Path";
+ ListView_InsertColumn(hList, COL_PATH, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_CENTER;
+ lvc->cx = 130;
+ lvc->pszText = L"Name";
+ ListView_InsertColumn(hList, COL_NAME, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_CENTER;
+ lvc->cx = 70;
+ lvc->pszText = L"ImageBase";
+ ListView_InsertColumn(hList, COL_IMAGEBASE, lvc);
+
+ lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lvc->fmt = LVCFMT_CENTER;
+ lvc->cx = 70;
+ lvc->pszText = L"ImageSize";
+ ListView_InsertColumn(hList, COL_IMAGESIZE, lvc);
+
+ free(lvc);
+ }
+}
+
+void PickDllGui::getModuleListItem(int column, int iItem, WCHAR * buffer)
+{
+ LVITEM pitem = {0};
+ pitem.iItem = iItem;
+ pitem.iSubItem = column;
+ pitem.mask = LVIF_TEXT;
+ pitem.cchTextMax = 256;
+ pitem.pszText = buffer;
+ ListView_GetItem(GetDlgItem(hWndDlg, IDC_LIST_DLLSELECT),&pitem);
+}
+
+bool PickDllGui::displayModuleList()
+{
+ LVITEM item;
+ WCHAR temp[20];
+ HWND hList = GetDlgItem(hWndDlg, IDC_LIST_DLLSELECT);
+
+ ListView_DeleteAllItems(hList);
+
+ item.mask = LVIF_TEXT;
+
+
+
+ std::vector<ModuleInfo>::iterator iter;
+ int count = 0;
+
+ for( iter = (*moduleList).begin(); iter != (*moduleList).end(); iter++ , count++) {
+ item.iItem = count;
+ item.iSubItem = COL_PATH;
+ item.pszText = iter->fullPath;
+ item.iItem = ListView_InsertItem(hList, &item);
+
+ item.iSubItem = COL_NAME;
+ item.pszText = iter->getFilename();
+ ListView_SetItem(hList, &item);
+
+ item.iSubItem = COL_IMAGEBASE;
+ swprintf_s(temp,_countof(temp),L"%08X",iter->modBaseAddr);
+ item.pszText = temp;
+ ListView_SetItem(hList, &item);
+
+ item.iSubItem = COL_IMAGESIZE;
+ swprintf_s(temp,_countof(temp),L"%08X",iter->modBaseSize);
+ item.pszText = temp;
+ ListView_SetItem(hList, &item);
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/Scylla/PickDllGui.h b/Scylla/PickDllGui.h
new file mode 100644
index 0000000..d04f253
--- /dev/null
+++ b/Scylla/PickDllGui.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "MainGui.h"
+
+static const enum ListColumns {
+ COL_PATH,
+ COL_NAME,
+ COL_IMAGEBASE,
+ COL_IMAGESIZE
+};
+
+class PickDllGui {
+public:
+ static HWND hWndDlg;
+
+ static std::vector<ModuleInfo> * moduleList;
+
+ static ModuleInfo * selectedModule;
+
+ static LRESULT CALLBACK pickDllDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent, std::vector<ModuleInfo> &moduleList);
+
+ static void addColumnsToModuleList(HWND hList);
+
+ static void getModuleListItem(int column, int iItem, WCHAR * buffer);
+
+ static bool displayModuleList();
+};
\ No newline at end of file
diff --git a/Scylla/PluginLoader.cpp b/Scylla/PluginLoader.cpp
new file mode 100644
index 0000000..57ca43b
--- /dev/null
+++ b/Scylla/PluginLoader.cpp
@@ -0,0 +1,258 @@
+#include "PluginLoader.h"
+#include "Logger.h"
+
+#include "ProcessAccessHelp.h"
+
+std::vector<Plugin> PluginLoader::pluginList;
+WCHAR PluginLoader::dirSearchString[MAX_PATH];
+WCHAR PluginLoader::baseDirPath[MAX_PATH];
+
+//#define DEBUG_COMMENTS
+
+std::vector<Plugin> & PluginLoader::getPluginList()
+{
+ return pluginList;
+}
+
+bool PluginLoader::findAllPlugins()
+{
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = 0;
+ DWORD dwError = 0;
+ Plugin pluginData;
+
+ if (!pluginList.empty())
+ {
+ pluginList.clear();
+ }
+
+ if (!buildSearchString())
+ {
+ return false;
+ }
+
+ hFind = FindFirstFile(dirSearchString, &ffd);
+
+ dwError = GetLastError();
+
+ if (dwError == ERROR_FILE_NOT_FOUND)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findAllPlugins :: No files found\r\n");
+#endif
+ return true;
+ }
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("findAllPlugins :: FindFirstFile failed %d\r\n", dwError);
+#endif
+ return false;
+ }
+
+ do
+ {
+ if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+
+ if ((ffd.nFileSizeHigh != 0) || (ffd.nFileSizeLow < 200))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("findAllPlugins :: Plugin invalid file size: %s\r\n"), ffd.cFileName);
+#endif
+ }
+ else
+ {
+ pluginData.fileSize = ffd.nFileSizeLow;
+ wcscpy_s(pluginData.fullpath, _countof(baseDirPath), baseDirPath);
+ wcscat_s(pluginData.fullpath, _countof(baseDirPath), ffd.cFileName);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"findAllPlugins :: Plugin %s\r\n",pluginData.fullpath);
+#endif
+ if (isValidDllFile(pluginData.fullpath))
+ {
+ if (getPluginName(&pluginData))
+ {
+ //add valid plugin
+ pluginList.push_back(pluginData);
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Cannot get plugin name %s\r\n"),pluginData.fullpath);
+#endif
+ }
+ }
+
+ }
+
+ }
+ }
+ while (FindNextFile(hFind, &ffd) != 0);
+
+ dwError = GetLastError();
+
+ if (dwError == ERROR_NO_MORE_FILES)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool PluginLoader::getPluginName(Plugin * pluginData)
+{
+ bool retValue = false;
+ char * pluginName = 0;
+ size_t convertedChars = 0;
+ def_ScyllaPluginNameW ScyllaPluginNameW = 0;
+ def_ScyllaPluginNameA ScyllaPluginNameA = 0;
+
+ HMODULE hModule = LoadLibraryEx(pluginData->fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
+
+ if (hModule)
+ {
+ ScyllaPluginNameW = (def_ScyllaPluginNameW)GetProcAddress(hModule, "ScyllaPluginNameW");
+
+ if (ScyllaPluginNameW)
+ {
+ wcscpy_s(pluginData->pluginName, MAX_PATH, ScyllaPluginNameW());
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"getPluginName :: Plugin name %s\r\n", pluginData->pluginName);
+#endif
+
+ retValue = true;
+ }
+ else
+ {
+ ScyllaPluginNameA = (def_ScyllaPluginNameA)GetProcAddress(hModule, "ScyllaPluginNameA");
+
+ if (ScyllaPluginNameA)
+ {
+ pluginName = ScyllaPluginNameA();
+
+ mbstowcs_s(&convertedChars, pluginData->pluginName, strlen(pluginName) + 1, pluginName, _TRUNCATE);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"getPluginName :: Plugin name mbstowcs_s %s\r\n", pluginData->pluginName);
+#endif
+
+ if (convertedChars > 1)
+ {
+ retValue = true;
+ }
+ else
+ {
+ retValue = false;
+ }
+ }
+ else
+ {
+ retValue = false;
+ }
+ }
+
+ FreeLibrary(hModule);
+
+ return retValue;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"getPluginName :: LoadLibraryEx failed %s\r\n", pluginData->fullpath);
+#endif
+ return false;
+ }
+}
+
+bool PluginLoader::buildSearchString()
+{
+ ZeroMemory(dirSearchString, sizeof(dirSearchString));
+ ZeroMemory(baseDirPath, sizeof(baseDirPath));
+
+ if (!GetModuleFileName(0, dirSearchString, _countof(dirSearchString)))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("buildSearchString :: GetModuleFileName failed %d\r\n",GetLastError());
+#endif
+ return false;
+ }
+
+ //wprintf(L"dirSearchString 1 %s\n\n", dirSearchString);
+
+
+ //remove exe file name
+ for (size_t i = wcslen(dirSearchString) - 1; i >= 0; i--)
+ {
+ if (dirSearchString[i] == L'\\')
+ {
+ dirSearchString[i + 1] = 0;
+ break;
+ }
+ }
+
+ //wprintf(L"dirSearchString 2 %s\n\n", dirSearchString);
+
+ wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_DIR)TEXT("\\") );
+
+ wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString);
+
+ wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_SEARCH_STRING) );
+
+ //wprintf(L"dirSearchString 3 %s\n\n", dirSearchString);
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"dirSearchString final %s\r\n", dirSearchString);
+#endif
+
+
+ return true;
+}
+
+bool PluginLoader::isValidDllFile( const WCHAR * fullpath )
+{
+ BYTE * data = 0;
+ DWORD lpNumberOfBytesRead = 0;
+ PIMAGE_DOS_HEADER pDos = 0;
+ PIMAGE_NT_HEADERS pNT = 0;
+ bool retValue = false;
+
+ HANDLE hFile = CreateFile(fullpath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ data = new BYTE[sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100];
+
+ if (ReadFile(hFile, data, sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100, &lpNumberOfBytesRead, 0))
+ {
+ pDos = (PIMAGE_DOS_HEADER)data;
+
+ if (pDos->e_magic == IMAGE_DOS_SIGNATURE)
+ {
+ pNT = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew);
+
+ if (pNT->Signature == IMAGE_NT_SIGNATURE)
+ {
+#ifdef _WIN64
+ if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+#else
+ if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+#endif
+ {
+ retValue = true;
+ }
+ }
+ }
+ }
+
+ delete [] data;
+ CloseHandle(hFile);
+ }
+
+ return retValue;
+}
diff --git a/Scylla/PluginLoader.h b/Scylla/PluginLoader.h
new file mode 100644
index 0000000..27c3f0b
--- /dev/null
+++ b/Scylla/PluginLoader.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <windows.h>
+#include <stdio.h>
+#include <vector>
+
+class Plugin {
+public:
+ DWORD fileSize;
+ WCHAR fullpath[MAX_PATH];
+ WCHAR pluginName[MAX_PATH];
+};
+
+#define PLUGIN_DIR "Plugins"
+#define PLUGIN_SEARCH_STRING "*.dll"
+
+typedef wchar_t * (__cdecl * def_ScyllaPluginNameW)();
+typedef char * (__cdecl * def_ScyllaPluginNameA)();
+
+class PluginLoader {
+public:
+ static bool findAllPlugins();
+
+ static std::vector<Plugin> & getPluginList();
+
+private:
+ static std::vector<Plugin> pluginList;
+
+ static WCHAR dirSearchString[MAX_PATH];
+ static WCHAR baseDirPath[MAX_PATH];
+
+ static bool buildSearchString();
+ static bool getPluginName(Plugin * pluginData);
+ static bool isValidDllFile( const WCHAR * fullpath );
+};
\ No newline at end of file
diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp
new file mode 100644
index 0000000..06d08e3
--- /dev/null
+++ b/Scylla/ProcessAccessHelp.cpp
@@ -0,0 +1,775 @@
+
+#include "ProcessAccessHelp.h"
+
+#include "Logger.h"
+#include "NativeWinApi.h"
+
+HANDLE ProcessAccessHelp::hProcess = 0;
+
+ModuleInfo * ProcessAccessHelp::selectedModule;
+DWORD_PTR ProcessAccessHelp::targetImageBase = 0;
+DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0;
+DWORD_PTR ProcessAccessHelp::maxValidAddress = 0;
+
+std::vector<ModuleInfo> ProcessAccessHelp::moduleList; //target process module list
+std::vector<ModuleInfo> ProcessAccessHelp::ownModuleList; //own module list
+
+
+_DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS];
+
+_CodeInfo ProcessAccessHelp::decomposerCi = {0};
+
+_DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS];
+unsigned int ProcessAccessHelp::decodedInstructionsCount = 0;
+
+BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
+
+//#define DEBUG_COMMENTS
+
+bool ProcessAccessHelp::openProcessHandle(DWORD dwPID)
+{
+ if (dwPID > 0)
+ {
+ if (hProcess)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("openProcessHandle :: There is already a process handle, HANDLE %X\r\n"),hProcess);
+#endif
+ return false;
+ }
+ else
+ {
+ //hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID);
+ //if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid)))
+
+ hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID);
+
+ if (hProcess)
+ {
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("openProcessHandle :: Failed to open handle, PID %X\r\n"),dwPID);
+#endif
+ return false;
+ }
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("openProcessHandle :: Wrong PID, PID %X \r\n"),dwPID);
+#endif
+ return false;
+ }
+
+}
+
+HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId)
+{
+ HANDLE hProcess = 0;
+ CLIENT_ID cid = {0};
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS ntStatus = 0;
+
+ InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
+ cid.UniqueProcess = (HANDLE)dwProcessId;
+
+ ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ return hProcess;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X\r\n"),dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus));
+#endif
+ return 0;
+ }
+}
+
+void ProcessAccessHelp::closeProcessHandle()
+{
+ CloseHandle(hProcess);
+ hProcess = 0;
+ moduleList.clear();
+ targetImageBase = 0;
+ selectedModule = 0;
+}
+
+bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
+{
+ SIZE_T lpNumberOfBytesRead = 0;
+ DWORD dwProtect = 0;
+ bool returnValue = false;
+
+ if (!hProcess)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromProcess :: hProcess == NULL\r\n"));
+#endif
+ return returnValue;
+ }
+
+ if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
+ {
+ if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u\r\n"),address,size,GetLastError());
+#endif
+ returnValue = false;
+ }
+ else
+ {
+ if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u\r\n"),address,size,GetLastError());
+#endif
+ returnValue = false;
+ }
+ else
+ {
+ returnValue = true;
+ }
+ VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect);
+ }
+ }
+ else
+ {
+ returnValue = true;
+ }
+
+ if (returnValue)
+ {
+ if (size != lpNumberOfBytesRead)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes\r\n"), lpNumberOfBytesRead, size);
+#endif
+ returnValue = false;
+ }
+ else
+ {
+ returnValue = true;
+ }
+ }
+
+ return returnValue;
+}
+
+bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress)
+{
+
+ ZeroMemory(&decomposerCi, sizeof(_CodeInfo));
+ decomposerCi.code = dataBuffer;
+ decomposerCi.codeLen = (int)bufferSize;
+ decomposerCi.dt = dt;
+ decomposerCi.codeOffset = startAddress;
+
+ decomposerInstructionsCount = 0;
+
+ if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("decomposeMemory :: distorm_decompose == DECRES_INPUTERR\r\n"));
+#endif
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
+{
+ // Holds the result of the decoding.
+ _DecodeResult res;
+
+ // next is used for instruction's offset synchronization.
+ // decodedInstructionsCount holds the count of filled instructions' array by the decoder.
+
+ decodedInstructionsCount = 0;
+
+ _OffsetType offset = startOffset;
+
+ res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
+
+/* for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
+#ifdef SUPPORT_64BIT_OFFSET
+ printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
+#else
+ printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
+#endif
+
+ }*/
+
+ if (res == DECRES_INPUTERR)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("disassembleMemory :: res == DECRES_INPUTERR\r\n"));
+#endif
+ return false;
+ }
+ else if (res == DECRES_SUCCESS)
+ {
+ //printf("disassembleMemory :: res == DECRES_SUCCESS\n");
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("disassembleMemory :: res == %d\r\n"),res);
+#endif
+ return false;
+ }
+}
+
+DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask)
+{
+ DWORD pos = 0;
+ size_t searchLen = strlen(mask) - 1;
+
+ for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++)
+ {
+ if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' )
+ {
+ if(mask[pos+1] == 0x00)
+ {
+ return (retAddress - searchLen);
+ }
+ pos++;
+ } else {
+ pos = 0;
+ }
+ }
+ return 0;
+}
+
+bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath)
+{
+ return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath);
+}
+
+LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath)
+{
+ LONGLONG fileSize = 0;
+
+ HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ fileSize = getFileSize(hFile);
+ CloseHandle(hFile);
+ hFile = 0;
+ }
+
+ return fileSize;
+}
+
+LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile)
+{
+ LARGE_INTEGER lpFileSize = {0};
+
+ if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
+ {
+ if (!GetFileSizeEx(hFile, &lpFileSize))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u\r\n"),GetLastError());
+#endif
+ return 0;
+ }
+ else
+ {
+ return lpFileSize.QuadPart;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize hFile invalid\r\n"));
+#endif
+ return 0;
+ }
+}
+
+
+bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
+{
+ DWORD lpNumberOfBytesRead = 0;
+ DWORD retValue = 0;
+ DWORD dwError = 0;
+
+ if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
+ {
+ retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
+ dwError = GetLastError();
+
+ if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromFile :: SetFilePointer failed error %u\r\n"),dwError);
+#endif
+ return false;
+ }
+ else
+ {
+ if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0))
+ {
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromFile :: ReadFile failed - size %d - error %u\r\n"),size,GetLastError());
+#endif
+ return false;
+ }
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readMemoryFromFile :: hFile invalid\r\n"));
+#endif
+ return false;
+ }
+}
+
+bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
+{
+ DWORD lpNumberOfBytesWritten = 0;
+ DWORD retValue = 0;
+ DWORD dwError = 0;
+
+ if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
+ {
+ retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
+ dwError = GetLastError();
+
+ if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("writeMemoryToFile :: SetFilePointer failed error %u\r\n"),dwError);
+#endif
+ return false;
+ }
+ else
+ {
+ if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
+ {
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("writeMemoryToFile :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError());
+#endif
+ return false;
+ }
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("writeMemoryToFile :: hFile invalid\r\n"));
+#endif
+ return false;
+ }
+}
+
+bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer)
+{
+ DWORD lpNumberOfBytesWritten = 0;
+ DWORD retValue = 0;
+
+ if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
+ {
+ SetFilePointer(hFile, 0, 0, FILE_END);
+
+ if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
+ {
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("writeMemoryToFileEnd :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError());
+#endif
+ return false;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("writeMemoryToFileEnd :: hFile invalid\r\n"));
+#endif
+ return false;
+ }
+}
+
+bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath)
+{
+ DWORD lpNumberOfBytesRead = 0;
+ LONGLONG fileSize = 0;
+ DWORD dwSize = 0;
+ bool returnValue = 0;
+
+ HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("readHeaderFromFile :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError());
+#endif
+ returnValue = false;
+ }
+ else
+ {
+ fileSize = getFileSize(hFile);
+
+ if (fileSize > 0)
+ {
+ if (fileSize > bufferSize)
+ {
+ dwSize = bufferSize;
+ }
+ else
+ {
+ dwSize = (DWORD)(fileSize - 1);
+ }
+
+ returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer);
+ }
+
+ CloseHandle(hFile);
+ }
+
+ return returnValue;
+}
+
+LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath)
+{
+ return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ);
+}
+
+LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath)
+{
+ return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS);
+}
+
+LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap)
+{
+ HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError());
+#endif
+ return NULL;
+ }
+
+ HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
+ CloseHandle(hFile);
+
+ if( hMappedFile == NULL )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("createFileMappingView :: hMappedFile == NULL\r\n"));
+#endif
+ return NULL;
+ }
+
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n"));
+#endif
+ return NULL;
+ }
+
+ LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0);
+
+ if( addrMappedDll == NULL )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("createFileMappingView :: addrMappedDll == NULL\r\n"));
+#endif
+ CloseHandle(hMappedFile);
+ return NULL;
+ }
+
+ CloseHandle(hMappedFile);
+
+ return addrMappedDll;
+}
+
+DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName)
+{
+ DWORD dwPID = 0;
+ HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ PROCESSENTRY32W pe32;
+ pe32.dwSize = sizeof(PROCESSENTRY32W);
+
+ if( !Process32FirstW( hProcessSnap, &pe32 ) )
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getProcessByName :: Error getting first Process\r\n"));
+#endif
+ CloseHandle( hProcessSnap );
+ return 0;
+ }
+
+ do
+ {
+ if(!_wcsicmp(pe32.szExeFile, processName))
+ {
+ dwPID = pe32.th32ProcessID;
+ break;
+ }
+ } while(Process32NextW(hProcessSnap, &pe32));
+
+ CloseHandle(hProcessSnap);
+
+ return dwPID;
+}
+
+bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector<ModuleInfo> &moduleList)
+{
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32;
+ ModuleInfo module;
+
+ // Take a snapshot of all modules in the specified process.
+ hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
+ if( hModuleSnap == INVALID_HANDLE_VALUE )
+ {
+ return false;
+ }
+
+ // Set the size of the structure before using it.
+ me32.dwSize = sizeof( MODULEENTRY32 );
+
+ // Retrieve information about the first module,
+ // and exit if unsuccessful
+ if( !Module32First( hModuleSnap, &me32 ) )
+ {
+ CloseHandle( hModuleSnap );
+ return false;
+ }
+
+ // Now walk the module list of the process,
+ // and display information about each module
+
+ //the first is always the .exe
+ if (!Module32Next(hModuleSnap, &me32))
+ {
+ CloseHandle( hModuleSnap );
+ return false;
+ }
+
+ moduleList.reserve(20);
+
+ do
+ {
+ //printf(TEXT("\n MODULE NAME: %s"), me32.szModule);
+ module.modBaseAddr = (DWORD_PTR)me32.modBaseAddr;
+ module.modBaseSize = me32.modBaseSize;
+ module.isAlreadyParsed = false;
+ module.parsing = false;
+ wcscpy_s(module.fullPath, MAX_PATH, me32.szExePath);
+
+ moduleList.push_back(module);
+
+ } while(Module32Next(hModuleSnap, &me32));
+
+ CloseHandle( hModuleSnap );
+ return true;
+}
+
+bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize)
+{
+ MEMORY_BASIC_INFORMATION memBasic;
+
+ if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getMemoryRegionFromAddress :: VirtualQueryEx error %u\r\n"), GetLastError());
+#endif
+ return false;
+ }
+ else
+ {
+ *memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress;
+ *memoryRegionSize = memBasic.RegionSize;
+ return true;
+ }
+}
+
+bool ProcessAccessHelp::getSizeOfImageCurrentProcess()
+{
+ DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
+
+ if (newSizeOfImage != 0)
+ {
+ ProcessAccessHelp::targetSizeOfImage = newSizeOfImage;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase)
+{
+ SIZE_T sizeOfImage = 0;
+ MEMORY_BASIC_INFORMATION lpBuffer = {0};
+ SIZE_T dwLength = sizeof(MEMORY_BASIC_INFORMATION);
+
+ do
+ {
+ moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize);
+ sizeOfImage += lpBuffer.RegionSize;
+
+ //printf("Query 0x"PRINTF_DWORD_PTR_FULL" size 0x%08X\n",moduleBase,sizeOfImage);
+
+ if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, dwLength))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getSizeOfImageProcess :: VirtualQuery failed %X\r\n"),GetLastError());
+#endif
+ lpBuffer.Type = 0;
+ sizeOfImage = 0;
+ }
+ /*else
+ {
+ printf("\nAllocationBase %X\n",lpBuffer.AllocationBase);
+ printf("AllocationProtect %X\n",lpBuffer.AllocationProtect);
+ printf("BaseAddress %X\n",lpBuffer.BaseAddress);
+ printf("Protect %X\n",lpBuffer.Protect);
+ printf("RegionSize %X\n",lpBuffer.RegionSize);
+ printf("State %X\n",lpBuffer.State);
+ printf("Type %X\n",lpBuffer.Type);
+ }*/
+ } while (lpBuffer.Type == MEM_IMAGE);
+
+ //printf("Real sizeOfImage %X\n",sizeOfImage);
+
+ return sizeOfImage;
+}
+
+//OFN_FILEMUSTEXIST
+WCHAR * ProcessAccessHelp::selectFileToSave(DWORD flags, int type)
+{
+ OPENFILENAME ofn = {0};
+ WCHAR * targetFile = new WCHAR[MAX_PATH];
+ targetFile[0] = 0;
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = 0;
+
+ switch (type)
+ {
+ case 0:
+ {
+ ofn.lpstrFilter = TEXT("Dynamic Link Library (*.dll)\0*.dll\00");
+ ofn.lpstrDefExt = TEXT(".dll");
+ }
+ break;
+ case 1:
+ {
+ ofn.lpstrFilter = TEXT("Executable (*.exe)\0*.exe\00");
+ ofn.lpstrDefExt = TEXT(".exe");
+ }
+ break;
+ default:
+ {
+ ofn.lpstrFilter = TEXT("Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\00");
+ ofn.lpstrDefExt = 0;
+ }
+ }
+
+ ofn.lpstrCustomFilter = 0;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = targetFile;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = 0;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = 0;
+ ofn.lpstrTitle = TEXT("Select a file");
+ ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING | flags;
+
+ if(GetOpenFileName(&ofn)) {
+ Logger::printfDialog(TEXT("Selected %s"),targetFile);
+ return targetFile;
+ } else {
+ delete [] targetFile;
+
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("selectFileToSave :: CommDlgExtendedError 0x%X\r\n"), CommDlgExtendedError());
+#endif
+ return 0;
+ }
+}
+
+DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath)
+{
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+
+ readHeaderFromCurrentFile(filePath);
+
+ pDosHeader = (PIMAGE_DOS_HEADER)fileHeaderFromDisk;
+
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ return 0;
+ }
+
+ pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileHeaderFromDisk + (DWORD_PTR)(pDosHeader->e_lfanew));
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ return 0;
+ }
+
+ return pNtHeader->OptionalHeader.AddressOfEntryPoint;
+}
+
+bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath)
+{
+ size_t fileNameLength = wcslen(filePath) + (5 * sizeof(WCHAR)); //.bak + null
+ BOOL retValue = 0;
+ WCHAR * backupFile = new WCHAR[fileNameLength];
+
+ if (backupFile)
+ {
+ wcscpy_s(backupFile, fileNameLength, filePath);
+ wcscat_s(backupFile, fileNameLength, TEXT(".bak"));
+ retValue = CopyFile(filePath, backupFile, FALSE);
+
+ if (!retValue)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("createBackupFile :: CopyFile failed with error 0x%X\r\n"), GetLastError());
+#endif
+ }
+
+ delete [] backupFile;
+
+ return retValue != 0;
+ }
+ else
+ {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Scylla/ProcessAccessHelp.h b/Scylla/ProcessAccessHelp.h
new file mode 100644
index 0000000..81ee0c3
--- /dev/null
+++ b/Scylla/ProcessAccessHelp.h
@@ -0,0 +1,215 @@
+#pragma once
+
+#include <stdio.h>
+#include <windows.h>
+#include <tlhelp32.h>
+#include <hash_map>
+#include <map>
+
+
+/************************************************************************/
+/* distorm */
+/************************************************************************/
+#include "distorm.h"
+
+#ifdef _WIN64
+#pragma comment(lib, "distorm_x64.lib")
+#else
+#pragma comment(lib, "distorm_x86.lib")
+#endif
+
+// The number of the array of instructions the decoder function will use to return the disassembled instructions.
+// Play with this value for performance...
+#define MAX_INSTRUCTIONS (200)
+
+/************************************************************************/
+
+class ApiInfo;
+
+class ModuleInfo {
+public:
+ WCHAR fullPath[MAX_PATH];
+ DWORD_PTR modBaseAddr;
+ DWORD modBaseSize;
+
+ bool isAlreadyParsed;
+ bool parsing;
+
+ /*
+ for iat rebuilding with duplicate entries:
+
+ ntdll = low priority
+ kernelbase = low priority
+ SHLWAPI = low priority
+
+ kernel32 = high priority
+
+ priority = 1 -> normal/high priority
+ priority = 0 -> low priority
+ */
+ int priority;
+
+ std::vector<ApiInfo *> apiList;
+
+ ModuleInfo()
+ {
+ modBaseAddr = 0;
+ modBaseSize = 0;
+ priority = 1;
+ isAlreadyParsed = false;
+ parsing = false;
+ }
+
+ WCHAR * getFilename()
+ {
+ for (size_t i = wcslen(fullPath) - 1; i >= 0; i--)
+ {
+ if (fullPath[i] == L'\\')
+ {
+ return (&fullPath[i] + 1);
+ }
+ }
+ return fullPath;
+ }
+};
+
+class ApiInfo {
+ public:
+ char name[MAX_PATH];
+ DWORD hint;
+ DWORD_PTR va;
+ DWORD_PTR rva;
+ DWORD_PTR ordinal;
+ bool isForwarded;
+ ModuleInfo * module;
+};
+
+class ProcessAccessHelp {
+public:
+ static HANDLE hProcess; //OpenProcess handle to target process
+
+ static DWORD_PTR targetImageBase;
+ static DWORD_PTR targetSizeOfImage;
+ static DWORD_PTR maxValidAddress;
+
+ static ModuleInfo * selectedModule;
+
+ static std::vector<ModuleInfo> moduleList; //target process module list
+ static std::vector<ModuleInfo> ownModuleList; //own module list
+
+ static const int PE_HEADER_BYTES_COUNT = 2000;
+
+ static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
+
+
+ //for decomposer
+ static _DInst decomposerResult[MAX_INSTRUCTIONS];
+ static unsigned int decomposerInstructionsCount;
+ static _CodeInfo decomposerCi;
+
+ //distorm :: Decoded instruction information.
+ static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
+ static unsigned int decodedInstructionsCount;
+#ifdef _WIN64
+ static const _DecodeType dt = Decode64Bits;
+#else
+ static const _DecodeType dt = Decode32Bits;
+#endif
+
+ /*
+ * 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<ModuleInfo> &moduleList);
+
+
+ /*
+ * file mapping view with different access level
+ */
+ static LPVOID createFileMappingViewRead(const WCHAR * filePath);
+ static LPVOID createFileMappingViewFull(const WCHAR * filePath);
+
+ /*
+ * Create a file mapping view of a file
+ */
+ static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap);
+
+ /*
+ * Read memory from target process
+ */
+ static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer);
+
+ /*
+ * Read memory from file
+ */
+ static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer);
+
+ /*
+ * Write memory to file
+ */
+ static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer);
+
+ /*
+ * Write memory to file end
+ */
+ static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer);
+
+ /*
+ * Disassemble Memory
+ */
+ static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset);
+
+ static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress);
+
+ /*
+ * Search for pattern
+ */
+ static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask);
+
+ /*
+ * Get process ID by process name
+ */
+ static DWORD getProcessByName(const WCHAR * processName);
+
+ /*
+ * Get memory region from address
+ */
+ bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize);
+
+
+ /*
+ * Read PE Header from file
+ */
+ static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath);
+
+ static bool readHeaderFromCurrentFile(const WCHAR * filePath);
+
+ /*
+ * Get real sizeOfImage value
+ */
+ static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase);
+
+ /*
+ * Get real sizeOfImage value current process
+ */
+ static bool getSizeOfImageCurrentProcess();
+
+
+ static LONGLONG getFileSize(HANDLE hFile);
+ static LONGLONG getFileSize(const WCHAR * filePath);
+
+ static WCHAR * selectFileToSave(DWORD flags, int type);
+
+ static DWORD getEntryPointFromFile(const WCHAR * filePath);
+
+
+ static bool createBackupFile(const WCHAR * filePath);
+};
diff --git a/Scylla/ProcessLister.cpp b/Scylla/ProcessLister.cpp
new file mode 100644
index 0000000..96eb708
--- /dev/null
+++ b/Scylla/ProcessLister.cpp
@@ -0,0 +1,364 @@
+#include "ProcessLister.h"
+
+#include "SystemInformation.h"
+#include "Logger.h"
+#include "ProcessAccessHelp.h"
+
+//#define DEBUG_COMMENTS
+
+def_IsWow64Process ProcessLister::_IsWow64Process = 0;
+
+std::vector<Process>& 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] = TEXT(':');
+
+ for ( WCHAR shortD = TEXT('a'); shortD < TEXT('z'); shortD++ )
+ {
+ shortName[0] = shortD;
+ if (QueryDosDeviceW( shortName, longName, MAX_PATH ) > 0)
+ {
+ hardDisk.shortName[0] = towupper(shortD);
+ hardDisk.shortName[1] = TEXT(':');
+ hardDisk.shortName[2] = 0;
+
+ hardDisk.longNameLength = wcslen(longName);
+
+ wcscpy_s(hardDisk.longName, MAX_PATH, 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))
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s\r\n"), processPath);
+#endif
+ }
+ return true;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("getAbsoluteFilePath :: GetProcessImageFileName failed %u\r\n"),GetLastError());
+#endif
+ CloseHandle(hProcess);
+ return false;
+ }
+
+}
+
+std::vector<Process>& ProcessLister::getProcessListSnapshot()
+{
+ HANDLE hProcessSnap;
+ ProcessType processType;
+ PROCESSENTRY32 pe32;
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32 = {0};
+ Process process;
+
+ processList.reserve(34);
+
+ if (!processList.empty())
+ {
+ processList.clear();
+ }
+
+ 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, MAX_PATH, pe32.szExeFile);
+
+ getAbsoluteFilePath(&process);
+
+ processList.push_back(process);
+ }
+ }
+ }
+ } while(Process32Next(hProcessSnap, &pe32));
+
+ CloseHandle(hProcessSnap);
+
+ //get module informations
+ //getAllModuleInformation();
+
+ 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,sizeof(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,MAX_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
new file mode 100644
index 0000000..120da44
--- /dev/null
+++ b/Scylla/ProcessLister.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <windows.h>
+#include <tlhelp32.h>
+#include <vector>
+#include <Psapi.h>
+
+#pragma comment(lib, "Psapi.lib")
+
+
+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();
+ _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),"IsWow64Process");
+ }
+
+ std::vector<Process>& getProcessList();
+ static bool isWindows64();
+ static DWORD setDebugPrivileges();
+ std::vector<Process>& ProcessLister::getProcessListSnapshot();
+
+private:
+ std::vector<Process> processList;
+
+ std::vector<HardDisk> deviceNameList;
+
+ 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.vcxproj b/Scylla/Scylla.vcxproj
new file mode 100644
index 0000000..9106a59
--- /dev/null
+++ b/Scylla/Scylla.vcxproj
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{710434C9-FC4B-4F1D-B318-E10ADC78499F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>Scylla</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v90</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="AboutGui.cpp" />
+ <ClCompile Include="ApiReader.cpp" />
+ <ClCompile Include="ConfigurationHolder.cpp" />
+ <ClCompile Include="DisassemblerGui.cpp" />
+ <ClCompile Include="DllInjection.cpp" />
+ <ClCompile Include="DllInjectionPlugin.cpp" />
+ <ClCompile Include="IATSearch.cpp" />
+ <ClCompile Include="ImportRebuild.cpp" />
+ <ClCompile Include="ImportsHandling.cpp" />
+ <ClCompile Include="Logger.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="MainGui.cpp" />
+ <ClCompile Include="NativeWinApi.cpp" />
+ <ClCompile Include="OptionsGui.cpp" />
+ <ClCompile Include="PeDump.cpp" />
+ <ClCompile Include="PeRebuild.cpp" />
+ <ClCompile Include="PickDllGui.cpp" />
+ <ClCompile Include="PluginLoader.cpp" />
+ <ClCompile Include="ProcessAccessHelp.cpp" />
+ <ClCompile Include="ProcessLister.cpp" />
+ <ClCompile Include="SystemInformation.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AboutGui.h" />
+ <ClInclude Include="ApiReader.h" />
+ <ClInclude Include="ConfigurationHolder.h" />
+ <ClInclude Include="definitions.h" />
+ <ClInclude Include="DisassemblerGui.h" />
+ <ClInclude Include="distorm.h" />
+ <ClInclude Include="DllInjection.h" />
+ <ClInclude Include="DllInjectionPlugin.h" />
+ <ClInclude Include="IATSearch.h" />
+ <ClInclude Include="ImportRebuild.h" />
+ <ClInclude Include="ImportsHandling.h" />
+ <ClInclude Include="Logger.h" />
+ <ClInclude Include="MainGui.h" />
+ <ClInclude Include="NativeWinApi.h" />
+ <ClInclude Include="OptionsGui.h" />
+ <ClInclude Include="PeDump.h" />
+ <ClInclude Include="PeRebuild.h" />
+ <ClInclude Include="PickDllGui.h" />
+ <ClInclude Include="PluginLoader.h" />
+ <ClInclude Include="ProcessAccessHelp.h" />
+ <ClInclude Include="ProcessLister.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="SystemInformation.h" />
+ <ClInclude Include="Thunks.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="MainGui.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="scylla.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/Scylla/Scylla.vcxproj.filters b/Scylla/Scylla.vcxproj.filters
new file mode 100644
index 0000000..98cc2a3
--- /dev/null
+++ b/Scylla/Scylla.vcxproj.filters
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Quelldateien">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Headerdateien">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Ressourcendateien">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Headerdateien\GUI">
+ <UniqueIdentifier>{e037d0d5-35ad-4034-83db-746a56a4fee7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Quelldateien\GUI">
+ <UniqueIdentifier>{6f76186f-b79c-41e2-8939-05d9de028aad}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="MainGui.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="Logger.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="ProcessLister.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="PickDllGui.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="ImportsHandling.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="ApiReader.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="IATSearch.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="ProcessAccessHelp.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="ImportRebuild.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="PeDump.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="PeRebuild.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="DllInjection.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="DllInjectionPlugin.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="PluginLoader.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="ConfigurationHolder.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="DisassemblerGui.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="NativeWinApi.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="SystemInformation.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="AboutGui.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="OptionsGui.cpp">
+ <Filter>Quelldateien\GUI</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="resource.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="MainGui.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="Logger.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="ProcessLister.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="PickDllGui.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="ImportsHandling.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="ApiReader.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="IATSearch.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="distorm.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="ProcessAccessHelp.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="Thunks.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="PeRebuild.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="PeDump.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="ImportRebuild.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="ConfigurationHolder.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="DllInjectionPlugin.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="DllInjection.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="PluginLoader.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="definitions.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="DisassemblerGui.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="NativeWinApi.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="SystemInformation.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="AboutGui.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="OptionsGui.h">
+ <Filter>Headerdateien\GUI</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="MainGui.rc">
+ <Filter>Ressourcendateien</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="scylla.ico">
+ <Filter>Ressourcendateien</Filter>
+ </None>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Scylla/Scylla.vcxproj.user b/Scylla/Scylla.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/Scylla/Scylla.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
diff --git a/Scylla/SystemInformation.cpp b/Scylla/SystemInformation.cpp
new file mode 100644
index 0000000..bce7a6b
--- /dev/null
+++ b/Scylla/SystemInformation.cpp
@@ -0,0 +1,62 @@
+#include "SystemInformation.h"
+
+OPERATING_SYSTEM SystemInformation::currenOS = UNKNOWN_OS;
+
+bool SystemInformation::getSystemInformation()
+{
+ OSVERSIONINFOEX osvi = {0};
+ SYSTEM_INFO si = {0};
+ def_GetNativeSystemInfo _GetNativeSystemInfo = 0;
+
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if (!GetVersionEx((OSVERSIONINFO*) &osvi))
+ {
+ return false;
+ }
+
+ if ((osvi.dwMajorVersion < 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)))
+ {
+ return false;
+ }
+
+ _GetNativeSystemInfo = (def_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+ if (_GetNativeSystemInfo)
+ {
+ _GetNativeSystemInfo(&si);
+ }
+ else
+ {
+ GetSystemInfo(&si);
+ }
+
+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
+ {
+ currenOS = WIN_VISTA_64;
+ }
+ else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
+ {
+ currenOS = WIN_VISTA_32;
+ }
+ else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
+ {
+ currenOS = WIN_7_64;
+ }
+ else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
+ {
+ currenOS = WIN_7_32;
+ }
+ else if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
+ {
+ currenOS = WIN_XP_64;
+ }
+ else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+ {
+ currenOS = WIN_XP_32;
+ }
+ else
+ {
+ currenOS = UNKNOWN_OS;
+ }
+
+ return (currenOS != UNKNOWN_OS);
+}
\ No newline at end of file
diff --git a/Scylla/SystemInformation.h b/Scylla/SystemInformation.h
new file mode 100644
index 0000000..ccac3a4
--- /dev/null
+++ b/Scylla/SystemInformation.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <windows.h>
+
+enum OPERATING_SYSTEM {
+ UNKNOWN_OS,
+ WIN_XP_32,
+ WIN_XP_64,
+ WIN_VISTA_32,
+ WIN_VISTA_64,
+ WIN_7_32,
+ WIN_7_64,
+};
+
+typedef void (WINAPI *def_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
+
+class SystemInformation {
+public:
+ static OPERATING_SYSTEM currenOS;
+ static bool getSystemInformation();
+private:
+};
\ No newline at end of file
diff --git a/Scylla/Thunks.h b/Scylla/Thunks.h
new file mode 100644
index 0000000..586c34b
--- /dev/null
+++ b/Scylla/Thunks.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <windows.h>
+#include <Commctrl.h>
+#include <map>
+
+class ImportModuleThunk;
+class ImportThunk;
+
+class ImportThunk {
+public:
+ WCHAR moduleName[MAX_PATH];
+ char name[MAX_PATH];
+ DWORD_PTR va;
+ DWORD_PTR rva;
+ DWORD_PTR ordinal;
+ DWORD_PTR apiAddressVA;
+ WORD hint;
+ bool valid;
+ bool suspect;
+
+ HTREEITEM hTreeItem;
+};
+
+
+class ImportModuleThunk {
+public:
+ WCHAR moduleName[MAX_PATH];
+ std::map<DWORD_PTR, ImportThunk> thunkList;
+
+ DWORD_PTR firstThunk;
+
+ HTREEITEM hTreeItem;
+
+ DWORD_PTR getFirstThunk();
+ bool isValid();
+
+ ~ImportModuleThunk()
+ {
+ if (!thunkList.empty())
+ {
+ thunkList.clear();
+ }
+ }
+
+};
\ No newline at end of file
diff --git a/Scylla/definitions.h b/Scylla/definitions.h
new file mode 100644
index 0000000..588c0bc
--- /dev/null
+++ b/Scylla/definitions.h
@@ -0,0 +1,34 @@
+
+#pragma once
+
+#define APPNAME "Scylla"
+
+#ifdef _WIN64
+
+#define ARCHITECTURE "x64"
+#define PRINTF_DWORD_PTR "%I64X"
+#define PRINTF_DWORD_PTR_FULL "%016I64X"
+#define PRINTF_DWORD_PTR_HALF "%08I64X"
+#define MAX_HEX_VALUE_EDIT_LENGTH 16
+
+#else
+
+#define ARCHITECTURE "x86"
+#define PRINTF_DWORD_PTR "%X"
+#define PRINTF_DWORD_PTR_FULL "%08X"
+#define PRINTF_DWORD_PTR_HALF "%08X"
+#define MAX_HEX_VALUE_EDIT_LENGTH 8
+
+#endif
+
+#define APPVERSION "v0.2a"
+
+#define RECOMMENDED_OS "This tool was designed to work with Windows 7 x64"
+#define DEVELOPED "Developed with Microsoft Visual Studio 2010, written in pure C/C++"
+#define CREDIT_DISTORM "This tool uses the diStorm disassembler library http://code.google.com/p/distorm/"
+#define CREDIT_YODA "The PE Rebuilder engine is based on the Realign DLL version 1.5 by yoda"
+#define GREETINGS "Greetz: metr0, G36KV and all from the gRn Team"
+#define VISIT "Visit http://kickme.to/grn and http://forum.tuts4you.com "
+
+
+#define PLUGIN_MENU_BASE_ID 0x10
\ No newline at end of file
diff --git a/Scylla/main.cpp b/Scylla/main.cpp
new file mode 100644
index 0000000..be84b32
--- /dev/null
+++ b/Scylla/main.cpp
@@ -0,0 +1,8 @@
+#include "MainGui.h"
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ //start main dialog
+ MainGui::initDialog(hInstance);
+ return 0;
+}
\ No newline at end of file
diff --git a/Scylla/resource.h b/Scylla/resource.h
new file mode 100644
index 0000000..2104e9d
Binary files /dev/null and b/Scylla/resource.h differ
diff --git a/Scylla/scylla.ico b/Scylla/scylla.ico
new file mode 100644
index 0000000..08811ac
Binary files /dev/null and b/Scylla/scylla.ico differ
diff --git a/readme b/readme
deleted file mode 100644
index e69de29..0000000

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 21, 10:09 PM (1 d, 17 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
4c/12/13afc8d5a203e188ec9104b8289d

Event Timeline