diff --git a/Scylla/AboutGui.cpp b/Scylla/AboutGui.cpp index 05ed1b4..3f806e3 100644 --- a/Scylla/AboutGui.cpp +++ b/Scylla/AboutGui.cpp @@ -1,123 +1,124 @@ #include "AboutGui.h" -#include "definitions.h" +#include "Scylla.h" +#include "Architecture.h" const WCHAR AboutGui::TEXT_VISIT[] = L"Visit http://kickme.to/grn and http://forum.tuts4you.com"; const WCHAR AboutGui::TEXT_DEVELOPED[] = L"Developed with Microsoft Visual Studio, written in pure C/C++"; const WCHAR AboutGui::TEXT_CREDIT_DISTORM[] = L"This tool uses the diStorm disassembler library v3"; const WCHAR AboutGui::TEXT_CREDIT_YODA[] = L"The PE Rebuilder engine is based on Realign DLL v1.5 by yoda"; const WCHAR AboutGui::TEXT_CREDIT_SILK[] = L"The small icons are taken from the Silk icon package"; const WCHAR AboutGui::TEXT_CREDIT_WTL[] = L"Windows Template Library v8 is used for the GUI"; const WCHAR AboutGui::TEXT_GREETINGS[] = L"Greetz: metr0, G36KV and all from the gRn Team"; const WCHAR AboutGui::TEXT_LICENSE[] = L"Scylla is licensed under the GNU General Public License v3"; const WCHAR AboutGui::TEXT_TINYXML[] = L"XML support is provided by TinyXML"; const WCHAR AboutGui::URL_VISIT1[] = L"http://kickme.to/grn"; const WCHAR AboutGui::URL_VISIT2[] = L"http://forum.tuts4you.com"; const WCHAR AboutGui::URL_DISTORM[] = L"http://code.google.com/p/distorm/"; const WCHAR AboutGui::URL_WTL[] = L"http://wtl.sourceforge.net"; const WCHAR AboutGui::URL_SILK[] = L"http://www.famfamfam.com"; const WCHAR AboutGui::URL_LICENSE[] = L"http://www.gnu.org/licenses/gpl-3.0.html"; const WCHAR AboutGui::URL_TINYXML[] = L"http://sourceforge.net/projects/tinyxml/"; BOOL AboutGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls // Create a bold font for the title LOGFONT lf; CFontHandle font = StaticTitle.GetFont(); font.GetLogFont(&lf); lf.lfWeight = FW_BOLD; FontBold.CreateFontIndirect(&lf); StaticTitle.SetFont(FontBold, FALSE); - StaticTitle.SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); + StaticTitle.SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION); StaticDeveloped.SetWindowText(TEXT_DEVELOPED); StaticGreetings.SetWindowText(TEXT_GREETINGS); StaticYoda.SetWindowText(TEXT_CREDIT_YODA); setupLinks(); CenterWindow(); // Set focus to the OK button GotoDlgCtrl(GetDlgItem(IDOK)); return FALSE; } void AboutGui::OnClose() { TooltipDistorm.DestroyWindow(); TooltipWTL.DestroyWindow(); TooltipSilk.DestroyWindow(); TooltipLicense.DestroyWindow(); FontBold.DeleteObject(); EndDialog(0); } LRESULT AboutGui::OnLink(NMHDR* pnmh) { const NMLINK* link = (NMLINK*)pnmh; ShellExecute(NULL, L"open", link->item.szUrl, NULL, NULL, SW_SHOW); return 0; } void AboutGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { SendMessage(WM_CLOSE); } void AboutGui::setupLinks() { // Set link text (must be set before assigning URLs) LinkVisit.SetWindowText(TEXT_VISIT); LinkDistorm.SetWindowText(TEXT_CREDIT_DISTORM); LinkWTL.SetWindowText(TEXT_CREDIT_WTL); LinkSilk.SetWindowText(TEXT_CREDIT_SILK); LinkTinyxml.SetWindowText(TEXT_TINYXML); LinkLicense.SetWindowText(TEXT_LICENSE); // Assign URLs to anchors in the link text - setLinkURL(LinkVisit, URL_VISIT1, 0); - setLinkURL(LinkVisit, URL_VISIT2, 1); + setLinkURL(LinkVisit, URL_VISIT1, 0); + setLinkURL(LinkVisit, URL_VISIT2, 1); setLinkURL(LinkDistorm, URL_DISTORM); - setLinkURL(LinkWTL, URL_WTL); - setLinkURL(LinkSilk, URL_SILK); + setLinkURL(LinkWTL, URL_WTL); + setLinkURL(LinkSilk, URL_SILK); setLinkURL(LinkTinyxml, URL_TINYXML); setLinkURL(LinkLicense, URL_LICENSE); // Create tooltips for the links TooltipDistorm.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); - TooltipWTL.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); - TooltipSilk.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); + TooltipWTL.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); + TooltipSilk.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); TooltipTinyxml.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); TooltipLicense.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); // Assign control and text to the tooltips setupTooltip(TooltipDistorm, LinkDistorm, URL_DISTORM); - setupTooltip(TooltipWTL, LinkWTL, URL_WTL); - setupTooltip(TooltipSilk, LinkSilk, URL_SILK); + setupTooltip(TooltipWTL, LinkWTL, URL_WTL); + setupTooltip(TooltipSilk, LinkSilk, URL_SILK); setupTooltip(TooltipTinyxml, LinkTinyxml, URL_TINYXML); setupTooltip(TooltipLicense, LinkLicense, URL_LICENSE); } void AboutGui::setLinkURL(CLinkCtrl& link, const WCHAR* url, int index) { LITEM item; item.mask = LIF_ITEMINDEX | LIF_URL; item.iLink = index; wcscpy_s(item.szUrl, _countof(item.szUrl), url); link.SetItem(&item); } void AboutGui::setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text) { CToolInfo ti(TTF_SUBCLASS, window); window.GetClientRect(&ti.rect); ti.lpszText = const_cast(text); tooltip.AddTool(ti); } diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp index 54683b7..3975f31 100644 --- a/Scylla/ApiReader.cpp +++ b/Scylla/ApiReader.cpp @@ -1,1326 +1,1325 @@ #include "ApiReader.h" -#include "Logger.h" -#include "definitions.h" +#include "Scylla.h" +#include "Architecture.h" #include "SystemInformation.h" stdext::hash_multimap ApiReader::apiList; //api look up table std::map * ApiReader::moduleThunkList; //store found apis DWORD_PTR ApiReader::minApiAddress = 0xFFFFFFFF; DWORD_PTR ApiReader::maxApiAddress = 0; //#define DEBUG_COMMENTS void ApiReader::readApisFromModuleList() { for (unsigned int i = 0; i < moduleList.size();i++) { setModulePriority(&moduleList[i]); if (moduleList[i].modBaseAddr + moduleList[i].modBaseSize > maxValidAddress) { maxValidAddress = moduleList[i].modBaseAddr + moduleList[i].modBaseSize; } - Logger::printfDialog(TEXT("Module parsing: %s"),moduleList[i].fullPath); + Scylla::windowLog.log(L"Module parsing: %s",moduleList[i].fullPath); if (!moduleList[i].isAlreadyParsed) { parseModule(&moduleList[i]); } } #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("Address Min ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Max ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\nimagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" maxValidAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),minApiAddress,maxApiAddress,targetImageBase,maxValidAddress); + 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)) { parseModuleWithOwnProcess(module); } else { parseModuleWithProcess(module); } - module->isAlreadyParsed = true; } void ApiReader::parseModuleWithMapping(ModuleInfo *moduleInfo) { LPVOID fileMapping = 0; PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; fileMapping = createFileMappingViewRead(moduleInfo->fullPath); if (fileMapping == 0) return; pDosHeader = (PIMAGE_DOS_HEADER)fileMapping; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping); } UnmapViewOfFile(fileMapping); } inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader) { if ((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size))) { return true; } else { return false; } } void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer,char * functionNameParent, DWORD_PTR rvaParent, 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,sizeof(dllName),fordwardedString,dllNameLength); } searchFunctionName++; //Windows 7 if (!strncmp(dllName,"api-ms-win-", 11)) { /* Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html */ FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName); if (addy != 0) { addApi(functionNameParent,0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent); } return; } strcat_s(dllName,sizeof(dllName),".dll"); size_t convertedChars = 0; mbstowcs_s(&convertedChars, dllNameW, strlen(dllName) + 1, dllName, _TRUNCATE); if (!_wcsicmp(dllNameW, moduleParent->getFilename())) { module = moduleParent; } else { module = findModuleByName(dllNameW); } if (module != 0) // module == 0 -> can be ignored { /*if ((module->isAlreadyParsed == false) && (module != moduleParent)) { //do API extract if (module->parsing == true) { //some stupid circle dependency printf("stupid circle dependency %s\n",module->getFilename()); } else { parseModule(module); } }*/ if (strchr(searchFunctionName,'#')) { //forwarding by ordinal searchFunctionName++; ordinal = (WORD)atoi(searchFunctionName); findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi); } else { findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi); } if (rvaApi == 0) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"handleForwardedApi :: Api not found, this is really BAD! %S\r\n",fordwardedString); + 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, _countof(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 - Logger::debugLog(L"getHeaderFromProcess :: Error reading header\r\n"); + 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 - Logger::debugLog(L"Something is wrong with the PE Header here Export table size %d\r\n",readSize); + 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(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"getExportTableFromProcess :: Error reading export table from process\r\n"); + 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; bufferHeader = getHeaderFromProcess(module); if (bufferHeader == 0) return; pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { bufferExportTable = getExportTableFromProcess(module, pNtHeader); if(bufferExportTable) { parseExportTable(module,pNtHeader,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); delete[] bufferExportTable; } } delete[] bufferHeader; } void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress) { DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0; WORD *addressOfNameOrdinalsArray = 0; char *functionName = 0; DWORD_PTR RVA = 0, VA = 0; 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 - Logger::debugLog(L"parseExportTable :: module %s NumberOfNames %X\r\n",module->fullPath,pExportDir->NumberOfNames); + 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 - Logger::debugLog(TEXT("parseExportTable :: api %S ")TEXT(" ordinal %d imagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),functionName,ordinal,module->modBaseAddr,RVA,VA); + 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 (ordinal) { *vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal); } else { *vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName); } if (vaApi) { *rvaApi = (*vaApi) - (DWORD_PTR)hModule; *vaApi = (*rvaApi) + module->modBaseAddr; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("findApiByModule :: vaApi == NULL, should never happen %S\r\n"),searchFunctionName); + Scylla::debugLog.log(L"findApiByModule :: vaApi == NULL, should never happen %S", searchFunctionName); #endif } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("findApiByModule :: hModule == NULL, should never happen %s\r\n"),module->getFilename()); + 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 - Logger::debugLog(TEXT("parseModuleWithOwnProcess :: hModule is NULL\r\n")); + Scylla::debugLog.log(L"parseModuleWithOwnProcess :: hModule is NULL"); #endif } } bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader) { if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { - Logger::printfDialog(TEXT("-> IMAGE_NT_SIGNATURE doesn't match.")); + 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)) { - Logger::printfDialog(TEXT("-> No export table.")); + 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, TEXT("kernelbase.dll"))) + if (!_wcsicmp(moduleFileName, L"kernelbase.dll")) { module->priority = -1; } - else if (!_wcsicmp(moduleFileName, TEXT("ntdll.dll"))) + else if (!_wcsicmp(moduleFileName, L"ntdll.dll")) { module->priority = 0; } - else if (!_wcsicmp(moduleFileName, TEXT("shlwapi.dll"))) + else if (!_wcsicmp(moduleFileName, L"shlwapi.dll")) { module->priority = 0; } - else if (!_wcsicmp(moduleFileName, TEXT("ShimEng.dll"))) + else if (!_wcsicmp(moduleFileName, L"ShimEng.dll")) { module->priority = 0; } - else if (!_wcsicmp(moduleFileName, TEXT("kernel32.dll"))) + else if (!_wcsicmp(moduleFileName, L"kernel32.dll")) { module->priority = 2; } else { module->priority = 1; } } bool ApiReader::isApiAddressValid(DWORD_PTR virtualAddress) { return apiList.count(virtualAddress) > 0; } ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect) { stdext::hash_multimap::iterator it1, it2; size_t c = 0; size_t countDuplicates = apiList.count(virtualAddress); int countHighPriority = 0; ApiInfo *apiFound = 0; if (countDuplicates == 0) { - Logger::printfDialog(TEXT("getApiByVirtualAddress :: No Api found ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress); + Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, virtualAddress); return 0; } else if (countDuplicates == 1) { //API is 100% correct *isSuspect = false; it1 = apiList.find(virtualAddress); // Find first match. return (ApiInfo *)((*it1).second); } else { it1 = apiList.find(virtualAddress); // Find first match. //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 - Logger::printfDialog(TEXT("getApiByVirtualAddress :: There is a api resolving bug, VA: ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress); + 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); - Logger::printfDialog(TEXT("-> Possible API: %S ord: %d "),apiFound->name,apiFound->ordinal); + Scylla::windowLog.log(L"-> Possible API: %S ord: %d ", apiFound->name, apiFound->ordinal); } return (ApiInfo *) 1; } /*ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect) { stdext::hash_multimap::iterator it1, it2; size_t c = 0; size_t countDuplicates = apiList.count(virtualAddress); int countHighPriority = 0; ApiInfo *apiFound = 0; if (countDuplicates == 0) { - Logger::printfDialog(TEXT("getApiByVirtualAddress :: No Api found ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress); + Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, virtualAddress); return 0; } else if (countDuplicates == 1) { //API is 100% correct *isSuspect = false; it1 = apiList.find(virtualAddress); // Find first match. return (ApiInfo *)((*it1).second); } else { it1 = apiList.find(virtualAddress); // Find first match. it2 = it1; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority >= 1) //1 == high priority { countHighPriority++; } } it1 = it2; This is flawed: It chooses api(prio:1, name:no) over api(prio:0, name:yes) (e.g. SHLWAPI.PathCombineW vs SHELL32.#25) Maybe there should be a check higher up in the code, to see if this API is surrounded by APIs of a DLL and pick the duplicate from that DLL if (countHighPriority == 0) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == 0 ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),virtualAddress); + Scylla::debugLog.log(L"getApiByVirtualAddress :: countHighPriority == 0 " PRINTF_DWORD_PTR_FULL, virtualAddress); #endif *isSuspect = true; return (ApiInfo *)((*it1).second); } else if (countHighPriority == 1) // what about kernel32, it has priority 2 { //API is 100% correct if countHighPriority == 1 and name export *isSuspect = false; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority { return apiFound; } } } //else // fall through for case api1(priority:1, name:false) <> api2(priority:0, name:true) { //API not 100% correct #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == %d ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),countHighPriority,virtualAddress); + Scylla::debugLog.log(L"getApiByVirtualAddress :: countHighPriority == %d " PRINTF_DWORD_PTR_FULL, countHighPriority, virtualAddress); #endif *isSuspect = true; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); - Logger::printfDialog("%s - %s %X %X\n",apiFound->name,apiFound->module->getFilename(),apiFound->rva, apiFound->ordinal); + Scylla::windowLog.log(L"%s - %s %X %X\n",apiFound->name, apiFound->module->getFilename(), apiFound->rva, apiFound->ordinal); } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); //prefer APIs with a name if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority { //prefer ANSI/UNICODE APIs - if (strrchr(apiFound->name,TEXT('W')) || strrchr(apiFound->name,TEXT('A'))) + if (strrchr(apiFound->name, 'W') || strrchr(apiFound->name, 'A')) { return apiFound; } } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); //prefer APIs with a name - if (apiFound->module->priority == 2 && !strrchr(apiFound->name,TEXT('_'))) //1 == high priority + if (apiFound->module->priority == 2 && !strrchr(apiFound->name, '_')) //1 == high priority { return apiFound; } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority == 1 && apiFound->name[0] != 0x00) //1 == high priority { return apiFound; } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority == 1) //1 == high priority { return apiFound; } } } } //is never reached - Logger::printfDialog(TEXT("getApiByVirtualAddress :: There is a big bug")); + Scylla::windowLog.log(L"getApiByVirtualAddress :: There is a big bug"); return (ApiInfo *) 1; }*/ ApiInfo * ApiReader::getScoredApi(stdext::hash_multimap::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 &moduleListNew) { moduleThunkList = &moduleListNew; BYTE *dataIat = new BYTE[sizeIAT]; if (readMemoryFromProcess(addressIAT,sizeIAT,dataIat)) { parseIAT(addressIAT,dataIat,sizeIAT); } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ApiReader::readAndParseIAT :: error reading iat ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),addressIAT); + 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); bool foundModuleBreak = false; for (SIZE_T i = 0; i < sizeIAT; i++) { - //Logger::printfDialog("%08X %08X %d von %d",addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer,pIATAddress[i],i,sizeIAT); + //Scylla::windowLog.log(L"%08X %08X %d von %d", addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i],i,sizeIAT); if (pIATAddress[i] == 0 || pIATAddress[i] == -1) { /*if (pIATAddress[i+1] != 0) { printf("parseIAT :: Module break\n"); }*/ /*else { printf("parseIAT :: IAT finished\n"); break; }*/ foundModuleBreak = true; } else if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) ) { apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect); if (apiFound == (ApiInfo *)1) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("apiFound == (ApiInfo *)1 -> ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),pIATAddress[i]); + Scylla::debugLog.log(L"apiFound == (ApiInfo *)1 -> " PRINTF_DWORD_PTR_FULL, pIATAddress[i]); #endif } else if (apiFound) { countApiFound++; #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %s %d %s\r\n"),apiFound->va, apiFound->module->getFilename(), apiFound->ordinal,apiFound->name); + 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]); } } - Logger::printfDialog(TEXT("IAT parsing finished, found %d valid APIs, missed %d APIs"),countApiFound,countApiNotFound); + 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, _countof(module.moduleName), moduleName); (*moduleThunkList).insert(std::pair(firstThunk,module)); return true; } void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; - wcscpy_s(module.moduleName, _countof(module.moduleName), TEXT("?")); + wcscpy_s(module.moduleName, _countof(module.moduleName), L"?"); (*moduleThunkList).insert(std::pair(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::iterator iterator1; if ((*moduleThunkList).size() > 1) { iterator1 = (*moduleThunkList).begin(); while (iterator1 != (*moduleThunkList).end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == (*moduleThunkList).end()) { iterator1--; module = &(iterator1->second); break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n")); + Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()"); #endif break; } } } else { iterator1 = (*moduleThunkList).begin(); module = &(iterator1->second); } if (!module) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); + 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, _countof(import.moduleName), apiFound->module->getFilename()); strcpy_s(import.name, _countof(import.name), apiFound->name); module->thunkList.insert(std::pair(import.rva, import)); return true; } void ApiReader::clearAll() { minApiAddress = -1; maxApiAddress = 0; for ( stdext::hash_multimap::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::iterator iterator1; DWORD_PTR rva = iatAddressVA - targetImageBase; if ((*moduleThunkList).size() > 0) { iterator1 = (*moduleThunkList).begin(); while (iterator1 != (*moduleThunkList).end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == (*moduleThunkList).end()) { iterator1--; //new unknown module if (iterator1->second.moduleName[0] == L'?') { module = &(iterator1->second); } else { addUnknownModuleToModuleList(rva); module = &((*moduleThunkList).find(rva)->second); } break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n")); + 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 - Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); + 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, _countof(import.moduleName), TEXT("?")); + wcscpy_s(import.moduleName, _countof(import.moduleName), L"?"); strcpy_s(import.name, _countof(import.name), "?"); module->thunkList.insert(std::pair(import.rva, import)); return true; } bool ApiReader::isApiBlacklisted( const char * functionName ) { if (SystemInformation::currenOS < WIN_VISTA_32) { if (!strcmp(functionName, "RestoreLastError")) { return true; } else { return false; } } else { return false; } /*#ifdef _WIN64 else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer")) { return true; } #endif*/ } bool ApiReader::isWinSxSModule( ModuleInfo * module ) { - if (wcsstr(module->fullPath, TEXT("\\WinSxS\\"))) + if (wcsstr(module->fullPath, L"\\WinSxS\\")) { return true; } - else if (wcsstr(module->fullPath, TEXT("\\winsxs\\"))) + else if (wcsstr(module->fullPath, L"\\winsxs\\")) { return true; } else { return false; } } diff --git a/Scylla/ConfigurationHolder.cpp b/Scylla/ConfigurationHolder.cpp index b051379..7e6e0c6 100644 --- a/Scylla/ConfigurationHolder.cpp +++ b/Scylla/ConfigurationHolder.cpp @@ -1,259 +1,208 @@ - #include "ConfigurationHolder.h" -#include "resource.h" -#include "definitions.h" -WCHAR ConfigurationHolder::configPath[MAX_PATH]; -ConfigurationInitializer ConfigurationHolder::config; +#include +#include +#include "Architecture.h" + +const WCHAR ConfigurationHolder::CONFIG_FILE_NAME[] = L"Scylla.ini"; +const WCHAR ConfigurationHolder::CONFIG_FILE_SECTION_NAME[] = L"SCYLLA_CONFIG"; //#define DEBUG_COMMENTS ConfigurationInitializer::ConfigurationInitializer() { ConfigObject configObject; - mapConfig[USE_PE_HEADER_FROM_DISK] = configObject.newValues(L"USE_PE_HEADER_FROM_DISK", Boolean, IDC_CHECK_PE_HEADER_FROM_DISK); - mapConfig[DEBUG_PRIVILEGE] = configObject.newValues(L"DEBUG_PRIVILEGE", Boolean, IDC_CHECK_DEBUG_PRIVILEGES); - mapConfig[CREATE_BACKUP] = configObject.newValues(L"CREATE_BACKUP", Boolean, IDC_CHECK_CREATE_BACKUP); - mapConfig[DLL_INJECTION_AUTO_UNLOAD] = configObject.newValues(L"DLL_INJECTION_AUTO_UNLOAD", Boolean, IDC_CHECK_UNLOAD_DLL); - mapConfig[UPDATE_HEADER_CHECKSUM] = configObject.newValues(L"UPDATE_HEADER_CHECKSUM", Boolean, IDC_CHECK_HEADER_CHECKSUM); - - mapConfig[IAT_SECTION_NAME] = configObject.newValues(L"IAT_SECTION_NAME", String, IDC_OPTIONS_SECTIONNAME); + mapConfig[USE_PE_HEADER_FROM_DISK] = configObject.newValues(L"USE_PE_HEADER_FROM_DISK", Boolean); + mapConfig[DEBUG_PRIVILEGE] = configObject.newValues(L"DEBUG_PRIVILEGE", Boolean); + mapConfig[CREATE_BACKUP] = configObject.newValues(L"CREATE_BACKUP", Boolean); + mapConfig[DLL_INJECTION_AUTO_UNLOAD] = configObject.newValues(L"DLL_INJECTION_AUTO_UNLOAD", Boolean); + mapConfig[UPDATE_HEADER_CHECKSUM] = configObject.newValues(L"UPDATE_HEADER_CHECKSUM", Boolean); + mapConfig[IAT_SECTION_NAME] = configObject.newValues(L"IAT_SECTION_NAME", String); } - bool ConfigurationHolder::loadConfiguration() { std::map::iterator mapIter; if (!buildConfigFilePath()) { return false; } for (mapIter = config.mapConfig.begin() ; mapIter != config.mapConfig.end(); mapIter++) { if (!loadConfig((*mapIter).second)) { return false; } } return true; } bool ConfigurationHolder::saveConfiguration() { std::map::iterator mapIter; if (!buildConfigFilePath()) { return false; } for (mapIter = config.mapConfig.begin() ; mapIter != config.mapConfig.end(); mapIter++) { if (!saveConfig((*mapIter).second)) { return false; } } return true; } bool ConfigurationHolder::saveNumericToConfigFile(ConfigObject & configObject, int nBase) { if (nBase == 16) { - swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT(PRINTF_DWORD_PTR_FULL),configObject.valueNumeric); + swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, PRINTF_DWORD_PTR_FULL, configObject.valueNumeric); } else { - swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT(PRINTF_INTEGER),configObject.valueNumeric); + swprintf_s(configObject.valueString, CONFIG_OPTIONS_STRING_LENGTH, PRINTF_INTEGER, configObject.valueNumeric); } - if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, configObject.valueString, configPath)) - { - return true; - } - else - { - return false; - } + BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.name, configObject.valueString, configPath); + return ret == TRUE; } bool ConfigurationHolder::readNumericFromConfigFile(ConfigObject & configObject, int nBase) { - GetPrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME),configObject.name,TEXT(""),configObject.valueString, 100, configPath); + DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.name, L"", configObject.valueString, _countof(configObject.valueString), configPath); - if (wcslen(configObject.valueString) > 0) + if (read > 0 && wcslen(configObject.valueString) > 0) { #ifdef _WIN64 configObject.valueNumeric = _wcstoui64(configObject.valueString, NULL, nBase); #else configObject.valueNumeric = wcstoul(configObject.valueString, NULL, nBase); #endif - if (configObject.valueNumeric) - { - return true; - } - else - { - return false; - } + return (configObject.valueNumeric != 0); } else { return false; } } - bool ConfigurationHolder::saveStringToConfigFile(ConfigObject & configObject) { - if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, configObject.valueString, configPath)) - { - return true; - } - else - { - return false; - } + BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.name, configObject.valueString, configPath); + return ret == TRUE; } bool ConfigurationHolder::readStringFromConfigFile(ConfigObject & configObject) { - GetPrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME),configObject.name,TEXT(""),configObject.valueString, 100, configPath); - - if (wcslen(configObject.valueString) > 0) - { - return true; - } - else - { - return false; - } + DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.name, L"", configObject.valueString, _countof(configObject.valueString), configPath); + return (read > 0 && wcslen(configObject.valueString) > 0); } bool ConfigurationHolder::readBooleanFromConfigFile(ConfigObject & configObject) { - if (GetPrivateProfileInt(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, 0, configPath) != 0) - { - configObject.valueNumeric = 1; - } - else - { - configObject.valueNumeric = 0; - } - + UINT val = GetPrivateProfileInt(CONFIG_FILE_SECTION_NAME, configObject.name, 0, configPath); + configObject.valueNumeric = val ? 1 : 0; return true; } bool ConfigurationHolder::saveBooleanToConfigFile(ConfigObject & configObject) { WCHAR *boolValue = 0; if (configObject.valueNumeric == 0) { boolValue = L"0"; } else { boolValue = L"1"; } - if (WritePrivateProfileString(TEXT(CONFIG_FILE_SECTION_NAME), configObject.name, boolValue, configPath)) - { - return true; - } - else - { - return false; - } + BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.name, boolValue, configPath); + return ret == TRUE; } bool ConfigurationHolder::loadConfig(ConfigObject & configObject) { switch (configObject.configType) { case String: return readStringFromConfigFile(configObject); break; case Boolean: return readBooleanFromConfigFile(configObject); break; case Decimal: return readNumericFromConfigFile(configObject, 10); break; case Hexadecimal: return readNumericFromConfigFile(configObject, 16); break; default: return false; } } bool ConfigurationHolder::saveConfig(ConfigObject & configObject) { switch (configObject.configType) { case String: return saveStringToConfigFile(configObject); break; case Boolean: return saveBooleanToConfigFile(configObject); break; case Decimal: return saveNumericToConfigFile(configObject, 10); break; case Hexadecimal: return saveNumericToConfigFile(configObject, 16); break; default: return false; } } ConfigObject * ConfigurationHolder::getConfigObject(Configuration configuration) { return &(config.mapConfig[configuration]); } bool ConfigurationHolder::buildConfigFilePath() { ZeroMemory(configPath, sizeof(configPath)); if (!GetModuleFileName(0, configPath, _countof(configPath))) { #ifdef DEBUG_COMMENTS - Logger::debugLog("buildConfigFilePath :: GetModuleFileName failed %d\r\n",GetLastError()); + Scylla::debugLog.log(L"buildConfigFilePath :: GetModuleFileName failed %d", GetLastError()); #endif return false; } - //remove exe file name - for (size_t i = wcslen(configPath) - 1; i >= 0; i--) - { - if (configPath[i] == L'\\') - { - configPath[i + 1] = 0; - break; - } - } - - wcscat_s(configPath, _countof(configPath), TEXT(CONFIG_FILE_NAME) ); + PathRemoveFileSpec(configPath); + PathAppend(configPath, CONFIG_FILE_NAME); //wprintf(L"configPath %s\n\n", configPath); return true; } std::map & ConfigurationHolder::getConfigList() { return config.mapConfig; -} \ No newline at end of file +} diff --git a/Scylla/ConfigurationHolder.h b/Scylla/ConfigurationHolder.h index c617832..498b015 100644 --- a/Scylla/ConfigurationHolder.h +++ b/Scylla/ConfigurationHolder.h @@ -1,100 +1,94 @@ - #pragma once #include -#include #include -#define CONFIG_FILE_NAME "Scylla.ini" -#define CONFIG_FILE_SECTION_NAME "SCYLLA_CONFIG" - enum ConfigType { String, Decimal, Hexadecimal, Boolean }; enum Configuration { USE_PE_HEADER_FROM_DISK, DEBUG_PRIVILEGE, CREATE_BACKUP, DLL_INJECTION_AUTO_UNLOAD, IAT_SECTION_NAME, UPDATE_HEADER_CHECKSUM, }; -#define CONFIG_OPTIONS_STRING_LENGTH 100 +const size_t CONFIG_OPTIONS_STRING_LENGTH = 100; class ConfigObject { public: WCHAR name[MAX_PATH]; ConfigType configType; DWORD_PTR valueNumeric; WCHAR valueString[CONFIG_OPTIONS_STRING_LENGTH]; - int dialogItemValue; - - ConfigObject& newValues(WCHAR * configname, ConfigType config, int dlgValue) + ConfigObject& newValues(WCHAR * configname, ConfigType config) { wcscpy_s(name, MAX_PATH, configname); configType = config; valueNumeric = 0; ZeroMemory(valueString, sizeof(valueString)); - dialogItemValue = dlgValue; return *this; } bool isTrue() { return (valueNumeric == 1); } void setTrue() { valueNumeric = 1; } void setFalse() { valueNumeric = 0; } }; class ConfigurationInitializer { public: std::map mapConfig; ConfigurationInitializer(); }; class ConfigurationHolder { public: - static bool loadConfiguration(); - static bool saveConfiguration(); + bool loadConfiguration(); + bool saveConfiguration(); - static ConfigObject * getConfigObject(Configuration configuration); - static std::map & getConfigList(); + ConfigObject * getConfigObject(Configuration configuration); + std::map & getConfigList(); private: - static ConfigurationInitializer config; - static WCHAR configPath[MAX_PATH]; - static bool buildConfigFilePath(); + static const WCHAR CONFIG_FILE_NAME[]; + static const WCHAR CONFIG_FILE_SECTION_NAME[]; - + ConfigurationInitializer config; + WCHAR configPath[MAX_PATH]; - static bool readStringFromConfigFile(ConfigObject & configObject); - static bool readBooleanFromConfigFile(ConfigObject & configObject); - static bool readNumericFromConfigFile(ConfigObject & configObject, int nBase); + bool buildConfigFilePath(); - static bool saveStringToConfigFile(ConfigObject & configObject); - static bool saveBooleanToConfigFile(ConfigObject & configObject); - static bool saveNumericToConfigFile(ConfigObject & configObject, int nBase); + bool readStringFromConfigFile(ConfigObject & configObject); + bool readBooleanFromConfigFile(ConfigObject & configObject); + bool readNumericFromConfigFile(ConfigObject & configObject, int nBase); - static bool loadConfig(ConfigObject & configObject); - static bool saveConfig(ConfigObject & configObject); -}; \ No newline at end of file + bool saveStringToConfigFile(ConfigObject & configObject); + bool saveBooleanToConfigFile(ConfigObject & configObject); + bool saveNumericToConfigFile(ConfigObject & configObject, int nBase); + + bool loadConfig(ConfigObject & configObject); + bool saveConfig(ConfigObject & configObject); +}; diff --git a/Scylla/DllInjection.cpp b/Scylla/DllInjection.cpp index bdd8d38..d309309 100644 --- a/Scylla/DllInjection.cpp +++ b/Scylla/DllInjection.cpp @@ -1,246 +1,246 @@ #include "DllInjection.h" #include "Logger.h" #include #include "NativeWinApi.h" //#define DEBUG_COMMENTS HMODULE DllInjection::dllInjection(HANDLE hProcess, const WCHAR * filename) { LPVOID remoteMemory = 0; SIZE_T memorySize = 0; HANDLE hThread = 0; HMODULE hModule = 0; memorySize = (wcslen(filename) + 1) * sizeof(WCHAR); if (memorySize < 7) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dllInjection :: memorySize invalid\r\n"); + Scylla::debugLog.log(L"dllInjection :: memorySize invalid"); #endif return 0; } remoteMemory = VirtualAllocEx(hProcess, NULL, memorySize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (remoteMemory == 0) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dllInjection :: VirtualAllocEx failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"dllInjection :: VirtualAllocEx failed 0x%X", GetLastError()); #endif return 0; } if (WriteProcessMemory(hProcess, remoteMemory, filename, memorySize, &memorySize)) { hThread = startRemoteThread(hProcess,LoadLibraryW,remoteMemory); if (hThread) { WaitForSingleObject(hThread, INFINITE); #ifdef _WIN64 hModule = getModuleHandleByFilename(hProcess, filename); #else //returns only 32 bit values -> design bug by microsoft if (!GetExitCodeThread(hThread, (LPDWORD) &hModule)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dllInjection :: GetExitCodeThread failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"dllInjection :: GetExitCodeThread failed 0x%X", GetLastError()); #endif hModule = 0; } #endif CloseHandle(hThread); } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dllInjection :: CreateRemoteThread failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"dllInjection :: CreateRemoteThread failed 0x%X", GetLastError()); #endif } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dllInjection :: WriteProcessMemory failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"dllInjection :: WriteProcessMemory failed 0x%X", GetLastError()); #endif } VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); return hModule; } bool DllInjection::unloadDllInProcess(HANDLE hProcess, HMODULE hModule) { HANDLE hThread = 0; DWORD lpThreadId = 0; BOOL freeLibraryRet = 0; hThread = startRemoteThread(hProcess,FreeLibrary,hModule); if (hThread) { WaitForSingleObject(hThread, INFINITE); if (!GetExitCodeThread(hThread, (LPDWORD) &freeLibraryRet)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"unloadDllInProcess :: GetExitCodeThread failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"unloadDllInProcess :: GetExitCodeThread failed 0x%X", GetLastError()); #endif freeLibraryRet = 0; } CloseHandle(hThread); } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"unloadDllInProcess :: CreateRemoteThread failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"unloadDllInProcess :: CreateRemoteThread failed 0x%X", GetLastError()); #endif } return freeLibraryRet != 0; } HMODULE DllInjection::getModuleHandleByFilename( HANDLE hProcess, const WCHAR * filename ) { HMODULE * hMods = 0; HMODULE hModResult = 0; DWORD count = 0; WCHAR target[MAX_PATH]; DWORD cbNeeded = 0; bool notEnough = true; count = 100; hMods = new HMODULE[count]; do { if (!EnumProcessModules(hProcess, hMods, count * sizeof(HMODULE), &cbNeeded)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"DllInjection::getModuleHandle :: EnumProcessModules failed count %d\r\n",count); + Scylla::debugLog.log(L"DllInjection::getModuleHandle :: EnumProcessModules failed count %d", count); #endif delete [] hMods; return 0; } if ( (count * sizeof(HMODULE)) < cbNeeded ) { delete [] hMods; count += 100; hMods = new HMODULE[count]; } else { notEnough = false; } } while (notEnough); for (DWORD i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) { if (GetModuleFileNameExW(hProcess, hMods[i], target, _countof(target))) { if (!_wcsicmp(target,filename)) { hModResult = hMods[i]; break; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"DllInjection::getModuleHandle :: GetModuleFileNameExW failed 0x%X\r\n", GetLastError()); + Scylla::debugLog.log(L"DllInjection::getModuleHandle :: GetModuleFileNameExW failed 0x%X", GetLastError()); #endif } } if (!hModResult) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"DllInjection::getModuleHandle :: Handle not found\r\n"); + Scylla::debugLog.log(L"DllInjection::getModuleHandle :: Handle not found"); #endif } delete [] hMods; return hModResult; } void DllInjection::specialThreadSettings( HANDLE hThread ) { if (hThread) { if (!SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"specialThreadSettings :: SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL) failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"specialThreadSettings :: SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL) failed 0x%X", GetLastError()); #endif } if (NativeWinApi::NtSetInformationThread) { if (NativeWinApi::NtSetInformationThread(hThread, ThreadHideFromDebugger, 0, 0) != STATUS_SUCCESS) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"specialThreadSettings :: NtSetInformationThread ThreadHideFromDebugger failed\r\n"); + Scylla::debugLog.log(L"specialThreadSettings :: NtSetInformationThread ThreadHideFromDebugger failed"); #endif } } } } HANDLE DllInjection::startRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter) { HANDLE hThread = 0; hThread = customCreateRemoteThread(hProcess, lpStartAddress, lpParameter); if (hThread) { specialThreadSettings(hThread); ResumeThread(hThread); } return hThread; } HANDLE DllInjection::customCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter) { DWORD lpThreadId = 0; HANDLE hThread = 0; NTSTATUS ntStatus = 0; if (NativeWinApi::NtCreateThreadEx) { #define THREAD_ALL_ACCESS_VISTA_7 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF) //for windows vista/7 ntStatus = NativeWinApi::NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS_VISTA_7, 0, hProcess, (LPTHREAD_START_ROUTINE)lpStartAddress, (LPVOID)lpParameter, TRUE, 0, 0, 0, 0); if (NT_SUCCESS(ntStatus)) { return hThread; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"customCreateRemoteThread :: NtCreateThreadEx failed 0x%X\r\n",NativeWinApi::RtlNtStatusToDosError(ntStatus)); + Scylla::debugLog.log(L"customCreateRemoteThread :: NtCreateThreadEx failed 0x%X", NativeWinApi::RtlNtStatusToDosError(ntStatus)); #endif return 0; } } else { return CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)lpStartAddress,lpParameter,CREATE_SUSPENDED,&lpThreadId); } } diff --git a/Scylla/DllInjectionPlugin.cpp b/Scylla/DllInjectionPlugin.cpp index a2c898b..75c5d14 100644 --- a/Scylla/DllInjectionPlugin.cpp +++ b/Scylla/DllInjectionPlugin.cpp @@ -1,303 +1,303 @@ #include "DllInjectionPlugin.h" -#include "Logger.h" +#include "Scylla.h" const WCHAR * DllInjectionPlugin::FILE_MAPPING_NAME = L"ScyllaPluginExchange"; HANDLE DllInjectionPlugin::hProcess = 0; //#define DEBUG_COMMENTS void DllInjectionPlugin::injectPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize) { PSCYLLA_EXCHANGE scyllaExchange = 0; PUNRESOLVED_IMPORT unresImp = 0; BYTE * dataBuffer = 0; DWORD_PTR numberOfUnresolvedImports = getNumberOfUnresolvedImports(moduleList); if (numberOfUnresolvedImports == 0) { - Logger::printfDialog(L"No unresolved Imports"); + Scylla::windowLog.log(L"No unresolved Imports"); return; } if (!createFileMapping((DWORD)(sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports)))) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"injectPlugin :: createFileMapping %X failed\r\n",sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports)); + Scylla::debugLog.log(L"injectPlugin :: createFileMapping %X failed",sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports)); #endif return; } scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile; scyllaExchange->status = 0xFF; scyllaExchange->imageBase = imageBase; scyllaExchange->imageSize = imageSize; scyllaExchange->numberOfUnresolvedImports = numberOfUnresolvedImports; scyllaExchange->offsetUnresolvedImportsArray = sizeof(SCYLLA_EXCHANGE); unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)lpViewOfFile + sizeof(SCYLLA_EXCHANGE)); addUnresolvedImports(unresImp, moduleList); UnmapViewOfFile(lpViewOfFile); lpViewOfFile = 0; HMODULE hDll = dllInjection(hProcess, plugin.fullpath); if (hDll) { - Logger::printfDialog(L"Plugin injection was successful"); + Scylla::windowLog.log(L"Plugin injection was successful"); if (!unloadDllInProcess(hProcess,hDll)) { - Logger::printfDialog(L"Plugin unloading failed"); + Scylla::windowLog.log(L"Plugin unloading failed"); } lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (lpViewOfFile) { scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile; handlePluginResults(scyllaExchange, moduleList); } } else { - Logger::printfDialog(L"Plugin injection failed"); + Scylla::windowLog.log(L"Plugin injection failed"); } closeAllHandles(); } void DllInjectionPlugin::injectImprecPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize) { Plugin newPlugin; size_t mapSize = (wcslen(plugin.fullpath) + 1) * sizeof(WCHAR); HANDLE hImprecMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, (DWORD)mapSize, TEXT(PLUGIN_IMPREC_EXCHANGE_DLL_PATH)); if (hImprecMap == NULL) { #ifdef DEBUG_COMMENTS - Logger::debugLog("injectImprecPlugin :: CreateFileMapping failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"injectImprecPlugin :: CreateFileMapping failed 0x%X", GetLastError()); #endif return; } LPVOID lpImprecViewOfFile = MapViewOfFile(hImprecMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (lpImprecViewOfFile == NULL) { #ifdef DEBUG_COMMENTS - Logger::debugLog("injectImprecPlugin :: MapViewOfFile failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"injectImprecPlugin :: MapViewOfFile failed 0x%X", GetLastError()); #endif CloseHandle(hImprecMap); return; } CopyMemory(lpImprecViewOfFile,plugin.fullpath, mapSize); UnmapViewOfFile(lpImprecViewOfFile); newPlugin.fileSize = plugin.fileSize; wcscpy_s(newPlugin.pluginName, _countof(newPlugin.pluginName), plugin.pluginName); - wcscpy_s(newPlugin.fullpath, _countof(newPlugin.fullpath), PluginLoader::imprecWrapperDllPath); + wcscpy_s(newPlugin.fullpath, _countof(newPlugin.fullpath), Scylla::plugins.imprecWrapperDllPath); injectPlugin(newPlugin,moduleList,imageBase,imageSize); CloseHandle(hImprecMap); } bool DllInjectionPlugin::createFileMapping(DWORD mappingSize) { hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, mappingSize, FILE_MAPPING_NAME); if (hMapFile == NULL) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMapping :: CreateFileMapping failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"createFileMapping :: CreateFileMapping failed 0x%X", GetLastError()); #endif return false; } lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (lpViewOfFile == NULL) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMapping :: MapViewOfFile failed 0x%X\r\n",GetLastError()); + Scylla::debugLog.log(L"createFileMapping :: MapViewOfFile failed 0x%X", GetLastError()); #endif CloseHandle(hMapFile); hMapFile = 0; return false; } else { return true; } } void DllInjectionPlugin::closeAllHandles() { if (lpViewOfFile) { UnmapViewOfFile(lpViewOfFile); lpViewOfFile = 0; } if (hMapFile) { CloseHandle(hMapFile); hMapFile = 0; } } DWORD_PTR DllInjectionPlugin::getNumberOfUnresolvedImports( std::map & moduleList ) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk = 0; ImportThunk * importThunk = 0; DWORD_PTR dwNumber = 0; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->valid == false) { dwNumber++; } iterator2++; } iterator1++; } return dwNumber; } void DllInjectionPlugin::addUnresolvedImports( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList ) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk = 0; ImportThunk * importThunk = 0; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->valid == false) { firstUnresImp->InvalidApiAddress = importThunk->apiAddressVA; firstUnresImp->ImportTableAddressPointer = importThunk->va; firstUnresImp++; } iterator2++; } iterator1++; } firstUnresImp->InvalidApiAddress = 0; firstUnresImp->ImportTableAddressPointer = 0; } void DllInjectionPlugin::handlePluginResults( PSCYLLA_EXCHANGE scyllaExchange, std::map & moduleList ) { PUNRESOLVED_IMPORT unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray);; switch (scyllaExchange->status) { case SCYLLA_STATUS_SUCCESS: - Logger::printfDialog(L"Plugin was successful"); + Scylla::windowLog.log(L"Plugin was successful"); updateImportsWithPluginResult(unresImp, moduleList); break; case SCYLLA_STATUS_UNKNOWN_ERROR: - Logger::printfDialog(L"Plugin reported Unknown Error"); + Scylla::windowLog.log(L"Plugin reported Unknown Error"); break; case SCYLLA_STATUS_UNSUPPORTED_PROTECTION: - Logger::printfDialog(L"Plugin detected unknown protection"); + Scylla::windowLog.log(L"Plugin detected unknown protection"); updateImportsWithPluginResult(unresImp, moduleList); break; case SCYLLA_STATUS_IMPORT_RESOLVING_FAILED: - Logger::printfDialog(L"Plugin import resolving failed"); + Scylla::windowLog.log(L"Plugin import resolving failed"); updateImportsWithPluginResult(unresImp, moduleList); break; case SCYLLA_STATUS_MAPPING_FAILED: - Logger::printfDialog(L"Plugin file mapping failed"); + Scylla::windowLog.log(L"Plugin file mapping failed"); break; default: - Logger::printfDialog(L"Plugin failed without reason"); + Scylla::windowLog.log(L"Plugin failed without reason"); } } void DllInjectionPlugin::updateImportsWithPluginResult( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList ) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk = 0; ImportThunk * importThunk = 0; ApiInfo * apiInfo = 0; bool isSuspect = 0; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->valid == false) { if (apiReader->isApiAddressValid(firstUnresImp->InvalidApiAddress)) { apiInfo = apiReader->getApiByVirtualAddress(firstUnresImp->InvalidApiAddress,&isSuspect); importThunk->suspect = isSuspect; importThunk->valid = true; importThunk->apiAddressVA = firstUnresImp->InvalidApiAddress; importThunk->hint = (WORD)apiInfo->hint; importThunk->ordinal = apiInfo->ordinal; strcpy_s(importThunk->name, _countof(importThunk->name),apiInfo->name); wcscpy_s(importThunk->moduleName, _countof(importThunk->moduleName), apiInfo->module->getFilename()); - if (moduleThunk->moduleName[0] == TEXT('?')) + if (moduleThunk->moduleName[0] == L'?') { wcscpy_s(moduleThunk->moduleName, _countof(importThunk->moduleName), apiInfo->module->getFilename()); } } firstUnresImp++; } iterator2++; } iterator1++; } } diff --git a/Scylla/IATSearch.cpp b/Scylla/IATSearch.cpp index 513c9dc..13e6fca 100644 --- a/Scylla/IATSearch.cpp +++ b/Scylla/IATSearch.cpp @@ -1,374 +1,373 @@ #include "IATSearch.h" -#include "Logger.h" -#include "definitions.h" +#include "Scylla.h" +#include "Architecture.h" //#define DEBUG_COMMENTS - bool IATSearch::searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT) { DWORD_PTR addressInIAT = 0; addressInIAT = findAPIAddressInIAT(startAddress); if(!addressInIAT) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("searchImportAddressTableInProcess :: addressInIAT not found, startAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),startAddress); + Scylla::debugLog.log(L"searchImportAddressTableInProcess :: addressInIAT not found, startAddress " PRINTF_DWORD_PTR_FULL, startAddress); #endif return false; } else { return findIATStartAndSize(addressInIAT, addressIAT,sizeIAT); } } DWORD_PTR IATSearch::findAPIAddressInIAT(DWORD_PTR startAddress) { static const int MEMORY_READ_SIZE = 200; BYTE *dataBuffer = new BYTE[MEMORY_READ_SIZE]; DWORD_PTR iatPointer = 0; int counter = 0; // to detect stolen api memoryAddress = 0; memorySize = 0; do { counter++; if (!readMemoryFromProcess(startAddress,MEMORY_READ_SIZE,dataBuffer)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("findAPIAddressInIAT :: error reading memory ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), startAddress); + Scylla::debugLog.log(L"findAPIAddressInIAT :: error reading memory " PRINTF_DWORD_PTR_FULL, startAddress); #endif return 0; } - if (decomposeMemory(dataBuffer,MEMORY_READ_SIZE,startAddress)) + if (decomposeMemory(dataBuffer, MEMORY_READ_SIZE, startAddress)) { iatPointer = findIATPointer(); if (iatPointer) { if (isIATPointerValid(iatPointer)) { delete[] dataBuffer; return iatPointer; } } } startAddress = findNextFunctionAddress(); //printf("startAddress %08X\n",startAddress); } while (startAddress != 0 && counter != 8); delete[] dataBuffer; return 0; } DWORD_PTR IATSearch::findNextFunctionAddress() { #ifdef DEBUG_COMMENTS _DecodedInst inst; #endif for (unsigned int i = 0; i < decomposerInstructionsCount; i++) { if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) { if (decomposerResult[i].size >= 5) { if (decomposerResult[i].ops[0].type == O_PC) { #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); - Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), inst.mnemonic.p, inst.operands.p,decomposerResult[i].ops[0].type,decomposerResult[i].size, INSTRUCTION_GET_TARGET(&decomposerResult[i])); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_TARGET(&decomposerResult[i])); #endif return (DWORD_PTR)INSTRUCTION_GET_TARGET(&decomposerResult[i]); } } } } } return 0; } DWORD_PTR IATSearch::findIATPointer() { #ifdef DEBUG_COMMENTS _DecodedInst inst; #endif for (unsigned int i = 0; i < decomposerInstructionsCount; i++) { if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) { if (decomposerResult[i].size >= 5) { #ifdef _WIN64 if (decomposerResult[i].flags & FLAG_RIP_RELATIVE) { #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); - Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), inst.mnemonic.p, inst.operands.p,decomposerResult[i].ops[0].type,decomposerResult[i].size,INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); #endif return INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i]); } #else if (decomposerResult[i].ops[0].type == O_DISP) { //jmp dword ptr || call dword ptr #ifdef DEBUG_COMMENTS distorm_format(&decomposerCi, &decomposerResult[i], &inst); - Logger::debugLog(TEXT("%S %S %d %d - target address: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"), inst.mnemonic.p, inst.operands.p,decomposerResult[i].ops[0].type,decomposerResult[i].size,decomposerResult[i].disp); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, decomposerResult[i].disp); #endif return (DWORD_PTR)decomposerResult[i].disp; } #endif } } } } return 0; } /*DWORD_PTR IATSearch::findAddressFromWORDString(char * stringBuffer) { char * pAddress = 0; char * pTemp = 0; DWORD_PTR address = 0; //string split it e.g. DWORD [0x40f0fc], QWORD [RIP+0x40f0] pAddress = strchr(stringBuffer, 'x'); if (pAddress) { pAddress++; pTemp = strchr(pAddress, ']'); *pTemp = 0x00; address = strtoul(pAddress, 0, 16); //printf("findAddressFromWORDString :: %08X\n",address); if (address == ULONG_MAX) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findAddressFromDWORDString :: strtoul ULONG_MAX\r\n"); + Scylla::debugLog.log(L"findAddressFromDWORDString :: strtoul ULONG_MAX"); #endif return 0; } else { return address; } } else { return 0; } }*/ /*DWORD_PTR IATSearch::findAddressFromNormalCALLString(char * stringBuffer) { char * pAddress = 0; DWORD_PTR address = 0; //e.g. CALL 0x7238 pAddress = strchr(stringBuffer, 'x'); if (pAddress) { pAddress++; address = strtoul(pAddress, 0, 16); //printf("findAddressFromNormalCALLString :: %08X\n",address); if (address == ULONG_MAX) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findAddressFromNormalCALLString :: strtoul ULONG_MAX\r\n"); + Scylla::debugLog.log(L"findAddressFromNormalCALLString :: strtoul ULONG_MAX"); #endif return 0; } else { return address; } } else { return 0; } }*/ bool IATSearch::isIATPointerValid(DWORD_PTR iatPointer) { DWORD_PTR apiAddress = 0; if (!readMemoryFromProcess(iatPointer,sizeof(DWORD_PTR),&apiAddress)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("isIATPointerValid :: error reading memory\r\n"); + Scylla::debugLog.log(L"isIATPointerValid :: error reading memory"); #endif return false; } //printf("Win api ? %08X\n",apiAddress); if (isApiAddressValid(apiAddress) != 0) { return true; } else { //maybe redirected import? //if the address is 2 times inside a memory region it is possible a redirected api if (apiAddress > memoryAddress && apiAddress < (memoryAddress+memorySize)) { return true; } else { getMemoryRegionFromAddress(apiAddress, &memoryAddress, &memorySize); return false; } } } bool IATSearch::findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT) { MEMORY_BASIC_INFORMATION memBasic = {0}; BYTE *dataBuffer = 0; - if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) + if (VirtualQueryEx(hProcess,(LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findIATStartAddress :: VirtualQueryEx error %u\r\n",GetLastError()); + Scylla::debugLog.log(L"findIATStartAddress :: VirtualQueryEx error %u", GetLastError()); #endif return false; } //(sizeof(DWORD_PTR) * 3) added to prevent buffer overflow dataBuffer = new BYTE[memBasic.RegionSize + (sizeof(DWORD_PTR) * 3)]; ZeroMemory(dataBuffer, memBasic.RegionSize + (sizeof(DWORD_PTR) * 3)); if (!readMemoryFromProcess((DWORD_PTR)memBasic.BaseAddress, memBasic.RegionSize, dataBuffer)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findIATStartAddress :: error reading memory\r\n"); + Scylla::debugLog.log(L"findIATStartAddress :: error reading memory"); #endif return false; } //printf("address %X memBasic.BaseAddress %X memBasic.RegionSize %X\n",address,memBasic.BaseAddress,memBasic.RegionSize); *addressIAT = findIATStartAddress((DWORD_PTR)memBasic.BaseAddress, address, dataBuffer); - *sizeIAT = findIATSize((DWORD_PTR)memBasic.BaseAddress, *addressIAT,dataBuffer,(DWORD)memBasic.RegionSize); + *sizeIAT = findIATSize((DWORD_PTR)memBasic.BaseAddress, *addressIAT, dataBuffer, (DWORD)memBasic.RegionSize); delete [] dataBuffer; return true; } DWORD_PTR IATSearch::findIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE * dataBuffer) { DWORD_PTR *pIATAddress = 0; pIATAddress = (DWORD_PTR *)((startAddress - baseAddress) + (DWORD_PTR)dataBuffer); while((DWORD_PTR)pIATAddress != (DWORD_PTR)dataBuffer) { if ( (*pIATAddress < 0xFFFF) || !isAddressAccessable(*pIATAddress) ) { if ( (*(pIATAddress - 1) < 0xFFFF) || !isAddressAccessable(*(pIATAddress - 1)) ) { //IAT end if ((DWORD_PTR)(pIATAddress - 2) >= (DWORD_PTR)dataBuffer) { if (!isApiAddressValid(*(pIATAddress - 2))) { return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress); } } else { return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress); } } } pIATAddress--; } return baseAddress; } DWORD IATSearch::findIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE * dataBuffer, DWORD bufferSize) { DWORD_PTR *pIATAddress = 0; pIATAddress = (DWORD_PTR *)((iatAddress - baseAddress) + (DWORD_PTR)dataBuffer); #ifdef DEBUG_COMMENTS - Logger::debugLog("findIATSize :: baseAddress %X iatAddress %X dataBuffer %X pIATAddress %X\r\n",baseAddress,iatAddress, dataBuffer,pIATAddress); + Scylla::debugLog.log(L"findIATSize :: baseAddress %X iatAddress %X dataBuffer %X pIATAddress %X", baseAddress, iatAddress, dataBuffer, pIATAddress); #endif while((DWORD_PTR)pIATAddress < ((DWORD_PTR)dataBuffer + bufferSize - 1)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findIATSize :: %X %X %X\r\n",pIATAddress,*pIATAddress, *(pIATAddress + 1)); + Scylla::debugLog.log(L"findIATSize :: %X %X %X", pIATAddress, *pIATAddress, *(pIATAddress + 1)); #endif if ( (*pIATAddress < 0xFFFF) || !isAddressAccessable(*pIATAddress) ) //normal is 0 { if ( (*(pIATAddress + 1) < 0xFFFF) || !isAddressAccessable(*(pIATAddress + 1)) ) { //IAT end if (!isApiAddressValid(*(pIATAddress + 2))) { return (DWORD)((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer - (iatAddress - baseAddress)); } } } pIATAddress++; } return bufferSize; } bool IATSearch::isAddressAccessable(DWORD_PTR address) { BYTE junk[3]; SIZE_T numberOfBytesRead = 0; if (ReadProcessMemory(hProcess, (LPCVOID)address, junk, sizeof(junk), &numberOfBytesRead)) { if (numberOfBytesRead == sizeof(junk)) { if (junk[0] != 0x00) { return true; } } } return false; } \ No newline at end of file diff --git a/Scylla/ImportRebuild.cpp b/Scylla/ImportRebuild.cpp index a0130ae..088b109 100644 --- a/Scylla/ImportRebuild.cpp +++ b/Scylla/ImportRebuild.cpp @@ -1,715 +1,715 @@ #include "ImportRebuild.h" -#include "Logger.h" -#include "ConfigurationHolder.h" +#include "Scylla.h" +//#include "ConfigurationHolder.h" //#define DEBUG_COMMENTS ImportRebuild::ImportRebuild() { imageData = NULL; sizeOfFile = 0; pDosStub = NULL; pOverlay = NULL; sizeOfOverlay = 0; pImportDescriptor = NULL; pThunkData = NULL; pImportByName = NULL; numberOfImportDescriptors = 0; sizeOfImportSection = 0; sizeOfApiAndModuleNames = 0; importSectionIndex = 0; } ImportRebuild::~ImportRebuild() { delete [] pDosStub; delete [] imageData; for (size_t i = 0; i < vecSectionData.size(); i++) { delete [] vecSectionData[i]; } delete [] pOverlay; } bool ImportRebuild::splitTargetFile() { PIMAGE_SECTION_HEADER pSecHeader = 0; BYTE * data = 0; DWORD alignment = 0; DosHeader = *(IMAGE_DOS_HEADER*)imageData; if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { return false; } NTHeader = *(IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew); if (NTHeader.Signature != IMAGE_NT_SIGNATURE) { return false; } if (DosHeader.e_lfanew > sizeof(IMAGE_DOS_HEADER)) { size_t sizeOfStub = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER); pDosStub = new BYTE[sizeOfStub]; CopyMemory(pDosStub, imageData + sizeof(IMAGE_DOS_HEADER), sizeOfStub); } pSecHeader = IMAGE_FIRST_SECTION((IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew)); for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++) { const DWORD SECTION_SIZE_MAX = 300000000; DWORD sizeOfSection = pSecHeader->SizeOfRawData; if (sizeOfSection > SECTION_SIZE_MAX) { sizeOfSection = SECTION_SIZE_MAX; } //TODO better use section alignment because it is better? alignment = alignValue(sizeOfSection, NTHeader.OptionalHeader.SectionAlignment); data = new BYTE[alignment]; ZeroMemory(data, alignment); CopyMemory(data, imageData + pSecHeader->PointerToRawData, sizeOfSection); vecSectionData.push_back(data); vecSectionHeaders.push_back(*pSecHeader); pSecHeader++; } if(NTHeader.FileHeader.NumberOfSections > 0) // ?? { const IMAGE_SECTION_HEADER* pLastSec = &(*vecSectionHeaders.rbegin()); DWORD calcSize = pLastSec->PointerToRawData + pLastSec->SizeOfRawData; if (calcSize < sizeOfFile) { sizeOfOverlay = sizeOfFile - calcSize; pOverlay = new BYTE[sizeOfOverlay]; memcpy(pOverlay, imageData + calcSize, sizeOfOverlay); } } delete [] imageData; imageData = 0; return true; } bool ImportRebuild::alignSectionHeaders() { for (WORD i = 0; i < vecSectionHeaders.size(); i++) { vecSectionHeaders[i].VirtualAddress = alignValue(vecSectionHeaders[i].VirtualAddress, NTHeader.OptionalHeader.SectionAlignment); vecSectionHeaders[i].Misc.VirtualSize = alignValue(vecSectionHeaders[i].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment); vecSectionHeaders[i].PointerToRawData = alignValue(vecSectionHeaders[i].PointerToRawData, NTHeader.OptionalHeader.FileAlignment); vecSectionHeaders[i].SizeOfRawData = alignValue(vecSectionHeaders[i].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment); } return true; } bool ImportRebuild::saveNewFile(const WCHAR * filepath) { DWORD fileOffset = 0; DWORD dwWriteSize = 0; size_t i = 0; if (vecSectionHeaders.size() != vecSectionData.size()) { return false; } HANDLE hFile = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("saveNewFile :: INVALID_HANDLE_VALUE %u\r\n",GetLastError()); + Scylla::debugLog.log(L"saveNewFile :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif return false; } //alignSectionHeaders(); updatePeHeader(); fileOffset = 0; dwWriteSize = sizeof(IMAGE_DOS_HEADER); ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &DosHeader); fileOffset += dwWriteSize; dwWriteSize = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER); ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pDosStub); fileOffset += dwWriteSize; dwWriteSize = sizeof(IMAGE_NT_HEADERS); ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &NTHeader); fileOffset += dwWriteSize; dwWriteSize = sizeof(IMAGE_SECTION_HEADER); for (i = 0; i < vecSectionHeaders.size(); i++) { if (!ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &vecSectionHeaders[i])) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("saveNewFile :: writeMemoryToFile failed offset %X size %X\r\n"),fileOffset,dwWriteSize); + Scylla::debugLog.log(L"saveNewFile :: writeMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize); #endif CloseHandle(hFile); return false; } fileOffset += dwWriteSize; } for (i = 0; i < vecSectionHeaders.size(); i++) { dwWriteSize = vecSectionHeaders[i].PointerToRawData - fileOffset; if (dwWriteSize) { if (!writeZeroMemoryToFile(hFile, fileOffset, dwWriteSize)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("saveNewFile :: writeZeroMemoryToFile failed offset %X size %X\r\n"),fileOffset,dwWriteSize); + Scylla::debugLog.log(L"saveNewFile :: writeZeroMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize); #endif CloseHandle(hFile); return false; } fileOffset += dwWriteSize; } dwWriteSize = vecSectionHeaders[i].SizeOfRawData; ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, vecSectionData[i]); fileOffset += dwWriteSize; } if(pOverlay) { ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, sizeOfOverlay, pOverlay); fileOffset += sizeOfOverlay; } CloseHandle(hFile); return true; } bool ImportRebuild::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size) { bool retValue = false; PVOID zeromemory = calloc(size, 1); if (zeromemory) { retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory); free(zeromemory); } else { retValue = false; } return retValue; } bool ImportRebuild::addNewSection(char * sectionName, DWORD sectionSize, BYTE * sectionData) { BYTE * newBuffer = 0; IMAGE_SECTION_HEADER pNewSection = {0}; size_t lastSectionIndex = vecSectionHeaders.size() - 1; size_t nameLength = strlen(sectionName); if (nameLength > IMAGE_SIZEOF_SHORT_NAME) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("addNewSection :: sectionname is too long %d\r\n"),nameLength); + Scylla::debugLog.log(L"addNewSection :: sectionname is too long %d", nameLength); #endif return false; } memcpy_s(pNewSection.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength); pNewSection.SizeOfRawData = alignValue(sectionSize, NTHeader.OptionalHeader.FileAlignment); pNewSection.Misc.VirtualSize = alignValue(sectionSize, NTHeader.OptionalHeader.SectionAlignment); pNewSection.PointerToRawData = alignValue(vecSectionHeaders[lastSectionIndex].PointerToRawData + vecSectionHeaders[lastSectionIndex].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment); pNewSection.VirtualAddress = alignValue(vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment); pNewSection.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA; vecSectionHeaders.push_back(pNewSection); if ( (sectionSize != pNewSection.SizeOfRawData) || (sectionData == 0) ) { newBuffer = new BYTE[pNewSection.SizeOfRawData]; ZeroMemory(newBuffer, pNewSection.SizeOfRawData); if (sectionData) { CopyMemory(newBuffer, sectionData, sectionSize); } } else { newBuffer = sectionData; } vecSectionData.push_back(newBuffer); return true; } bool ImportRebuild::loadTargetFile(const WCHAR * filepath) { HANDLE hTargetFile = INVALID_HANDLE_VALUE; DWORD fileSize = 0; bool retValue = false; hTargetFile = CreateFile(filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hTargetFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("loadTargetFile :: INVALID_HANDLE_VALUE %u\r\n",GetLastError()); + Scylla::debugLog.log(L"loadTargetFile :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif return false; } fileSize = (DWORD)ProcessAccessHelp::getFileSize(hTargetFile); if (!fileSize) { CloseHandle(hTargetFile); hTargetFile = 0; return false; } imageData = new BYTE[fileSize]; if (!imageData) { retValue = false; } else { sizeOfFile = fileSize; retValue = ProcessAccessHelp::readMemoryFromFile(hTargetFile, 0, fileSize, imageData); } CloseHandle(hTargetFile); hTargetFile = 0; return retValue; } DWORD ImportRebuild::alignValue(DWORD badValue, DWORD alignTo) { return (((badValue + alignTo - 1) / alignTo) * alignTo); } DWORD ImportRebuild::convertRVAToOffsetVector(DWORD dwRVA) { for (size_t i = 0; i < vecSectionHeaders.size(); i++) { if ((vecSectionHeaders[i].VirtualAddress <= dwRVA) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > dwRVA)) { return ((dwRVA - vecSectionHeaders[i].VirtualAddress) + vecSectionHeaders[i].PointerToRawData); } } return 0; } /* DWORD ImportRebuild::convertRVAToOffset(DWORD dwRVA) { PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader); for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++) { if ((pSectionHeader->VirtualAddress <= dwRVA) && ((pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize) > dwRVA)) { return ((dwRVA - pSectionHeader->VirtualAddress) + pSectionHeader->PointerToRawData); } pSectionHeader++; } return 0; } */ DWORD_PTR ImportRebuild::convertOffsetToRVAVector(DWORD dwOffset) { for (size_t i = 0; i < vecSectionHeaders.size(); i++) { if ((vecSectionHeaders[i].PointerToRawData <= dwOffset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > dwOffset)) { return ((dwOffset - vecSectionHeaders[i].PointerToRawData) + vecSectionHeaders[i].VirtualAddress); } } return 0; } /* DWORD ImportRebuild::convertOffsetToRVA(DWORD dwOffset) { PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader); for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++) { if ((pSectionHeader->PointerToRawData <= dwOffset) && ((pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData) > dwOffset)) { return ((dwOffset - pSectionHeader->PointerToRawData) + pSectionHeader->VirtualAddress); } pSectionHeader++; } return 0; } */ void ImportRebuild::updatePeHeader() { size_t lastSectionIndex = vecSectionHeaders.size() - 1; NTHeader.FileHeader.NumberOfSections = (WORD)(lastSectionIndex + 1); NTHeader.OptionalHeader.SizeOfImage = vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize; NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; if (NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) { for (size_t i = 0; i < vecSectionHeaders.size(); i++) { if ((vecSectionHeaders[i].VirtualAddress <= NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress)) { //section must be read and writeable vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; } } NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0; NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0; } NTHeader.OptionalHeader.NumberOfRvaAndSizes = 0x10; NTHeader.OptionalHeader.SizeOfHeaders = alignValue(DosHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + NTHeader.FileHeader.SizeOfOptionalHeader + (NTHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), NTHeader.OptionalHeader.FileAlignment); } bool ImportRebuild::buildNewImportTable(std::map & moduleList) { createNewImportSection(moduleList); importSectionIndex = vecSectionHeaders.size() - 1; DWORD dwSize = fillImportSection(moduleList); if (!dwSize) { return false; } setFlagToIATSection((*moduleList.begin()).second.firstThunk); NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vecSectionHeaders[importSectionIndex].VirtualAddress; NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); return true; } bool ImportRebuild::createNewImportSection(std::map & moduleList) { char sectionName[9] = {0}; size_t i = 0; //DWORD sectionSize = calculateMinSize(moduleList); calculateImportSizes(moduleList); - if (wcslen(ConfigurationHolder::getConfigObject(IAT_SECTION_NAME)->valueString) > IMAGE_SIZEOF_SHORT_NAME) + if (wcslen(Scylla::config.getConfigObject(IAT_SECTION_NAME)->valueString) > IMAGE_SIZEOF_SHORT_NAME) { strcpy_s(sectionName, sizeof(sectionName), ".SCY"); } else { - wcstombs_s(&i, sectionName, sizeof(sectionName), ConfigurationHolder::getConfigObject(IAT_SECTION_NAME)->valueString, _TRUNCATE); + wcstombs_s(&i, sectionName, sizeof(sectionName), Scylla::config.getConfigObject(IAT_SECTION_NAME)->valueString, _TRUNCATE); } return addNewSection(sectionName, (DWORD)sizeOfImportSection, 0); } /*DWORD ImportRebuild::calculateMinSize(std::map & moduleList) { DWORD dwSize = 0; std::map::iterator mapIt; std::map::iterator mapIt2; dwSize = (DWORD)((moduleList.size() + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)); //last is zero'ed for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ ) { //dwSize += (DWORD)((*mapIt).second.thunkList.size() + sizeof(IMAGE_IMPORT_BY_NAME)); dwSize += (DWORD)(wcslen((*mapIt).second.moduleName) + 1); for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ ) { if((*mapIt2).second.name[0] != '\0') { dwSize += sizeof(IMAGE_IMPORT_BY_NAME); dwSize += (DWORD)strlen((*mapIt2).second.name); } } } return dwSize; }*/ BYTE * ImportRebuild::getMemoryPointerFromRVA(DWORD_PTR dwRVA) { DWORD_PTR offset = convertRVAToOffsetVector((DWORD)dwRVA); for (size_t i = 0; i < vecSectionHeaders.size(); i++) { if ((vecSectionHeaders[i].PointerToRawData <= offset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > offset)) { return (BYTE *)((DWORD_PTR)vecSectionData[i] + (offset - vecSectionHeaders[i].PointerToRawData)); } } return 0; } DWORD ImportRebuild::fillImportSection( std::map & moduleList ) { std::map::iterator mapIt; std::map::iterator mapIt2; PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0; PIMAGE_IMPORT_BY_NAME pImportByName = 0; PIMAGE_THUNK_DATA pThunk = 0; ImportModuleThunk * importModuleThunk = 0; ImportThunk * importThunk = 0; size_t stringLength = 0; DWORD_PTR lastRVA = 0; BYTE * sectionData = vecSectionData[importSectionIndex]; DWORD offset = 0; pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(sectionData); //skip the IMAGE_IMPORT_DESCRIPTOR offset += (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ ) { importModuleThunk = &((*mapIt).second); stringLength = addImportDescriptor(importModuleThunk, offset); #ifdef DEBUG_COMMENTS - Logger::debugLog("fillImportSection :: importDesc.Name %X\r\n", pImportDescriptor->Name); + Scylla::debugLog.log(L"fillImportSection :: importDesc.Name %X", pImportDescriptor->Name); #endif offset += (DWORD)stringLength; //stringLength has null termination char pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)sectionData + offset); //pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importModuleThunk->firstThunk)); lastRVA = importModuleThunk->firstThunk - sizeof(DWORD_PTR); for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ ) { importThunk = &((*mapIt2).second); pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importThunk->rva)); //check wrong iat pointer if (!pThunk) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("fillImportSection :: Failed to get pThunk RVA: %X\n"), importThunk->rva); + Scylla::debugLog.log(L"fillImportSection :: Failed to get pThunk RVA: %X", importThunk->rva); #endif return 0; } if ((lastRVA + sizeof(DWORD_PTR)) != importThunk->rva) { //add additional import desc addSpecialImportDescriptor(importThunk->rva); } lastRVA = importThunk->rva; #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X\n"), importThunk,pThunk,pImportByName,offset); + Scylla::debugLog.log(L"fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X", importThunk,pThunk,pImportByName,offset); #endif stringLength = addImportToImportTable(importThunk, pThunk, pImportByName, offset); offset += (DWORD)stringLength; //is 0 bei import by ordinal pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + stringLength); } pImportDescriptor++; } return offset; } bool ImportRebuild::rebuildImportTable(const WCHAR * targetFilePath, const WCHAR * newFilePath, std::map & moduleList) { bool retValue = false; if (loadTargetFile(targetFilePath)) { splitTargetFile(); retValue = buildNewImportTable(moduleList); if (retValue) { retValue = saveNewFile(newFilePath); } return retValue; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("rebuildImportTable ::Failed to load target %s\n"), targetFilePath); + Scylla::debugLog.log(L"rebuildImportTable ::Failed to load target %s", targetFilePath); #endif return false; } } void ImportRebuild::setFlagToIATSection(DWORD_PTR iatAddress) { for (size_t i = 0; i < vecSectionHeaders.size(); i++) { if ((vecSectionHeaders[i].VirtualAddress <= iatAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > iatAddress)) { //section must be read and writeable vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; } } } size_t ImportRebuild::addImportToImportTable( ImportThunk * pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset) { size_t stringLength = 0; if(pImport->name[0] == '\0') { pThunk->u1.AddressOfData = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG); } else { pImportByName->Hint = pImport->hint; stringLength = strlen(pImport->name) + 1; memcpy(pImportByName->Name, pImport->name, stringLength); pThunk->u1.AddressOfData = convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset); if (!pThunk->u1.AddressOfData) { #ifdef DEBUG_COMMENTS - Logger::debugLog("addImportToImportTable :: failed to get AddressOfData %X %X\n",vecSectionHeaders[importSectionIndex].PointerToRawData, sectionOffset); + Scylla::debugLog.log(L"addImportToImportTable :: failed to get AddressOfData %X %X", vecSectionHeaders[importSectionIndex].PointerToRawData, sectionOffset); #endif } //next import should be nulled pThunk++; pThunk->u1.AddressOfData = 0; #ifdef DEBUG_COMMENTS - Logger::debugLog("addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X\n",pThunk->u1.AddressOfData, pThunk, vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset); + Scylla::debugLog.log(L"addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X", pThunk->u1.AddressOfData, pThunk, vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset); #endif stringLength += sizeof(WORD); } return stringLength; } size_t ImportRebuild::addImportDescriptor(ImportModuleThunk * pImportModule, DWORD sectionOffset) { char dllName[MAX_PATH]; size_t stringLength = 0; wcstombs_s(&stringLength, dllName, (size_t)_countof(dllName), pImportModule->moduleName, (size_t)_countof(pImportModule->moduleName)); memcpy((vecSectionData[importSectionIndex] + sectionOffset), dllName, stringLength); //copy module name to section pImportDescriptor->FirstThunk = (DWORD)pImportModule->firstThunk; pImportDescriptor->Name = (DWORD)convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset); return stringLength; } void ImportRebuild::addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk) { PIMAGE_IMPORT_DESCRIPTOR oldID = pImportDescriptor; pImportDescriptor++; pImportDescriptor->FirstThunk = (DWORD)rvaFirstThunk; pImportDescriptor->Name = oldID->Name; } void ImportRebuild::calculateImportSizes(std::map & moduleList) { std::map::iterator mapIt; std::map::iterator mapIt2; DWORD_PTR lastRVA = 0; numberOfImportDescriptors = 0; sizeOfImportSection = 0; sizeOfApiAndModuleNames = 0; numberOfImportDescriptors = moduleList.size() + 1; //last is zero'd for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ ) { lastRVA = (*mapIt).second.firstThunk - sizeof(DWORD_PTR); sizeOfApiAndModuleNames += (DWORD)(wcslen((*mapIt).second.moduleName) + 1); for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ ) { if ((lastRVA + sizeof(DWORD_PTR)) != (*mapIt2).second.rva) { numberOfImportDescriptors++; //add additional import desc } if((*mapIt2).second.name[0] != '\0') { sizeOfApiAndModuleNames += sizeof(WORD); //Hint from IMAGE_IMPORT_BY_NAME sizeOfApiAndModuleNames += (DWORD)(strlen((*mapIt2).second.name) + 1); } lastRVA = (*mapIt2).second.rva; } } sizeOfImportSection = sizeOfApiAndModuleNames + (numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); } \ No newline at end of file diff --git a/Scylla/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp index f149aba..fe2b182 100644 --- a/Scylla/ImportsHandling.cpp +++ b/Scylla/ImportsHandling.cpp @@ -1,807 +1,807 @@ #include "ImportsHandling.h" #include "Thunks.h" -#include "definitions.h" +#include "Architecture.h" #include #include #include "multitree.h" // CMultiSelectTreeViewCtrl #include "resource.h" //#define DEBUG_COMMENTS void ImportThunk::invalidate() { ordinal = 0; hint = 0; valid = false; suspect = false; moduleName[0] = 0; name[0] = 0; } bool ImportModuleThunk::isValid() const { std::map::const_iterator iterator = thunkList.begin(); while (iterator != thunkList.end()) { if (iterator->second.valid == false) { return false; } iterator++; } return true; } DWORD_PTR ImportModuleThunk::getFirstThunk() const { if (thunkList.size() > 0) { const std::map::const_iterator iterator = thunkList.begin(); return iterator->first; } else { return 0; } } ImportsHandling::ImportsHandling(CMultiSelectTreeViewCtrl& TreeImports) : TreeImports(TreeImports) { hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16); hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16); hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16); CDCHandle dc = CWindow(::GetDesktopWindow()).GetDC(); int bits = dc.GetDeviceCaps(BITSPIXEL); const UINT FLAGS = bits > 16 ? ILC_COLOR32 : (ILC_COLOR24 | ILC_MASK); TreeIcons.Create(16, 16, FLAGS, 3, 1); TreeIcons.AddIcon(hIconCheck); TreeIcons.AddIcon(hIconWarning); TreeIcons.AddIcon(hIconError); m_thunkCount = m_invalidThunkCount = m_suspectThunkCount = 0; } ImportsHandling::~ImportsHandling() { TreeIcons.Destroy(); } bool ImportsHandling::isModule(CTreeItem item) { return (0 != getModuleThunk(item)); } bool ImportsHandling::isImport(CTreeItem item) { return (0 != getImportThunk(item)); } ImportModuleThunk * ImportsHandling::getModuleThunk(CTreeItem item) { stdext::hash_map::const_iterator it; it = itemData.find(item); if(it != itemData.end()) { const TreeItemData * data = &it->second; if(data->isModule) { return data->module; } } return NULL; } ImportThunk * ImportsHandling::getImportThunk(CTreeItem item) { stdext::hash_map::const_iterator it; TreeItemData * data = getItemData(item); if(data && !data->isModule) { return data->import; } return NULL; } void ImportsHandling::setItemData(CTreeItem item, const TreeItemData * data) { itemData[item] = *data; } ImportsHandling::TreeItemData * ImportsHandling::getItemData(CTreeItem item) { stdext::hash_map::iterator it; it = itemData.find(item); if(it != itemData.end()) { return &it->second; } return NULL; } void ImportsHandling::updateCounts() { std::map::iterator it_module; std::map::iterator it_import; m_thunkCount = m_invalidThunkCount = m_suspectThunkCount = 0; it_module = moduleList.begin(); while (it_module != moduleList.end()) { ImportModuleThunk &moduleThunk = it_module->second; it_import = moduleThunk.thunkList.begin(); while (it_import != moduleThunk.thunkList.end()) { ImportThunk &importThunk = it_import->second; m_thunkCount++; if(!importThunk.valid) m_invalidThunkCount++; else if(importThunk.suspect) m_suspectThunkCount++; it_import++; } it_module++; } } /*bool ImportsHandling::addImport(const WCHAR * moduleName, const CHAR * name, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if (moduleList.size() > 1) { iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleList.end()) { iterator1--; module = &(iterator1->second); break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } } } else { iterator1 = moduleList.begin(); module = &(iterator1->second); } if (!module) { - Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(""),rva); + Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva); return false; } //TODO import.suspect = true; import.valid = false; import.va = va; import.rva = rva; import.ordinal = ordinal; wcscpy_s(import.moduleName, MAX_PATH, moduleName); strcpy_s(import.name, MAX_PATH, name); module->thunkList.insert(std::pair(import.rva, import)); return true; } */ /* bool ImportsHandling::addModule(const WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, moduleName); moduleList.insert(std::pair(firstThunk,module)); return true; } */ void ImportsHandling::displayAllImports() { std::map::iterator it_module; std::map::iterator it_import; TreeImports.DeleteAllItems(); itemData.clear(); TreeImports.SetImageList(TreeIcons); it_module = moduleList.begin(); while (it_module != moduleList.end()) { ImportModuleThunk &moduleThunk = it_module->second; moduleThunk.key = moduleThunk.firstThunk; // This belongs elsewhere... moduleThunk.hTreeItem = addDllToTreeView(TreeImports, &moduleThunk); it_import = moduleThunk.thunkList.begin(); while (it_import != moduleThunk.thunkList.end()) { ImportThunk &importThunk = it_import->second; importThunk.key = importThunk.rva; // This belongs elsewhere... importThunk.hTreeItem = addApiToTreeView(TreeImports, moduleThunk.hTreeItem, &importThunk); it_import++; } it_module++; } updateCounts(); } void ImportsHandling::clearAllImports() { TreeImports.DeleteAllItems(); itemData.clear(); moduleList.clear(); updateCounts(); } CTreeItem ImportsHandling::addDllToTreeView(CMultiSelectTreeViewCtrl& idTreeView, ImportModuleThunk * moduleThunk) { CTreeItem item = idTreeView.InsertItem(L"", NULL, TVI_ROOT); item.SetData(itemData.size()); TreeItemData data; data.isModule = true; data.module = moduleThunk; setItemData(item, &data); updateModuleInTreeView(moduleThunk, item); return item; } CTreeItem ImportsHandling::addApiToTreeView(CMultiSelectTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk) { CTreeItem item = idTreeView.InsertItem(L"", parentDll, TVI_LAST); item.SetData(itemData.size()); TreeItemData data; data.isModule = false; data.import = importThunk; setItemData(item, &data); updateImportInTreeView(importThunk, item); return item; } void ImportsHandling::selectImports(bool invalid, bool suspect) { std::map::iterator it_module; std::map::iterator it_import; TreeImports.SelectAllItems(FALSE); //remove selection it_module = moduleList.begin(); while (it_module != moduleList.end()) { ImportModuleThunk &moduleThunk = it_module->second; it_import = moduleThunk.thunkList.begin(); while (it_import != moduleThunk.thunkList.end()) { ImportThunk &importThunk = it_import->second; if ((invalid && !importThunk.valid) || (suspect && importThunk.suspect)) { TreeImports.SelectItem(importThunk.hTreeItem, TRUE); importThunk.hTreeItem.EnsureVisible(); } it_import++; } it_module++; } } bool ImportsHandling::invalidateImport(CTreeItem item) { ImportThunk * import = getImportThunk(item); if(import) { CTreeItem parent = item.GetParent(); if(!parent.IsNull()) { const ImportModuleThunk * module = getModuleThunk(parent); if(module) { import->invalidate(); updateImportInTreeView(import, import->hTreeItem); updateModuleInTreeView(module, module->hTreeItem); updateCounts(); return true; } } } return false; } bool ImportsHandling::invalidateModule(CTreeItem item) { ImportModuleThunk * module = getModuleThunk(item); if(module) { std::map::iterator it_import; it_import = module->thunkList.begin(); while(it_import != module->thunkList.end()) { ImportThunk * import = &it_import->second; import->invalidate(); updateImportInTreeView(import, import->hTreeItem); it_import++; } updateModuleInTreeView(module, module->hTreeItem); updateCounts(); return true; } return false; } bool ImportsHandling::setImport(CTreeItem item, const WCHAR * moduleName, const CHAR * apiName, WORD ordinal, WORD hint, bool valid, bool suspect) { ImportThunk * import = getImportThunk(item); if(import) { CTreeItem parent = item.GetParent(); if(!parent.IsNull()) { const ImportModuleThunk * module = getModuleThunk(parent); if(module) { wcscpy_s(import->moduleName, _countof(import->moduleName), moduleName); strcpy_s(import->name, _countof(import->name), apiName); import->ordinal = ordinal; //import->apiAddressVA = api->va; //?? import->hint = hint; import->valid = valid; import->suspect = suspect; updateImportInTreeView(import, item); updateModuleInTreeView(module, module->hTreeItem); updateCounts(); return true; } } } return false; } void ImportsHandling::updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item) { if (importThunk->valid) { WCHAR tempString[300]; if (importThunk->name[0] != 0x00) { - swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name); + swprintf_s(tempString, _countof(tempString), L"ord: %04X name: %S", importThunk->ordinal, importThunk->name); } else { - swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal); + swprintf_s(tempString, _countof(tempString), L"ord: %04X", importThunk->ordinal); } - swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->rva,importThunk->moduleName,tempString); + swprintf_s(stringBuffer, _countof(stringBuffer), L" rva: " PRINTF_DWORD_PTR_HALF L" mod: %s %s", importThunk->rva, importThunk->moduleName, tempString); } else { - swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" ptr: ")TEXT(PRINTF_DWORD_PTR_FULL),importThunk->rva,importThunk->apiAddressVA); + swprintf_s(stringBuffer, _countof(stringBuffer), L" rva: " PRINTF_DWORD_PTR_HALF L" ptr: " PRINTF_DWORD_PTR_FULL, importThunk->rva, importThunk->apiAddressVA); } item.SetText(stringBuffer); Icon icon = getAppropiateIcon(importThunk); item.SetImage(icon, icon); } void ImportsHandling::updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item) { - swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s (%d) FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF),importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk); + swprintf_s(stringBuffer, _countof(stringBuffer),L"%s (%d) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk); item.SetText(stringBuffer); Icon icon = getAppropiateIcon(importThunk->isValid()); item.SetImage(icon, icon); } ImportsHandling::Icon ImportsHandling::getAppropiateIcon(const ImportThunk * importThunk) { if(importThunk->valid) { if(importThunk->suspect) { return iconWarning; } else { return iconCheck; } } else { return iconError; } } ImportsHandling::Icon ImportsHandling::getAppropiateIcon(bool valid) { if(valid) { return iconCheck; } else { return iconError; } } bool ImportsHandling::cutImport(CTreeItem item) { ImportThunk * import = getImportThunk(item); if(import) { CTreeItem parent = item.GetParent(); if(!parent.IsNull()) { ImportModuleThunk * module = getModuleThunk(parent); if(module) { itemData.erase(item); import->hTreeItem.Delete(); module->thunkList.erase(import->key); import = 0; if (module->thunkList.empty()) { itemData.erase(parent); module->hTreeItem.Delete(); moduleList.erase(module->key); module = 0; } else { if (module->isValid() && module->moduleName[0] == L'?') { //update module name wcscpy_s(module->moduleName,_countof(module->moduleName),(*module->thunkList.begin()).second.moduleName); } module->firstThunk = (*module->thunkList.begin()).second.rva; updateModuleInTreeView(module, module->hTreeItem); } updateCounts(); return true; } } } return false; } bool ImportsHandling::cutModule(CTreeItem item) { ImportModuleThunk * module = getModuleThunk(item); if(module) { CTreeItem child = item.GetChild(); while(!child.IsNull()) { itemData.erase(child); child = child.GetNextSibling(); } itemData.erase(item); module->hTreeItem.Delete(); moduleList.erase(module->key); module = 0; updateCounts(); return true; } return false; } DWORD_PTR ImportsHandling::getApiAddressByNode(CTreeItem item) { const ImportThunk * import = getImportThunk(item); if(import) { return import->apiAddressVA; } return 0; } void ImportsHandling::scanAndFixModuleList() { std::map::iterator it_module; std::map::iterator it_import; it_module = moduleList.begin(); while (it_module != moduleList.end()) { ImportModuleThunk &moduleThunk = it_module->second; it_import = moduleThunk.thunkList.begin(); while (it_import != moduleThunk.thunkList.end()) { ImportThunk &importThunk = it_import->second; if (importThunk.moduleName[0] == 0 || importThunk.moduleName[0] == L'?') { addNotFoundApiToModuleList(&importThunk); } else { if (isNewModule(importThunk.moduleName)) { addModuleToModuleList(importThunk.moduleName, importThunk.rva); } addFunctionToModuleList(&importThunk); } it_import++; } moduleThunk.thunkList.clear(); it_module++; } moduleList = moduleListNew; moduleListNew.clear(); } bool ImportsHandling::findNewModules(std::map & thunkList) { throw std::exception("The method or operation is not implemented."); } bool ImportsHandling::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, _countof(module.moduleName), moduleName); module.key = module.firstThunk; moduleListNew[module.key] = module; return true; } bool ImportsHandling::isNewModule(const WCHAR * moduleName) { std::map::iterator it_module; it_module = moduleListNew.begin(); while (it_module != moduleListNew.end()) { if (!_wcsicmp(it_module->second.moduleName, moduleName)) { return false; } it_module++; } return true; } void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, _countof(module.moduleName), L"?"); module.key = module.firstThunk; moduleListNew[module.key] = module; } bool ImportsHandling::addNotFoundApiToModuleList(const ImportThunk * apiNotFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator it_module; DWORD_PTR rva = apiNotFound->rva; if (moduleListNew.size() > 0) { it_module = moduleListNew.begin(); while (it_module != moduleListNew.end()) { if (rva >= it_module->second.firstThunk) { it_module++; if (it_module == moduleListNew.end()) { it_module--; //new unknown module if (it_module->second.moduleName[0] == L'?') { module = &(it_module->second); } else { addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } break; } else if (rva < it_module->second.firstThunk) { it_module--; module = &(it_module->second); break; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("Error iterator1 != (*moduleThunkList).end()\r\n"); + Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()"); #endif break; } } } else { //new unknown module addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } if (!module) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); + 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 = apiNotFound->va; import.rva = apiNotFound->rva; import.apiAddressVA = apiNotFound->apiAddressVA; import.ordinal = 0; wcscpy_s(import.moduleName, _countof(import.moduleName), L"?"); strcpy_s(import.name, _countof(import.name), "?"); import.key = import.rva; module->thunkList[import.key] = import; return true; } bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator it_module; if (moduleListNew.size() > 1) { it_module = moduleListNew.begin(); while (it_module != moduleListNew.end()) { if (apiFound->rva >= it_module->second.firstThunk) { it_module++; if (it_module == moduleListNew.end()) { it_module--; module = &(it_module->second); break; } else if (apiFound->rva < it_module->second.firstThunk) { it_module--; module = &(it_module->second); break; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("Error iterator1 != moduleListNew.end()\r\n")); + Scylla::debugLog.log(L"Error iterator1 != moduleListNew.end()"); #endif break; } } } else { it_module = moduleListNew.begin(); module = &(it_module->second); } if (!module) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),apiFound->rva); + Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, apiFound->rva); #endif return false; } import.suspect = apiFound->suspect; import.valid = apiFound->valid; import.va = apiFound->va; import.rva = apiFound->rva; import.apiAddressVA = apiFound->apiAddressVA; import.ordinal = apiFound->ordinal; import.hint = apiFound->hint; wcscpy_s(import.moduleName, _countof(import.moduleName), apiFound->moduleName); strcpy_s(import.name, _countof(import.name), apiFound->name); import.key = import.rva; module->thunkList[import.key] = import; return true; } void ImportsHandling::expandAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_EXPAND); } void ImportsHandling::collapseAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_COLLAPSE); } void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag) { std::map::iterator it_module; it_module = moduleList.begin(); while (it_module != moduleList.end()) { ImportModuleThunk &moduleThunk = it_module->second; moduleThunk.hTreeItem.Expand(flag); it_module++; } } diff --git a/Scylla/Logger.cpp b/Scylla/Logger.cpp index 120eeae..f25d7d3 100644 --- a/Scylla/Logger.cpp +++ b/Scylla/Logger.cpp @@ -1,92 +1,112 @@ #include "Logger.h" -#include "MainGui.h" +#include +#include +#include -extern MainGui* pMainGui; - -WCHAR Logger::debugLogFile[MAX_PATH]; WCHAR Logger::logbuf[300]; char Logger::logbufChar[300]; -void Logger::getDebugLogFilePath() -{ - GetModuleFileName(0, debugLogFile, MAX_PATH); - - for(size_t i = wcslen(debugLogFile); i > 0; i--) - { - if(debugLogFile[i] == L'\\') - { - debugLogFile[i+1] = 0x00; - break; - } - } - - wcscat_s(debugLogFile, _countof(debugLogFile), TEXT(DEBUG_LOG_FILENAME)); -} - - -void Logger::debugLog(const WCHAR * format, ...) +void Logger::log(const WCHAR * format, ...) { - FILE * pFile; - va_list va_alist; - if (!format) { return; } - ZeroMemory(logbuf, sizeof(logbuf)); + //ZeroMemory(logbuf, sizeof(logbuf)); + va_list va_alist; va_start (va_alist, format); _vsnwprintf_s(logbuf, _countof(logbuf), _countof(logbuf) - 1, format, va_alist); va_end (va_alist); - if (_wfopen_s(&pFile,debugLogFile,L"a") == NULL) - { - fputws(logbuf,pFile); - fclose (pFile); - } + write(logbuf); } -void Logger::debugLog(const char * format, ...) +void Logger::log(const char * format, ...) { - FILE * pFile; - va_list va_alist; - if (!format) { return; } - ZeroMemory(logbufChar, sizeof(logbufChar)); + //ZeroMemory(logbufChar, sizeof(logbufChar)); + va_list va_alist; va_start (va_alist, format); _vsnprintf_s(logbufChar, _countof(logbufChar), _countof(logbufChar) - 1, format, va_alist); va_end (va_alist); - if (_wfopen_s(&pFile,debugLogFile,L"a") == NULL) - { - fputs(logbufChar,pFile); - fclose (pFile); - } + write(logbufChar); } -void Logger::printfDialog(const WCHAR * format, ...) +void Logger::write(const CHAR * str) { - va_list va_alist; + size_t len = strlen(str) + 1; + WCHAR * buf = new WCHAR[len]; - if (!format) - { - return; - } + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, buf, len, str, _TRUNCATE); - ZeroMemory(logbuf, sizeof(logbuf)); + write(buf); - va_start (va_alist, format); - _vsnwprintf_s(logbuf, _countof(logbuf), _countof(logbuf) - 1, format, va_alist); - va_end (va_alist); + delete[] buf; +} + +FileLog::FileLog(const WCHAR * fileName) +{ + GetModuleFileName(0, this->filePath, _countof(this->filePath)); + PathRemoveFileSpec(this->filePath); + PathAppend(this->filePath, fileName); +} + +void FileLog::write(const CHAR * str) +{ + /* + std::wofstream file(filePath, std::wofstream::app); + if(!file.fail()) + { + file << str << std::endl; + } + */ + FILE * pFile; + if (_wfopen_s(&pFile, filePath, L"a") == 0) + { + fputs(str, pFile); + fputs("\r\n", pFile); + fclose(pFile); + } +} + +void FileLog::write(const WCHAR * str) +{ + /* + std::wofstream file(filePath, std::wofstream::app); + if(!file.fail()) + { + file << str << std::endl; + } + */ - pMainGui->addTextToOutputLog(logbuf); - UpdateWindow(pMainGui->m_hWnd); -} \ No newline at end of file + FILE * pFile; + if (_wfopen_s(&pFile, filePath, L"a") == 0) + { + fputws(str, pFile); + fputws(L"\r\n", pFile); + fclose(pFile); + } +} + +void ListboxLog::setWindow(HWND window) +{ + this->window = window; +} + +void ListboxLog::write(const WCHAR * str) +{ + LRESULT index = SendMessageW(window, LB_ADDSTRING, 0, reinterpret_cast(str)); + SendMessage(window, LB_SETCURSEL, index, 0); + UpdateWindow(window); +} diff --git a/Scylla/Logger.h b/Scylla/Logger.h index 5e6a2e7..a4f22e8 100644 --- a/Scylla/Logger.h +++ b/Scylla/Logger.h @@ -1,20 +1,53 @@ #pragma once #include -#define DEBUG_LOG_FILENAME "Scylla_debug.log" - -class Logger { +class Logger +{ public: - static void debugLog(const WCHAR * format, ...); - static void debugLog(const CHAR * format, ...); - static void printfDialog(const WCHAR * format, ...); - static void getDebugLogFilePath(); + virtual void log(const WCHAR * format, ...); + virtual void log(const CHAR * format, ...); + +protected: + + virtual void write(const WCHAR * str) = 0; + virtual void write(const CHAR * str); private: - static WCHAR debugLogFile[MAX_PATH]; + static WCHAR logbuf[300]; static char logbufChar[300]; }; + +class FileLog : public Logger +{ +public: + + FileLog(const WCHAR * fileName); + +private: + + void write(const WCHAR * str); + void write(const CHAR * str); + + WCHAR filePath[MAX_PATH]; +}; + +class ListboxLog : public Logger +{ +public: + + ListboxLog() : window(0) { } + ListboxLog(HWND window); + + void setWindow(HWND window); + +private: + + void write(const WCHAR * str); + //void write(const CHAR * str); + + HWND window; +}; diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp index 8d652e8..9825a45 100644 --- a/Scylla/MainGui.cpp +++ b/Scylla/MainGui.cpp @@ -1,1239 +1,1248 @@ #include "MainGui.h" -#include "definitions.h" -#include "PluginLoader.h" -#include "ConfigurationHolder.h" +#include "Architecture.h" +//#include "PluginLoader.h" +//#include "ConfigurationHolder.h" #include "PeDump.h" #include "PeRebuild.h" #include "DllInjectionPlugin.h" #include "DisassemblerGui.h" #include "PickApiGui.h" -#include "NativeWinApi.h" +//#include "NativeWinApi.h" #include "ImportRebuild.h" #include "SystemInformation.h" +#include "Scylla.h" #include "AboutGui.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::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::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"; MainGui::MainGui() : selectedProcess(0), importsHandling(TreeImports), TreeImportsSubclass(this, IDC_TREE_IMPORTS) { + /* Logger::getDebugLogFilePath(); ConfigurationHolder::loadConfiguration(); PluginLoader::findAllPlugins(); NativeWinApi::initialize(); SystemInformation::getSystemInformation(); if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue()) { processLister.setDebugPrivileges(); } + ProcessAccessHelp::getProcessModules(GetCurrentProcessId(), ProcessAccessHelp::ownModuleList); + */ + + Scylla::init(); hIcon.LoadIcon(IDI_ICON_SCYLLA); hMenuImports.LoadMenu(IDR_MENU_IMPORTS); hMenuLog.LoadMenu(IDR_MENU_LOG); accelerators.LoadAccelerators(IDR_ACCELERATOR_MAIN); hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16); hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16); hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16); - - appendPluginListToMenu(hMenuImports.GetSubMenu(0)); } 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; } 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(); 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)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) + if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { pluginActionHandler(nID); return; } } SetMsgHandled(FALSE); } LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh) { if(TreeImports.GetCount() < 1) return 0; // Get item under cursor CTreeItem over = findTreeItem(CPoint(GetMessagePos()), true); if(over && importsHandling.isImport(over)) { pickApiActionHandler(over); } return 0; } LRESULT MainGui::OnTreeImportsKeyDown(const NMHDR* pnmh) { const NMTVKEYDOWN * tkd = (NMTVKEYDOWN *)pnmh; switch(tkd->wVKey) { case VK_RETURN: { CTreeItem selected = TreeImports.GetFocusItem(); if(!selected.IsNull() && importsHandling.isImport(selected)) { pickApiActionHandler(selected); } } return 1; case VK_DELETE: deleteSelectedImportsActionHandler(); return 1; } SetMsgHandled(FALSE); return 0; } UINT MainGui::OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg) { if(lpMsg) { switch(lpMsg->wParam) { case VK_RETURN: return DLGC_WANTMESSAGE; } } SetMsgHandled(FALSE); return 0; } void MainGui::OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_RETURN: break; default: SetMsgHandled(FALSE); break; } } void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl) { fillProcessListComboBox(ComboProcessList); } void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { processSelectedActionHandler(ComboProcessList.GetCurSel()); } void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl) { pickDllActionHandler(); } void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl) { optionsActionHandler(); } void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl) { dumpActionHandler(); } void MainGui::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::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) { DestroyWindow(); } void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl) { showAboutDialog(); } 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, _countof(stringBuffer), TEXT("\tImports: %u"), totalImports); + swprintf_s(stringBuffer, _countof(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, _countof(stringBuffer), TEXT("\tInvalid: %u"), invalidImports); + swprintf_s(stringBuffer, _countof(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, _countof(stringBuffer), TEXT("\tImagebase: ")TEXT(PRINTF_DWORD_PTR_FULL), imageBase); + swprintf_s(stringBuffer, _countof(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] = _T('\0'); + 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(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); + 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; - Logger::printfDialog(TEXT("->>> Module %s selected."), ProcessAccessHelp::selectedModule->getFilename()); - Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),ProcessAccessHelp::selectedModule->modBaseAddr,ProcessAccessHelp::selectedModule->modBaseSize); + Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename()); + Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize); } 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, _countof(stringBuffer), TEXT("Can't read memory at ")TEXT(PRINTF_DWORD_PTR_FULL),address); + swprintf_s(stringBuffer, _countof(stringBuffer), L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address); MessageBox(stringBuffer, L"Failure", MB_ICONERROR); } else { DisassemblerGui dlgDisassembler(address); dlgDisassembler.DoModal(); } } } void MainGui::processSelectedActionHandler(int index) { - std::vector& processList = processLister.getProcessList(); + std::vector& processList = Scylla::processLister.getProcessList(); Process &process = processList.at(index); selectedProcess = 0; clearImportsActionHandler(); - Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath); + Scylla::windowLog.log(L"Analyzing %s", process.fullPath); if (ProcessAccessHelp::hProcess != 0) { ProcessAccessHelp::closeProcessHandle(); apiReader.clearAll(); } if (!ProcessAccessHelp::openProcessHandle(process.PID)) { enableDialogControls(FALSE); - Logger::printfDialog(TEXT("Error: Cannot open process handle.")); + Scylla::windowLog.log(L"Error: Cannot open process handle."); updateStatusBar(); return; } ProcessAccessHelp::getProcessModules(process.PID, ProcessAccessHelp::moduleList); apiReader.readApisFromModuleList(); - Logger::printfDialog(TEXT("Loading modules done.")); + Scylla::windowLog.log(L"Loading modules done."); //TODO improve ProcessAccessHelp::selectedModule = 0; ProcessAccessHelp::targetSizeOfImage = process.imageSize; ProcessAccessHelp::targetImageBase = process.imageBase; ProcessAccessHelp::getSizeOfImageCurrentProcess(); process.imageSize = (DWORD)ProcessAccessHelp::targetSizeOfImage; - Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),process.imageBase, process.imageSize); + Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", process.imageBase, process.imageSize); process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath); EditOEPAddress.SetValue(process.entryPoint + process.imageBase); selectedProcess = &process; enableDialogControls(TRUE); updateStatusBar(); } void MainGui::fillProcessListComboBox(CComboBox& hCombo) { hCombo.ResetContent(); - std::vector& processList = processLister.getProcessListSnapshot(); + std::vector& processList = Scylla::processLister.getProcessListSnapshot(); for (size_t i = 0; i < processList.size(); i++) { - swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("0x%04X - %s - %s"),processList[i].PID,processList[i].filename,processList[i].fullPath); + swprintf_s(stringBuffer, _countof(stringBuffer), L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath); hCombo.AddString(stringBuffer); } } +/* void MainGui::addTextToOutputLog(const WCHAR * text) { if (m_hWnd) { ListLog.SetCurSel(ListLog.AddString(text)); } } +*/ void MainGui::clearOutputLog() { if (m_hWnd) { ListLog.ResetContent(); } } bool MainGui::saveLogToFile(const WCHAR * file) { const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian const WCHAR newLine[] = L"\r\n"; bool success = true; HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile != INVALID_HANDLE_VALUE) { ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM); WCHAR * buffer = 0; size_t bufsize = 0; for(int i = 0; i < ListLog.GetCount(); i++) { size_t size = ListLog.GetTextLen(i); size += _countof(newLine)-1; if(size+1 > bufsize) { bufsize = size+1; delete[] buffer; try { buffer = new WCHAR[bufsize]; } catch(std::bad_alloc&) { buffer = 0; success = false; break; } } ListLog.GetText(i, buffer); wcscat_s(buffer, bufsize, newLine); ProcessAccessHelp::writeMemoryToFileEnd(hFile, (DWORD)(size * sizeof(WCHAR)), buffer); } delete[] buffer; CloseHandle(hFile); } return success; } void MainGui::showInvalidImportsActionHandler() { importsHandling.selectImports(true, false); GotoDlgCtrl(TreeImports); } void MainGui::showSuspectImportsActionHandler() { importsHandling.selectImports(false, true); GotoDlgCtrl(TreeImports); } void MainGui::deleteSelectedImportsActionHandler() { CTreeItem selected = TreeImports.GetFirstSelectedItem(); while(!selected.IsNull()) { if(importsHandling.isModule(selected)) { importsHandling.cutModule(selected); } else { importsHandling.cutImport(selected); } selected = TreeImports.GetNextSelectedItem(selected); } updateStatusBar(); } void MainGui::invalidateSelectedImportsActionHandler() { CTreeItem selected = TreeImports.GetFirstSelectedItem(); while(!selected.IsNull()) { if(importsHandling.isImport(selected)) { importsHandling.invalidateImport(selected); } selected = TreeImports.GetNextSelectedItem(selected); } updateStatusBar(); } void MainGui::loadTreeActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; TreeImportExport treeIO; DWORD_PTR addrOEP = 0; DWORD_PTR addrIAT = 0; DWORD sizeIAT = 0; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, false, NULL, filterXml, NULL, stringBuffer)) { if(!treeIO.importTreeList(selectedFilePath, importsHandling.moduleList, &addrOEP, &addrIAT, &sizeIAT)) { - Logger::printfDialog(TEXT("Loading tree file failed %s"), selectedFilePath); + 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(); - Logger::printfDialog(TEXT("Loaded tree file %s"), selectedFilePath); - Logger::printfDialog(TEXT("-> OEP: ")TEXT(PRINTF_DWORD_PTR_FULL), addrOEP); - Logger::printfDialog(TEXT("-> IAT: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: ")TEXT(PRINTF_DWORD_PTR), addrIAT, sizeIAT); + 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]; TreeImportExport treeIO; DWORD_PTR addrOEP; DWORD_PTR addrIAT; DWORD sizeIAT; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, filterXml, L"xml", stringBuffer)) { addrOEP = EditOEPAddress.GetValue(); addrIAT = EditIATAddress.GetValue(); sizeIAT = EditIATSize.GetValue(); if(!treeIO.exportTreeList(selectedFilePath, importsHandling.moduleList, selectedProcess, addrOEP, addrIAT, sizeIAT)) { - Logger::printfDialog(TEXT("Saving tree file failed %s"), selectedFilePath); + Scylla::windowLog.log(L"Saving tree file failed %s", selectedFilePath); MessageBox(L"Saving tree file failed.", L"Failure", MB_ICONERROR); } else { - Logger::printfDialog(TEXT("Saved tree file %s"), selectedFilePath); + Scylla::windowLog.log(L"Saved tree file %s", selectedFilePath); } } } void MainGui::iatAutosearchActionHandler() { DWORD_PTR searchAddress = 0; DWORD_PTR addressIAT = 0; DWORD sizeIAT = 0; IATSearch iatSearch; if(!selectedProcess) return; if(EditOEPAddress.GetWindowTextLength() > 0) { searchAddress = EditOEPAddress.GetValue(); if (searchAddress) { if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT)) { - Logger::printfDialog(TEXT("IAT found at VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d)"),addressIAT, addressIAT - ProcessAccessHelp::targetImageBase,sizeIAT,sizeIAT); + Scylla::windowLog.log(L"IAT found at VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT); EditIATAddress.SetValue(addressIAT); EditIATSize.SetValue(sizeIAT); - swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("IAT found:\r\n\r\nStart: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\nSize: 0x%04X (%d) "),addressIAT,sizeIAT,sizeIAT); + swprintf_s(stringBuffer, _countof(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); } else { - Logger::printfDialog(TEXT("IAT not found at OEP ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("!"),searchAddress); + Scylla::windowLog.log(L"IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress); } } } } void MainGui::getImportsActionHandler() { if(!selectedProcess) return; DWORD_PTR addressIAT = EditIATAddress.GetValue(); DWORD sizeIAT = EditIATSize.GetValue(); if (addressIAT && sizeIAT) { - apiReader.readAndParseIAT(addressIAT, sizeIAT,importsHandling.moduleList); + apiReader.readAndParseIAT(addressIAT, sizeIAT, importsHandling.moduleList); importsHandling.displayAllImports(); updateStatusBar(); } } void MainGui::SetupImportsMenuItems(CTreeItem item) { bool isItem, isImport = false; isItem = !item.IsNull(); if(isItem) { isImport = importsHandling.isImport(item); } CMenuHandle hSub = hMenuImports.GetSubMenu(0); UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED; UINT importOnly = isImport ? MF_ENABLED : MF_GRAYED; hSub.EnableMenuItem(ID__INVALIDATE, itemOnly); hSub.EnableMenuItem(ID__DISASSEMBLE, importOnly); hSub.EnableMenuItem(ID__CUTTHUNK, importOnly); hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly); } void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt) { if(TreeImports.GetCount() < 1) return; CTreeItem over, parent; if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; over = TreeImports.GetFocusItem(); if(over) { over.EnsureVisible(); over.GetRect(&pos, TRUE); TreeImports.ClientToScreen(&pos); } else { TreeImports.GetWindowRect(&pos); } pt = pos.TopLeft(); } else { // Get item under cursor over = findTreeItem(pt, true); } SetupImportsMenuItems(over); CMenuHandle hSub = hMenuImports.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { - if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) + if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { //wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName); //MessageBox(stringBuffer, L"plugin selection"); pluginActionHandler(menuItem); return; } switch (menuItem) { case ID__INVALIDATE: if(importsHandling.isModule(over)) importsHandling.invalidateModule(over); else importsHandling.invalidateImport(over); break; case ID__DISASSEMBLE: startDisassemblerGui(over); break; case ID__EXPANDALLNODES: importsHandling.expandAllTreeNodes(); break; case ID__COLLAPSEALLNODES: importsHandling.collapseAllTreeNodes(); break; case ID__CUTTHUNK: importsHandling.cutImport(over); break; case ID__DELETETREENODE: importsHandling.cutModule(importsHandling.isImport(over) ? over.GetParent() : over); break; } } updateStatusBar(); } void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt) { if(pt.x == -1 && pt.y == -1) // invoked by keyboard { CRect pos; ListLog.GetWindowRect(&pos); pt = pos.TopLeft(); } CMenuHandle hSub = hMenuLog.GetSubMenu(0); BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { switch (menuItem) { case ID__SAVE: WCHAR selectedFilePath[MAX_PATH]; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt", stringBuffer)) { saveLogToFile(selectedFilePath); } break; case ID__CLEAR: clearOutputLog(); break; } } } void MainGui::appendPluginListToMenu(CMenuHandle hMenu) { - std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); - std::vector &imprecPluginList = PluginLoader::getImprecPluginList(); + std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList(); + std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList(); if (scyllaPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < scyllaPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins"); } if (imprecPluginList.size() > 0) { CMenuHandle newMenu; newMenu.CreatePopupMenu(); for (size_t i = 0; i < imprecPluginList.size(); i++) { newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName); } hMenu.AppendMenu(MF_MENUBARBREAK); hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins"); } } void MainGui::dumpActionHandler() { if(!selectedProcess) return; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; const WCHAR * defExtension; PeDump peDump; if (ProcessAccessHelp::selectedModule) { fileFilter = filterDll; defExtension = L"dll"; } else { fileFilter = filterExe; defExtension = L"exe"; } getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer)) { if (ProcessAccessHelp::selectedModule) { //dump DLL peDump.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr; peDump.sizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize; //get it from gui peDump.entryPoint = EditOEPAddress.GetValue(); wcscpy_s(peDump.fullpath, _countof(peDump.fullpath), ProcessAccessHelp::selectedModule->fullPath); } else { peDump.imageBase = ProcessAccessHelp::targetImageBase; peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage; //get it from gui peDump.entryPoint = EditOEPAddress.GetValue(); wcscpy_s(peDump.fullpath, _countof(peDump.fullpath), selectedProcess->fullPath); } - peDump.useHeaderFromDisk = ConfigurationHolder::getConfigObject(USE_PE_HEADER_FROM_DISK)->isTrue(); + peDump.useHeaderFromDisk = Scylla::config.getConfigObject(USE_PE_HEADER_FROM_DISK)->isTrue(); if (peDump.dumpCompleteProcessToDisk(selectedFilePath)) { - Logger::printfDialog(TEXT("Dump success %s"),selectedFilePath); + Scylla::windowLog.log(L"Dump success %s", selectedFilePath); } else { - Logger::printfDialog(TEXT("Error: Cannot dump image.")); + Scylla::windowLog.log(L"Error: Cannot dump image."); MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR); } } } void MainGui::peRebuildActionHandler() { DWORD newSize = 0; WCHAR selectedFilePath[MAX_PATH]; PeRebuild peRebuild; getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL, stringBuffer)) { - if (ConfigurationHolder::getConfigObject(CREATE_BACKUP)->isTrue()) + if (Scylla::config.getConfigObject(CREATE_BACKUP)->isTrue()) { if (!ProcessAccessHelp::createBackupFile(selectedFilePath)) { - Logger::printfDialog(TEXT("Creating backup file failed %s"), selectedFilePath); + Scylla::windowLog.log(L"Creating backup file failed %s", selectedFilePath); } } LONGLONG fileSize = ProcessAccessHelp::getFileSize(selectedFilePath); LPVOID mapped = peRebuild.createFileMappingViewFull(selectedFilePath); newSize = peRebuild.realignPE(mapped, (DWORD)fileSize); peRebuild.closeAllMappingHandles(); if (newSize < 10) { - Logger::printfDialog(TEXT("Rebuild failed %s"), selectedFilePath); + Scylla::windowLog.log(L"Rebuild failed %s", selectedFilePath); MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR); } else { peRebuild.truncateFile(selectedFilePath, newSize); - Logger::printfDialog(TEXT("Rebuild success %s"), selectedFilePath); - Logger::printfDialog(TEXT("-> Old file size 0x%08X new file size 0x%08X (%d %%)"), (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) ); + Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath); + Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) ); } } } void MainGui::dumpFixActionHandler() { if(!selectedProcess) return; if (TreeImports.GetCount() < 2) { - Logger::printfDialog(TEXT("Nothing to rebuild")); + Scylla::windowLog.log(L"Nothing to rebuild"); return; } WCHAR newFilePath[MAX_PATH]; WCHAR selectedFilePath[MAX_PATH]; const WCHAR * fileFilter; if (ProcessAccessHelp::selectedModule) { fileFilter = filterDll; } else { fileFilter = filterExe; } getCurrentModulePath(stringBuffer, _countof(stringBuffer)); if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL, stringBuffer)) { wcscpy_s(newFilePath,_countof(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, _countof(newFilePath), L"_SCY"); if(extension) { wcscat_s(newFilePath, _countof(newFilePath), extension); } ImportRebuild importRebuild; if (importRebuild.rebuildImportTable(selectedFilePath,newFilePath,importsHandling.moduleList)) { - Logger::printfDialog(TEXT("Import Rebuild success %s"), newFilePath); + Scylla::windowLog.log(L"Import Rebuild success %s", newFilePath); } else { - Logger::printfDialog(TEXT("Import Rebuild failed %s"), selectedFilePath); + 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_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.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::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 && ConfigurationHolder::getConfigObject(DLL_INJECTION_AUTO_UNLOAD)->isTrue()) + if (hMod && Scylla::config.getConfigObject(DLL_INJECTION_AUTO_UNLOAD)->isTrue()) { if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod)) { - Logger::printfDialog(TEXT("DLL unloading failed, target %s"), selectedFilePath); + Scylla::windowLog.log(L"DLL unloading failed, target %s", selectedFilePath); } } if (hMod) { - Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), selectedFilePath); + Scylla::windowLog.log(L"DLL Injection was successful, target %s", selectedFilePath); } else { - Logger::printfDialog(TEXT("DLL Injection failed, target %s"), selectedFilePath); + Scylla::windowLog.log(L"DLL Injection failed, target %s", selectedFilePath); } } } void MainGui::optionsActionHandler() { OptionsGui dlgOptions; dlgOptions.DoModal(); } void MainGui::clearImportsActionHandler() { importsHandling.clearAllImports(); updateStatusBar(); } void MainGui::pluginActionHandler( int menuItem ) { if(!selectedProcess) return; DllInjectionPlugin dllInjectionPlugin; - std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); - std::vector &imprecPluginList = PluginLoader::getImprecPluginList(); + std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList(); + std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList(); menuItem -= PLUGIN_MENU_BASE_ID; dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess; dllInjectionPlugin.apiReader = &apiReader; if (menuItem < (int)scyllaPluginList.size()) { //scylla plugin dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); } else { #ifndef _WIN64 menuItem -= (int)scyllaPluginList.size(); //imprec plugin dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); #endif } importsHandling.scanAndFixModuleList(); importsHandling.displayAllImports(); updateStatusBar(); } bool MainGui::getCurrentModulePath(TCHAR * 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; } diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h index 6c6a199..592ba90 100644 --- a/Scylla/MainGui.h +++ b/Scylla/MainGui.h @@ -1,297 +1,301 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL window frame helpers #include // WTL utility classes #include // WTL enhanced msg map macros #include // WTL controls #include // WTL dialog data exchange #include "multitree.h" #include "hexedit.h" //#define _CRTDBG_MAP_ALLOC //#include //#include //#include #include "Logger.h" #include "ProcessLister.h" #include "IATSearch.h" #include "PickDllGui.h" #include "ImportsHandling.h" class MainGui : public CDialogImpl, public CWinDataExchange, public CDialogResize, public CMessageFilter { public: enum { IDD = IDD_DLG_MAIN }; // Dialog Data eXchange, attaches/subclasses child controls to wrappers // DDX_CONTROL : subclass // DDX_CONTROL_HANDLE : attach BEGIN_DDX_MAP(MainGui) DDX_CONTROL(IDC_TREE_IMPORTS, TreeImportsSubclass) // needed for message reflection DDX_CONTROL(IDC_TREE_IMPORTS, TreeImports) DDX_CONTROL_HANDLE(IDC_CBO_PROCESSLIST, ComboProcessList) DDX_CONTROL_HANDLE(IDC_LIST_LOG, ListLog) DDX_CONTROL(IDC_EDIT_OEPADDRESS, EditOEPAddress) DDX_CONTROL(IDC_EDIT_IATADDRESS, EditIATAddress) DDX_CONTROL(IDC_EDIT_IATSIZE, EditIATSize) END_DDX_MAP() // Our message map // Messages are passed from top to bottom // The first handler that doesn't call SetMsgHandled(FALSE) aborts the chain // If none signals the message as handled, it will be passed to mixins (CHAIN_MSG_MAP) // or ultimately passed to DefWindowProc BEGIN_MSG_MAP_EX(MainGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_DESTROY(OnDestroy) MSG_WM_SIZE(OnSize) MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_COMMAND(OnCommand) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_DBLCLK, OnTreeImportsDoubleClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, TVN_KEYDOWN, OnTreeImportsKeyDown) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_DROPDOWN, OnProcessListDrop) COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_SELENDOK, OnProcessListSelected) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL, OnPickDLL) COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(IDC_BTN_DUMP, OnDump) COMMAND_ID_HANDLER_EX(IDC_BTN_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(IDC_BTN_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(IDC_BTN_IATAUTOSEARCH, OnIATAutoSearch) COMMAND_ID_HANDLER_EX(IDC_BTN_GETIMPORTS, OnGetImports) COMMAND_ID_HANDLER_EX(IDC_BTN_INVALIDIMPORTS, OnInvalidImports) COMMAND_ID_HANDLER_EX(IDC_BTN_SUSPECTIMPORTS, OnSuspectImports) COMMAND_ID_HANDLER_EX(IDC_BTN_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_FILE_DUMP, OnDump) COMMAND_ID_HANDLER_EX(ID_FILE_PEREBUILD, OnPERebuild) COMMAND_ID_HANDLER_EX(ID_FILE_FIXDUMP, OnFixDump) COMMAND_ID_HANDLER_EX(ID_FILE_EXIT, OnExit) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWINVALID, OnInvalidImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWSUSPECT, OnSuspectImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_INVALIDATESELECTED, OnInvalidateSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CUTSELECTED, OnCutSelected) COMMAND_ID_HANDLER_EX(ID_IMPORTS_CLEARIMPORTS, OnClearImports) COMMAND_ID_HANDLER_EX(ID_IMPORTS_SAVETREE, OnSaveTree) COMMAND_ID_HANDLER_EX(ID_IMPORTS_LOADTREE, OnLoadTree) COMMAND_ID_HANDLER_EX(ID_TRACE_AUTOTRACE, OnAutotrace) COMMAND_ID_HANDLER_EX(ID_MISC_DLLINJECTION, OnDLLInject) COMMAND_ID_HANDLER_EX(ID_MISC_OPTIONS, OnOptions) COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) REFLECT_NOTIFY_ID(IDC_TREE_IMPORTS) // pass WM_NOTIFY to child control CHAIN_MSG_MAP(CDialogResize) // Message map for subclassed treeview // CContainedWindow forwards all messages to this map ALT_MSG_MAP(IDC_TREE_IMPORTS) MSG_WM_GETDLGCODE(OnTreeImportsSubclassGetDlgCode) MSG_WM_CHAR(OnTreeImportsSubclassChar) END_MSG_MAP() // Dialog resize 'table' // States if child controls move or resize or center in a specific direction // when the parent dialog is resized BEGIN_DLGRESIZE_MAP(MainGui) DLGRESIZE_CONTROL(IDC_GROUP_ATTACH, DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_CBO_PROCESSLIST, DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_BTN_PICKDLL, DLSZ_MOVE_X) DLGRESIZE_CONTROL(IDC_GROUP_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_TREE_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y) DLGRESIZE_CONTROL(IDC_BTN_INVALIDIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_SUSPECTIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_CLEARIMPORTS, DLSZ_MOVE_X | DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_IATINFO, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_OEPADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_IATADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_STATIC_IATSIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_OEPADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_IATADDRESS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_EDIT_IATSIZE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_IATAUTOSEARCH, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_GETIMPORTS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_ACTIONS, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_AUTOTRACE, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_DUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_DUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_PEREBUILD, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_BTN_FIXDUMP, DLSZ_MOVE_Y) DLGRESIZE_CONTROL(IDC_GROUP_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X) DLGRESIZE_CONTROL(IDC_LIST_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X) END_DLGRESIZE_MAP() MainGui(); - void addTextToOutputLog(const WCHAR * text); + //void addTextToOutputLog(const WCHAR * text); + + //CWindow getLogListboxHandle() const { return ListLog; } protected: // Variables - ProcessLister processLister; + WCHAR stringBuffer[600]; ImportsHandling importsHandling; //ProcessAccessHelp processAccessHelp; ApiReader apiReader; Process * selectedProcess; // File selection filters static const WCHAR filterExe[]; static const WCHAR filterDll[]; static const WCHAR filterExeDll[]; static const WCHAR filterTxt[]; static const WCHAR filterXml[]; // Controls CMultiSelectTreeViewCtrl TreeImports; CComboBox ComboProcessList; CHexEdit EditOEPAddress; CHexEdit EditIATAddress; CHexEdit EditIATSize; CListBox ListLog; CStatusBarCtrl StatusBar; enum StatusParts { PART_COUNT = 0, PART_INVALID, PART_IMAGEBASE, PART_MODULE }; CContainedWindow TreeImportsSubclass; // Handles CIcon hIcon; CMenu hMenuImports; CMenu hMenuLog; CAccelerator accelerators; CIcon hIconCheck; CIcon hIconWarning; CIcon hIconError; static const int MenuImportsOffsetTrace = 2; static const int MenuImportsTraceOffsetScylla = 2; static const int MenuImportsTraceOffsetImpRec = 4; + static const int PLUGIN_MENU_BASE_ID = 0x10; + protected: virtual BOOL PreTranslateMessage(MSG* pMsg); // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnDestroy(); void OnSize(UINT nType, CSize size); void OnContextMenu(CWindow wnd, CPoint point); void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl); // WM_NOTIFY handlers LRESULT OnTreeImportsDoubleClick(const NMHDR* pnmh); LRESULT OnTreeImportsKeyDown(const NMHDR* pnmh); // Forwarded messages from subclassed treeview UINT OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg); void OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags); // WM_COMMAND handlers void OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl); void OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl); void OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl); void OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl); void OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl); void OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl); void OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl); void OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions bool showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter = NULL, const WCHAR * defExtension = NULL, const WCHAR * directory = NULL); void setupStatusBar(); void updateStatusBar(); void fillProcessListComboBox(CComboBox& hCombo); void setIconAndDialogCaption(); void enableDialogControls(BOOL value); CTreeItem findTreeItem(CPoint pt, bool screenCoordinates); // Actions void pickDllActionHandler(); void pickApiActionHandler(CTreeItem item); void processSelectedActionHandler(int index); void showInvalidImportsActionHandler(); void showSuspectImportsActionHandler(); void deleteSelectedImportsActionHandler(); void invalidateSelectedImportsActionHandler(); void loadTreeActionHandler(); void saveTreeActionHandler(); void iatAutosearchActionHandler(); void getImportsActionHandler(); void dumpActionHandler(); void peRebuildActionHandler(); void startDisassemblerGui(CTreeItem selectedTreeNode); void dumpFixActionHandler(); void showAboutDialog(); void dllInjectActionHandler(); void optionsActionHandler(); void clearImportsActionHandler(); void pluginActionHandler(int menuItem); // Popup menu functions void SetupImportsMenuItems(CTreeItem item); void appendPluginListToMenu(CMenuHandle hMenuTrackPopup); void DisplayContextMenuImports(CWindow, CPoint); void DisplayContextMenuLog(CWindow, CPoint); // Log void clearOutputLog(); bool saveLogToFile(const WCHAR * file); // Misc bool getCurrentModulePath(TCHAR * buffer, size_t bufferSize); }; diff --git a/Scylla/NativeWinApi.cpp b/Scylla/NativeWinApi.cpp index 42cda73..b4e1779 100644 --- a/Scylla/NativeWinApi.cpp +++ b/Scylla/NativeWinApi.cpp @@ -1,66 +1,66 @@ #include "NativeWinApi.h" def_NtCreateThreadEx NativeWinApi::NtCreateThreadEx = 0; def_NtDuplicateObject NativeWinApi::NtDuplicateObject = 0; def_NtOpenProcess NativeWinApi::NtOpenProcess = 0; def_NtOpenThread NativeWinApi::NtOpenThread = 0; def_NtQueryObject NativeWinApi::NtQueryObject = 0; def_NtQueryInformationFile NativeWinApi::NtQueryInformationFile = 0; def_NtQueryInformationProcess NativeWinApi::NtQueryInformationProcess = 0; def_NtQueryInformationThread NativeWinApi::NtQueryInformationThread = 0; def_NtQuerySystemInformation NativeWinApi::NtQuerySystemInformation = 0; def_NtResumeThread NativeWinApi::NtResumeThread = 0; def_NtSetInformationThread NativeWinApi::NtSetInformationThread = 0; def_NtTerminateProcess NativeWinApi::NtTerminateProcess = 0; def_RtlNtStatusToDosError NativeWinApi::RtlNtStatusToDosError = 0; void NativeWinApi::initialize() { - HMODULE hModuleNtdll = GetModuleHandle(TEXT("ntdll.dll")); + HMODULE hModuleNtdll = GetModuleHandle(L"ntdll.dll"); if (!hModuleNtdll) { return; } NtCreateThreadEx = (def_NtCreateThreadEx)GetProcAddress(hModuleNtdll, "NtCreateThreadEx"); NtDuplicateObject = (def_NtDuplicateObject)GetProcAddress(hModuleNtdll, "NtDuplicateObject"); NtOpenProcess = (def_NtOpenProcess)GetProcAddress(hModuleNtdll, "NtOpenProcess"); NtOpenThread = (def_NtOpenThread)GetProcAddress(hModuleNtdll, "NtOpenThread"); NtQueryObject = (def_NtQueryObject)GetProcAddress(hModuleNtdll, "NtQueryObject"); NtQueryInformationFile = (def_NtQueryInformationFile)GetProcAddress(hModuleNtdll, "NtQueryInformationFile"); NtQueryInformationProcess = (def_NtQueryInformationProcess)GetProcAddress(hModuleNtdll, "NtQueryInformationProcess"); NtQueryInformationThread = (def_NtQueryInformationThread)GetProcAddress(hModuleNtdll, "NtQueryInformationThread"); NtQuerySystemInformation = (def_NtQuerySystemInformation)GetProcAddress(hModuleNtdll, "NtQuerySystemInformation"); NtResumeThread = (def_NtResumeThread)GetProcAddress(hModuleNtdll, "NtResumeThread"); NtSetInformationThread = (def_NtSetInformationThread)GetProcAddress(hModuleNtdll, "NtSetInformationThread"); NtTerminateProcess = (def_NtTerminateProcess)GetProcAddress(hModuleNtdll, "NtTerminateProcess"); RtlNtStatusToDosError = (def_RtlNtStatusToDosError)GetProcAddress(hModuleNtdll, "RtlNtStatusToDosError"); } PPEB NativeWinApi::getCurrentProcessEnvironmentBlock() { return getProcessEnvironmentBlockAddress(GetCurrentProcess()); } PPEB NativeWinApi::getProcessEnvironmentBlockAddress(HANDLE processHandle) { ULONG lReturnLength = 0; PROCESS_BASIC_INFORMATION processBasicInformation; if ((NtQueryInformationProcess(processHandle,ProcessBasicInformation,&processBasicInformation,sizeof(PROCESS_BASIC_INFORMATION),&lReturnLength) >= 0) && (lReturnLength == sizeof(PROCESS_BASIC_INFORMATION))) { //printf("NtQueryInformationProcess success %d\n",sizeof(PROCESS_BASIC_INFORMATION)); return processBasicInformation.PebBaseAddress; } else { //printf("NtQueryInformationProcess failed %d vs %d\n",lReturnLength,sizeof(PROCESS_BASIC_INFORMATION)); return 0; } } \ No newline at end of file diff --git a/Scylla/OptionsGui.cpp b/Scylla/OptionsGui.cpp index fb035ca..f29cb36 100644 --- a/Scylla/OptionsGui.cpp +++ b/Scylla/OptionsGui.cpp @@ -1,89 +1,89 @@ #include "OptionsGui.h" -#include "ConfigurationHolder.h" +#include "Scylla.h" BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { loadOptions(); DoDataExchange(DDX_LOAD); // show settings EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME); CenterWindow(); return TRUE; } void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { DoDataExchange(DDX_SAVE); saveOptions(); - ConfigurationHolder::saveConfiguration(); + Scylla::config.saveConfiguration(); EndDialog(0); } void OptionsGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void OptionsGui::saveOptions() { std::map::iterator mapIter; - for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++) + for (mapIter = Scylla::config.getConfigList().begin() ; mapIter != Scylla::config.getConfigList().end(); mapIter++) { switch(mapIter->first) { case USE_PE_HEADER_FROM_DISK: usePEHeaderFromDisk ? mapIter->second.setTrue() : mapIter->second.setFalse(); break; case DEBUG_PRIVILEGE: debugPrivilege ? mapIter->second.setTrue() : mapIter->second.setFalse(); break; case CREATE_BACKUP: createBackup ? mapIter->second.setTrue() : mapIter->second.setFalse(); break; case DLL_INJECTION_AUTO_UNLOAD: dllInjectionAutoUnload ? mapIter->second.setTrue() : mapIter->second.setFalse(); break; case UPDATE_HEADER_CHECKSUM: updateHeaderChecksum ? mapIter->second.setTrue() : mapIter->second.setFalse(); break; case IAT_SECTION_NAME: wcscpy_s(mapIter->second.valueString, _countof(mapIter->second.valueString), iatSectionName); break; } } } void OptionsGui::loadOptions() { std::map::iterator mapIter; - for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++) + for (mapIter = Scylla::config.getConfigList().begin() ; mapIter != Scylla::config.getConfigList().end(); mapIter++) { switch(mapIter->first) { case USE_PE_HEADER_FROM_DISK: usePEHeaderFromDisk = mapIter->second.isTrue(); break; case DEBUG_PRIVILEGE: debugPrivilege = mapIter->second.isTrue(); break; case CREATE_BACKUP: createBackup = mapIter->second.isTrue(); break; case DLL_INJECTION_AUTO_UNLOAD: dllInjectionAutoUnload = mapIter->second.isTrue(); break; case UPDATE_HEADER_CHECKSUM: updateHeaderChecksum = mapIter->second.isTrue(); break; case IAT_SECTION_NAME: wcsncpy_s(iatSectionName, _countof(iatSectionName), mapIter->second.valueString, _countof(iatSectionName)-1); iatSectionName[_countof(iatSectionName)-1] = L'\0'; break; } } } diff --git a/Scylla/PeDump.cpp b/Scylla/PeDump.cpp index 84c9e4d..27aab73 100644 --- a/Scylla/PeDump.cpp +++ b/Scylla/PeDump.cpp @@ -1,437 +1,437 @@ #include "PeDump.h" #include "ProcessAccessHelp.h" -#include "Logger.h" -#include "definitions.h" +#include "Scylla.h" +#include "Architecture.h" bool PeDump::useHeaderFromDisk = true; bool PeDump::appendOverlayData = true; //#define DEBUG_COMMENTS bool PeDump::fillPeHeaderStructs(bool fromDisk) { DWORD dwSize = ProcessAccessHelp::PE_HEADER_BYTES_COUNT; if (dwSize > sizeOfImage) { dwSize = (DWORD)sizeOfImage; } headerData = new BYTE[dwSize]; if (!headerData) return false; if (fromDisk) { //from disk if (!ProcessAccessHelp::readHeaderFromFile(headerData, dwSize, fullpath)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"fillPeHeaderStructs -> ProcessAccessHelp::readHeaderFromFile failed - %X %s\r\n", dwSize, fullpath); + Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readHeaderFromFile failed - %X %s", dwSize, fullpath); #endif return false; } } else { //from memory if (!ProcessAccessHelp::readMemoryFromProcess(imageBase, dwSize, headerData)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("fillPeHeaderStructs -> ProcessAccessHelp::readMemoryFromProcess failed - ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %X ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),imageBase, dwSize, headerData); + Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readMemoryFromProcess failed - " PRINTF_DWORD_PTR_FULL L" %X " PRINTF_DWORD_PTR_FULL, imageBase, dwSize, headerData); #endif return false; } } pDOSHeader = (PIMAGE_DOS_HEADER)headerData; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)headerData + (DWORD_PTR)pDOSHeader->e_lfanew); pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader); return true; } bool PeDump::validateHeaders() { if ((pDOSHeader != 0) && (pDOSHeader->e_magic == IMAGE_DOS_SIGNATURE) && (pNTHeader->Signature == IMAGE_NT_SIGNATURE)) { #ifdef _WIN64 if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) #else if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) #endif { return true; } else { return false; } } else { return false; } } bool PeDump::dumpCompleteProcessToDisk(const WCHAR * dumpFilePath) { if (!fillPeHeaderStructs(useHeaderFromDisk)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("dumpCompleteProcessToDisk -> fillPeHeaderStructs failed\r\n"); + Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> fillPeHeaderStructs failed"); #endif return false; } if (!validateHeaders()) { #ifdef DEBUG_COMMENTS - Logger::debugLog("dumpCompleteProcessToDisk -> validateHeaders failed\r\n"); + Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> validateHeaders failed"); #endif return false; } dumpData = new BYTE[sizeOfImage]; if (dumpData) { if (!ProcessAccessHelp::readMemoryFromProcess(imageBase,sizeOfImage,dumpData)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("dumpCompleteProcessToDisk -> readMemoryFromProcess failed\r\n"); + Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> readMemoryFromProcess failed"); #endif return false; } else { fixDump(dumpData); if (saveDumpToDisk(dumpFilePath, dumpData, (DWORD)sizeOfImage)) { if (appendOverlayData) { appendOverlayDataToDump(dumpFilePath); } //printf("dump success\n"); return true; } else { return false; } } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("dumpCompleteProcessToDisk -> new BYTE[sizeOfImage] failed %X\r\n",sizeOfImage); + Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> new BYTE[sizeOfImage] failed %X", sizeOfImage); #endif return false; } } bool PeDump::appendOverlayDataToDump(const WCHAR *dumpFilePath) { DWORD_PTR offset = 0; DWORD size = 0; if (getOverlayData(fullpath,&offset,&size)) { if (offset == 0) { #ifdef DEBUG_COMMENTS - Logger::debugLog("appendOverlayDataToDump :: No overlay exists\r\n"); + Scylla::debugLog.log(L"appendOverlayDataToDump :: No overlay exists"); #endif return true; } else { if (copyFileDataFromOffset(fullpath, dumpFilePath, offset, size)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("appendOverlayDataToDump :: appending overlay success\r\n"); + Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay success"); #endif return true; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("appendOverlayDataToDump :: appending overlay failed\r\n"); + Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay failed"); #endif return false; } } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("appendOverlayDataToDump :: getOverlayData failed\r\n"); + Scylla::debugLog.log(L"appendOverlayDataToDump :: getOverlayData failed"); #endif return false; } } bool PeDump::copyFileDataFromOffset(const WCHAR * sourceFile, const WCHAR * destFile, DWORD_PTR fileOffset, DWORD dwSize) { HANDLE hSourceFile, hDestFile; BYTE * dataBuffer = 0; bool retValue = false; hSourceFile = CreateFile(sourceFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hSourceFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("copyFileDataFromOffset :: failed to open source file\r\n"); + Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open source file"); #endif return false; } hDestFile = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(hSourceFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("copyFileDataFromOffset :: failed to open destination file\r\n"); + Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open destination file"); #endif CloseHandle(hSourceFile); return false; } dataBuffer = new BYTE[dwSize]; if (ProcessAccessHelp::readMemoryFromFile(hSourceFile, (LONG)fileOffset, dwSize, dataBuffer)) { if (ProcessAccessHelp::writeMemoryToFileEnd(hDestFile,dwSize,dataBuffer)) { retValue = true; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("copyFileDataFromOffset :: writeMemoryToFileEnd failed\r\n"); + Scylla::debugLog.log(L"copyFileDataFromOffset :: writeMemoryToFileEnd failed"); #endif retValue = false; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("copyFileDataFromOffset :: readMemoryFromFile failed to read from source file\r\n"); + Scylla::debugLog.log(L"copyFileDataFromOffset :: readMemoryFromFile failed to read from source file"); #endif retValue = false; } delete [] dataBuffer; CloseHandle(hSourceFile); CloseHandle(hDestFile); return retValue; } void PeDump::fixDump(BYTE * dumpBuffer) { int counter = 0; PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)dumpBuffer; PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD_PTR)dumpBuffer + pDos->e_lfanew); PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(pNt); fixNtHeaderForDump(pNt, pNTHeader); do { fixSectionHeaderForDump(pSec, pSectionHeader); pSectionHeader++; pSec++; counter++; } while (counter < pNt->FileHeader.NumberOfSections); } void PeDump::fixBadNtHeaderValues(PIMAGE_NT_HEADERS pNtHead) { //maybe imagebase in process is not real imagebase pNtHead->OptionalHeader.ImageBase = imageBase; pNtHead->OptionalHeader.AddressOfEntryPoint = (DWORD)(entryPoint - imageBase); pNtHead->OptionalHeader.SizeOfImage = sizeOfImage; } void PeDump::fixSectionHeaderForDump(PIMAGE_SECTION_HEADER oldSecHead, PIMAGE_SECTION_HEADER newSecHead) { memcpy_s(oldSecHead->Name, IMAGE_SIZEOF_SHORT_NAME, newSecHead->Name, IMAGE_SIZEOF_SHORT_NAME); oldSecHead->Characteristics = newSecHead->Characteristics; oldSecHead->Misc.VirtualSize = newSecHead->Misc.VirtualSize; oldSecHead->VirtualAddress = newSecHead->VirtualAddress; oldSecHead->SizeOfRawData = newSecHead->Misc.VirtualSize; oldSecHead->PointerToRawData = newSecHead->VirtualAddress; } void PeDump::fixNtHeaderForDump(PIMAGE_NT_HEADERS oldNtHead, PIMAGE_NT_HEADERS newNtHead) { //some special fixBadNtHeaderValues(newNtHead); //fix FileHeader oldNtHead->FileHeader.NumberOfSections = newNtHead->FileHeader.NumberOfSections; //fix OptionalHeader oldNtHead->OptionalHeader.ImageBase = newNtHead->OptionalHeader.ImageBase; oldNtHead->OptionalHeader.SizeOfImage = newNtHead->OptionalHeader.SizeOfImage; oldNtHead->OptionalHeader.BaseOfCode = newNtHead->OptionalHeader.BaseOfCode; oldNtHead->OptionalHeader.AddressOfEntryPoint = newNtHead->OptionalHeader.AddressOfEntryPoint; oldNtHead->OptionalHeader.SectionAlignment = newNtHead->OptionalHeader.SectionAlignment; oldNtHead->OptionalHeader.FileAlignment = newNtHead->OptionalHeader.SectionAlignment; //deleted in x64 PE #ifndef _WIN64 oldNtHead->OptionalHeader.BaseOfData = newNtHead->OptionalHeader.BaseOfData; #endif } bool PeDump::saveDumpToDisk(const WCHAR * dumpFilePath, BYTE *dumpBuffer, DWORD dumpSize) { DWORD lpNumberOfBytesWritten = 0; bool retValue = false; HANDLE hFile = CreateFile(dumpFilePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hFile == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("saveDumpToDisk :: INVALID_HANDLE_VALUE %u\r\n",GetLastError()); + Scylla::debugLog.log(L"saveDumpToDisk :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif retValue = false; } else { if (WriteFile(hFile, dumpBuffer, dumpSize, &lpNumberOfBytesWritten, 0)) { if (lpNumberOfBytesWritten != dumpSize) { #ifdef DEBUG_COMMENTS - Logger::debugLog("saveDumpToDisk :: lpNumberOfBytesWritten != dumpSize %d %d\r\n",lpNumberOfBytesWritten,dumpSize); + Scylla::debugLog.log(L"saveDumpToDisk :: lpNumberOfBytesWritten != dumpSize %d %d", lpNumberOfBytesWritten,dumpSize); #endif retValue = false; } else { retValue = true; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog("saveDumpToDisk :: WriteFile failed %u\r\n",GetLastError()); + Scylla::debugLog.log(L"saveDumpToDisk :: WriteFile failed %u",GetLastError()); #endif retValue = false; } CloseHandle(hFile); } return retValue; } bool PeDump::getOverlayData(const WCHAR * filepath, DWORD_PTR * overlayFileOffset, DWORD * overlaySize) { LONGLONG fileSize = 0; DWORD dwSize = 0; DWORD bufferSize = 1000; BYTE *buffer = 0; bool returnValue = 0; PIMAGE_DOS_HEADER pDOSh = 0; PIMAGE_NT_HEADERS pNTh = 0; PIMAGE_SECTION_HEADER pSech = 0; int counter = 0; DWORD calcSize = 0; HANDLE hFile = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if( hFile == INVALID_HANDLE_VALUE ) { #ifdef DEBUG_COMMENTS - Logger::debugLog("getOverlayData :: INVALID_HANDLE_VALUE %u\r\n",GetLastError()); + Scylla::debugLog.log(L"getOverlayData :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif returnValue = false; } else { fileSize = ProcessAccessHelp::getFileSize(hFile); if (fileSize > 0) { if (fileSize > bufferSize) { dwSize = bufferSize; } else { dwSize = (DWORD)(fileSize - 1); } buffer = new BYTE[dwSize]; if (ProcessAccessHelp::readMemoryFromFile(hFile, 0, dwSize, buffer)) { pDOSh = (PIMAGE_DOS_HEADER)buffer; pNTh = (PIMAGE_NT_HEADERS)((DWORD_PTR)buffer + pDOSh->e_lfanew); //first section pSech = IMAGE_FIRST_SECTION(pNTh); counter = 1; //get last section while(counter < pNTh->FileHeader.NumberOfSections) { counter++; pSech++; } //printf("PointerToRawData %X\nSizeOfRawData %X\nfile size %X\n",pSech->PointerToRawData,pSech->SizeOfRawData,pSech->PointerToRawData+pSech->SizeOfRawData); calcSize = pSech->PointerToRawData + pSech->SizeOfRawData; if (calcSize < fileSize) { //overlay found *overlayFileOffset = calcSize; *overlaySize = (DWORD)(fileSize - calcSize); } else { *overlayFileOffset = 0; *overlaySize = 0; } returnValue = true; } else { returnValue = false; } delete [] buffer; } else { returnValue = false; } CloseHandle(hFile); } return returnValue; } \ No newline at end of file diff --git a/Scylla/PeRebuild.cpp b/Scylla/PeRebuild.cpp index 14be173..a8106af 100644 --- a/Scylla/PeRebuild.cpp +++ b/Scylla/PeRebuild.cpp @@ -1,736 +1,736 @@ #include "PeRebuild.h" #include #pragma comment(lib,"imagehlp.lib") #include "ProcessAccessHelp.h" -#include "Logger.h" -#include "ConfigurationHolder.h" +#include "Scylla.h" +//#include "ConfigurationHolder.h" //#define DEBUG_COMMENTS bool PeRebuild::truncateFile(WCHAR * szFilePath, DWORD dwNewFsize) { bool retValue = true; HANDLE hFile = CreateFile(szFilePath,GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { return false; } if (SetFilePointer(hFile, dwNewFsize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { if (GetLastError() == NO_ERROR) { retValue = true; } else { retValue = false; } } else { retValue = true; } if (!SetEndOfFile(hFile)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("SetEndOfFile failed error %d\r\n", GetLastError()); + Scylla::debugLog.log(L"SetEndOfFile failed error %d", GetLastError()); #endif retValue = false; } CloseHandle(hFile); return retValue; } DWORD PeRebuild::validAlignment(DWORD BadSize) { div_t DivRes; DivRes = div(BadSize, FileAlignmentConstant); if (DivRes.rem == 0) return BadSize; return ((DivRes.quot+1) * FileAlignmentConstant); } DWORD PeRebuild::validAlignmentNew(DWORD badAddress) { DWORD moduloResult = badAddress % FileAlignmentConstant; if (moduloResult) { return (FileAlignmentConstant - moduloResult); } else { return 0; } } bool PeRebuild::isRoundedTo(DWORD_PTR dwTarNum, DWORD_PTR dwRoundNum) { return (dwTarNum % dwRoundNum) == 0; // WTF: /* #ifdef _WIN64 lldiv_t d; d = div((__int64)dwTarNum, (__int64)dwRoundNum); #else ldiv_t d; d = div((long)dwTarNum, (long)dwRoundNum); #endif return (d.rem == 0); */ } void PeRebuild::cleanSectionPointer() { if (pSections) { for (int j = 0; j < MAX_SEC_NUM; j++) { if (pSections[j]) { free(pSections[j]); pSections[j] = 0; } } } } DWORD PeRebuild::realignPE(LPVOID AddressOfMapFile, DWORD dwFsize) { PIMAGE_DOS_HEADER pDosh = 0; PIMAGE_NT_HEADERS pPeh = 0; PIMAGE_SECTION_HEADER pSectionh = 0; int i = 0; DWORD extraAlign = 0; ZeroMemory(&pSections, sizeof(pSections)); // get the other parameters pMap = AddressOfMapFile; dwMapBase = (DWORD_PTR)pMap; if (dwFsize == 0 || pMap == NULL) return 1; // access the PE Header and check whether it's a valid one pDosh = (PIMAGE_DOS_HEADER)(pMap); pPeh = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh+pDosh->e_lfanew); if (!validatePeHeaders(pDosh)) { return 0; } if (pPeh->FileHeader.NumberOfSections > MAX_SEC_NUM) { return 3; } __try { /* START */ pPeh->OptionalHeader.FileAlignment = FileAlignmentConstant; /* Realign the PE Header */ // get the size of all headers dwTmpNum = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pPeh->FileHeader.SizeOfOptionalHeader + (pPeh->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); // kill room between the "win32 pls" message and the PE signature // find the end of the message pW = (WORD*)(dwMapBase + ScanStartDS); while (*pW != 0 || (!isRoundedTo((DWORD_PTR)pW, 0x10))) { pW = (WORD*)((DWORD_PTR)pW + 1); } wTmpNum = (WORD)((DWORD_PTR)pW - dwMapBase); if (wTmpNum < pDosh->e_lfanew) { CopyMemory((LPVOID)pW,(VOID*)pPeh,dwTmpNum); // copy the Header to the right place pDosh->e_lfanew = wTmpNum; } dwSectionBase = validAlignment(dwTmpNum + pDosh->e_lfanew); pPeh = (PIMAGE_NT_HEADERS)(dwMapBase + pDosh->e_lfanew); // because the NT header moved // correct the SizeOfHeaders pPeh->OptionalHeader.SizeOfHeaders = dwSectionBase; /* Realign all sections */ // make a copy of all sections // this is needed if the sections aren't sorted by their RawOffset (e.g. Petite) pSectionh = IMAGE_FIRST_SECTION(pPeh); for (i=0; iFileHeader.NumberOfSections; i++) { if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0) { ++pSectionh; continue; } // get a valid size dwTmpNum = pSectionh->SizeOfRawData; if ((pSectionh->SizeOfRawData + pSectionh->PointerToRawData) > dwFsize) { dwTmpNum = dwFsize - pSectionh->PointerToRawData; } //dwTmpNum -= 1; // copy the section into some memory // limit max section size to 300 MB = 300000 KB = 300000000 B if (dwTmpNum > 300000000) { dwTmpNum = 300000000; } //because of validAlignment we need some extra space, max 0x200 extra extraAlign = validAlignmentNew(dwTmpNum); pSections[i] = malloc(dwTmpNum + extraAlign); ZeroMemory(pSections[i], dwTmpNum + extraAlign); if (pSections[i] == NULL) // fatal error !!! { #ifdef DEBUG_COMMENTS - Logger::debugLog("realignPE :: malloc failed with dwTmpNum %08X %08X\r\n", dwTmpNum, extraAlign); + Scylla::debugLog.log(L"realignPE :: malloc failed with dwTmpNum %08X %08X", dwTmpNum, extraAlign); #endif cleanSectionPointer(); return 4; } CopyMemory(pSections[i],(LPVOID)(pSectionh->PointerToRawData+dwMapBase),dwTmpNum); ++pSectionh; } // start realigning the sections pSectionh = IMAGE_FIRST_SECTION(pPeh); for (i=0;iFileHeader.NumberOfSections;i++) { // some anti crash code :P if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0) { ++pSectionh; if (pSectionh->PointerToRawData == 0) { continue; } pSectionh->PointerToRawData = dwSectionBase; continue; } // let pCH point to the end of the current section if ((pSectionh->PointerToRawData+pSectionh->SizeOfRawData) <= dwFsize) { pCH = (char*)(dwMapBase+pSectionh->PointerToRawData+pSectionh->SizeOfRawData-1); } else { pCH = (char*)(dwMapBase+dwFsize-1); } // look for the end of this section while (*pCH == 0) { --pCH; } // calculate the new RawSize dwTmpNum = (DWORD)(((DWORD_PTR)pCH - dwMapBase) + MinSectionTerm - pSectionh->PointerToRawData); if (dwTmpNum < pSectionh->SizeOfRawData) { pSectionh->SizeOfRawData = dwTmpNum; } else // the new size is too BIG { dwTmpNum = pSectionh->SizeOfRawData; } // copy the section to the new place if (i != pPeh->FileHeader.NumberOfSections-1) { dwTmpNum = validAlignment(dwTmpNum); } CopyMemory((LPVOID)(dwMapBase+dwSectionBase), pSections[i], dwTmpNum); // set the RawOffset pSectionh->PointerToRawData = dwSectionBase; // get the RawOffset for the next section dwSectionBase = dwTmpNum+dwSectionBase; // the last section doesn't need to be aligned // go to the next section ++pSectionh; } // delete bound import directories because it is destroyed if present pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; // clean up cleanSectionPointer(); } __except(1) { // clean up cleanSectionPointer(); #ifdef DEBUG_COMMENTS - Logger::debugLog("realignPE :: Exception occured\r\n"); + Scylla::debugLog.log(L"realignPE :: Exception occured"); #endif return 0; } - if (ConfigurationHolder::getConfigObject(UPDATE_HEADER_CHECKSUM)->isTrue()) + if (Scylla::config.getConfigObject(UPDATE_HEADER_CHECKSUM)->isTrue()) { updatePeHeaderChecksum(AddressOfMapFile, dwSectionBase); } return dwSectionBase; // return the new filesize } // returns: // -1 - access violation // -2 - no relocation found // -3 - no own section // -4 - dll characteristics found // -5 - invalid PE file // else the new raw size DWORD PeRebuild::wipeReloc(void* pMap, DWORD dwFsize) { PIMAGE_DOS_HEADER pDosH; PIMAGE_NT_HEADERS pNTH; PIMAGE_SECTION_HEADER pSecH; PIMAGE_SECTION_HEADER pSH, pSH2; DWORD dwRelocRVA, i; BOOL bOwnSec = FALSE; DWORD dwNewFsize; __try // =) { // get pe header pointers pDosH = (PIMAGE_DOS_HEADER)pMap; if (pDosH->e_magic != IMAGE_DOS_SIGNATURE) return -5; pNTH = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosH + pDosH->e_lfanew); if (pNTH->Signature != IMAGE_NT_SIGNATURE) return -5; pSecH = IMAGE_FIRST_SECTION(pNTH); // has PE dll characteristics ? if (pNTH->FileHeader.Characteristics & IMAGE_FILE_DLL) return -4; // is there a reloc section ? dwRelocRVA = pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; if (!dwRelocRVA) return -2; // check whether the relocation has an own section pSH = pSecH; for (i=0; i < pNTH->FileHeader.NumberOfSections; i++) { if (pSH->VirtualAddress == dwRelocRVA) { bOwnSec = TRUE; break; // pSH -> reloc section header and i == section index } ++pSH; } if (!bOwnSec) return -3; if (i+1 == pNTH->FileHeader.NumberOfSections) { //--- relocation is the last section --- // truncate at the start of the reloc section dwNewFsize = pSH->PointerToRawData; } else { //--- relocation isn't the last section --- dwNewFsize = dwFsize - pSH->SizeOfRawData; //-> copy the section(s) after the relocation to the start of the relocation pSH2 = pSH; ++pSH2; // pSH2 -> pointer to first section after relocation memcpy( (void*)(pSH->PointerToRawData + (DWORD)pMap), (const void*)(pSH2->PointerToRawData + (DWORD)pMap), dwFsize - pSH2->PointerToRawData); //-> fix the section headers // (pSH -> reloc section header) // (pSH2 -> first section after reloc section) for (++i; i < pNTH->FileHeader.NumberOfSections; i++) { // apply important values pSH->SizeOfRawData = pSH2->SizeOfRawData; pSH->VirtualAddress = pSH2->VirtualAddress; pSH->Misc.VirtualSize = pSH2->Misc.VirtualSize; // apply section name memcpy( (void*)(pSH->Name), (const void*)(pSH2->Name), sizeof(pSH2->Name)); ++pSH; ++pSH2; } } // dec section number --pNTH->FileHeader.NumberOfSections; // kill reloc directory entry pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; // fix virtual parts of the PE Header (a must for win2k) pSH2 = pSH = pSecH; ++pSH2; for (i=0; i < (DWORD)pNTH->FileHeader.NumberOfSections-1; i++) { pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress; ++pSH; ++pSH2; } // (pSH -> pointer to last section) if (pSH->Misc.PhysicalAddress) pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->Misc.VirtualSize; else // WATCOM is always a bit special >:-) pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->SizeOfRawData; } __except(1) { // an access violation occurred :( return -1; } return dwNewFsize; } bool PeRebuild::validatePE(void* pPEImage, DWORD dwFileSize) { PIMAGE_NT_HEADERS pNTh; PIMAGE_SECTION_HEADER pSech,pSH, pSH2, pLastSH; UINT i; DWORD dwHeaderSize; // get PE base information pNTh = ImageNtHeader(pPEImage); if (!pNTh) return FALSE; pSech = IMAGE_FIRST_SECTION(pNTh); // FIX: // ... the SizeOfHeaders pSH = pSech; dwHeaderSize = 0xFFFFFFFF; for(i=0; i < pNTh->FileHeader.NumberOfSections; i++) { if (pSH->PointerToRawData && pSH->PointerToRawData < dwHeaderSize) { dwHeaderSize = pSH->PointerToRawData; } ++pSH; } pNTh->OptionalHeader.SizeOfHeaders = dwHeaderSize; // ...Virtual Sizes pSH2 = pSH = pSech; ++pSH2; for (i=0; i < (DWORD)pNTh->FileHeader.NumberOfSections-1; i++) { pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress; ++pSH; ++pSH2; } // (pSH -> pointer to last section) pLastSH = pSH; // ...RawSize of the last section pLastSH->SizeOfRawData = dwFileSize - pLastSH->PointerToRawData; // ...SizeOfImage if (pLastSH->Misc.PhysicalAddress) { pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->Misc.VirtualSize; } else // WATCOM is always a bit special >:-) { pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->SizeOfRawData; } return true; } ReBaseErr PeRebuild::reBasePEImage(void* pPE, DWORD_PTR dwNewBase) { PIMAGE_NT_HEADERS pNT; PIMAGE_RELOCATION pR; ReBaseErr ret; DWORD_PTR dwDelta; DWORD *pdwAddr, dwRva, dwType; UINT iItems, i; WORD *pW; // dwNewBase valid ? if (dwNewBase & 0xFFFF) { ret = RB_INVALIDNEWBASE; goto Exit; // ERR } // // get relocation dir ptr // pNT = ImageNtHeader(pPE); if (!pNT) { ret = RB_INVALIDPE; goto Exit; // ERR } // new base = old base ? if (pNT->OptionalHeader.ImageBase == dwNewBase) { ret = RB_OK; goto Exit; // OK } if (!pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { ret = RB_NORELOCATIONINFO; goto Exit; // ERR } pR = (PIMAGE_RELOCATION)ImageRvaToVa( pNT, pPE, pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, NULL); if (!pR) { ret = RB_INVALIDRVA; goto Exit; // ERR } // // add delta to relocation items // dwDelta = dwNewBase - pNT->OptionalHeader.ImageBase; __try { do { // get number of items if (pR->SymbolTableIndex) iItems = (pR->SymbolTableIndex - 8) / 2; else break; // no items in this block // trace/list block items... pW = (WORD*)((DWORD_PTR)pR + 8); for (i = 0; i < iItems; i++) { dwRva = (*pW & 0xFFF) + pR->VirtualAddress; dwType = *pW >> 12; if (dwType != 0) // fully compatible ??? { // add delta pdwAddr = (PDWORD)ImageRvaToVa( pNT, pPE, dwRva, NULL); if (!pdwAddr) { ret = RB_INVALIDRVA; goto Exit; // ERR } *pdwAddr += dwDelta; } // next item ++pW; } pR = (PIMAGE_RELOCATION)pW; // pR -> next block header } while ( *(DWORD*)pW ); } __except(EXCEPTION_EXECUTE_HANDLER) { ret = RB_ACCESSVIOLATION; goto Exit; // ERR } // apply new base to header pNT->OptionalHeader.ImageBase = dwNewBase; ret = RB_OK; // OK Exit: return ret; } bool PeRebuild::updatePeHeaderChecksum(LPVOID AddressOfMapFile, DWORD dwFsize) { PIMAGE_NT_HEADERS32 pNTHeader32 = 0; PIMAGE_NT_HEADERS64 pNTHeader64 = 0; DWORD headerSum = 0; DWORD checkSum = 0; pNTHeader32 = (PIMAGE_NT_HEADERS32)CheckSumMappedFile(AddressOfMapFile, dwFsize, &headerSum, &checkSum); if (!pNTHeader32) { #ifdef DEBUG_COMMENTS - Logger::debugLog("updatePeHeaderChecksum :: CheckSumMappedFile failed error %X\r\n", GetLastError()); + Scylla::debugLog.log(L"updatePeHeaderChecksum :: CheckSumMappedFile failed error %X", GetLastError()); #endif return false; } #ifdef DEBUG_COMMENTS - Logger::debugLog("Old checksum %08X new checksum %08X\r\n",headerSum,checkSum); + Scylla::debugLog.log(L"Old checksum %08X new checksum %08X", headerSum, checkSum); #endif if (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader32; pNTHeader64->OptionalHeader.CheckSum = checkSum; } else { pNTHeader32->OptionalHeader.CheckSum = checkSum; } return true; } LPVOID PeRebuild::createFileMappingViewFull(const WCHAR * filePath) { hFileToMap = CreateFile(filePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if( hFileToMap == INVALID_HANDLE_VALUE ) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n",GetLastError()); + Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError()); #endif hMappedFile = 0; hFileToMap = 0; addrMappedDll = 0; return NULL; } hMappedFile = CreateFileMapping(hFileToMap, 0, PAGE_READWRITE, 0, 0, NULL); if( hMappedFile == NULL ) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMappingViewFull :: hMappedFile == NULL\r\n"); + Scylla::debugLog.log(L"createFileMappingViewFull :: hMappedFile == NULL"); #endif CloseHandle(hFileToMap); hMappedFile = 0; hFileToMap = 0; addrMappedDll = 0; return NULL; } if (GetLastError() == ERROR_ALREADY_EXISTS) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n"); + Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS"); #endif CloseHandle(hFileToMap); hMappedFile = 0; hFileToMap = 0; addrMappedDll = 0; return NULL; } addrMappedDll = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(!addrMappedDll) { #ifdef DEBUG_COMMENTS - Logger::debugLog("createFileMappingView :: addrMappedDll == NULL\r\n"); + Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL"); #endif CloseHandle(hFileToMap); CloseHandle(hMappedFile); hMappedFile = 0; hFileToMap = 0; return NULL; } return addrMappedDll; } void PeRebuild::closeAllMappingHandles() { if (addrMappedDll) { if (!FlushViewOfFile(addrMappedDll, 0)) { #ifdef DEBUG_COMMENTS - Logger::debugLog("closeAllMappingHandles :: Could not flush memory to disk (%d)\r\n", GetLastError()); + Scylla::debugLog.log(L"closeAllMappingHandles :: Could not flush memory to disk (%d)", GetLastError()); #endif } UnmapViewOfFile(addrMappedDll); addrMappedDll = 0; } if (hMappedFile) { CloseHandle(hMappedFile); hMappedFile = 0; } if (hFileToMap) { CloseHandle(hFileToMap); hFileToMap = 0; } } bool PeRebuild::validatePeHeaders( PIMAGE_DOS_HEADER pDosh ) { PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh + pDosh->e_lfanew); if ((pDosh != 0) && (pDosh->e_magic == IMAGE_DOS_SIGNATURE) && (pNTHeader->Signature == IMAGE_NT_SIGNATURE)) { #ifdef _WIN64 if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) #else if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) #endif { return true; } else { return false; } } else { return false; } } diff --git a/Scylla/PluginLoader.cpp b/Scylla/PluginLoader.cpp index c8c8a8c..f39a829 100644 --- a/Scylla/PluginLoader.cpp +++ b/Scylla/PluginLoader.cpp @@ -1,373 +1,361 @@ #include "PluginLoader.h" #include "Logger.h" #include "ProcessAccessHelp.h" +#include +#include -std::vector PluginLoader::scyllaPluginList; -std::vector PluginLoader::imprecPluginList; -WCHAR PluginLoader::dirSearchString[MAX_PATH]; -WCHAR PluginLoader::baseDirPath[MAX_PATH]; -WCHAR PluginLoader::imprecWrapperDllPath[MAX_PATH]; +const WCHAR PluginLoader::PLUGIN_DIR[] = L"Plugins\\"; +const WCHAR PluginLoader::PLUGIN_SEARCH_STRING[] = L"*.dll"; +const WCHAR PluginLoader::PLUGIN_IMPREC_DIR[] = L"ImpRec_Plugins\\"; +const WCHAR PluginLoader::PLUGIN_IMPREC_WRAPPER_DLL[] = L"Imprec_Wrapper_DLL.dll"; //#define DEBUG_COMMENTS std::vector & PluginLoader::getScyllaPluginList() { return scyllaPluginList; } std::vector & PluginLoader::getImprecPluginList() { return imprecPluginList; } bool PluginLoader::findAllPlugins() { if (!scyllaPluginList.empty()) { scyllaPluginList.clear(); } if (!imprecPluginList.empty()) { imprecPluginList.clear(); } if (!buildSearchString()) { return false; } if (!searchForPlugin(scyllaPluginList, dirSearchString, true)) { return false; } #ifndef _WIN64 if (!buildSearchStringImprecPlugins()) { return false; } if (!searchForPlugin(imprecPluginList, dirSearchString, false)) { return false; } #endif return true; } bool PluginLoader::searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin) { WIN32_FIND_DATA ffd; HANDLE hFind = 0; DWORD dwError = 0; Plugin pluginData; hFind = FindFirstFile(searchPath, &ffd); dwError = GetLastError(); if (dwError == ERROR_FILE_NOT_FOUND) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findAllPlugins :: No files found\r\n"); + Scylla::debugLog.log(L"findAllPlugins :: No files found"); #endif return true; } if (hFind == INVALID_HANDLE_VALUE) { #ifdef DEBUG_COMMENTS - Logger::debugLog("findAllPlugins :: FindFirstFile failed %d\r\n", dwError); + Scylla::debugLog.log(L"findAllPlugins :: FindFirstFile failed %d", dwError); #endif return false; } do { if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { if ((ffd.nFileSizeHigh != 0) || (ffd.nFileSizeLow < 200)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("findAllPlugins :: Plugin invalid file size: %s\r\n"), ffd.cFileName); + Scylla::debugLog.log(L"findAllPlugins :: Plugin invalid file size: %s", ffd.cFileName); #endif } else { pluginData.fileSize = ffd.nFileSizeLow; wcscpy_s(pluginData.fullpath, _countof(baseDirPath), baseDirPath); wcscat_s(pluginData.fullpath, _countof(baseDirPath), ffd.cFileName); #ifdef DEBUG_COMMENTS - Logger::debugLog(L"findAllPlugins :: Plugin %s\r\n",pluginData.fullpath); + Scylla::debugLog.log(L"findAllPlugins :: Plugin %s", pluginData.fullpath); #endif if (isValidDllFile(pluginData.fullpath)) { if (isScyllaPlugin) { if (getScyllaPluginName(&pluginData)) { //add valid plugin newPluginList.push_back(pluginData); } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("Cannot get scylla plugin name %s\r\n"),pluginData.fullpath); + Scylla::debugLog.log(L"Cannot get scylla plugin name %s", pluginData.fullpath); #endif } } else { if (isValidImprecPlugin(pluginData.fullpath)) { wcscpy_s(pluginData.pluginName, MAX_PATH, ffd.cFileName); newPluginList.push_back(pluginData); } } } } } } while (FindNextFile(hFind, &ffd) != 0); dwError = GetLastError(); FindClose(hFind); if (dwError == ERROR_NO_MORE_FILES) { return true; } else { return false; } } bool PluginLoader::getScyllaPluginName(Plugin * pluginData) { bool retValue = false; char * pluginName = 0; size_t convertedChars = 0; def_ScyllaPluginNameW ScyllaPluginNameW = 0; def_ScyllaPluginNameA ScyllaPluginNameA = 0; HMODULE hModule = LoadLibraryEx(pluginData->fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain if (hModule) { ScyllaPluginNameW = (def_ScyllaPluginNameW)GetProcAddress(hModule, "ScyllaPluginNameW"); if (ScyllaPluginNameW) { wcscpy_s(pluginData->pluginName, MAX_PATH, ScyllaPluginNameW()); #ifdef DEBUG_COMMENTS - Logger::debugLog(L"getPluginName :: Plugin name %s\r\n", pluginData->pluginName); + Scylla::debugLog.log(L"getPluginName :: Plugin name %s", pluginData->pluginName); #endif retValue = true; } else { ScyllaPluginNameA = (def_ScyllaPluginNameA)GetProcAddress(hModule, "ScyllaPluginNameA"); if (ScyllaPluginNameA) { pluginName = ScyllaPluginNameA(); mbstowcs_s(&convertedChars, pluginData->pluginName, strlen(pluginName) + 1, pluginName, _TRUNCATE); #ifdef DEBUG_COMMENTS - Logger::debugLog(L"getPluginName :: Plugin name mbstowcs_s %s\r\n", pluginData->pluginName); + Scylla::debugLog.log(L"getPluginName :: Plugin name mbstowcs_s %s", pluginData->pluginName); #endif if (convertedChars > 1) { retValue = true; } else { retValue = false; } } else { retValue = false; } } FreeLibrary(hModule); return retValue; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"getPluginName :: LoadLibraryEx failed %s\r\n", pluginData->fullpath); + Scylla::debugLog.log(L"getPluginName :: LoadLibraryEx failed %s", pluginData->fullpath); #endif return false; } } bool PluginLoader::buildSearchString() { ZeroMemory(dirSearchString, sizeof(dirSearchString)); ZeroMemory(baseDirPath, sizeof(baseDirPath)); if (!GetModuleFileName(0, dirSearchString, _countof(dirSearchString))) { #ifdef DEBUG_COMMENTS - Logger::debugLog("buildSearchString :: GetModuleFileName failed %d\r\n",GetLastError()); + Scylla::debugLog.log(L"buildSearchString :: GetModuleFileName failed %d", GetLastError()); #endif return false; } //wprintf(L"dirSearchString 1 %s\n\n", dirSearchString); - - - //remove exe file name - for (size_t i = wcslen(dirSearchString) - 1; i >= 0; i--) - { - if (dirSearchString[i] == L'\\') - { - dirSearchString[i + 1] = 0; - break; - } - } - + PathRemoveFileSpec(dirSearchString); //wprintf(L"dirSearchString 2 %s\n\n", dirSearchString); - - wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_DIR)TEXT("\\") ); + PathAppend(dirSearchString, PLUGIN_DIR); wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString); - - wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_SEARCH_STRING) ); + wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_SEARCH_STRING); //wprintf(L"dirSearchString 3 %s\n\n", dirSearchString); #ifdef DEBUG_COMMENTS - Logger::debugLog(L"dirSearchString final %s\r\n", dirSearchString); + Scylla::debugLog.log(L"dirSearchString final %s", dirSearchString); #endif return true; } bool PluginLoader::isValidDllFile( const WCHAR * fullpath ) { BYTE * data = 0; DWORD lpNumberOfBytesRead = 0; PIMAGE_DOS_HEADER pDos = 0; PIMAGE_NT_HEADERS pNT = 0; bool retValue = false; HANDLE hFile = CreateFile(fullpath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { data = new BYTE[sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100]; if (ReadFile(hFile, data, sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100, &lpNumberOfBytesRead, 0)) { pDos = (PIMAGE_DOS_HEADER)data; if (pDos->e_magic == IMAGE_DOS_SIGNATURE) { pNT = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew); if (pNT->Signature == IMAGE_NT_SIGNATURE) { #ifdef _WIN64 if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) #else if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) #endif { retValue = true; } } } } delete [] data; CloseHandle(hFile); } return retValue; } bool PluginLoader::isValidImprecPlugin(const WCHAR * fullpath) { def_Imprec_Trace Imprec_Trace = 0; bool retValue = false; HMODULE hModule = LoadLibraryEx(fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain if (hModule) { Imprec_Trace = (def_Imprec_Trace)GetProcAddress(hModule, "Trace"); if (Imprec_Trace) { retValue = true; } else { retValue = false; } FreeLibrary(hModule); return retValue; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(L"isValidImprecPlugin :: LoadLibraryEx failed %s\r\n", pluginData->fullpath); + Scylla::debugLog.log(L"isValidImprecPlugin :: LoadLibraryEx failed %s", pluginData->fullpath); #endif return false; } } bool PluginLoader::buildSearchStringImprecPlugins() { wcscpy_s(dirSearchString, _countof(dirSearchString), baseDirPath); - wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_IMPREC_DIR)TEXT("\\") ); + wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_IMPREC_DIR); wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString); //build imprec wrapper dll path wcscpy_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), dirSearchString); - wcscat_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), TEXT(PLUGIN_IMPREC_WRAPPER_DLL) ); + wcscat_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), PLUGIN_IMPREC_WRAPPER_DLL); if (!fileExists(imprecWrapperDllPath)) { return false; } - wcscat_s(dirSearchString, _countof(dirSearchString), TEXT(PLUGIN_SEARCH_STRING) ); + wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_SEARCH_STRING); return true; } bool PluginLoader::fileExists(const WCHAR * fileName) { if (GetFileAttributesW(fileName) == INVALID_FILE_ATTRIBUTES) { return false; } else { return true; } } diff --git a/Scylla/PluginLoader.h b/Scylla/PluginLoader.h index b9d0fd0..92bf330 100644 --- a/Scylla/PluginLoader.h +++ b/Scylla/PluginLoader.h @@ -1,48 +1,49 @@ #pragma once #include -#include #include class Plugin { public: DWORD fileSize; WCHAR fullpath[MAX_PATH]; WCHAR pluginName[MAX_PATH]; }; -#define PLUGIN_DIR "Plugins" -#define PLUGIN_SEARCH_STRING "*.dll" -#define PLUGIN_IMPREC_DIR "ImpRec_Plugins" -#define PLUGIN_IMPREC_WRAPPER_DLL "Imprec_Wrapper_DLL.dll" - typedef wchar_t * (__cdecl * def_ScyllaPluginNameW)(); typedef char * (__cdecl * def_ScyllaPluginNameA)(); typedef DWORD ( * def_Imprec_Trace)(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall); class PluginLoader { public: - static WCHAR imprecWrapperDllPath[MAX_PATH]; + WCHAR imprecWrapperDllPath[MAX_PATH]; - static bool findAllPlugins(); + bool findAllPlugins(); - static std::vector & getScyllaPluginList(); - static std::vector & getImprecPluginList(); + std::vector & getScyllaPluginList(); + std::vector & getImprecPluginList(); private: - static std::vector scyllaPluginList; - static std::vector imprecPluginList; - static WCHAR dirSearchString[MAX_PATH]; - static WCHAR baseDirPath[MAX_PATH]; + static const WCHAR PLUGIN_DIR[]; + static const WCHAR PLUGIN_SEARCH_STRING[]; + static const WCHAR PLUGIN_IMPREC_DIR[]; + static const WCHAR PLUGIN_IMPREC_WRAPPER_DLL[]; - static bool buildSearchString(); - static bool getScyllaPluginName(Plugin * pluginData); - static bool isValidDllFile( const WCHAR * fullpath ); - static bool searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin); - static bool isValidImprecPlugin(const WCHAR * fullpath); - static bool buildSearchStringImprecPlugins(); + std::vector scyllaPluginList; + std::vector imprecPluginList; + + WCHAR dirSearchString[MAX_PATH]; + WCHAR baseDirPath[MAX_PATH]; + + bool buildSearchString(); + bool buildSearchStringImprecPlugins(); + + bool getScyllaPluginName(Plugin * pluginData); + bool searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin); static bool fileExists(const WCHAR * fileName); -}; \ No newline at end of file + static bool isValidDllFile(const WCHAR * fullpath); + static bool isValidImprecPlugin(const WCHAR * fullpath); +}; diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp index 376780b..01e1464 100644 --- a/Scylla/ProcessAccessHelp.cpp +++ b/Scylla/ProcessAccessHelp.cpp @@ -1,715 +1,715 @@ #include "ProcessAccessHelp.h" #include "Logger.h" #include "NativeWinApi.h" HANDLE ProcessAccessHelp::hProcess = 0; ModuleInfo * ProcessAccessHelp::selectedModule; DWORD_PTR ProcessAccessHelp::targetImageBase = 0; DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0; DWORD_PTR ProcessAccessHelp::maxValidAddress = 0; std::vector ProcessAccessHelp::moduleList; //target process module list std::vector ProcessAccessHelp::ownModuleList; //own module list _DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS]; unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0; _CodeInfo ProcessAccessHelp::decomposerCi = {0}; _DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS]; unsigned int ProcessAccessHelp::decodedInstructionsCount = 0; BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; //#define DEBUG_COMMENTS bool ProcessAccessHelp::openProcessHandle(DWORD dwPID) { if (dwPID > 0) { if (hProcess) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("openProcessHandle :: There is already a process handle, HANDLE %X\r\n"),hProcess); + Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", hProcess); #endif return false; } else { //hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID); //if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid))) hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID); if (hProcess) { return true; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("openProcessHandle :: Failed to open handle, PID %X\r\n"),dwPID); + Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID); #endif return false; } } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("openProcessHandle :: Wrong PID, PID %X \r\n"),dwPID); + 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 - Logger::debugLog(TEXT("NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X\r\n"),dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus)); + Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus)); #endif return 0; } } void ProcessAccessHelp::closeProcessHandle() { CloseHandle(hProcess); hProcess = 0; moduleList.clear(); targetImageBase = 0; selectedModule = 0; } bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) { SIZE_T lpNumberOfBytesRead = 0; DWORD dwProtect = 0; bool returnValue = false; if (!hProcess) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("readMemoryFromProcess :: hProcess == NULL\r\n")); + Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL"); #endif return returnValue; } if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) { if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u\r\n"),address,size,GetLastError()); + 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 - Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u\r\n"),address,size,GetLastError()); + 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 - Logger::debugLog(TEXT("readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes\r\n"), lpNumberOfBytesRead, size); + 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 - Logger::debugLog(TEXT("decomposeMemory :: distorm_decompose == DECRES_INPUTERR\r\n")); + 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 - Logger::debugLog(TEXT("disassembleMemory :: res == DECRES_INPUTERR\r\n")); + 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 - Logger::debugLog(TEXT("disassembleMemory :: res == %d\r\n"),res); + Scylla::debugLog.log(L"disassembleMemory :: res == %d", res); #endif return false; } } DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask) { DWORD pos = 0; size_t searchLen = strlen(mask) - 1; for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++) { if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' ) { if(mask[pos+1] == 0x00) { return (retAddress - searchLen); } pos++; } else { pos = 0; } } return 0; } bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath) { return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath); } LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath) { LONGLONG fileSize = 0; HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { fileSize = getFileSize(hFile); CloseHandle(hFile); hFile = 0; } return fileSize; } LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile) { LARGE_INTEGER lpFileSize = {0}; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { if (!GetFileSizeEx(hFile, &lpFileSize)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u\r\n"),GetLastError()); + Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError()); #endif return 0; } else { return lpFileSize.QuadPart; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("ProcessAccessHelp::getFileSize hFile invalid\r\n")); + Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid"); #endif return 0; } } bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer) { DWORD lpNumberOfBytesRead = 0; DWORD retValue = 0; DWORD dwError = 0; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); dwError = GetLastError(); if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("readMemoryFromFile :: SetFilePointer failed error %u\r\n"),dwError); + 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 - Logger::debugLog(TEXT("readMemoryFromFile :: ReadFile failed - size %d - error %u\r\n"),size,GetLastError()); + Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("readMemoryFromFile :: hFile invalid\r\n")); + Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid"); #endif return false; } } bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer) { DWORD lpNumberOfBytesWritten = 0; DWORD retValue = 0; DWORD dwError = 0; if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) { retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); dwError = GetLastError(); if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("writeMemoryToFile :: SetFilePointer failed error %u\r\n"),dwError); + 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 - Logger::debugLog(TEXT("writeMemoryToFile :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError()); + Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("writeMemoryToFile :: hFile invalid\r\n")); + 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 - Logger::debugLog(TEXT("writeMemoryToFileEnd :: WriteFile failed - size %d - error %u\r\n"),size,GetLastError()); + Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError()); #endif return false; } } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("writeMemoryToFileEnd :: hFile invalid\r\n")); + 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 - Logger::debugLog(TEXT("readHeaderFromFile :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError()); + 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 - Logger::debugLog(TEXT("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n"),GetLastError()); + 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 - Logger::debugLog(TEXT("createFileMappingView :: hMappedFile == NULL\r\n")); + Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL"); #endif return NULL; } if (GetLastError() == ERROR_ALREADY_EXISTS) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n")); + 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 - Logger::debugLog(TEXT("createFileMappingView :: addrMappedDll == NULL\r\n")); + 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 - Logger::debugLog(TEXT("getProcessByName :: Error getting first Process\r\n")); + Scylla::debugLog.log(L"getProcessByName :: Error getting first Process"); #endif CloseHandle( hProcessSnap ); return 0; } do { if(!_wcsicmp(pe32.szExeFile, processName)) { dwPID = pe32.th32ProcessID; break; } } while(Process32NextW(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); return dwPID; } bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector &moduleList) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; ModuleInfo module; // Take a snapshot of all modules in the specified process. hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); if( hModuleSnap == INVALID_HANDLE_VALUE ) { return false; } // Set the size of the structure before using it. me32.dwSize = sizeof( MODULEENTRY32 ); // Retrieve information about the first module, // and exit if unsuccessful if( !Module32First( hModuleSnap, &me32 ) ) { CloseHandle( hModuleSnap ); return false; } // Now walk the module list of the process, // and display information about each module //the first is always the .exe if (!Module32Next(hModuleSnap, &me32)) { CloseHandle( hModuleSnap ); return false; } moduleList.reserve(20); do { - //printf(TEXT("\n MODULE NAME: %s"), me32.szModule); + //printf(L"\n MODULE NAME: %s", me32.szModule); module.modBaseAddr = (DWORD_PTR)me32.modBaseAddr; module.modBaseSize = me32.modBaseSize; module.isAlreadyParsed = false; module.parsing = false; wcscpy_s(module.fullPath, MAX_PATH, me32.szExePath); moduleList.push_back(module); } while(Module32Next(hModuleSnap, &me32)); CloseHandle( hModuleSnap ); return true; } bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize) { MEMORY_BASIC_INFORMATION memBasic; if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getMemoryRegionFromAddress :: VirtualQueryEx error %u\r\n"), GetLastError()); + Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", GetLastError()); #endif return false; } else { *memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress; *memoryRegionSize = memBasic.RegionSize; return true; } } bool ProcessAccessHelp::getSizeOfImageCurrentProcess() { DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase); if (newSizeOfImage != 0) { ProcessAccessHelp::targetSizeOfImage = newSizeOfImage; return true; } else { return false; } } SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase) { SIZE_T sizeOfImage = 0; MEMORY_BASIC_INFORMATION lpBuffer = {0}; SIZE_T dwLength = sizeof(MEMORY_BASIC_INFORMATION); do { moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize); sizeOfImage += lpBuffer.RegionSize; //printf("Query 0x"PRINTF_DWORD_PTR_FULL" size 0x%08X\n",moduleBase,sizeOfImage); if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, dwLength)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getSizeOfImageProcess :: VirtualQuery failed %X\r\n"),GetLastError()); + Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", GetLastError()); #endif lpBuffer.Type = 0; sizeOfImage = 0; } /*else { printf("\nAllocationBase %X\n",lpBuffer.AllocationBase); printf("AllocationProtect %X\n",lpBuffer.AllocationProtect); printf("BaseAddress %X\n",lpBuffer.BaseAddress); printf("Protect %X\n",lpBuffer.Protect); printf("RegionSize %X\n",lpBuffer.RegionSize); printf("State %X\n",lpBuffer.State); printf("Type %X\n",lpBuffer.Type); }*/ } while (lpBuffer.Type == MEM_IMAGE); //printf("Real sizeOfImage %X\n",sizeOfImage); return sizeOfImage; } DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath) { PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; readHeaderFromCurrentFile(filePath); pDosHeader = (PIMAGE_DOS_HEADER)fileHeaderFromDisk; if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileHeaderFromDisk + (DWORD_PTR)(pDosHeader->e_lfanew)); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; } return pNtHeader->OptionalHeader.AddressOfEntryPoint; } bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath) { size_t fileNameLength = wcslen(filePath) + 5; //.bak + null BOOL retValue = 0; WCHAR * backupFile = new WCHAR[fileNameLength]; wcscpy_s(backupFile, fileNameLength, filePath); - wcscat_s(backupFile, fileNameLength, TEXT(".bak")); + wcscat_s(backupFile, fileNameLength, L".bak"); retValue = CopyFile(filePath, backupFile, FALSE); if (!retValue) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("createBackupFile :: CopyFile failed with error 0x%X\r\n"), GetLastError()); + Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError()); #endif } delete [] backupFile; return retValue != 0; } diff --git a/Scylla/ProcessLister.cpp b/Scylla/ProcessLister.cpp index 96eb708..c48274f 100644 --- a/Scylla/ProcessLister.cpp +++ b/Scylla/ProcessLister.cpp @@ -1,364 +1,364 @@ #include "ProcessLister.h" #include "SystemInformation.h" #include "Logger.h" #include "ProcessAccessHelp.h" //#define DEBUG_COMMENTS def_IsWow64Process ProcessLister::_IsWow64Process = 0; std::vector& ProcessLister::getProcessList() { return processList; } bool ProcessLister::isWindows64() { #ifdef _WIN64 //compiled 64bit application return true; #else //32bit exe, check wow64 BOOL bIsWow64 = FALSE; //not available in all windows operating systems //Minimum supported client: Windows Vista, Windows XP with SP2 //Minimum supported server: Windows Server 2008, Windows Server 2003 with SP1 if (_IsWow64Process) { _IsWow64Process(GetCurrentProcess(), &bIsWow64); if (bIsWow64 == TRUE) { return true; } else { return false; } } else { return false; } #endif } void ProcessLister::initDeviceNameList() { TCHAR shortName[3] = {0}; TCHAR longName[MAX_PATH] = {0}; HardDisk hardDisk; - shortName[1] = TEXT(':'); + shortName[1] = L':'; - for ( WCHAR shortD = TEXT('a'); shortD < TEXT('z'); shortD++ ) + for ( WCHAR shortD = L'a'; shortD < L'z'; shortD++ ) { shortName[0] = shortD; if (QueryDosDeviceW( shortName, longName, MAX_PATH ) > 0) { hardDisk.shortName[0] = towupper(shortD); - hardDisk.shortName[1] = TEXT(':'); + hardDisk.shortName[1] = L':'; hardDisk.shortName[2] = 0; hardDisk.longNameLength = wcslen(longName); wcscpy_s(hardDisk.longName, MAX_PATH, longName); deviceNameList.push_back(hardDisk); } } } //only needed in windows xp DWORD ProcessLister::setDebugPrivileges() { DWORD err = 0; HANDLE hToken = 0; TOKEN_PRIVILEGES Debug_Privileges = {0}; if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Debug_Privileges.Privileges[0].Luid)) { return GetLastError(); } if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { err = GetLastError(); if(hToken) CloseHandle(hToken); return err; } Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Debug_Privileges.PrivilegeCount = 1; AdjustTokenPrivileges(hToken, false, &Debug_Privileges, 0, NULL, NULL); CloseHandle(hToken); return GetLastError(); } /************************************************************************/ /* Check if a process is 32 or 64bit */ /************************************************************************/ ProcessType ProcessLister::checkIsProcess64(DWORD dwPID) { HANDLE hProcess; BOOL bIsWow64 = FALSE; if (dwPID == 0) { //unknown return PROCESS_UNKNOWN; } //hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, NULL, dwPID); hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, dwPID); if(!hProcess) { //missing rights return PROCESS_MISSING_RIGHTS; } if (!isWindows64()) { //32bit win can only run 32bit process CloseHandle(hProcess); return PROCESS_32; } _IsWow64Process(hProcess, &bIsWow64); CloseHandle(hProcess); if (bIsWow64 == FALSE) { //process not running under wow return PROCESS_64; } else { //process running under wow -> 32bit return PROCESS_32; } } bool ProcessLister::getAbsoluteFilePath(Process * process) { WCHAR processPath[MAX_PATH]; HANDLE hProcess; //hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, NULL, process->PID); hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION, process->PID); if(!hProcess) { //missing rights return false; } if (GetProcessImageFileName(hProcess, processPath, _countof(processPath)) > 0) { CloseHandle(hProcess); if (!resolveDeviceLongNameToShort(processPath, process->fullPath)) { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s\r\n"), processPath); + Scylla::debugLog.log(L"getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s", processPath); #endif } return true; } else { #ifdef DEBUG_COMMENTS - Logger::debugLog(TEXT("getAbsoluteFilePath :: GetProcessImageFileName failed %u\r\n"),GetLastError()); + Scylla::debugLog.log(L"getAbsoluteFilePath :: GetProcessImageFileName failed %u", GetLastError()); #endif CloseHandle(hProcess); return false; } } std::vector& ProcessLister::getProcessListSnapshot() { HANDLE hProcessSnap; ProcessType processType; PROCESSENTRY32 pe32; HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32 = {0}; Process process; processList.reserve(34); if (!processList.empty()) { processList.clear(); } hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { return processList; } pe32.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap); return processList; } do { //filter process list if (pe32.th32ProcessID > 4) { processType = checkIsProcess64(pe32.th32ProcessID); if (processType != PROCESS_MISSING_RIGHTS) { #ifdef _WIN64 if (processType == PROCESS_64) #else if (processType == PROCESS_32) #endif { process.PID = pe32.th32ProcessID; hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process.PID); if(hModuleSnap != INVALID_HANDLE_VALUE) { me32.dwSize = sizeof(MODULEENTRY32); Module32First(hModuleSnap, &me32); process.imageBase = (DWORD_PTR)me32.hModule; process.imageSize = me32.modBaseSize; CloseHandle(hModuleSnap); } wcscpy_s(process.filename, MAX_PATH, pe32.szExeFile); getAbsoluteFilePath(&process); processList.push_back(process); } } } } while(Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); //get module informations //getAllModuleInformation(); return processList; } void ProcessLister::getAllModuleInformation() { /*for (std::size_t i = 0; i < processList.size(); i++) { getModuleInformationByProcess(&processList[i]); }*/ } void ProcessLister::getModuleInformationByProcess(Process *process) { /* MODULEENTRY32 me32 = {0}; HANDLE hModuleSnap = INVALID_HANDLE_VALUE; char temp[111]; if (process->PID == 0) { MessageBox(0, "PID == NULL","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); return; } #ifdef _WIN64 if (!process->is64BitProcess) { //MessageBox(hWndDlg, "I'm a x64 process and you're trying to access a 32-bit process!","displayModuleList", MB_OK); return; } #else if (process->is64BitProcess) { //MessageBox(hWndDlg, "I'm a 32-bit process and you're trying to access a x64 process!","displayModuleList", MB_OK); return; } #endif hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process->PID); if(hModuleSnap == INVALID_HANDLE_VALUE) { sprintf_s(temp,sizeof(temp),"GetLastError %d",GetLastError()); MessageBox(0, temp,"ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); return; } me32.dwSize = sizeof(MODULEENTRY32); if(!Module32First(hModuleSnap, &me32)) { MessageBox(0, "Module32First error","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING); CloseHandle(hModuleSnap); return; } do { ModuleInfo moduleInfo; if (!_strnicmp(me32.szExePath,"\\Systemroot",11)) { char * path = (char *)malloc(MAX_PATH); sprintf_s(path,MAX_PATH,"%s\\%s",getenv("SystemRoot"),(me32.szExePath + 12)); strcpy_s(moduleInfo.fullPath,MAX_PATH, path); free(path); } else if(!_strnicmp(me32.szExePath,"\\??\\",4)) { strcpy_s(moduleInfo.fullPath,MAX_PATH, (me32.szExePath + 4)); } else { strcpy_s(moduleInfo.fullPath,MAX_PATH,me32.szExePath); } moduleInfo.hModule = (DWORD_PTR)me32.hModule; moduleInfo.modBaseSize = me32.modBaseSize; moduleInfo.modBaseAddr = (DWORD_PTR)me32.modBaseAddr; process->moduleList[moduleInfo.hModule] = moduleInfo; } while(Module32Next(hModuleSnap, &me32)); CloseHandle(hModuleSnap);*/ } bool ProcessLister::resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ) { for (unsigned int i = 0; i < deviceNameList.size(); i++) { if (!_wcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength)) { wcscpy_s(targetPath, MAX_PATH,deviceNameList[i].shortName); wcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength); return true; } } return false; } diff --git a/Scylla/ProcessLister.h b/Scylla/ProcessLister.h index 120da44..4a61362 100644 --- a/Scylla/ProcessLister.h +++ b/Scylla/ProcessLister.h @@ -1,73 +1,73 @@ #pragma once #include #include #include #include #pragma comment(lib, "Psapi.lib") typedef BOOL (WINAPI *def_IsWow64Process)(HANDLE hProcess,PBOOL Wow64Process); class Process { public: DWORD PID; DWORD_PTR imageBase; DWORD entryPoint; //without imagebase DWORD imageSize; WCHAR filename[MAX_PATH]; WCHAR fullPath[MAX_PATH]; Process() { PID = 0; } }; class HardDisk { public: WCHAR shortName[3]; WCHAR longName[MAX_PATH]; size_t longNameLength; }; enum ProcessType { PROCESS_UNKNOWN, PROCESS_MISSING_RIGHTS, PROCESS_32, PROCESS_64 }; class ProcessLister { public: static def_IsWow64Process _IsWow64Process; ProcessLister() { initDeviceNameList(); - _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),"IsWow64Process"); + _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"); } std::vector& getProcessList(); static bool isWindows64(); static DWORD setDebugPrivileges(); std::vector& ProcessLister::getProcessListSnapshot(); private: std::vector processList; std::vector deviceNameList; ProcessType checkIsProcess64(DWORD dwPID); void initDeviceNameList(); bool getAbsoluteFilePath(Process * process); void getAllModuleInformation(); void getModuleInformationByProcess(Process *process); bool resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath ); }; \ No newline at end of file diff --git a/Scylla/Scylla.vcxproj b/Scylla/Scylla.vcxproj index 8e1291d..c38dc6e 100644 --- a/Scylla/Scylla.vcxproj +++ b/Scylla/Scylla.vcxproj @@ -1,229 +1,233 @@  Debug Win32 Debug x64 Release Win32 Release x64 {710434C9-FC4B-4F1D-B318-E10ADC78499F} Win32Proj Scylla Application true Unicode Application true Unicode Application false true Unicode v100 Application false true Unicode true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ true false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false Level3 Disabled WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) Windows true $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' Level3 Disabled WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) Windows true $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) true Windows false true true $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded $(SolutionDir)diStorm\include;$(SolutionDir)tinyxml;%(AdditionalIncludeDirectories) true Windows false true true $(SolutionDir)$(Platform)\$(Configuration)\diStorm.lib;$(SolutionDir)$(Platform)\$(Configuration)\tinyxml.lib;%(AdditionalDependencies) type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' + + + + \ No newline at end of file diff --git a/Scylla/Scylla.vcxproj.filters b/Scylla/Scylla.vcxproj.filters index 7f3c14a..b5919e2 100644 --- a/Scylla/Scylla.vcxproj.filters +++ b/Scylla/Scylla.vcxproj.filters @@ -1,196 +1,208 @@  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {e037d0d5-35ad-4034-83db-746a56a4fee7} {6f76186f-b79c-41e2-8939-05d9de028aad} Quelldateien Quelldateien\GUI Quelldateien\GUI Quelldateien Quelldateien\GUI Quelldateien\GUI Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien Quelldateien\GUI Quelldateien Quelldateien Quelldateien\GUI Quelldateien\GUI Quelldateien\GUI Quelldateien + + Quelldateien + + + Quelldateien + Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien Headerdateien Headerdateien Headerdateien\GUI Headerdateien Headerdateien Headerdateien Headerdateien Headerdateien Headerdateien Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien Headerdateien Headerdateien\GUI Headerdateien\GUI Headerdateien\GUI Headerdateien\GUI Headerdateien Headerdateien\GUI + + Headerdateien + + + Headerdateien + Ressourcendateien Ressourcendateien Ressourcendateien Ressourcendateien Ressourcendateien \ No newline at end of file diff --git a/Scylla/SystemInformation.cpp b/Scylla/SystemInformation.cpp index bce7a6b..c4c3f27 100644 --- a/Scylla/SystemInformation.cpp +++ b/Scylla/SystemInformation.cpp @@ -1,62 +1,62 @@ #include "SystemInformation.h" OPERATING_SYSTEM SystemInformation::currenOS = UNKNOWN_OS; bool SystemInformation::getSystemInformation() { OSVERSIONINFOEX osvi = {0}; SYSTEM_INFO si = {0}; def_GetNativeSystemInfo _GetNativeSystemInfo = 0; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (!GetVersionEx((OSVERSIONINFO*) &osvi)) { return false; } if ((osvi.dwMajorVersion < 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0))) { return false; } - _GetNativeSystemInfo = (def_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); + _GetNativeSystemInfo = (def_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo"); if (_GetNativeSystemInfo) { _GetNativeSystemInfo(&si); } else { GetSystemInfo(&si); } if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { currenOS = WIN_VISTA_64; } else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { currenOS = WIN_VISTA_32; } else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) { currenOS = WIN_7_64; } else if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL && osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) { currenOS = WIN_7_32; } else if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 && osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { currenOS = WIN_XP_64; } else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { currenOS = WIN_XP_32; } else { currenOS = UNKNOWN_OS; } return (currenOS != UNKNOWN_OS); } \ No newline at end of file diff --git a/Scylla/TreeImportExport.cpp b/Scylla/TreeImportExport.cpp index 6f36613..a6cf3e2 100644 --- a/Scylla/TreeImportExport.cpp +++ b/Scylla/TreeImportExport.cpp @@ -1,346 +1,346 @@ #include "TreeImportExport.h" -#include "definitions.h" -#include "Logger.h" +#include "Architecture.h" +#include "Scylla.h" #define DEBUG_COMMENTS bool TreeImportExport::exportTreeList(const WCHAR * targetXmlFile, std::map & moduleList, const Process * process, const DWORD_PTR addressOEP, const DWORD_PTR addressIAT, const DWORD sizeIAT) { TiXmlDocument doc; TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); doc.LinkEndChild(decl); TiXmlElement * rootElement = new TiXmlElement("target"); setTargetInformation(rootElement, process,addressOEP,addressIAT,sizeIAT); addModuleListToRootElement(rootElement, moduleList); doc.LinkEndChild(rootElement); return saveXmlToFile(doc,targetXmlFile); } bool TreeImportExport::importTreeList(const WCHAR * targetXmlFile, std::map & moduleList, DWORD_PTR * addressOEP, DWORD_PTR * addressIAT, DWORD * sizeIAT) { TiXmlElement * targetElement; TiXmlDocument doc; char * buffer = readXmlFile(targetXmlFile); int count = 0; moduleList.clear(); if (buffer) { doc.Parse(buffer); if (doc.Error()) { - Logger::printfDialog(TEXT("Load Tree :: Error parsing xml %S: %S\r\n"), doc.Value(), doc.ErrorDesc()); + Scylla::windowLog.log(L"Load Tree :: Error parsing xml %S: %S\r\n", doc.Value(), doc.ErrorDesc()); delete [] buffer; return false; } targetElement = doc.FirstChildElement(); *addressOEP = ConvertStringToDwordPtr(targetElement->Attribute("oep_va")); *addressIAT = ConvertStringToDwordPtr(targetElement->Attribute("iat_va")); *sizeIAT = (DWORD)ConvertStringToDwordPtr(targetElement->Attribute("iat_size")); //test = targetElement->Attribute("filename"); parseAllElementModules(targetElement, moduleList); delete [] buffer; } return true; } void TreeImportExport::setTargetInformation(TiXmlElement * rootElement, const Process * process, const DWORD_PTR addressOEP, const DWORD_PTR addressIAT, const DWORD sizeIAT) { size_t stringLength = 0; wcstombs_s(&stringLength, xmlStringBuffer, (size_t)_countof(xmlStringBuffer), process->filename, (size_t)_countof(process->filename)); rootElement->SetAttribute("filename", xmlStringBuffer); ConvertDwordPtrToString(addressOEP); rootElement->SetAttribute("oep_va",xmlStringBuffer); ConvertDwordPtrToString(addressIAT); rootElement->SetAttribute("iat_va",xmlStringBuffer); ConvertDwordPtrToString(sizeIAT); rootElement->SetAttribute("iat_size",xmlStringBuffer); } char * TreeImportExport::readXmlFile(const WCHAR * xmlFilePath) { FILE * pFile = 0; long lSize = 0; char * buffer = 0; if (_wfopen_s(&pFile,xmlFilePath,L"r") == NULL) { fseek(pFile, 0, SEEK_END); lSize = ftell(pFile); fseek(pFile, 0, SEEK_SET); if (lSize > 2) { buffer = new char[lSize + sizeof(char)]; ZeroMemory(buffer, lSize + sizeof(char)); fread(buffer, sizeof(char), lSize, pFile); if (!feof(pFile) || ferror(pFile)) { delete [] buffer; buffer = 0; } } fclose (pFile); return buffer; } else { return 0; } } bool TreeImportExport::saveXmlToFile(TiXmlDocument doc, const WCHAR * xmlFilePath) { FILE * pFile = 0; if (_wfopen_s(&pFile,xmlFilePath,L"w") == NULL) { doc.Print(pFile); fclose (pFile); return true; } else { return false; } } void TreeImportExport::addModuleListToRootElement( TiXmlElement * rootElement, std::map & moduleList ) { std::map::iterator mapIt; std::map::iterator mapIt2; ImportModuleThunk * importModuleThunk = 0; ImportThunk * importThunk = 0; TiXmlElement * moduleElement; TiXmlElement * importElement; for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ ) { importModuleThunk = &((*mapIt).second); moduleElement = getModuleXmlElement(importModuleThunk); for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ ) { importThunk = &((*mapIt2).second); importElement = getImportXmlElement(importThunk); moduleElement->LinkEndChild(importElement); } rootElement->LinkEndChild(moduleElement); } } TiXmlElement * TreeImportExport::getModuleXmlElement(const ImportModuleThunk * importModuleThunk) { size_t stringLength = 0; TiXmlElement * moduleElement = new TiXmlElement("module"); wcstombs_s(&stringLength, xmlStringBuffer, (size_t)_countof(xmlStringBuffer), importModuleThunk->moduleName, (size_t)_countof(importModuleThunk->moduleName)); moduleElement->SetAttribute("filename", xmlStringBuffer); ConvertDwordPtrToString(importModuleThunk->getFirstThunk()); moduleElement->SetAttribute("first_thunk_rva",xmlStringBuffer); return moduleElement; } TiXmlElement * TreeImportExport::getImportXmlElement(const ImportThunk * importThunk) { TiXmlElement * importElement = 0; if (importThunk->valid) { importElement = new TiXmlElement("import_valid"); if(importThunk->name[0] != '\0') { importElement->SetAttribute("name",importThunk->name); } ConvertWordToString(importThunk->ordinal); importElement->SetAttribute("ordinal",xmlStringBuffer); ConvertWordToString(importThunk->hint); importElement->SetAttribute("hint",xmlStringBuffer); ConvertBoolToString(importThunk->suspect); importElement->SetAttribute("suspect", xmlStringBuffer); } else { importElement = new TiXmlElement("import_invalid"); } ConvertDwordPtrToString(importThunk->rva); importElement->SetAttribute("iat_rva", xmlStringBuffer); ConvertDwordPtrToString(importThunk->apiAddressVA); importElement->SetAttribute("address_va",xmlStringBuffer); return importElement; } void TreeImportExport::ConvertBoolToString(const bool boolValue) { if (boolValue) { strcpy_s(xmlStringBuffer,_countof(xmlStringBuffer),"1"); } else { strcpy_s(xmlStringBuffer,_countof(xmlStringBuffer),"0"); } } bool TreeImportExport::ConvertStringToBool(const char * strValue) { if (strValue) { if (strValue[0] == '1') { return true; } } return false; } void TreeImportExport::ConvertDwordPtrToString(const DWORD_PTR dwValue) { - sprintf_s(xmlStringBuffer, _countof(xmlStringBuffer), PRINTF_DWORD_PTR_FULL, dwValue); + sprintf_s(xmlStringBuffer, _countof(xmlStringBuffer), PRINTF_DWORD_PTR_FULL_S, dwValue); } DWORD_PTR TreeImportExport::ConvertStringToDwordPtr(const char * strValue) { DWORD_PTR result = 0; if (strValue) { #ifdef _WIN64 result = _strtoi64(strValue, NULL, 16); #else result = strtoul(strValue, NULL, 16); #endif } return result; } void TreeImportExport::ConvertWordToString(const WORD dwValue) { sprintf_s(xmlStringBuffer, _countof(xmlStringBuffer), "%04X", dwValue); } WORD TreeImportExport::ConvertStringToWord(const char * strValue) { WORD result = 0; if (strValue) { result = (WORD)strtoul(strValue, NULL, 16); } return result; } void TreeImportExport::parseAllElementModules( TiXmlElement * targetElement, std::map & moduleList ) { TiXmlElement * moduleElement = 0; ImportModuleThunk importModuleThunk; size_t convertedChars = 0; const char * filename = 0; for(moduleElement = targetElement->FirstChildElement(); moduleElement; moduleElement = moduleElement->NextSiblingElement()) { filename = moduleElement->Attribute("filename"); if (filename) { mbstowcs_s(&convertedChars, importModuleThunk.moduleName, _countof(importModuleThunk.moduleName), filename, _TRUNCATE); importModuleThunk.firstThunk = ConvertStringToDwordPtr(moduleElement->Attribute("first_thunk_rva")); importModuleThunk.thunkList.clear(); parseAllElementImports(moduleElement, &importModuleThunk); moduleList.insert(std::pair(importModuleThunk.firstThunk, importModuleThunk)); } } } void TreeImportExport::parseAllElementImports( TiXmlElement * moduleElement, ImportModuleThunk * importModuleThunk ) { TiXmlElement * importElement = 0; ImportThunk importThunk; const char * temp = 0; for(importElement = moduleElement->FirstChildElement(); importElement; importElement = importElement->NextSiblingElement()) { temp = importElement->Value(); if (!strcmp(temp, "import_valid")) { temp = importElement->Attribute("name"); if (temp) { strcpy_s(importThunk.name, _countof(importThunk.name),temp); } else { importThunk.name[0] = 0; } wcscpy_s(importThunk.moduleName,_countof(importThunk.moduleName), importModuleThunk->moduleName); importThunk.suspect = ConvertStringToBool(importElement->Attribute("suspect")); importThunk.ordinal = ConvertStringToWord(importElement->Attribute("ordinal")); importThunk.hint = ConvertStringToWord(importElement->Attribute("hint")); importThunk.valid = true; } else { importThunk.valid = false; importThunk.suspect = true; } importThunk.apiAddressVA = ConvertStringToDwordPtr(importElement->Attribute("address_va")); importThunk.rva = ConvertStringToDwordPtr(importElement->Attribute("iat_rva")); if (importThunk.rva != 0) { importModuleThunk->thunkList.insert(std::pair(importThunk.rva, importThunk)); } } } diff --git a/Scylla/definitions.h b/Scylla/definitions.h deleted file mode 100644 index 54dd117..0000000 --- a/Scylla/definitions.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#define APPNAME "Scylla" - -#ifdef _WIN64 - -#define ARCHITECTURE "x64" -#define PRINTF_DWORD_PTR "%I64X" -#define PRINTF_DWORD_PTR_FULL "%016I64X" -#define PRINTF_DWORD_PTR_HALF "%08I64X" -#define PRINTF_INTEGER "%I64u" -#define MAX_HEX_VALUE_EDIT_LENGTH 16 - -#else - -#define ARCHITECTURE "x86" -#define PRINTF_DWORD_PTR "%X" -#define PRINTF_DWORD_PTR_FULL "%08X" -#define PRINTF_DWORD_PTR_HALF "%08X" -#define PRINTF_INTEGER "%u" -#define MAX_HEX_VALUE_EDIT_LENGTH 8 - -#endif - -#define APPVERSION "v0.5a" - -#define PLUGIN_MENU_BASE_ID 0x10 \ No newline at end of file