Page MenuHomedesp's stash

No OneTemporary

diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp
index 4a4dd0a..97a4974 100644
--- a/Scylla/ApiReader.cpp
+++ b/Scylla/ApiReader.cpp
@@ -1,1225 +1,1225 @@
#include "ApiReader.h"
#include "Scylla.h"
#include "Architecture.h"
#include "SystemInformation.h"
#include "StringConversion.h"
#include "PeParser.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()
{
if (Scylla::config[APIS_ALWAYS_FROM_DISK].isTrue())
{
readExportTableAlwaysFromDisk = true;
}
else
{
readExportTableAlwaysFromDisk = false;
}
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;
}
Scylla::windowLog.log(L"Module parsing: %s",moduleList[i].fullPath);
if (!moduleList[i].isAlreadyParsed)
{
parseModule(&moduleList[i]);
}
}
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Address Min " PRINTF_DWORD_PTR_FULL L" Max " PRINTF_DWORD_PTR_FULL L"\nimagebase " PRINTF_DWORD_PTR_FULL L" maxValidAddress " PRINTF_DWORD_PTR_FULL, minApiAddress, maxApiAddress, targetImageBase ,maxValidAddress);
#endif
}
void ApiReader::parseModule(ModuleInfo *module)
{
module->parsing = true;
if (isWinSxSModule(module))
{
parseModuleWithMapping(module);
}
else if (isModuleLoadedInOwnProcess(module)) //this is always ok
{
parseModuleWithOwnProcess(module);
}
else
{
if (readExportTableAlwaysFromDisk)
{
parseModuleWithMapping(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, WORD ordinalParent, ModuleInfo *moduleParent)
{
size_t dllNameLength = 0;
WORD 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, 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, ".dll");
StringConversion::ToUTF16(dllName, dllNameW, _countof(dllNameW));
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 = (WORD)atoi(searchFunctionName);
findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi);
}
else
{
findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi);
}
if (rvaApi == 0)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"handleForwardedApi :: Api not found, this is really BAD! %S",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(WORD 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, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo)
{
ApiInfo *apiInfo = new ApiInfo();
if ((functionName != 0) && (strlen(functionName) < _countof(apiInfo->name)))
{
strcpy_s(apiInfo->name, 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
Scylla::debugLog.log(L"getHeaderFromProcess :: Error reading header");
#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
Scylla::debugLog.log(L"Something is wrong with the PE Header here Export table size %d", readSize);
#endif
readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100;
}
if (readSize)
{
bufferExportTable = new BYTE[readSize];
if (!bufferExportTable)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Something is wrong with the PE Header here Export table size %d", readSize);
#endif
return 0;
}
if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getExportTableFromProcess :: Error reading export table from process");
#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;
PeParser peParser(module->modBaseAddr, false);
if (!peParser.isValidPeFile())
return;
pNtHeader = peParser.getCurrentNtHeader();
if (peParser.hasExportDirectory())
{
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;
}
}
}
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;
WORD ordinal = 0;
WORD 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
Scylla::debugLog.log(L"parseExportTable :: module %s NumberOfNames %X", module->fullPath, pExportDir->NumberOfNames);
#endif
for (i = 0; i < pExportDir->NumberOfNames; i++)
{
functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
ordinal = (WORD)(addressOfNameOrdinalsArray[i] + pExportDir->Base);
RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"parseExportTable :: api %S ordinal %d imagebase " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" VA " PRINTF_DWORD_PTR_FULL, functionName, ordinal, module->modBaseAddr, RVA, VA);
#endif
if (!isApiBlacklisted(functionName))
{
if (!isApiForwarded(RVA,pNtHeader))
{
addApi(functionName, 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 = (WORD)(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, WORD 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, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
if (isModuleLoadedInOwnProcess(module))
{
HMODULE hModule = GetModuleHandle(module->getFilename());
if (hModule)
{
if (vaApi)
{
if (ordinal)
{
*vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal);
}
else
{
*vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName);
}
*rvaApi = (*vaApi) - (DWORD_PTR)hModule;
*vaApi = (*rvaApi) + module->modBaseAddr;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findApiByModule :: vaApi == NULL, should never happen %S", searchFunctionName);
#endif
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findApiByModule :: hModule == NULL, should never happen %s", 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
Scylla::debugLog.log(L"parseModuleWithOwnProcess :: hModule is NULL");
#endif
}
}
bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader)
{
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
Scylla::windowLog.log(L"-> 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))
{
Scylla::windowLog.log(L"-> No export table.");
return false;
}
else
{
return true;
}
}
void ApiReader::findApiInProcess(ModuleInfo * module, char * searchFunctionName, WORD 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, WORD 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)
{
const WCHAR *moduleFileName = module->getFilename();
//imports by kernelbase don't exist
if (!_wcsicmp(moduleFileName, L"kernelbase.dll"))
{
module->priority = -1;
}
else if (!_wcsicmp(moduleFileName, L"ntdll.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"shlwapi.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"ShimEng.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"kernel32.dll"))
{
module->priority = 2;
}
else if (!_wcsnicmp(moduleFileName, L"api-ms-win-", 11))
{
module->priority = 0;
}
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)
{
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.
//any high priority with a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,true,false,false,false,false);
if (apiFound)
return apiFound;
*isSuspect = true;
//high priority with a name and ansi/unicode name
apiFound = getScoredApi(it1,countDuplicates,true,true,false,true,false,false,false,false);
if (apiFound)
return apiFound;
//priority 2 with no underline in name
apiFound = getScoredApi(it1,countDuplicates,true,false,true,false,false,false,true,false);
if (apiFound)
return apiFound;
//priority 1 with a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,false,false,true,false,false);
if (apiFound)
return apiFound;
//With a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,false,false,false,false,false);
if (apiFound)
return apiFound;
//any with priority, name, ansi/unicode
apiFound = getScoredApi(it1,countDuplicates,true,true,false,true,false,false,false,true);
if (apiFound)
return apiFound;
//any with priority
apiFound = getScoredApi(it1,countDuplicates,false,false,false,true,false,false,false,true);
if (apiFound)
return apiFound;
//has prio 0 and name
apiFound = getScoredApi(it1,countDuplicates,false,false,false,false,true,false,false,true);
if (apiFound)
return apiFound;
}
//is never reached
Scylla::windowLog.log(L"getApiByVirtualAddress :: There is a api resolving bug, VA: " PRINTF_DWORD_PTR_FULL, virtualAddress);
for (size_t c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
Scylla::windowLog.log(L"-> Possible API: %S ord: %d ", apiFound->name, apiFound->ordinal);
}
return (ApiInfo *) 1;
}
ApiInfo * ApiReader::getScoredApi(stdext::hash_multimap<DWORD_PTR, ApiInfo *>::iterator it1,size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll,bool hasPrio0Dll,bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin )
{
ApiInfo * foundApi = 0;
ApiInfo * foundMatchingApi = 0;
int countFoundApis = 0;
int scoreNeeded = 0;
int scoreValue = 0;
size_t apiNameLength = 0;
if (hasUnicodeAnsiName || hasNoUnderlineInName)
{
hasName = true;
}
if (hasName)
scoreNeeded++;
if (hasUnicodeAnsiName)
scoreNeeded++;
if (hasNoUnderlineInName)
scoreNeeded++;
if (hasPrioDll)
scoreNeeded++;
if (hasPrio0Dll)
scoreNeeded++;
if (hasPrio1Dll)
scoreNeeded++;
if (hasPrio2Dll)
scoreNeeded++;
for (size_t c = 0; c < countDuplicates; c++, it1++)
{
foundApi = (ApiInfo *)((*it1).second);
scoreValue = 0;
if (hasName)
{
if (foundApi->name[0] != 0x00)
{
scoreValue++;
if (hasUnicodeAnsiName)
{
apiNameLength = strlen(foundApi->name);
if ((foundApi->name[apiNameLength - 1] == 'W') || (foundApi->name[apiNameLength - 1] == 'A'))
{
scoreValue++;
}
}
if (hasNoUnderlineInName)
{
if (!strrchr(foundApi->name, '_'))
{
scoreValue++;
}
}
}
}
if (hasPrioDll)
{
if (foundApi->module->priority >= 1)
{
scoreValue++;
}
}
if (hasPrio0Dll)
{
if (foundApi->module->priority == 0)
{
scoreValue++;
}
}
if (hasPrio1Dll)
{
if (foundApi->module->priority == 1)
{
scoreValue++;
}
}
if (hasPrio2Dll)
{
if (foundApi->module->priority == 2)
{
scoreValue++;
}
}
if (scoreValue == scoreNeeded)
{
foundMatchingApi = foundApi;
countFoundApis++;
if (firstWin)
{
return foundMatchingApi;
}
}
}
if (countFoundApis == 1)
{
return foundMatchingApi;
}
else
{
return (ApiInfo *)0;
}
}
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
Scylla::debugLog.log(L"ApiReader::readAndParseIAT :: error reading iat " PRINTF_DWORD_PTR_FULL, 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);
for (SIZE_T i = 0; i < sizeIAT; i++)
{
//Scylla::windowLog.log(L"%08X %08X %d von %d", addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i],i,sizeIAT);
if (!isInvalidMemoryForIat(pIATAddress[i]))
{
if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) )
{
apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect);
if (apiFound == 0)
{
Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, pIATAddress[i]);
}
if (apiFound == (ApiInfo *)1)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"apiFound == (ApiInfo *)1 -> " PRINTF_DWORD_PTR_FULL, pIATAddress[i]);
#endif
}
else if (apiFound)
{
countApiFound++;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" %s %d %s", 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]);
}
}
}
Scylla::windowLog.log(L"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, 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, L"?");
(*moduleThunkList).insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
}
bool ApiReader::addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, WORD 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
Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()");
#endif
break;
}
}
}
else
{
iterator1 = (*moduleThunkList).begin();
module = &(iterator1->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, 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, apiFound->module->getFilename());
strcpy_s(import.name, 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_map<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
Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()\r\n");
#endif
break;
}
}
}
else
{
//new unknown module
addUnknownModuleToModuleList(rva);
module = &((*moduleThunkList).find(rva)->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL,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, L"?");
strcpy_s(import.name, "?");
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, L"\\WinSxS\\"))
{
return true;
}
else if (wcsstr(module->fullPath, L"\\winsxs\\"))
{
return true;
}
else
{
return false;
}
}
bool ApiReader::isInvalidMemoryForIat( DWORD_PTR address )
{
if (address == 0)
return true;
if (address == -1)
return true;
MEMORY_BASIC_INFORMATION memBasic = {0};
if (VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)))
{
- if((memBasic.State == MEM_COMMIT) && ProcessAccessHelp::isPageExecutable(memBasic.Protect))
+ if((memBasic.State == MEM_COMMIT) && ProcessAccessHelp::isPageAccessable(memBasic.Protect))
{
return false;
}
else
{
return true;
}
}
else
{
return true;
}
}
diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp
index 6d91608..07c44f3 100644
--- a/Scylla/MainGui.cpp
+++ b/Scylla/MainGui.cpp
@@ -1,1709 +1,1716 @@
#include "MainGui.h"
#include "Architecture.h"
//#include "PluginLoader.h"
//#include "ConfigurationHolder.h"
#include "PeParser.h"
#include "DllInjectionPlugin.h"
#include "DisassemblerGui.h"
#include "PickApiGui.h"
//#include "NativeWinApi.h"
#include "ImportRebuilder.h"
#include "SystemInformation.h"
#include "Scylla.h"
#include "AboutGui.h"
#include "DonateGui.h"
#include "OptionsGui.h"
#include "TreeImportExport.h"
extern CAppModule _Module; // o_O
const WCHAR MainGui::filterExe[] = L"Executable (*.exe)\0*.exe\0All files\0*.*\0";
const WCHAR MainGui::filterDll[] = L"Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterExeDll[] = L"Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterTxt[] = L"Text file (*.txt)\0*.txt\0All files\0*.*\0";
const WCHAR MainGui::filterXml[] = L"XML file (*.xml)\0*.xml\0All files\0*.*\0";
const WCHAR MainGui::filterMem[] = L"MEM file (*.mem)\0*.mem\0All files\0*.*\0";
MainGui::MainGui() : selectedProcess(0), isProcessSuspended(false), importsHandling(TreeImports), TreeImportsSubclass(this, IDC_TREE_IMPORTS)
{
/*
Logger::getDebugLogFilePath();
ConfigurationHolder::loadConfiguration();
PluginLoader::findAllPlugins();
NativeWinApi::initialize();
SystemInformation::getSystemInformation();
if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue())
{
processLister.setDebugPrivileges();
}
ProcessAccessHelp::getProcessModules(GetCurrentProcessId(), ProcessAccessHelp::ownModuleList);
*/
hIcon.LoadIcon(IDI_ICON_SCYLLA);
hMenuImports.LoadMenu(IDR_MENU_IMPORTS);
hMenuLog.LoadMenu(IDR_MENU_LOG);
accelerators.LoadAccelerators(IDR_ACCELERATOR_MAIN);
hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16);
hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16);
hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16);
}
BOOL MainGui::PreTranslateMessage(MSG* pMsg)
{
if(accelerators.TranslateAccelerator(m_hWnd, pMsg))
{
return TRUE; // handled keyboard shortcuts
}
else if(IsDialogMessage(pMsg))
{
return TRUE; // handled dialog messages
}
return FALSE;
}
void MainGui::InitDllStartWithPreSelect( PGUI_DLL_PARAMETER guiParam )
{
ComboProcessList.ResetContent();
std::vector<Process>& processList = Scylla::processLister.getProcessListSnapshotNative();
int newSel = -1;
for (size_t i = 0; i < processList.size(); i++)
{
if (processList[i].PID == guiParam->dwProcessId)
newSel = (int)i;
swprintf_s(stringBuffer, L"%04d - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
ComboProcessList.AddString(stringBuffer);
}
if (newSel != -1)
{
ComboProcessList.SetCurSel(newSel);
processSelectedActionHandler(newSel);
if (guiParam->mod) //init mod
{
//select DLL
size_t len = ProcessAccessHelp::moduleList.size();
newSel = -1;
for (size_t i = 0; i < len; i++)
{
if (ProcessAccessHelp::moduleList.at(i).modBaseAddr == (DWORD_PTR)guiParam->mod)
{
newSel = (int)i;
break;
}
}
if (newSel != -1)
{
//get selected module
ProcessAccessHelp::selectedModule = &ProcessAccessHelp::moduleList.at(newSel);
ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize;
DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath);
EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase);
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint);
}
}
}
}
BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
if (SystemInformation::currenOS == UNKNOWN_OS)
{
if(IDCANCEL == MessageBox(L"Operating System is not supported\r\nContinue anyway?", L"Scylla", MB_ICONWARNING | MB_OKCANCEL))
{
SendMessage(WM_CLOSE);
return FALSE;
}
}
// register ourselves to receive PreTranslateMessage
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->AddMessageFilter(this);
setupStatusBar();
DoDataExchange(); // attach controls
DlgResize_Init(true, true); // init CDialogResize
Scylla::windowLog.setWindow(ListLog);
appendPluginListToMenu(hMenuImports.GetSubMenu(0));
appendPluginListToMenu(CMenuHandle(GetMenu()).GetSubMenu(MenuImportsOffsetTrace));
enableDialogControls(FALSE);
setIconAndDialogCaption();
if (lInitParam)
{
InitDllStartWithPreSelect((PGUI_DLL_PARAMETER)lInitParam);
}
return TRUE;
}
void MainGui::OnDestroy()
{
PostQuitMessage(0);
}
void MainGui::OnSize(UINT nType, CSize size)
{
StatusBar.SendMessage(WM_SIZE);
SetMsgHandled(FALSE);
}
void MainGui::OnContextMenu(CWindow wnd, CPoint point)
{
switch(wnd.GetDlgCtrlID())
{
case IDC_TREE_IMPORTS:
DisplayContextMenuImports(wnd, point);
return;
case IDC_LIST_LOG:
DisplayContextMenuLog(wnd, point);
return;
}
SetMsgHandled(FALSE);
}
void MainGui::OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// Handle plugin trace menu selection
if(uNotifyCode == 0 && !wndCtl.IsWindow()) // make sure it's a menu
{
if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
pluginActionHandler(nID);
return;
}
}
SetMsgHandled(FALSE);
}
LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh)
{
if(TreeImports.GetCount() < 1)
return 0;
// Get item under cursor
CTreeItem over = findTreeItem(CPoint(GetMessagePos()), true);
if(over && importsHandling.isImport(over))
{
pickApiActionHandler(over);
}
return 0;
}
LRESULT MainGui::OnTreeImportsKeyDown(const NMHDR* pnmh)
{
const NMTVKEYDOWN * tkd = (NMTVKEYDOWN *)pnmh;
switch(tkd->wVKey)
{
case VK_RETURN:
{
CTreeItem selected = TreeImports.GetFocusItem();
if(!selected.IsNull() && importsHandling.isImport(selected))
{
pickApiActionHandler(selected);
}
}
return 1;
case VK_DELETE:
deleteSelectedImportsActionHandler();
return 1;
}
SetMsgHandled(FALSE);
return 0;
}
UINT MainGui::OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg)
{
if(lpMsg)
{
switch(lpMsg->wParam)
{
case VK_RETURN:
return DLGC_WANTMESSAGE;
}
}
SetMsgHandled(FALSE);
return 0;
}
void MainGui::OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_RETURN:
break;
default:
SetMsgHandled(FALSE);
break;
}
}
void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl)
{
fillProcessListComboBox(ComboProcessList);
}
void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
int index = ComboProcessList.GetCurSel();
if (index != CB_ERR)
{
processSelectedActionHandler(index);
}
}
void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl)
{
pickDllActionHandler();
}
void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl)
{
optionsActionHandler();
}
void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpActionHandler();
}
void MainGui::OnDumpMemory(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpMemoryActionHandler();
}
void MainGui::OnDumpSection(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpSectionActionHandler();
}
void MainGui::OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpFixActionHandler();
}
void MainGui::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl)
{
peRebuildActionHandler();
}
void MainGui::OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dllInjectActionHandler();
}
void MainGui::OnDisassembler(UINT uNotifyCode, int nID, CWindow wndCtl)
{
disassemblerActionHandler();
}
void MainGui::OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl)
{
iatAutosearchActionHandler();
}
void MainGui::OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
getImportsActionHandler();
}
void MainGui::OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showInvalidImportsActionHandler();
}
void MainGui::OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showSuspectImportsActionHandler();
}
void MainGui::OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
clearImportsActionHandler();
}
void MainGui::OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
invalidateSelectedImportsActionHandler();
}
void MainGui::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
deleteSelectedImportsActionHandler();
}
void MainGui::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
saveTreeActionHandler();
}
void MainGui::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
loadTreeActionHandler();
}
void MainGui::OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// TODO
}
void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl)
{
if (isProcessSuspended)
{
int msgboxID = MessageBox(L"Process is suspended. Do you want to terminate the process?\r\n\r\nYES = Terminate Process\r\nNO = Try to resume the process\r\nCancel = Do nothing", L"Information", MB_YESNOCANCEL|MB_ICONINFORMATION);
switch (msgboxID)
{
case IDYES:
ProcessAccessHelp::terminateProcess();
break;
case IDNO:
ProcessAccessHelp::resumeProcess();
break;
default:
break;
}
}
DestroyWindow();
}
void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showAboutDialog();
}
void MainGui::OnDonate(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showDonateDialog();
}
void MainGui::setupStatusBar()
{
StatusBar.Create(m_hWnd, NULL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_TOOLTIPS, NULL, IDC_STATUS_BAR);
CRect rcMain, rcStatus;
GetClientRect(&rcMain);
StatusBar.GetWindowRect(&rcStatus);
const int PARTS = 4;
int widths[PARTS];
widths[PART_COUNT] = rcMain.Width() / 5;
widths[PART_INVALID] = widths[PART_COUNT] + rcMain.Width() / 5;
widths[PART_IMAGEBASE] = widths[PART_INVALID] + rcMain.Width() / 3;
widths[PART_MODULE] = -1;
StatusBar.SetParts(PARTS, widths);
ResizeClient(rcMain.Width(), rcMain.Height() + rcStatus.Height(), FALSE);
}
void MainGui::updateStatusBar()
{
// Rewrite ImportsHandling so we get these easily
unsigned int totalImports = importsHandling.thunkCount();
unsigned int invalidImports = importsHandling.invalidThunkCount();
// \t = center, \t\t = right-align
swprintf_s(stringBuffer, L"\tImports: %u", totalImports);
StatusBar.SetText(PART_COUNT, stringBuffer);
if(invalidImports > 0)
{
StatusBar.SetIcon(PART_INVALID, hIconError);
}
else
{
StatusBar.SetIcon(PART_INVALID, hIconCheck);
}
swprintf_s(stringBuffer, L"\tInvalid: %u", invalidImports);
StatusBar.SetText(PART_INVALID, stringBuffer);
if(selectedProcess)
{
DWORD_PTR imageBase = 0;
const WCHAR * fileName = 0;
if(ProcessAccessHelp::selectedModule)
{
imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
fileName = ProcessAccessHelp::selectedModule->getFilename();
}
else
{
imageBase = selectedProcess->imageBase;
fileName = selectedProcess->filename;
}
swprintf_s(stringBuffer, L"\tImagebase: " PRINTF_DWORD_PTR_FULL, imageBase);
StatusBar.SetText(PART_IMAGEBASE, stringBuffer);
StatusBar.SetText(PART_MODULE, fileName);
StatusBar.SetTipText(PART_MODULE, fileName);
}
else
{
StatusBar.SetText(PART_IMAGEBASE, L"");
StatusBar.SetText(PART_MODULE, L"");
}
}
bool MainGui::showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter, const WCHAR * defExtension, const WCHAR * directory)
{
OPENFILENAME ofn = {0};
// WTL doesn't support new explorer styles on Vista and up
// This is because it uses a custom hook, we could remove it or derive
// from CFileDialog but this solution is easier and allows more control anyway (e.g. initial dir)
if(defFileName)
{
wcscpy_s(selectedFile, MAX_PATH, defFileName);
}
else
{
selectedFile[0] = L'\0';
}
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.lpstrFilter = filter;
ofn.lpstrDefExt = defExtension; // only first 3 chars are used, no dots!
ofn.lpstrFile = selectedFile;
ofn.lpstrInitialDir = directory;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
/*
*OFN_EXPLORER is automatically used, it only has to be specified
*if using a custom hook
*OFN_LONGNAMES is automatically used by explorer-style dialogs
*/
if(save)
ofn.Flags |= OFN_OVERWRITEPROMPT;
else
ofn.Flags |= OFN_FILEMUSTEXIST;
if(save)
return 0 != GetSaveFileName(&ofn);
else
return 0 != GetOpenFileName(&ofn);
}
void MainGui::setIconAndDialogCaption()
{
SetIcon(hIcon, TRUE);
SetIcon(hIcon, FALSE);
SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION);
}
void MainGui::pickDllActionHandler()
{
if(!selectedProcess)
return;
PickDllGui dlgPickDll(ProcessAccessHelp::moduleList);
if(dlgPickDll.DoModal())
{
//get selected module
ProcessAccessHelp::selectedModule = dlgPickDll.getSelectedModule();
ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize;
DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath);
EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase);
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint);
}
else
{
ProcessAccessHelp::selectedModule = 0;
}
updateStatusBar();
}
void MainGui::pickApiActionHandler(CTreeItem item)
{
if(!importsHandling.isImport(item))
return;
// TODO: new node when user picked an API from another DLL?
PickApiGui dlgPickApi(ProcessAccessHelp::moduleList);
if(dlgPickApi.DoModal())
{
const ApiInfo* api = dlgPickApi.getSelectedApi();
if(api && api->module)
{
importsHandling.setImport(item, api->module->getFilename(), api->name, api->ordinal, api->hint, true, api->isForwarded);
}
}
updateStatusBar();
}
void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode)
{
if(!selectedProcess)
return;
DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode);
if (address)
{
BYTE test;
if(!ProcessAccessHelp::readMemoryFromProcess(address, sizeof(test), &test))
{
swprintf_s(stringBuffer, L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address);
MessageBox(stringBuffer, L"Failure", MB_ICONERROR);
}
else
{
DisassemblerGui dlgDisassembler(address, &apiReader);
dlgDisassembler.DoModal();
}
}
}
void MainGui::processSelectedActionHandler(int index)
{
std::vector<Process>& processList = Scylla::processLister.getProcessList();
Process &process = processList.at(index);
selectedProcess = 0;
clearImportsActionHandler();
Scylla::windowLog.log(L"Analyzing %s", process.fullPath);
if (ProcessAccessHelp::hProcess != 0)
{
ProcessAccessHelp::closeProcessHandle();
apiReader.clearAll();
}
if (!ProcessAccessHelp::openProcessHandle(process.PID))
{
enableDialogControls(FALSE);
Scylla::windowLog.log(L"Error: Cannot open process handle.");
updateStatusBar();
return;
}
ProcessAccessHelp::getProcessModules(ProcessAccessHelp::hProcess, ProcessAccessHelp::moduleList);
apiReader.readApisFromModuleList();
Scylla::windowLog.log(L"Loading modules done.");
//TODO improve
ProcessAccessHelp::selectedModule = 0;
ProcessAccessHelp::targetImageBase = process.imageBase;
ProcessAccessHelp::targetSizeOfImage = process.imageSize;
process.imageSize = (DWORD)ProcessAccessHelp::targetSizeOfImage;
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", process.imageBase, process.imageSize);
process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath);
EditOEPAddress.SetValue(process.entryPoint + process.imageBase);
selectedProcess = &process;
enableDialogControls(TRUE);
updateStatusBar();
}
void MainGui::fillProcessListComboBox(CComboBox& hCombo)
{
hCombo.ResetContent();
std::vector<Process>& processList = Scylla::processLister.getProcessListSnapshotNative();
for (size_t i = 0; i < processList.size(); i++)
{
swprintf_s(stringBuffer, L"%04d - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
hCombo.AddString(stringBuffer);
}
}
/*
void MainGui::addTextToOutputLog(const WCHAR * text)
{
if (m_hWnd)
{
ListLog.SetCurSel(ListLog.AddString(text));
}
}
*/
void MainGui::clearOutputLog()
{
if (m_hWnd)
{
ListLog.ResetContent();
}
}
bool MainGui::saveLogToFile(const WCHAR * file)
{
const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian
const WCHAR newLine[] = L"\r\n";
bool success = true;
HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM);
WCHAR * buffer = 0;
size_t bufsize = 0;
for(int i = 0; i < ListLog.GetCount(); i++)
{
size_t size = ListLog.GetTextLen(i);
size += _countof(newLine)-1;
if(size+1 > bufsize)
{
bufsize = size+1;
delete[] buffer;
try
{
buffer = new WCHAR[bufsize];
}
catch(std::bad_alloc&)
{
buffer = 0;
success = false;
break;
}
}
ListLog.GetText(i, buffer);
wcscat_s(buffer, bufsize, newLine);
ProcessAccessHelp::writeMemoryToFileEnd(hFile, (DWORD)(size * sizeof(WCHAR)), buffer);
}
delete[] buffer;
CloseHandle(hFile);
}
return success;
}
void MainGui::showInvalidImportsActionHandler()
{
importsHandling.selectImports(true, false);
GotoDlgCtrl(TreeImports);
}
void MainGui::showSuspectImportsActionHandler()
{
importsHandling.selectImports(false, true);
GotoDlgCtrl(TreeImports);
}
void MainGui::deleteSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isModule(selected))
{
importsHandling.cutModule(selected);
}
else
{
importsHandling.cutImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::invalidateSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isImport(selected))
{
importsHandling.invalidateImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::loadTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterXml, NULL, stringBuffer))
{
TreeImportExport treeIO(selectedFilePath);
DWORD_PTR addrOEP = 0;
DWORD_PTR addrIAT = 0;
DWORD sizeIAT = 0;
if(!treeIO.importTreeList(importsHandling.moduleList, &addrOEP, &addrIAT, &sizeIAT))
{
Scylla::windowLog.log(L"Loading tree file failed %s", selectedFilePath);
MessageBox(L"Loading tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
EditOEPAddress.SetValue(addrOEP);
EditIATAddress.SetValue(addrIAT);
EditIATSize.SetValue(sizeIAT);
importsHandling.displayAllImports();
updateStatusBar();
Scylla::windowLog.log(L"Loaded tree file %s", selectedFilePath);
Scylla::windowLog.log(L"-> OEP: " PRINTF_DWORD_PTR_FULL, addrOEP);
Scylla::windowLog.log(L"-> IAT: " PRINTF_DWORD_PTR_FULL L" Size: " PRINTF_DWORD_PTR, addrIAT, sizeIAT);
}
}
}
void MainGui::saveTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterXml, L"xml", stringBuffer))
{
TreeImportExport treeIO(selectedFilePath);
DWORD_PTR addrOEP = EditOEPAddress.GetValue();
DWORD_PTR addrIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
if(!treeIO.exportTreeList(importsHandling.moduleList, selectedProcess, addrOEP, addrIAT, sizeIAT))
{
Scylla::windowLog.log(L"Saving tree file failed %s", selectedFilePath);
MessageBox(L"Saving tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
Scylla::windowLog.log(L"Saved tree file %s", selectedFilePath);
}
}
}
void MainGui::iatAutosearchActionHandler()
{
DWORD_PTR searchAddress = 0;
DWORD_PTR addressIAT = 0, addressIATAdv = 0;
DWORD sizeIAT = 0, sizeIATAdv = 0;
IATSearch iatSearch;
if(!selectedProcess)
return;
if(EditOEPAddress.GetWindowTextLength() > 0)
{
searchAddress = EditOEPAddress.GetValue();
if (searchAddress)
{
if (Scylla::config[USE_ADVANCED_IAT_SEARCH].isTrue())
{
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIATAdv, &sizeIATAdv, true))
{
Scylla::windowLog.log(L"IAT Search Adv: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIATAdv, addressIATAdv - ProcessAccessHelp::targetImageBase, sizeIATAdv, sizeIATAdv);
}
else
{
Scylla::windowLog.log(L"IAT Search Adv: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
}
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT, false))
{
Scylla::windowLog.log(L"IAT Search Nor: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT);
}
else
{
Scylla::windowLog.log(L"IAT Search Nor: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
if (addressIAT != 0 && addressIATAdv == 0)
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
else if (addressIAT == 0 && addressIATAdv != 0)
{
setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv);
}
else if (addressIAT != 0 && addressIATAdv != 0)
{
if (addressIATAdv != addressIAT || sizeIAT != sizeIATAdv)
{
int msgboxID = MessageBox(L"Result of advanced and normal search is different. Do you want to use the IAT Search Advanced result?", L"Information", MB_YESNO|MB_ICONINFORMATION);
if (msgboxID == IDYES)
{
setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv);
}
else
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
}
else
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
}
}
}
}
void MainGui::getImportsActionHandler()
{
if(!selectedProcess)
return;
DWORD_PTR addressIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
if (addressIAT && sizeIAT)
{
apiReader.readAndParseIAT(addressIAT, sizeIAT, importsHandling.moduleList);
importsHandling.displayAllImports();
updateStatusBar();
if (Scylla::config[SCAN_DIRECT_IMPORTS].isTrue())
{
iatReferenceScan.ScanForDirectImports = true;
iatReferenceScan.ScanForNormalImports = false;
iatReferenceScan.apiReader = &apiReader;
iatReferenceScan.startScan(ProcessAccessHelp::targetImageBase, (DWORD)ProcessAccessHelp::targetSizeOfImage, addressIAT, sizeIAT);
Scylla::windowLog.log(L"DIRECT IMPORTS - Found %d possible direct imports with %d unique APIs!", iatReferenceScan.numberOfFoundDirectImports(), iatReferenceScan.numberOfFoundUniqueDirectImports());
if (iatReferenceScan.numberOfFoundDirectImports() > 0)
{
if (iatReferenceScan.numberOfDirectImportApisNotInIat() > 0)
{
Scylla::windowLog.log(L"DIRECT IMPORTS - Found %d additional api addresses!", iatReferenceScan.numberOfDirectImportApisNotInIat());
DWORD sizeIatNew = iatReferenceScan.addAdditionalApisToList();
Scylla::windowLog.log(L"DIRECT IMPORTS - Old IAT size 0x%08X new IAT size 0x%08X!", sizeIAT, sizeIatNew);
EditIATSize.SetValue(sizeIatNew);
importsHandling.scanAndFixModuleList();
importsHandling.displayAllImports();
}
iatReferenceScan.printDirectImportLog();
if (Scylla::config[FIX_DIRECT_IMPORTS_NORMAL].isTrue() && (Scylla::config[FIX_DIRECT_IMPORTS_UNIVERSAL].isTrue() == false))
{
int msgboxID = MessageBox(L"Direct Imports found. I can patch only direct imports by JMP/CALL (use universal method if you don't like this) but where is the junk byte?\r\n\r\nYES = After Instruction\r\nNO = Before the Instruction\r\nCancel = Do nothing", L"Information", MB_YESNOCANCEL|MB_ICONINFORMATION);
if (msgboxID != IDCANCEL)
{
bool isAfter;
if (msgboxID == IDYES)
{
isAfter = true;
}
else
{
isAfter = false;
}
iatReferenceScan.patchDirectImportsMemory(isAfter);
Scylla::windowLog.log(L"DIRECT IMPORTS - Patched! Please dump target.");
}
}
}
}
if (isIATOutsidePeImage(addressIAT))
{
Scylla::windowLog.log(L"WARNING! IAT is not inside the PE image, requires rebasing!");
}
}
}
void MainGui::SetupImportsMenuItems(CTreeItem item)
{
bool isItem, isImport = false;
isItem = !item.IsNull();
if(isItem)
{
isImport = importsHandling.isImport(item);
}
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED;
UINT importOnly = isImport ? MF_ENABLED : MF_GRAYED;
hSub.EnableMenuItem(ID__INVALIDATE, itemOnly);
hSub.EnableMenuItem(ID__DISASSEMBLE, importOnly);
hSub.EnableMenuItem(ID__CUTTHUNK, importOnly);
hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly);
}
void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt)
{
if(TreeImports.GetCount() < 1)
return;
CTreeItem over, parent;
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
over = TreeImports.GetFocusItem();
if(over)
{
over.EnsureVisible();
over.GetRect(&pos, TRUE);
TreeImports.ClientToScreen(&pos);
}
else
{
TreeImports.GetWindowRect(&pos);
}
pt = pos.TopLeft();
}
else
{
// Get item under cursor
over = findTreeItem(pt, true);
}
SetupImportsMenuItems(over);
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
//wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName);
//MessageBox(stringBuffer, L"plugin selection");
pluginActionHandler(menuItem);
return;
}
switch (menuItem)
{
case ID__INVALIDATE:
if(importsHandling.isModule(over))
importsHandling.invalidateModule(over);
else
importsHandling.invalidateImport(over);
break;
case ID__DISASSEMBLE:
startDisassemblerGui(over);
break;
case ID__EXPANDALLNODES:
importsHandling.expandAllTreeNodes();
break;
case ID__COLLAPSEALLNODES:
importsHandling.collapseAllTreeNodes();
break;
case ID__CUTTHUNK:
importsHandling.cutImport(over);
break;
case ID__DELETETREENODE:
importsHandling.cutModule(importsHandling.isImport(over) ? over.GetParent() : over);
break;
}
}
updateStatusBar();
}
void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt)
{
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
ListLog.GetWindowRect(&pos);
pt = pos.TopLeft();
}
CMenuHandle hSub = hMenuLog.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
switch (menuItem)
{
case ID__SAVE:
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt", stringBuffer))
{
saveLogToFile(selectedFilePath);
}
break;
case ID__CLEAR:
clearOutputLog();
break;
}
}
}
void MainGui::appendPluginListToMenu(CMenuHandle hMenu)
{
std::vector<Plugin> &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector<Plugin> &imprecPluginList = Scylla::plugins.getImprecPluginList();
if (scyllaPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < scyllaPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins");
}
if (imprecPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < imprecPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins");
}
}
void MainGui::dumpMemoryActionHandler()
{
WCHAR selectedFilePath[MAX_PATH];
DumpMemoryGui dlgDumpMemory;
if(dlgDumpMemory.DoModal())
{
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, dlgDumpMemory.dumpFilename, filterMem, L"mem", stringBuffer))
{
if (ProcessAccessHelp::writeMemoryToNewFile(selectedFilePath,dlgDumpMemory.dumpedMemorySize,dlgDumpMemory.dumpedMemory))
{
Scylla::windowLog.log(L"Memory dump saved %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error! Cannot write memory dump to disk");
}
}
}
}
void MainGui::dumpSectionActionHandler()
{
WCHAR selectedFilePath[MAX_PATH] = {0};
WCHAR defaultFilename[MAX_PATH] = {0};
DumpSectionGui dlgDumpSection;
const WCHAR * fileFilter;
const WCHAR * defExtension;
PeParser * peFile = 0;
dlgDumpSection.entryPoint = EditOEPAddress.GetValue();
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
fileFilter = filterDll;
defExtension = L"dll";
dlgDumpSection.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
fileFilter = filterExe;
defExtension = L"exe";
dlgDumpSection.imageBase = ProcessAccessHelp::targetImageBase;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, selectedProcess->fullPath);
}
if(dlgDumpSection.DoModal())
{
getCurrentDefaultDumpFilename(defaultFilename, _countof(defaultFilename));
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, defaultFilename, fileFilter, defExtension, stringBuffer))
{
checkSuspendProcess();
if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue())
{
peFile = new PeParser(dlgDumpSection.fullpath, true);
}
else
{
peFile = new PeParser(dlgDumpSection.imageBase, true);
}
std::vector<PeSection> & sectionList = dlgDumpSection.getSectionList();
if (peFile->dumpProcess(dlgDumpSection.imageBase, dlgDumpSection.entryPoint, selectedFilePath, sectionList))
{
Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error: Cannot dump image.");
MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
}
delete peFile;
}
}
}
void MainGui::dumpActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH] = {0};
WCHAR defaultFilename[MAX_PATH] = {0};
const WCHAR * fileFilter;
const WCHAR * defExtension;
DWORD_PTR modBase = 0;
DWORD_PTR entrypoint = 0;
WCHAR * filename = 0;
PeParser * peFile = 0;
if (ProcessAccessHelp::selectedModule)
{
fileFilter = filterDll;
defExtension = L"dll";
}
else
{
fileFilter = filterExe;
defExtension = L"exe";
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
getCurrentDefaultDumpFilename(defaultFilename, _countof(defaultFilename));
if(showFileDialog(selectedFilePath, true, defaultFilename, fileFilter, defExtension, stringBuffer))
{
entrypoint = EditOEPAddress.GetValue();
checkSuspendProcess();
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
modBase = ProcessAccessHelp::selectedModule->modBaseAddr;
filename = ProcessAccessHelp::selectedModule->fullPath;
}
else
{
//dump exe
modBase = ProcessAccessHelp::targetImageBase;
filename = selectedProcess->fullPath;
}
if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue())
{
peFile = new PeParser(filename, true);
}
else
{
peFile = new PeParser(modBase, true);
}
- if (peFile->dumpProcess(modBase, entrypoint, selectedFilePath))
+ if (peFile->isValidPeFile())
{
- Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
+ if (peFile->dumpProcess(modBase, entrypoint, selectedFilePath))
+ {
+ Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
+ }
+ else
+ {
+ Scylla::windowLog.log(L"Error: Cannot dump image.");
+ MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
+ }
}
else
{
- Scylla::windowLog.log(L"Error: Cannot dump image.");
- MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
+ Scylla::windowLog.log(L"Error: Invalid PE file or invalid PE header. Try reading PE header from disk/process.");
}
delete peFile;
}
}
void MainGui::peRebuildActionHandler()
{
DWORD newSize = 0;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL, stringBuffer))
{
if (Scylla::config[CREATE_BACKUP].isTrue())
{
if (!ProcessAccessHelp::createBackupFile(selectedFilePath))
{
Scylla::windowLog.log(L"Creating backup file failed %s", selectedFilePath);
}
}
DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath);
PeParser peFile(selectedFilePath, true);
if (!peFile.isValidPeFile())
{
Scylla::windowLog.log(L"This is not a valid PE file %s", selectedFilePath);
MessageBox(L"Not a valid PE file.", L"Failure", MB_ICONERROR);
return;
}
if (peFile.readPeSectionsFromFile())
{
peFile.setDefaultFileAlignment();
if (Scylla::config[REMOVE_DOS_HEADER_STUB].isTrue())
{
peFile.removeDosStub();
}
peFile.alignAllSectionHeaders();
peFile.fixPeHeader();
if (peFile.savePeFileToDisk(selectedFilePath))
{
newSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath);
if (Scylla::config[UPDATE_HEADER_CHECKSUM].isTrue())
{
Scylla::windowLog.log(L"Generating PE header checksum");
if (!PeParser::updatePeHeaderChecksum(selectedFilePath, newSize))
{
Scylla::windowLog.log(L"Generating PE header checksum FAILED!");
}
}
Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath);
Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", fileSize, newSize, ((newSize * 100) / fileSize) );
}
else
{
Scylla::windowLog.log(L"Rebuild failed, cannot save file %s", selectedFilePath);
MessageBox(L"Rebuild failed. Cannot save file.", L"Failure", MB_ICONERROR);
}
}
else
{
Scylla::windowLog.log(L"Rebuild failed, cannot read file %s", selectedFilePath);
MessageBox(L"Rebuild failed. Cannot read file.", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::dumpFixActionHandler()
{
if(!selectedProcess)
return;
if (TreeImports.GetCount() < 2)
{
Scylla::windowLog.log(L"Nothing to rebuild");
return;
}
WCHAR newFilePath[MAX_PATH];
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
DWORD_PTR modBase = 0;
DWORD_PTR entrypoint = EditOEPAddress.GetValue();
if (ProcessAccessHelp::selectedModule)
{
modBase = ProcessAccessHelp::selectedModule->modBaseAddr;
fileFilter = filterDll;
}
else
{
modBase = ProcessAccessHelp::targetImageBase;
fileFilter = filterExe;
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL, stringBuffer))
{
wcscpy_s(newFilePath, selectedFilePath);
const WCHAR * extension = 0;
WCHAR* dot = wcsrchr(newFilePath, L'.');
if (dot)
{
*dot = L'\0';
extension = selectedFilePath + (dot - newFilePath); //wcsrchr(selectedFilePath, L'.');
}
wcscat_s(newFilePath, L"_SCY");
if(extension)
{
wcscat_s(newFilePath, extension);
}
ImportRebuilder importRebuild(selectedFilePath);
if (Scylla::config[IAT_FIX_AND_OEP_FIX].isTrue())
{
importRebuild.setEntryPointRva((DWORD)(entrypoint - modBase));
}
if (Scylla::config[OriginalFirstThunk_SUPPORT].isTrue())
{
importRebuild.enableOFTSupport();
}
if (Scylla::config[SCAN_DIRECT_IMPORTS].isTrue() && Scylla::config[FIX_DIRECT_IMPORTS_UNIVERSAL].isTrue())
{
if (iatReferenceScan.numberOfFoundDirectImports() > 0)
{
importRebuild.iatReferenceScan = &iatReferenceScan;
importRebuild.BuildDirectImportsJumpTable = true;
}
}
if (Scylla::config[CREATE_NEW_IAT_IN_SECTION].isTrue())
{
importRebuild.iatReferenceScan = &iatReferenceScan;
DWORD_PTR addressIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
importRebuild.enableNewIatInSection(addressIAT, sizeIAT);
}
if (importRebuild.rebuildImportTable(newFilePath, importsHandling.moduleList))
{
Scylla::windowLog.log(L"Import Rebuild success %s", newFilePath);
}
else
{
Scylla::windowLog.log(L"Import Rebuild failed %s", selectedFilePath);
MessageBox(L"Import Rebuild failed", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::enableDialogControls(BOOL value)
{
BOOL valButton = value ? TRUE : FALSE;
GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(valButton);
GetDlgItem(IDC_BTN_DUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(valButton);
GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(valButton);
CMenuHandle menu = GetMenu();
UINT valMenu = value ? MF_ENABLED : MF_GRAYED;
menu.EnableMenuItem(ID_FILE_DUMP, valMenu);
menu.EnableMenuItem(ID_FILE_DUMPMEMORY, valMenu);
menu.EnableMenuItem(ID_FILE_DUMPSECTION, valMenu);
menu.EnableMenuItem(ID_FILE_FIXDUMP, valMenu);
menu.EnableMenuItem(ID_IMPORTS_INVALIDATESELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_CUTSELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_SAVETREE, valMenu);
menu.EnableMenuItem(ID_IMPORTS_LOADTREE, valMenu);
menu.EnableMenuItem(ID_MISC_DLLINJECTION, valMenu);
menu.EnableMenuItem(ID_MISC_DISASSEMBLER, valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetScylla, MF_BYPOSITION | valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetImpRec, MF_BYPOSITION | valMenu);
//not yet implemented
GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE);
menu.EnableMenuItem(ID_TRACE_AUTOTRACE, MF_GRAYED);
}
CTreeItem MainGui::findTreeItem(CPoint pt, bool screenCoordinates)
{
if(screenCoordinates)
{
TreeImports.ScreenToClient(&pt);
}
UINT flags;
CTreeItem over = TreeImports.HitTest(pt, &flags);
if(over)
{
if(!(flags & TVHT_ONITEM))
{
over.m_hTreeItem = NULL;
}
}
return over;
}
void MainGui::showAboutDialog()
{
AboutGui dlgAbout;
dlgAbout.DoModal();
}
void MainGui::showDonateDialog()
{
DonateGui dlgDonate;
dlgDonate.DoModal();
}
void MainGui::dllInjectActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
HMODULE hMod = 0;
DllInjection dllInjection;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, filterDll, NULL, stringBuffer))
{
hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, selectedFilePath);
if (hMod && Scylla::config[DLL_INJECTION_AUTO_UNLOAD].isTrue())
{
if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod))
{
Scylla::windowLog.log(L"DLL unloading failed, target %s", selectedFilePath);
}
}
if (hMod)
{
Scylla::windowLog.log(L"DLL Injection was successful, target %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"DLL Injection failed, target %s", selectedFilePath);
}
}
}
void MainGui::disassemblerActionHandler()
{
DWORD_PTR oep = EditOEPAddress.GetValue();
DisassemblerGui disGuiDlg(oep, &apiReader);
disGuiDlg.DoModal();
}
void MainGui::optionsActionHandler()
{
OptionsGui dlgOptions;
dlgOptions.DoModal();
}
void MainGui::clearImportsActionHandler()
{
importsHandling.clearAllImports();
updateStatusBar();
}
void MainGui::pluginActionHandler( int menuItem )
{
if(!selectedProcess)
return;
DllInjectionPlugin dllInjectionPlugin;
std::vector<Plugin> &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector<Plugin> &imprecPluginList = Scylla::plugins.getImprecPluginList();
menuItem -= PLUGIN_MENU_BASE_ID;
dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
dllInjectionPlugin.apiReader = &apiReader;
if (menuItem < (int)scyllaPluginList.size())
{
//scylla plugin
dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
}
else
{
#ifndef _WIN64
menuItem -= (int)scyllaPluginList.size();
//imprec plugin
dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
#endif
}
importsHandling.scanAndFixModuleList();
importsHandling.displayAllImports();
updateStatusBar();
}
bool MainGui::getCurrentModulePath(WCHAR * buffer, size_t bufferSize)
{
if(!selectedProcess)
return false;
if(ProcessAccessHelp::selectedModule)
{
wcscpy_s(buffer, bufferSize, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
wcscpy_s(buffer, bufferSize, selectedProcess->fullPath);
}
WCHAR * slash = wcsrchr(buffer, L'\\');
if(slash)
{
*(slash+1) = L'\0';
}
return true;
}
void MainGui::checkSuspendProcess()
{
if (Scylla::config[SUSPEND_PROCESS_FOR_DUMPING].isTrue())
{
if (!ProcessAccessHelp::suspendProcess())
{
Scylla::windowLog.log(L"Error: Cannot suspend process.");
}
else
{
isProcessSuspended = true;
Scylla::windowLog.log(L"Suspending process successful, please resume manually.");
}
}
}
void MainGui::setDialogIATAddressAndSize( DWORD_PTR addressIAT, DWORD sizeIAT )
{
EditIATAddress.SetValue(addressIAT);
EditIATSize.SetValue(sizeIAT);
swprintf_s(stringBuffer, L"IAT found:\r\n\r\nStart: " PRINTF_DWORD_PTR_FULL L"\r\nSize: 0x%04X (%d) ", addressIAT, sizeIAT, sizeIAT);
MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION);
}
bool MainGui::isIATOutsidePeImage( DWORD_PTR addressIAT )
{
DWORD_PTR minAdd = 0, maxAdd = 0;
if(ProcessAccessHelp::selectedModule)
{
minAdd = ProcessAccessHelp::selectedModule->modBaseAddr;
maxAdd = minAdd + ProcessAccessHelp::selectedModule->modBaseSize;
}
else
{
minAdd = selectedProcess->imageBase;
maxAdd = minAdd + selectedProcess->imageSize;
}
if (addressIAT > minAdd && addressIAT < maxAdd)
{
return false; //inside pe image
}
else
{
return true; //outside pe image, requires rebasing iat
}
}
bool MainGui::getCurrentDefaultDumpFilename( WCHAR * buffer, size_t bufferSize )
{
if(!selectedProcess)
return false;
WCHAR * fullPath;
if(ProcessAccessHelp::selectedModule)
{
fullPath = ProcessAccessHelp::selectedModule->fullPath;
}
else
{
fullPath = selectedProcess->fullPath;
}
WCHAR * temp = wcsrchr(fullPath, L'\\');
if(temp)
{
temp++;
wcscpy_s(buffer, bufferSize, temp);
temp = wcsrchr(buffer, L'.');
if (temp)
{
*temp = 0;
if(ProcessAccessHelp::selectedModule)
{
wcscat_s(buffer, bufferSize, L"_dump.dll");
}
else
{
wcscat_s(buffer, bufferSize, L"_dump.exe");
}
}
return true;
}
return false;
}
diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp
index 8a7a613..76e490d 100644
--- a/Scylla/ProcessAccessHelp.cpp
+++ b/Scylla/ProcessAccessHelp.cpp
@@ -1,942 +1,958 @@
#include "ProcessAccessHelp.h"
#include "Scylla.h"
#include "NativeWinApi.h"
#include "PeParser.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
Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", hProcess);
#endif
return false;
}
else
{
//hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID);
//if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid)))
hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_SUSPEND_RESUME|PROCESS_TERMINATE, dwPID);
if (hProcess)
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID);
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Wrong PID, PID %X", dwPID);
#endif
return false;
}
}
HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId)
{
HANDLE hProcess = 0;
CLIENT_ID cid = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntStatus = 0;
InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
cid.UniqueProcess = (HANDLE)dwProcessId;
ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid);
if (NT_SUCCESS(ntStatus))
{
return hProcess;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus));
#endif
return 0;
}
}
void ProcessAccessHelp::closeProcessHandle()
{
if (hProcess)
{
CloseHandle(hProcess);
hProcess = 0;
}
moduleList.clear();
targetImageBase = 0;
selectedModule = 0;
}
bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
DWORD_PTR addressPart = 0;
DWORD_PTR readBytes = 0;
DWORD_PTR bytesToRead = 0;
MEMORY_BASIC_INFORMATION memBasic = {0};
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL");
#endif
return returnValue;
}
if (!readMemoryFromProcess(address, size, dataBuffer))
{
addressPart = address;
do
{
if (!VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)addressPart,&memBasic,sizeof(memBasic)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart,size, GetLastError());
#endif
break;
}
bytesToRead = memBasic.RegionSize;
if ( (readBytes+bytesToRead) > size)
{
bytesToRead = size - readBytes;
}
if (memBasic.State == MEM_COMMIT)
{
if (!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes)))
{
break;
}
}
else
{
ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes),bytesToRead);
}
readBytes += bytesToRead;
addressPart += memBasic.RegionSize;
} while (readBytes < size);
if (readBytes == size)
{
returnValue = true;
}
}
else
{
returnValue = true;
}
return returnValue;
}
bool ProcessAccessHelp::writeMemoryToProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
SIZE_T lpNumberOfBytesWritten = 0;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL");
#endif
return false;
}
return (WriteProcessMemory(hProcess,(LPVOID)address, dataBuffer, size,&lpNumberOfBytesWritten) != FALSE);
}
bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
SIZE_T lpNumberOfBytesRead = 0;
DWORD dwProtect = 0;
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL");
#endif
return returnValue;
}
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError());
#endif
if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u", address,size, GetLastError());
#endif
returnValue = false;
}
else
{
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError());
#endif
returnValue = false;
}
else
{
returnValue = true;
}
VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect);
}
}
else
{
returnValue = true;
}
if (returnValue)
{
if (size != lpNumberOfBytesRead)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes", lpNumberOfBytesRead, size);
#endif
returnValue = false;
}
else
{
returnValue = true;
}
}
return returnValue;
}
bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress)
{
ZeroMemory(&decomposerCi, sizeof(_CodeInfo));
decomposerCi.code = dataBuffer;
decomposerCi.codeLen = (int)bufferSize;
decomposerCi.dt = dt;
decomposerCi.codeOffset = startAddress;
decomposerInstructionsCount = 0;
if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"decomposeMemory :: distorm_decompose == DECRES_INPUTERR");
#endif
return false;
}
else
{
return true;
}
}
bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
{
// Holds the result of the decoding.
_DecodeResult res;
// next is used for instruction's offset synchronization.
// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
decodedInstructionsCount = 0;
_OffsetType offset = startOffset;
res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
/* for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
#ifdef SUPPORT_64BIT_OFFSET
printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#else
printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#endif
}*/
if (res == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR");
#endif
return false;
}
else if (res == DECRES_SUCCESS)
{
//printf("disassembleMemory :: res == DECRES_SUCCESS\n");
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == %d", res);
#endif
return true; //not all instructions fit in buffer
}
}
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);
}
return fileSize;
}
LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile)
{
LARGE_INTEGER lpFileSize = {0};
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
if (!GetFileSizeEx(hFile, &lpFileSize))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError());
#endif
return 0;
}
else
{
return lpFileSize.QuadPart;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid");
#endif
return 0;
}
}
bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesRead = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if (hFile != INVALID_HANDLE_VALUE)
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
bool resultValue = writeMemoryToFile(hFile,0,size,dataBuffer);
CloseHandle(hFile);
return resultValue;
}
else
{
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && dataBuffer)
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
SetFilePointer(hFile, 0, 0, FILE_END);
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath)
{
DWORD lpNumberOfBytesRead = 0;
LONGLONG fileSize = 0;
DWORD dwSize = 0;
bool returnValue = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readHeaderFromFile :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
returnValue = false;
}
else
{
fileSize = getFileSize(hFile);
if (fileSize > 0)
{
if (fileSize > bufferSize)
{
dwSize = bufferSize;
}
else
{
dwSize = (DWORD)(fileSize - 1);
}
returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer);
}
CloseHandle(hFile);
}
return returnValue;
}
LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ);
}
LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS);
}
LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap)
{
HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
return NULL;
}
HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
CloseHandle(hFile);
if( hMappedFile == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL");
#endif
return NULL;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS");
#endif
return NULL;
}
LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0);
if( addrMappedDll == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL");
#endif
CloseHandle(hMappedFile);
return NULL;
}
CloseHandle(hMappedFile);
return addrMappedDll;
}
DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName)
{
DWORD dwPID = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(PROCESSENTRY32W);
if( !Process32FirstW( hProcessSnap, &pe32 ) )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getProcessByName :: Error getting first Process");
#endif
CloseHandle( hProcessSnap );
return 0;
}
do
{
if(!_wcsicmp(pe32.szExeFile, processName))
{
dwPID = pe32.th32ProcessID;
break;
}
} while(Process32NextW(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return dwPID;
}
bool ProcessAccessHelp::getProcessModules(HANDLE hProcess, std::vector<ModuleInfo> &moduleList)
{
ModuleInfo module;
WCHAR filename[MAX_PATH*2] = {0};
DWORD cbNeeded = 0;
bool retVal = false;
DeviceNameResolver deviceNameResolver;
moduleList.reserve(20);
EnumProcessModules(hProcess, 0, 0, &cbNeeded);
HMODULE* hMods=(HMODULE*)malloc(cbNeeded*sizeof(HMODULE));
if (hMods)
{
if(EnumProcessModules(hProcess, hMods, cbNeeded, &cbNeeded))
{
for(unsigned int i = 1; i < (cbNeeded/sizeof(HMODULE)); i++) //skip first module!
{
module.modBaseAddr = (DWORD_PTR)hMods[i];
module.modBaseSize = (DWORD)getSizeOfImageProcess(hProcess, module.modBaseAddr);
module.isAlreadyParsed = false;
module.parsing = false;
filename[0] = 0;
module.fullPath[0] = 0;
if (GetMappedFileNameW(hProcess, (LPVOID)module.modBaseAddr, filename, _countof(filename)) > 0)
{
if (!deviceNameResolver.resolveDeviceLongNameToShort(filename, module.fullPath))
{
if (!GetModuleFileNameExW(hProcess, (HMODULE)module.modBaseAddr, module.fullPath, _countof(module.fullPath)))
{
wcscpy_s(module.fullPath, filename);
}
}
}
else
{
GetModuleFileNameExW(hProcess, (HMODULE)module.modBaseAddr, module.fullPath, _countof(module.fullPath));
}
moduleList.push_back(module);
}
retVal = true;
}
free(hMods);
}
return retVal;
}
bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize)
{
MEMORY_BASIC_INFORMATION memBasic;
if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", GetLastError());
#endif
return false;
}
else
{
*memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress;
*memoryRegionSize = memBasic.RegionSize;
return true;
}
}
bool ProcessAccessHelp::getSizeOfImageCurrentProcess()
{
DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
if (newSizeOfImage != 0)
{
ProcessAccessHelp::targetSizeOfImage = newSizeOfImage;
return true;
}
else
{
return false;
}
}
SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase)
{
SIZE_T sizeOfImage = 0, sizeOfImageNative = 0;
MEMORY_BASIC_INFORMATION lpBuffer = {0};
sizeOfImageNative = getSizeOfImageProcessNative(processHandle, moduleBase);
if (sizeOfImageNative)
{
return sizeOfImageNative;
}
WCHAR filenameOriginal[MAX_PATH*2] = {0};
WCHAR filenameTest[MAX_PATH*2] = {0};
GetMappedFileNameW(processHandle, (LPVOID)moduleBase, filenameOriginal, _countof(filenameOriginal));
do
{
moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize);
sizeOfImage += lpBuffer.RegionSize;
if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, sizeof(MEMORY_BASIC_INFORMATION)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", GetLastError());
#endif
lpBuffer.Type = 0;
sizeOfImage = 0;
}
GetMappedFileNameW(processHandle, (LPVOID)moduleBase, filenameTest, _countof(filenameTest));
if (_wcsicmp(filenameOriginal,filenameTest) != 0)//problem: 2 modules without free space
{
break;
}
} while (lpBuffer.Type == MEM_IMAGE);
//if (sizeOfImage != sizeOfImageNative)
//{
// WCHAR temp[1000] = {0};
// wsprintfW(temp, L"0x%X sizeofimage\n0x%X sizeOfImageNative", sizeOfImage, sizeOfImageNative);
// MessageBoxW(0, temp, L"Test", 0);
//}
return sizeOfImage;
}
DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath)
{
PeParser peFile(filePath, false);
return peFile.getEntryPoint();
}
bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath)
{
size_t fileNameLength = wcslen(filePath) + 5; //.bak + null
BOOL retValue = 0;
WCHAR * backupFile = new WCHAR[fileNameLength];
wcscpy_s(backupFile, fileNameLength, filePath);
wcscat_s(backupFile, fileNameLength, L".bak");
retValue = CopyFile(filePath, backupFile, FALSE);
if (!retValue)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError());
#endif
}
delete [] backupFile;
return retValue != 0;
}
DWORD ProcessAccessHelp::getModuleHandlesFromProcess(const HANDLE hProcess, HMODULE ** hMods)
{
DWORD count = 30;
DWORD cbNeeded = 0;
bool notEnough = true;
*hMods = new HMODULE[count];
do
{
if (!EnumProcessModules(hProcess, *hMods, count * sizeof(HMODULE), &cbNeeded))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getModuleHandlesFromProcess :: EnumProcessModules failed count %d", count);
#endif
delete [] *hMods;
return 0;
}
if ((count * sizeof(HMODULE)) < cbNeeded)
{
delete [] *hMods;
count = cbNeeded / sizeof(HMODULE);
*hMods = new HMODULE[count];
}
else
{
notEnough = false;
}
} while (notEnough);
return cbNeeded / sizeof(HMODULE);
}
void ProcessAccessHelp::setCurrentProcessAsTarget()
{
ProcessAccessHelp::hProcess = GetCurrentProcess();
}
bool ProcessAccessHelp::suspendProcess()
{
if (NativeWinApi::NtSuspendProcess)
{
if (NT_SUCCESS( NativeWinApi::NtSuspendProcess(ProcessAccessHelp::hProcess) ))
{
return true;
}
}
return false;
}
bool ProcessAccessHelp::resumeProcess()
{
if (NativeWinApi::NtResumeProcess)
{
if (NT_SUCCESS( NativeWinApi::NtResumeProcess(ProcessAccessHelp::hProcess) ))
{
return true;
}
}
return false;
}
bool ProcessAccessHelp::terminateProcess()
{
if (NativeWinApi::NtTerminateProcess)
{
if (NT_SUCCESS( NativeWinApi::NtTerminateProcess(ProcessAccessHelp::hProcess, 0) ))
{
return true;
}
}
return false;
}
+bool ProcessAccessHelp::isPageAccessable( DWORD Protect )
+{
+ if (Protect & PAGE_NOCACHE) Protect ^= PAGE_NOCACHE;
+ if (Protect & PAGE_GUARD) Protect ^= PAGE_GUARD;
+ if (Protect & PAGE_WRITECOMBINE) Protect ^= PAGE_WRITECOMBINE;
+
+ if (Protect != PAGE_NOACCESS)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
bool ProcessAccessHelp::isPageExecutable( DWORD Protect )
{
if (Protect & PAGE_NOCACHE) Protect ^= PAGE_NOCACHE;
if (Protect & PAGE_GUARD) Protect ^= PAGE_GUARD;
if (Protect & PAGE_WRITECOMBINE) Protect ^= PAGE_WRITECOMBINE;
switch(Protect)
{
case PAGE_EXECUTE:
{
return true;
}
case PAGE_EXECUTE_READ:
{
return true;
}
case PAGE_EXECUTE_READWRITE:
{
return true;
}
case PAGE_EXECUTE_WRITECOPY:
{
return true;
}
default:
return false;
}
}
SIZE_T ProcessAccessHelp::getSizeOfImageProcessNative( HANDLE processHandle, DWORD_PTR moduleBase )
{
MEMORY_REGION_INFORMATION memRegion = {0};
SIZE_T retLen = 0;
if (NativeWinApi::NtQueryVirtualMemory(processHandle, (PVOID)moduleBase, MemoryRegionInformation, &memRegion, sizeof(MEMORY_REGION_INFORMATION), &retLen) == STATUS_SUCCESS)
{
return memRegion.RegionSize;
}
return 0;
}
diff --git a/Scylla/ProcessAccessHelp.h b/Scylla/ProcessAccessHelp.h
index 6bdb63b..5524a52 100644
--- a/Scylla/ProcessAccessHelp.h
+++ b/Scylla/ProcessAccessHelp.h
@@ -1,229 +1,230 @@
#pragma once
#include <windows.h>
#include <tlhelp32.h>
#include <vector>
/************************************************************************/
/* distorm */
/************************************************************************/
#include <distorm.h>
#include <mnemonics.h>
// The number of the array of instructions the decoder function will use to return the disassembled instructions.
// Play with this value for performance...
#define MAX_INSTRUCTIONS (200)
/************************************************************************/
class ApiInfo;
class ModuleInfo
{
public:
WCHAR fullPath[MAX_PATH];
DWORD_PTR modBaseAddr;
DWORD modBaseSize;
bool isAlreadyParsed;
bool parsing;
/*
for iat rebuilding with duplicate entries:
ntdll = low priority
kernelbase = low priority
SHLWAPI = low priority
kernel32 = high priority
priority = 1 -> normal/high priority
priority = 0 -> low priority
*/
int priority;
std::vector<ApiInfo *> apiList;
ModuleInfo()
{
modBaseAddr = 0;
modBaseSize = 0;
priority = 1;
isAlreadyParsed = false;
parsing = false;
}
const WCHAR * getFilename() const
{
const WCHAR* slash = wcsrchr(fullPath, L'\\');
if(slash)
{
return slash+1;
}
return fullPath;
}
};
class ApiInfo
{
public:
char name[MAX_PATH];
WORD hint;
DWORD_PTR va;
DWORD_PTR rva;
WORD ordinal;
bool isForwarded;
ModuleInfo * module;
};
class ProcessAccessHelp
{
public:
static HANDLE hProcess; //OpenProcess handle to target process
static DWORD_PTR targetImageBase;
static DWORD_PTR targetSizeOfImage;
static DWORD_PTR maxValidAddress;
static ModuleInfo * selectedModule;
static std::vector<ModuleInfo> moduleList; //target process module list
static std::vector<ModuleInfo> ownModuleList; //own module list
static const size_t PE_HEADER_BYTES_COUNT = 2000;
static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
//for decomposer
static _DInst decomposerResult[MAX_INSTRUCTIONS];
static unsigned int decomposerInstructionsCount;
static _CodeInfo decomposerCi;
//distorm :: Decoded instruction information.
static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
static unsigned int decodedInstructionsCount;
#ifdef _WIN64
static const _DecodeType dt = Decode64Bits;
#else
static const _DecodeType dt = Decode32Bits;
#endif
/*
* Open a new process handle
*/
static bool openProcessHandle(DWORD dwPID);
static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId);
static void closeProcessHandle();
/*
* Get all modules from a process
*/
static bool getProcessModules(HANDLE hProcess, std::vector<ModuleInfo> &moduleList);
/*
* file mapping view with different access level
*/
static LPVOID createFileMappingViewRead(const WCHAR * filePath);
static LPVOID createFileMappingViewFull(const WCHAR * filePath);
/*
* Create a file mapping view of a file
*/
static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap);
/*
* Read memory from target process
*/
static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer);
static bool writeMemoryToProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer);
/*
* Read memory from target process and ignore no data pages
*/
static bool readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer);
/*
* Read memory from file
*/
static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer);
/*
* Write memory to file
*/
static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer);
/*
* Write memory to new file
*/
static bool writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer);
/*
* Write memory to file end
*/
static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer);
/*
* Disassemble Memory
*/
static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset);
static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress);
/*
* Search for pattern
*/
static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask);
/*
* Get process ID by process name
*/
static DWORD getProcessByName(const WCHAR * processName);
/*
* Get memory region from address
*/
static bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize);
/*
* Read PE Header from file
*/
static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath);
static bool readHeaderFromCurrentFile(const WCHAR * filePath);
/*
* Get real sizeOfImage value
*/
static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase);
/*
* Get real sizeOfImage value current process
*/
static bool getSizeOfImageCurrentProcess();
static LONGLONG getFileSize(HANDLE hFile);
static LONGLONG getFileSize(const WCHAR * filePath);
static DWORD getEntryPointFromFile(const WCHAR * filePath);
static bool createBackupFile(const WCHAR * filePath);
static DWORD getModuleHandlesFromProcess(const HANDLE hProcess, HMODULE ** hMods );
static void setCurrentProcessAsTarget();
static bool suspendProcess();
static bool resumeProcess();
static bool terminateProcess();
static bool isPageExecutable( DWORD Protect );
+ static bool isPageAccessable( DWORD Protect );
static SIZE_T getSizeOfImageProcessNative( HANDLE processHandle, DWORD_PTR moduleBase );
};
diff --git a/Scylla/Scylla.h b/Scylla/Scylla.h
index d12c9b1..3b66b2b 100644
--- a/Scylla/Scylla.h
+++ b/Scylla/Scylla.h
@@ -1,35 +1,35 @@
#pragma once
#include "ConfigurationHolder.h"
#include "PluginLoader.h"
#include "ProcessLister.h"
#include "Logger.h"
#define APPNAME_S "Scylla"
-#define APPVERSION_S "v0.9.6"
+#define APPVERSION_S "v0.9.6a"
#define APPVERSIONDWORD 0x00009600
#define DONATE_BTC_ADDRESS "1GmVrhWwUhwLohaCLP4SKV5kkz8rd16N8h"
#define APPNAME TEXT(APPNAME_S)
#define APPVERSION TEXT(APPVERSION_S)
class Scylla
{
public:
static void initAsGuiApp();
static void initAsDll();
static ConfigurationHolder config;
static PluginLoader plugins;
static ProcessLister processLister;
static FileLog debugLog;
static ListboxLog windowLog;
private:
static const WCHAR DEBUG_LOG_FILENAME[];
};

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jul 5, 11:24 AM (20 h, 22 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e1/98/79cb986560378dcb96d217990103

Event Timeline