Page MenuHomedesp's stash

No OneTemporary

diff --git a/README.txt b/README.txt
index 3b9f975..308c009 100644
--- a/README.txt
+++ b/README.txt
@@ -1,54 +1,54 @@
Scylla - x64/x86 Imports Reconstruction
******************************************************************
ImpREC, CHimpREC, Imports Fixer... this are all great tools to rebuild an import table,
but they all have some major disadvantages, so I decided to create my own tool for this job.
Scylla's key benefits are:
- x64 and x86 support
- full unicode support (probably some russian or chinese will like this :-) )
- written in C/C++
- plugin support
- works great with Windows 7
This tool was designed to be used with Windows 7 x64, so it is recommend to use this operating system.
But it may work with XP and Vista, too.
-Sour code is licensed under GNU GENERAL PUBLIC LICENSE v3.0
+Source code is licensed under GNU GENERAL PUBLIC LICENSE v3.0
******************************************************************
Known Bugs
******************************************************************
- Only Windows XP x64:
Windows XP x64 has some API bugs. 100% correct imports reconstruction is impossible.
If you still want to use XP x64, here are some hints:
* EncodePointer/DecodePointer exported by kernel32.dll have both the same VA. Scylla, CHimpREC and
other tools cannot know which API is correct. You need to fix this manually. Your fixed dump will probably
run fine on XP but crash on Vista/7.
******************************************************************
Changelog
******************************************************************
Version 0.2:
- improved process detection
- added some options
- new options dialog
- improved source code
diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp
index 7586b48..4739fe9 100644
--- a/Scylla/ApiReader.cpp
+++ b/Scylla/ApiReader.cpp
@@ -1,1103 +1,1107 @@
#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("ShimEng.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
+ //API is 100% correct if countHighPriority == 1 and name export
*isSuspect = false;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
- if (apiFound->module->priority >= 1) //1 == high priority
+ if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //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/DllInjectionPlugin.cpp b/Scylla/DllInjectionPlugin.cpp
index 097a81a..e74751e 100644
--- a/Scylla/DllInjectionPlugin.cpp
+++ b/Scylla/DllInjectionPlugin.cpp
@@ -1,264 +1,303 @@
#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();
}
+void DllInjectionPlugin::injectImprecPlugin(Plugin & plugin, std::map<DWORD_PTR, ImportModuleThunk> & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize)
+{
+ Plugin newPlugin;
+ size_t mapSize = (wcslen(plugin.fullpath) + 1) * sizeof(WCHAR);
+
+ HANDLE hImprecMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, (DWORD)mapSize, TEXT(PLUGIN_IMPREC_EXCHANGE_DLL_PATH));
+
+ if (hImprecMap == NULL)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("injectImprecPlugin :: CreateFileMapping failed 0x%X\r\n",GetLastError());
+#endif
+ return;
+ }
+
+ LPVOID lpImprecViewOfFile = MapViewOfFile(hImprecMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+
+ if (lpImprecViewOfFile == NULL)
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog("injectImprecPlugin :: MapViewOfFile failed 0x%X\r\n",GetLastError());
+#endif
+ CloseHandle(hImprecMap);
+ return;
+ }
+
+ CopyMemory(lpImprecViewOfFile,plugin.fullpath, mapSize);
+
+ UnmapViewOfFile(lpImprecViewOfFile);
+
+ newPlugin.fileSize = plugin.fileSize;
+ wcscpy_s(newPlugin.pluginName, plugin.pluginName);
+ wcscpy_s(newPlugin.fullpath, PluginLoader::imprecWrapperDllPath);
+
+ injectPlugin(newPlugin,moduleList,imageBase,imageSize);
+
+ CloseHandle(hImprecMap);
+}
+
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
index 9f8fb14..1f22613 100644
--- a/Scylla/DllInjectionPlugin.h
+++ b/Scylla/DllInjectionPlugin.h
@@ -1,61 +1,65 @@
#include "DllInjection.h"
#include "PluginLoader.h"
#include "Thunks.h"
#include "ApiReader.h"
+
+#define PLUGIN_IMPREC_EXCHANGE_DLL_PATH "ScyllaImprecPluginExchangePath"
+
#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);
+ void injectImprecPlugin(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/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp
index c94a798..246c871 100644
--- a/Scylla/ImportsHandling.cpp
+++ b/Scylla/ImportsHandling.cpp
@@ -1,825 +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);
+ swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" ptr: ")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
index 31aff46..8310733 100644
--- a/Scylla/ImportsHandling.h
+++ b/Scylla/ImportsHandling.h
@@ -1,54 +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];
+ WCHAR tempString[300];
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/MainGui.cpp b/Scylla/MainGui.cpp
index 567fd08..1037389 100644
--- a/Scylla/MainGui.cpp
+++ b/Scylla/MainGui.cpp
@@ -1,880 +1,930 @@
#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};
+WCHAR MainGui::stringBuffer[600] = {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:
+ /*case IDC_BTN_ABOUT:
showAboutDialog();
- return TRUE;
+ return TRUE;*/
case ID_HELP_ABOUT:
showAboutDialog();
return TRUE;
- case IDC_BTN_EXIT:
+ /*case IDC_BTN_EXIT:
PostQuitMessage(0);
EndDialog(hWndDlg, 0);
- return TRUE;
+ 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();
+ std::vector<Plugin> &pluginList = PluginLoader::getScyllaPluginList();
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)))
+ if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
//wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName);
//MessageBox(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();
+ pluginActionHandler(menuItem);
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();
+ std::vector<Plugin> &scyllaPluginList = PluginLoader::getScyllaPluginList();
+ std::vector<Plugin> &imprecPluginList = PluginLoader::getImprecPluginList();
- if (pluginList.size() > 0)
+ if (scyllaPluginList.size() > 0)
{
- for (size_t i = 0; i < pluginList.size(); i++)
+ for (size_t i = 0; i < scyllaPluginList.size(); i++)
{
- AppendMenu(newMenu, MF_STRING, i + PLUGIN_MENU_BASE_ID, pluginList[i].pluginName);
+ AppendMenu(newMenu, MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName);
}
AppendMenu(hMenuTrackPopup,MF_MENUBARBREAK,0,0);
- AppendMenu(hMenuTrackPopup,MF_POPUP,(UINT_PTR)newMenu,TEXT("Plugins"));
+ AppendMenu(hMenuTrackPopup,MF_POPUP,(UINT_PTR)newMenu,TEXT("Scylla Plugins"));
+ }
+
+ newMenu = CreatePopupMenu();
+
+ if (imprecPluginList.size() > 0)
+ {
+ for (size_t i = 0; i < imprecPluginList.size(); i++)
+ {
+ AppendMenu(newMenu, MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName);
+ }
+
+ AppendMenu(hMenuTrackPopup,MF_MENUBARBREAK,0,0);
+ AppendMenu(hMenuTrackPopup,MF_POPUP,(UINT_PTR)newMenu,TEXT("ImpREC 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 (processAccessHelp.selectedModule)
+ {
+ wcscat_s(newFilePath,MAX_PATH, L"_SCY.dll");
+ }
+ else
+ {
+ 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);
}
+
+void MainGui::pluginActionHandler( int menuItem )
+{
+ DllInjectionPlugin dllInjectionPlugin;
+
+ std::vector<Plugin> &scyllaPluginList = PluginLoader::getScyllaPluginList();
+ std::vector<Plugin> &imprecPluginList = PluginLoader::getImprecPluginList();
+
+ menuItem -= PLUGIN_MENU_BASE_ID;
+
+ dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
+ dllInjectionPlugin.apiReader = &apiReader;
+
+ if (menuItem < (int)scyllaPluginList.size())
+ {
+ //scylla plugin
+ dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
+ }
+ else
+ {
+#ifndef _WIN64
+
+ menuItem -= (int)scyllaPluginList.size();
+ //imprec plugin
+ dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
+
+#endif
+ }
+
+
+
+ importsHandling.scanAndFixModuleList();
+ importsHandling.displayAllImports();
+}
diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h
index e086863..9ff22a1 100644
--- a/Scylla/MainGui.h
+++ b/Scylla/MainGui.h
@@ -1,95 +1,96 @@
#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 WCHAR stringBuffer[600];
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();
+ static void pluginActionHandler( int menuItem );
};
\ No newline at end of file
diff --git a/Scylla/MainGui.rc b/Scylla/MainGui.rc
index 3e25378..7f30fce 100644
Binary files a/Scylla/MainGui.rc and b/Scylla/MainGui.rc differ
diff --git a/Scylla/PluginLoader.cpp b/Scylla/PluginLoader.cpp
index 57ca43b..c8c8a8c 100644
--- a/Scylla/PluginLoader.cpp
+++ b/Scylla/PluginLoader.cpp
@@ -1,258 +1,373 @@
#include "PluginLoader.h"
#include "Logger.h"
#include "ProcessAccessHelp.h"
-std::vector<Plugin> PluginLoader::pluginList;
+std::vector<Plugin> PluginLoader::scyllaPluginList;
+std::vector<Plugin> PluginLoader::imprecPluginList;
WCHAR PluginLoader::dirSearchString[MAX_PATH];
WCHAR PluginLoader::baseDirPath[MAX_PATH];
+WCHAR PluginLoader::imprecWrapperDllPath[MAX_PATH];
//#define DEBUG_COMMENTS
-std::vector<Plugin> & PluginLoader::getPluginList()
+std::vector<Plugin> & PluginLoader::getScyllaPluginList()
{
- return pluginList;
+ return scyllaPluginList;
+}
+
+std::vector<Plugin> & PluginLoader::getImprecPluginList()
+{
+ return imprecPluginList;
}
bool PluginLoader::findAllPlugins()
{
- WIN32_FIND_DATA ffd;
- HANDLE hFind = 0;
- DWORD dwError = 0;
- Plugin pluginData;
- if (!pluginList.empty())
+ if (!scyllaPluginList.empty())
{
- pluginList.clear();
+ scyllaPluginList.clear();
+ }
+
+ if (!imprecPluginList.empty())
+ {
+ imprecPluginList.clear();
}
if (!buildSearchString())
{
return false;
}
- hFind = FindFirstFile(dirSearchString, &ffd);
+ if (!searchForPlugin(scyllaPluginList, dirSearchString, true))
+ {
+ return false;
+ }
+
+#ifndef _WIN64
+ if (!buildSearchStringImprecPlugins())
+ {
+ return false;
+ }
+
+ if (!searchForPlugin(imprecPluginList, dirSearchString, false))
+ {
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+bool PluginLoader::searchForPlugin(std::vector<Plugin> & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin)
+{
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = 0;
+ DWORD dwError = 0;
+ Plugin pluginData;
+
+ hFind = FindFirstFile(searchPath, &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))
+ if (isScyllaPlugin)
{
- //add valid plugin
- pluginList.push_back(pluginData);
+ if (getScyllaPluginName(&pluginData))
+ {
+ //add valid plugin
+ newPluginList.push_back(pluginData);
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(TEXT("Cannot get scylla plugin name %s\r\n"),pluginData.fullpath);
+#endif
+ }
}
else
{
-#ifdef DEBUG_COMMENTS
- Logger::debugLog(TEXT("Cannot get plugin name %s\r\n"),pluginData.fullpath);
-#endif
+ if (isValidImprecPlugin(pluginData.fullpath))
+ {
+ wcscpy_s(pluginData.pluginName, MAX_PATH, ffd.cFileName);
+ newPluginList.push_back(pluginData);
+ }
}
+
}
}
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
+ FindClose(hFind);
+
if (dwError == ERROR_NO_MORE_FILES)
{
return true;
}
else
{
return false;
}
+
}
-bool PluginLoader::getPluginName(Plugin * pluginData)
+bool PluginLoader::getScyllaPluginName(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;
}
+
+bool PluginLoader::isValidImprecPlugin(const WCHAR * fullpath)
+{
+ def_Imprec_Trace Imprec_Trace = 0;
+ bool retValue = false;
+
+ HMODULE hModule = LoadLibraryEx(fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
+
+ if (hModule)
+ {
+ Imprec_Trace = (def_Imprec_Trace)GetProcAddress(hModule, "Trace");
+ if (Imprec_Trace)
+ {
+ retValue = true;
+ }
+ else
+ {
+ retValue = false;
+ }
+
+ FreeLibrary(hModule);
+ return retValue;
+ }
+ else
+ {
+#ifdef DEBUG_COMMENTS
+ Logger::debugLog(L"isValidImprecPlugin :: LoadLibraryEx failed %s\r\n", pluginData->fullpath);
+#endif
+ return false;
+ }
+}
+
+bool PluginLoader::buildSearchStringImprecPlugins()
+{
+ wcscpy_s(dirSearchString, _countof(dirSearchString), baseDirPath);
+
+ wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_IMPREC_DIR)TEXT("\\") );
+
+ wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString);
+
+ //build imprec wrapper dll path
+ wcscpy_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), dirSearchString);
+ wcscat_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), TEXT(PLUGIN_IMPREC_WRAPPER_DLL) );
+
+ if (!fileExists(imprecWrapperDllPath))
+ {
+ return false;
+ }
+
+ wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_SEARCH_STRING) );
+
+ return true;
+}
+
+bool PluginLoader::fileExists(const WCHAR * fileName)
+{
+ if (GetFileAttributesW(fileName) == INVALID_FILE_ATTRIBUTES)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
diff --git a/Scylla/PluginLoader.h b/Scylla/PluginLoader.h
index 27c3f0b..b9d0fd0 100644
--- a/Scylla/PluginLoader.h
+++ b/Scylla/PluginLoader.h
@@ -1,35 +1,48 @@
#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"
+#define PLUGIN_IMPREC_DIR "ImpRec_Plugins"
+#define PLUGIN_IMPREC_WRAPPER_DLL "Imprec_Wrapper_DLL.dll"
typedef wchar_t * (__cdecl * def_ScyllaPluginNameW)();
typedef char * (__cdecl * def_ScyllaPluginNameA)();
+typedef DWORD ( * def_Imprec_Trace)(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall);
+
class PluginLoader {
public:
+ static WCHAR imprecWrapperDllPath[MAX_PATH];
+
static bool findAllPlugins();
- static std::vector<Plugin> & getPluginList();
+ static std::vector<Plugin> & getScyllaPluginList();
+ static std::vector<Plugin> & getImprecPluginList();
private:
- static std::vector<Plugin> pluginList;
+ static std::vector<Plugin> scyllaPluginList;
+ static std::vector<Plugin> imprecPluginList;
static WCHAR dirSearchString[MAX_PATH];
static WCHAR baseDirPath[MAX_PATH];
static bool buildSearchString();
- static bool getPluginName(Plugin * pluginData);
+ static bool getScyllaPluginName(Plugin * pluginData);
static bool isValidDllFile( const WCHAR * fullpath );
+ static bool searchForPlugin(std::vector<Plugin> & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin);
+ static bool isValidImprecPlugin(const WCHAR * fullpath);
+ static bool buildSearchStringImprecPlugins();
+
+ static bool fileExists(const WCHAR * fileName);
};
\ No newline at end of file
diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp
index 06d08e3..59d5143 100644
--- a/Scylla/ProcessAccessHelp.cpp
+++ b/Scylla/ProcessAccessHelp.cpp
@@ -1,775 +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];
-
+unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0;
_CodeInfo ProcessAccessHelp::decomposerCi = {0};
_DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS];
unsigned int ProcessAccessHelp::decodedInstructionsCount = 0;
BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
//#define DEBUG_COMMENTS
bool ProcessAccessHelp::openProcessHandle(DWORD dwPID)
{
if (dwPID > 0)
{
if (hProcess)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("openProcessHandle :: There is already a process handle, HANDLE %X\r\n"),hProcess);
#endif
return false;
}
else
{
//hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID);
//if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid)))
hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID);
if (hProcess)
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("openProcessHandle :: Failed to open handle, PID %X\r\n"),dwPID);
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("openProcessHandle :: Wrong PID, PID %X \r\n"),dwPID);
#endif
return false;
}
}
HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId)
{
HANDLE hProcess = 0;
CLIENT_ID cid = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntStatus = 0;
InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
cid.UniqueProcess = (HANDLE)dwProcessId;
ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid);
if (NT_SUCCESS(ntStatus))
{
return hProcess;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X\r\n"),dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus));
#endif
return 0;
}
}
void ProcessAccessHelp::closeProcessHandle()
{
CloseHandle(hProcess);
hProcess = 0;
moduleList.clear();
targetImageBase = 0;
selectedModule = 0;
}
bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
SIZE_T lpNumberOfBytesRead = 0;
DWORD dwProtect = 0;
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromProcess :: hProcess == NULL\r\n"));
#endif
return returnValue;
}
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u\r\n"),address,size,GetLastError());
#endif
returnValue = false;
}
else
{
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u\r\n"),address,size,GetLastError());
#endif
returnValue = false;
}
else
{
returnValue = true;
}
VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect);
}
}
else
{
returnValue = true;
}
if (returnValue)
{
if (size != lpNumberOfBytesRead)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes\r\n"), lpNumberOfBytesRead, size);
#endif
returnValue = false;
}
else
{
returnValue = true;
}
}
return returnValue;
}
bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress)
{
ZeroMemory(&decomposerCi, sizeof(_CodeInfo));
decomposerCi.code = dataBuffer;
decomposerCi.codeLen = (int)bufferSize;
decomposerCi.dt = dt;
decomposerCi.codeOffset = startAddress;
decomposerInstructionsCount = 0;
if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("decomposeMemory :: distorm_decompose == DECRES_INPUTERR\r\n"));
#endif
return false;
}
else
{
return true;
}
}
bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
{
// Holds the result of the decoding.
_DecodeResult res;
// next is used for instruction's offset synchronization.
// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
decodedInstructionsCount = 0;
_OffsetType offset = startOffset;
res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
/* for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
#ifdef SUPPORT_64BIT_OFFSET
printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#else
printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#endif
}*/
if (res == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("disassembleMemory :: res == DECRES_INPUTERR\r\n"));
#endif
return false;
}
else if (res == DECRES_SUCCESS)
{
//printf("disassembleMemory :: res == DECRES_SUCCESS\n");
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("disassembleMemory :: res == %d\r\n"),res);
#endif
return false;
}
}
DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask)
{
DWORD pos = 0;
size_t searchLen = strlen(mask) - 1;
for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++)
{
if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' )
{
if(mask[pos+1] == 0x00)
{
return (retAddress - searchLen);
}
pos++;
} else {
pos = 0;
}
}
return 0;
}
bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath)
{
return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath);
}
LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath)
{
LONGLONG fileSize = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
fileSize = getFileSize(hFile);
CloseHandle(hFile);
hFile = 0;
}
return fileSize;
}
LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile)
{
LARGE_INTEGER lpFileSize = {0};
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
if (!GetFileSizeEx(hFile, &lpFileSize))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u\r\n"),GetLastError());
#endif
return 0;
}
else
{
return lpFileSize.QuadPart;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize hFile invalid\r\n"));
#endif
return 0;
}
}
bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesRead = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromFile :: SetFilePointer failed error %u\r\n"),dwError);
#endif
return false;
}
else
{
if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromFile :: ReadFile failed - size %d - error %u\r\n"),size,GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readMemoryFromFile :: hFile invalid\r\n"));
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("writeMemoryToFile :: SetFilePointer failed error %u\r\n"),dwError);
#endif
return false;
}
else
{
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("writeMemoryToFile :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("writeMemoryToFile :: hFile invalid\r\n"));
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
SetFilePointer(hFile, 0, 0, FILE_END);
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("writeMemoryToFileEnd :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError());
#endif
return false;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("writeMemoryToFileEnd :: hFile invalid\r\n"));
#endif
return false;
}
}
bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath)
{
DWORD lpNumberOfBytesRead = 0;
LONGLONG fileSize = 0;
DWORD dwSize = 0;
bool returnValue = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("readHeaderFromFile :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError());
#endif
returnValue = false;
}
else
{
fileSize = getFileSize(hFile);
if (fileSize > 0)
{
if (fileSize > bufferSize)
{
dwSize = bufferSize;
}
else
{
dwSize = (DWORD)(fileSize - 1);
}
returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer);
}
CloseHandle(hFile);
}
return returnValue;
}
LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ);
}
LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS);
}
LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap)
{
HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError());
#endif
return NULL;
}
HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
CloseHandle(hFile);
if( hMappedFile == NULL )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("createFileMappingView :: hMappedFile == NULL\r\n"));
#endif
return NULL;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n"));
#endif
return NULL;
}
LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0);
if( addrMappedDll == NULL )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("createFileMappingView :: addrMappedDll == NULL\r\n"));
#endif
CloseHandle(hMappedFile);
return NULL;
}
CloseHandle(hMappedFile);
return addrMappedDll;
}
DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName)
{
DWORD dwPID = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(PROCESSENTRY32W);
if( !Process32FirstW( hProcessSnap, &pe32 ) )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("getProcessByName :: Error getting first Process\r\n"));
#endif
CloseHandle( hProcessSnap );
return 0;
}
do
{
if(!_wcsicmp(pe32.szExeFile, processName))
{
dwPID = pe32.th32ProcessID;
break;
}
} while(Process32NextW(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return dwPID;
}
bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector<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/definitions.h b/Scylla/definitions.h
index 588c0bc..70a0e59 100644
--- a/Scylla/definitions.h
+++ b/Scylla/definitions.h
@@ -1,34 +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 APPVERSION "v0.3"
#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/resource.h b/Scylla/resource.h
index 2104e9d..51ba47c 100644
Binary files a/Scylla/resource.h and b/Scylla/resource.h differ

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 21, 9:54 PM (1 d, 16 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
83/57/4a5500efed1b6b11bef5bef7da21

Event Timeline