diff --git a/Scylla/AboutGui.cpp b/Scylla/AboutGui.cpp index 0a87d51..b5ea48f 100644 --- a/Scylla/AboutGui.cpp +++ b/Scylla/AboutGui.cpp @@ -1,25 +1,23 @@ #include "AboutGui.h" + #include "definitions.h" -INT_PTR AboutGui::initDialog(HINSTANCE hInstance, HWND hWndParent) +BOOL AboutGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT),hWndParent, (DLGPROC)aboutDlgProc); + StaticAbout.Attach(GetDlgItem(IDC_STATIC_ABOUT)); + + StaticAbout.SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)TEXT("\n\n")TEXT(DEVELOPED)TEXT("\n\n\n")TEXT(CREDIT_DISTORM)TEXT("\n")TEXT(CREDIT_YODA)TEXT("\n\n")TEXT(GREETINGS)TEXT("\n\n\n")TEXT(VISIT)); + CenterWindow(); + + return TRUE; } -LRESULT CALLBACK AboutGui::aboutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +void AboutGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { - switch (uMsg) - { - case WM_INITDIALOG: - SetDlgItemText(hWnd,IDC_STATIC_ABOUT, TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)TEXT("\n\n")TEXT(DEVELOPED)TEXT("\n\n\n")TEXT(CREDIT_DISTORM)TEXT("\n")TEXT(CREDIT_YODA)TEXT("\n\n")TEXT(GREETINGS)TEXT("\n\n\n")TEXT(VISIT)); - return TRUE; - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_BTN_ABOUT_OK: - EndDialog(hWnd, 0); - return TRUE; - } - } - return FALSE; -} \ No newline at end of file + EndDialog(0); +} + +void AboutGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) +{ + EndDialog(0); +} diff --git a/Scylla/AboutGui.h b/Scylla/AboutGui.h index 2fcd9d8..aa17105 100644 --- a/Scylla/AboutGui.h +++ b/Scylla/AboutGui.h @@ -1,13 +1,38 @@ #pragma once -#include "MainGui.h" +#include +#include "resource.h" +// WTL +#include // base ATL classes +#include // base WTL classes +#include // ATL GUI classes +#include // WTL enhanced msg map macros +#include // WTL controls -class AboutGui { +class AboutGui : public CDialogImpl +{ public: - - static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent); + enum { IDD = IDD_DLG_ABOUT }; -private: - static LRESULT CALLBACK aboutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -}; \ No newline at end of file + BEGIN_MSG_MAP(AboutGui) + MSG_WM_INITDIALOG(OnInitDialog) + + COMMAND_ID_HANDLER_EX(IDC_BTN_ABOUT_OK, OnOK) + COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) + END_MSG_MAP() + +protected: + + // Controls + + CStatic StaticAbout; + +protected: + + // Message handlers + + BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); + void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); + void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); +}; diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp index 4739fe9..532feca 100644 --- a/Scylla/ApiReader.cpp +++ b/Scylla/ApiReader.cpp @@ -1,1107 +1,1107 @@ #include "ApiReader.h" #include "Logger.h" #include "definitions.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); if (!moduleList[i].isAlreadyParsed) { parseModule(&moduleList[i]); } } #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("Address Min ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Max ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\nimagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" maxValidAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),minApiAddress,maxApiAddress,targetImageBase,maxValidAddress); #endif } void ApiReader::parseModule(ModuleInfo *module) { module->parsing = true; if (isWinSxSModule(module)) { parseModuleWithMapping(module); } else if (isModuleLoadedInOwnProcess(module)) { parseModuleWithOwnProcess(module); } else { parseModuleWithProcess(module); } module->isAlreadyParsed = true; } void ApiReader::parseModuleWithMapping(ModuleInfo *moduleInfo) { LPVOID fileMapping = 0; PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; fileMapping = createFileMappingViewRead(moduleInfo->fullPath); if (fileMapping == 0) return; pDosHeader = (PIMAGE_DOS_HEADER)fileMapping; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping); } UnmapViewOfFile(fileMapping); } inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader) { if ((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size))) { return true; } else { return false; } } void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer,char * functionNameParent, DWORD_PTR rvaParent, DWORD_PTR ordinalParent, ModuleInfo *moduleParent) { size_t dllNameLength = 0; DWORD_PTR ordinal = 0; ModuleInfo *module = 0; DWORD_PTR vaApi = 0; DWORD_PTR rvaApi = 0; char dllName[100] = {0}; WCHAR dllNameW[100] = {0}; char *fordwardedString = (char *)vaStringPointer; char *searchFunctionName = strchr(fordwardedString, '.'); if (!searchFunctionName) return; dllNameLength = searchFunctionName - fordwardedString; if (dllNameLength >= 99) { return; } else { strncpy_s(dllName,sizeof(dllName),fordwardedString,dllNameLength); } searchFunctionName++; //Windows 7 if (!strncmp(dllName,"api-ms-win-", 11)) { /* Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html */ FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName); if (addy != 0) { addApi(functionNameParent,0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent); } return; } strcat_s(dllName,sizeof(dllName),".dll"); size_t convertedChars = 0; mbstowcs_s(&convertedChars, dllNameW, strlen(dllName) + 1, dllName, _TRUNCATE); if (!_wcsicmp(dllNameW, moduleParent->getFilename())) { module = moduleParent; } else { module = findModuleByName(dllNameW); } if (module != 0) // module == 0 -> can be ignored { /*if ((module->isAlreadyParsed == false) && (module != moduleParent)) { //do API extract if (module->parsing == true) { //some stupid circle dependency printf("stupid circle dependency %s\n",module->getFilename()); } else { parseModule(module); } }*/ if (strchr(searchFunctionName,'#')) { //forwarding by ordinal searchFunctionName++; ordinal = atoi(searchFunctionName); findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi); } else { findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi); } if (rvaApi == 0) { #ifdef DEBUG_COMMENTS Logger::debugLog(L"handleForwardedApi :: Api not found, this is really BAD! %S\r\n",fordwardedString); #endif } else { addApi(functionNameParent,0, ordinalParent, vaApi, rvaApi, true, moduleParent); } } } ModuleInfo * ApiReader::findModuleByName(WCHAR *name) { for (unsigned int i = 0; i < moduleList.size(); i++) { if (!_wcsicmp(moduleList[i].getFilename(), name)) { return &moduleList[i]; } } return 0; } void ApiReader::addApiWithoutName(DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo) { addApi(0, 0, ordinal, va, rva, isForwarded, moduleInfo); } void ApiReader::addApi(char *functionName, WORD hint, DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo) { ApiInfo *apiInfo = new ApiInfo(); if ((functionName != 0) && (strlen(functionName) < MAX_PATH)) { strcpy_s(apiInfo->name, MAX_PATH, functionName); } else { apiInfo->name[0] = 0x00; } apiInfo->ordinal = ordinal; apiInfo->isForwarded = isForwarded; apiInfo->module = moduleInfo; apiInfo->rva = rva; apiInfo->va = va; apiInfo->hint = hint; setMinMaxApiAddress(va); moduleInfo->apiList.push_back(apiInfo); apiList.insert(API_Pair(va, apiInfo)); } BYTE * ApiReader::getHeaderFromProcess(ModuleInfo * module) { BYTE *bufferHeader = 0; DWORD readSize = 0; if (module->modBaseSize < PE_HEADER_BYTES_COUNT) { readSize = module->modBaseSize; } else { readSize = PE_HEADER_BYTES_COUNT; } bufferHeader = new BYTE[readSize]; if(!readMemoryFromProcess(module->modBaseAddr, readSize, bufferHeader)) { #ifdef DEBUG_COMMENTS Logger::debugLog(L"getHeaderFromProcess :: Error reading header\r\n"); #endif delete[] bufferHeader; return 0; } else { return bufferHeader; } } BYTE * ApiReader::getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader) { DWORD readSize = 0; BYTE *bufferExportTable = 0; readSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (readSize < (sizeof(IMAGE_EXPORT_DIRECTORY) + 8)) { //Something is wrong with the PE Header #ifdef DEBUG_COMMENTS Logger::debugLog(L"Something is wrong with the PE Header here Export table size %d\r\n",readSize); #endif readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100; } if (readSize) { bufferExportTable = new BYTE[readSize]; if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable)) { #ifdef DEBUG_COMMENTS Logger::debugLog(L"getExportTableFromProcess :: Error reading export table from process\r\n"); #endif delete[] bufferExportTable; return 0; } else { return bufferExportTable; } } else { return 0; } } void ApiReader::parseModuleWithProcess(ModuleInfo * module) { PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; BYTE *bufferHeader = 0; BYTE *bufferExportTable = 0; bufferHeader = getHeaderFromProcess(module); if (bufferHeader == 0) return; pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { bufferExportTable = getExportTableFromProcess(module, pNtHeader); if(bufferExportTable) { parseExportTable(module,pNtHeader,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); delete[] bufferExportTable; } } delete[] bufferHeader; } void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress) { DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0; WORD *addressOfNameOrdinalsArray = 0; char *functionName = 0; DWORD_PTR RVA = 0, VA = 0, ordinal = 0; DWORD i = 0, j = 0; bool withoutName; addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress); addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress); addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress); #ifdef DEBUG_COMMENTS Logger::debugLog(L"parseExportTable :: module %s NumberOfNames %X\r\n",module->fullPath,pExportDir->NumberOfNames); #endif for (i = 0; i < pExportDir->NumberOfNames; i++) { functionName = (char*)(addressOfNamesArray[i] + deltaAddress); ordinal = (addressOfNameOrdinalsArray[i] + pExportDir->Base); RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]]; VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr; #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("parseExportTable :: api %S ")TEXT(" ordinal %d imagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),functionName,ordinal,module->modBaseAddr,RVA,VA); #endif if (!isApiBlacklisted(functionName)) { if (!isApiForwarded(RVA,pNtHeader)) { addApi(functionName, (WORD)i, ordinal,VA,RVA,false,module); } else { //printf("Forwarded: %s\n",functionName); handleForwardedApi(RVA + deltaAddress,functionName,RVA,ordinal,module); } } } /*Exports without name*/ if (pExportDir->NumberOfNames != pExportDir->NumberOfFunctions) { for (i = 0; i < pExportDir->NumberOfFunctions; i++) { withoutName = true; for (j = 0; j < pExportDir->NumberOfNames; j++) { if(addressOfNameOrdinalsArray[j] == i) { withoutName = false; break; } } if (withoutName && addressOfFunctionsArray[i] != 0) { ordinal = (i+pExportDir->Base); RVA = addressOfFunctionsArray[i]; VA = (addressOfFunctionsArray[i] + module->modBaseAddr); if (!isApiForwarded(RVA,pNtHeader)) { addApiWithoutName(ordinal,VA,RVA,false,module); } else { handleForwardedApi(RVA + deltaAddress,0,RVA,ordinal,module); } } } } } void ApiReader::findApiByModuleAndOrdinal(ModuleInfo * module, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi) { findApiByModule(module,0,ordinal,vaApi,rvaApi); } void ApiReader::findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi) { findApiByModule(module,searchFunctionName,0,vaApi,rvaApi); } void ApiReader::findApiByModule(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi) { if (isModuleLoadedInOwnProcess(module)) { HMODULE hModule = GetModuleHandle(module->getFilename()); if (hModule) { if (ordinal) { *vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal); } else { *vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName); } if (vaApi) { *rvaApi = (*vaApi) - (DWORD_PTR)hModule; *vaApi = (*rvaApi) + module->modBaseAddr; } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("findApiByModule :: vaApi == NULL, should never happen %S\r\n"),searchFunctionName); #endif } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("findApiByModule :: hModule == NULL, should never happen %s\r\n"),module->getFilename()); #endif } } else { //search api in extern process findApiInProcess(module,searchFunctionName,ordinal,vaApi,rvaApi); } } bool ApiReader::isModuleLoadedInOwnProcess(ModuleInfo * module) { for (unsigned int i = 0; i < ownModuleList.size(); i++) { if (!_wcsicmp(module->fullPath, ownModuleList[i].fullPath)) { //printf("isModuleLoadedInOwnProcess :: %s %s\n",module->fullPath,ownModuleList[i].fullPath); return true; } } return false; } void ApiReader::parseModuleWithOwnProcess( ModuleInfo * module ) { PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; HMODULE hModule = GetModuleHandle(module->getFilename()); if (hModule) { pDosHeader = (PIMAGE_DOS_HEADER)hModule; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)hModule); } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("parseModuleWithOwnProcess :: hModule is NULL\r\n")); #endif } } bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader) { if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { Logger::printfDialog(TEXT("-> IMAGE_NT_SIGNATURE doesn't match.")); return false; } else if ((pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) || (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0)) { Logger::printfDialog(TEXT("-> No export table.")); return false; } else { return true; } } void ApiReader::findApiInProcess(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi) { PIMAGE_NT_HEADERS pNtHeader = 0; PIMAGE_DOS_HEADER pDosHeader = 0; BYTE *bufferHeader = 0; BYTE *bufferExportTable = 0; bufferHeader = getHeaderFromProcess(module); if (bufferHeader == 0) return; pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew)); if (isPeAndExportTableValid(pNtHeader)) { bufferExportTable = getExportTableFromProcess(module, pNtHeader); if(bufferExportTable) { findApiInExportTable(module,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,searchFunctionName,ordinal,vaApi,rvaApi); delete[] bufferExportTable; } } delete[] bufferHeader; } bool ApiReader::findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi) { DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0; WORD *addressOfNameOrdinalsArray = 0; char *functionName = 0; DWORD i = 0, j = 0; addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress); addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress); addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress); if (searchFunctionName) { for (i = 0; i < pExportDir->NumberOfNames; i++) { functionName = (char*)(addressOfNamesArray[i] + deltaAddress); if (!strcmp(functionName,searchFunctionName)) { *rvaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]]; *vaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr; return true; } } } else { for (i = 0; i < pExportDir->NumberOfFunctions; i++) { if (ordinal == (i+pExportDir->Base)) { *rvaApi = addressOfFunctionsArray[i]; *vaApi = (addressOfFunctionsArray[i] + module->modBaseAddr); return true; } } } return false; } void ApiReader::setModulePriority(ModuleInfo * module) { - WCHAR *moduleFileName = module->getFilename(); + const WCHAR *moduleFileName = module->getFilename(); if (!_wcsicmp(moduleFileName, TEXT("kernelbase.dll"))) { module->priority = 0; } else if (!_wcsicmp(moduleFileName, TEXT("ntdll.dll"))) { module->priority = 0; } else if (!_wcsicmp(moduleFileName, TEXT("shlwapi.dll"))) { module->priority = 0; } else if (!_wcsicmp(moduleFileName, TEXT("ShimEng.dll"))) { module->priority = 0; } else if (!_wcsicmp(moduleFileName, TEXT("kernel32.dll"))) { module->priority = 2; } else { module->priority = 1; } } bool ApiReader::isApiAddressValid(DWORD_PTR virtualAddress) { return apiList.count(virtualAddress) > 0; } ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect) { stdext::hash_multimap::iterator it1, it2; size_t c = 0; size_t countDuplicates = apiList.count(virtualAddress); int countHighPriority = 0; ApiInfo *apiFound = 0; if (countDuplicates == 0) { Logger::printfDialog(TEXT("getApiByVirtualAddress :: No Api found ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress); return 0; } else if (countDuplicates == 1) { //API is 100% correct *isSuspect = false; it1 = apiList.find(virtualAddress); // Find first match. return (ApiInfo *)((*it1).second); } else { it1 = apiList.find(virtualAddress); // Find first match. it2 = it1; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority >= 1) //1 == high priority { countHighPriority++; } } it1 = it2; if (countHighPriority == 0) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == 0 ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),virtualAddress); #endif *isSuspect = true; return (ApiInfo *)((*it1).second); } else if (countHighPriority == 1) { //API is 100% correct if countHighPriority == 1 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 { //API not 100% correct #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == %d ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),countHighPriority,virtualAddress); #endif *isSuspect = true; /*for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); Logger::printfDialog("%s - %s %X %X\n",apiFound->name,apiFound->module->getFilename(),apiFound->rva, apiFound->ordinal); } it1 = it2;*/ for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); //prefer APIs with a name if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority { //prefer ANSI/UNICODE APIs if (strrchr(apiFound->name,TEXT('W')) || strrchr(apiFound->name,TEXT('A'))) { return apiFound; } } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); //prefer APIs with a name if (apiFound->module->priority == 2 && !strrchr(apiFound->name,TEXT('_'))) //1 == high priority { return apiFound; } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority == 1 && apiFound->name[0] != 0x00) //1 == high priority { return apiFound; } } it1 = it2; for (c = 0; c < countDuplicates; c++, it1++) { apiFound = (ApiInfo *)((*it1).second); if (apiFound->module->priority == 1) //1 == high priority { return apiFound; } } } } //is never reached Logger::printfDialog(TEXT("getApiByVirtualAddress :: There is a big bug\n")); return (ApiInfo *) 1; } void ApiReader::setMinMaxApiAddress(DWORD_PTR virtualAddress) { if (virtualAddress < minApiAddress) { minApiAddress = virtualAddress - 1; } if (virtualAddress > maxApiAddress) { maxApiAddress = virtualAddress + 1; } } void ApiReader::readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map &moduleListNew) { moduleThunkList = &moduleListNew; BYTE *dataIat = new BYTE[sizeIAT]; if (readMemoryFromProcess(addressIAT,sizeIAT,dataIat)) { parseIAT(addressIAT,dataIat,sizeIAT); } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ApiReader::readAndParseIAT :: error reading iat ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),addressIAT); #endif } delete[] dataIat; } void ApiReader::parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size) { ApiInfo *apiFound = 0; ModuleInfo *module = 0; bool isSuspect = false; int countApiFound = 0, countApiNotFound = 0; DWORD_PTR * pIATAddress = (DWORD_PTR *)iatBuffer; SIZE_T sizeIAT = size / sizeof(DWORD_PTR); bool foundModuleBreak = false; for (SIZE_T i = 0; i < sizeIAT; i++) { //Logger::printfDialog("%08X %08X %d von %d",addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer,pIATAddress[i],i,sizeIAT); if (pIATAddress[i] == 0 || pIATAddress[i] == -1) { /*if (pIATAddress[i+1] != 0) { printf("parseIAT :: Module break\n"); }*/ /*else { printf("parseIAT :: IAT finished\n"); break; }*/ foundModuleBreak = true; } else if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) ) { apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect); if (apiFound == (ApiInfo *)1) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("apiFound == (ApiInfo *)1 -> ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),pIATAddress[i]); #endif } else if (apiFound) { countApiFound++; #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %s %d %s\r\n"),apiFound->va, apiFound->module->getFilename(), apiFound->ordinal,apiFound->name); #endif if (module != apiFound->module) { module = apiFound->module; addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, true, isSuspect); } else { addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, false, isSuspect); } } else { countApiNotFound++; addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]); //printf("parseIAT :: API not found %08X\n", pIATAddress[i]); } } else { //printf("parseIAT :: API not found %08X\n", pIATAddress[i]); countApiNotFound++; addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]); } } Logger::printfDialog(TEXT("IAT parsing finished, found %d valid APIs, missed %d APIs"),countApiFound,countApiNotFound); } void ApiReader::addFoundApiToModuleList(DWORD_PTR iatAddressVA, ApiInfo * apiFound, bool isNewModule, bool isSuspect) { if (isNewModule) { addModuleToModuleList(apiFound->module->getFilename(), iatAddressVA - targetImageBase); } addFunctionToModuleList(apiFound, iatAddressVA, iatAddressVA - targetImageBase, apiFound->ordinal, true, isSuspect); } bool ApiReader::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, moduleName); (*moduleThunkList).insert(std::pair(firstThunk,module)); return true; } void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, TEXT("?")); (*moduleThunkList).insert(std::pair(firstThunk,module)); } bool ApiReader::addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if ((*moduleThunkList).size() > 1) { iterator1 = (*moduleThunkList).begin(); while (iterator1 != (*moduleThunkList).end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == (*moduleThunkList).end()) { iterator1--; module = &(iterator1->second); break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n")); #endif break; } } } else { iterator1 = (*moduleThunkList).begin(); module = &(iterator1->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); #endif return false; } import.suspect = suspect; import.valid = valid; import.va = va; import.rva = rva; import.apiAddressVA = apiFound->va; import.ordinal = ordinal; import.hint = (WORD)apiFound->hint; wcscpy_s(import.moduleName, MAX_PATH, apiFound->module->getFilename()); strcpy_s(import.name, MAX_PATH, apiFound->name); module->thunkList.insert(std::pair(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")); #endif break; } } } else { //new unknown module addUnknownModuleToModuleList(rva); module = &((*moduleThunkList).find(rva)->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); #endif return false; } import.suspect = true; import.valid = false; import.va = iatAddressVA; import.rva = rva; import.apiAddressVA = apiAddress; import.ordinal = 0; wcscpy_s(import.moduleName, MAX_PATH, TEXT("?")); strcpy_s(import.name, MAX_PATH, "?"); module->thunkList.insert(std::pair(import.rva, import)); return true; } bool ApiReader::isApiBlacklisted( const char * functionName ) { if (SystemInformation::currenOS < WIN_VISTA_32) { if (!strcmp(functionName, "RestoreLastError")) { return true; } else { return false; } } else { return false; } /*#ifdef _WIN64 else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer")) { return true; } #endif*/ } bool ApiReader::isWinSxSModule( ModuleInfo * module ) { if (wcsstr(module->fullPath, TEXT("\\WinSxS\\"))) { return true; } else if (wcsstr(module->fullPath, TEXT("\\winsxs\\"))) { return true; } else { return false; } } diff --git a/Scylla/DisassemblerGui.cpp b/Scylla/DisassemblerGui.cpp index c1331ef..7a2b2b7 100644 --- a/Scylla/DisassemblerGui.cpp +++ b/Scylla/DisassemblerGui.cpp @@ -1,262 +1,135 @@ #include "DisassemblerGui.h" -#include "ProcessAccessHelp.h" -HWND DisassemblerGui::hWndDlg = 0; -HINSTANCE DisassemblerGui::hInstance = 0; -DWORD_PTR DisassemblerGui::startAddress = 0; -WCHAR DisassemblerGui::tempBuffer[100]; +#include "ProcessAccessHelp.h" -INT_PTR DisassemblerGui::initDialog(HINSTANCE hInst, HWND hWndParent, DWORD_PTR address) +BOOL DisassemblerGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - hInstance = hInst; - startAddress = address; - return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_DISASSEMBLER),hWndParent, (DLGPROC)disassemblerDlgProc); + ListDisassembler.Attach(GetDlgItem(IDC_LIST_DISASSEMBLER)); + + addColumnsToDisassembler(ListDisassembler); + displayDisassembly(ListDisassembler); + + return TRUE; } -LRESULT CALLBACK DisassemblerGui::disassemblerDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +void DisassemblerGui::OnContextMenu(CWindow wnd, CPoint point) { - hWndDlg = hWnd; - switch (uMsg) + if (wnd.GetDlgCtrlID() == IDC_LIST_DISASSEMBLER) { - case WM_INITDIALOG: - addColumnsToDisassembler(GetDlgItem(hWnd, IDC_LIST_DISASSEMBLER)); - displayDisassembly(); - break; + CMenuHandle hmenuTrackPopup = getCorrectSubMenu(IDR_MENU_DISASSEMBLER, 0); + + BOOL menuItem = hmenuTrackPopup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, wnd); + hmenuTrackPopup.DestroyMenu(); - case WM_CONTEXTMENU: - OnContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - break; - case WM_COMMAND: - switch(LOWORD(wParam)) + if (menuItem) { - case IDC_BTN_PICKDLL_OK: - /*index = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_DLLSELECT)); - if (index != -1) + int selection = ListDisassembler.GetSelectionMark(); + if (selection != -1) //valid selection? { - selectedModule = &(*moduleList).at(index); - EndDialog(hWnd, 1); - }*/ - - return TRUE; - case IDC_BTN_PICKDLL_CANCEL: - EndDialog(hWnd, 0); - return TRUE; - case IDCANCEL: - EndDialog(hWnd, 0); - return TRUE; + int column = -1; + switch (menuItem) + { + case ID__DIS_ADDRESS: + column = COL_ADDRESS; + break; + case ID__DIS_SIZE: + column = COL_INSTRUCTION_SIZE; + break; + case ID__DIS_OPCODES: + column = COL_OPCODES; + break; + case ID__DIS_INSTRUCTIONS: + column = COL_INSTRUCTION; + break; + } + if(column != -1) + { + tempBuffer[0] = '\0'; + ListDisassembler.GetItemText(selection, column, tempBuffer, _countof(tempBuffer)); + copyToClipboard(tempBuffer); + } + } } } - return FALSE; } -void DisassemblerGui::addColumnsToDisassembler( HWND list ) +void DisassemblerGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { - if (list) - { - LVCOLUMN * lvc = (LVCOLUMN*)malloc(sizeof(LVCOLUMN)); - - ListView_SetExtendedListViewStyleEx(list,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT); - - lvc->mask = LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_LEFT; - lvc->cx = 105; - lvc->pszText = L"Address"; - ListView_InsertColumn(list, COL_ADDRESS, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_CENTER; - lvc->cx = 40; - lvc->pszText = L"Size"; - ListView_InsertColumn(list, COL_INSTRUCTION_SIZE, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_LEFT; - lvc->cx = 130; - lvc->pszText = L"OpCodes"; - ListView_InsertColumn(list, COL_OPCODES, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_LEFT; - lvc->cx = 200; - lvc->pszText = L"Instructions"; - ListView_InsertColumn(list, COL_INSTRUCTION, lvc); - - - free(lvc); - } + EndDialog(0); } -void DisassemblerGui::displayDisassembly() +void DisassemblerGui::addColumnsToDisassembler(CListViewCtrl& list) { - LVITEM item; - HWND hList = GetDlgItem(hWndDlg, IDC_LIST_DISASSEMBLER); + list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - ListView_DeleteAllItems(hList); + list.InsertColumn(COL_ADDRESS, L"Address", LVCFMT_LEFT, 105); + list.InsertColumn(COL_INSTRUCTION_SIZE, L"Size", LVCFMT_CENTER, 40); + list.InsertColumn(COL_OPCODES, L"OpCodes", LVCFMT_LEFT, 130); + list.InsertColumn(COL_INSTRUCTION, L"Instructions", LVCFMT_LEFT, 200); +} - item.mask = LVIF_TEXT; +void DisassemblerGui::displayDisassembly(CListViewCtrl& list) +{ + BYTE data[DISASSEMBLER_GUI_MEMORY_SIZE]; - BYTE * data = new BYTE[DISASSEMBLER_GUI_MEMORY_SIZE]; + list.DeleteAllItems(); - ProcessAccessHelp::readMemoryFromProcess(startAddress,DISASSEMBLER_GUI_MEMORY_SIZE, data); + if(!ProcessAccessHelp::readMemoryFromProcess(startAddress, sizeof(data), data)) + return; - ProcessAccessHelp::disassembleMemory(data,DISASSEMBLER_GUI_MEMORY_SIZE, startAddress); + ProcessAccessHelp::disassembleMemory(data, sizeof(data), startAddress); for (unsigned int i = 0; i < ProcessAccessHelp::decodedInstructionsCount; i++) { #ifdef _WIN64 swprintf_s(tempBuffer, _countof(tempBuffer),L"%016I64X",ProcessAccessHelp::decodedInstructions[i].offset); #else swprintf_s(tempBuffer, _countof(tempBuffer),L"%08X",ProcessAccessHelp::decodedInstructions[i].offset); #endif - item.iItem = i; - item.iSubItem = COL_ADDRESS; - item.pszText = tempBuffer; - item.iItem = ListView_InsertItem(hList, &item); + list.InsertItem(i, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%02d",ProcessAccessHelp::decodedInstructions[i].size); - item.iSubItem = COL_INSTRUCTION_SIZE; - item.pszText = tempBuffer; - ListView_SetItem(hList, &item); + list.SetItemText(i, COL_INSTRUCTION_SIZE, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%-24S",(char *)ProcessAccessHelp::decodedInstructions[i].instructionHex.p); - item.iSubItem = COL_OPCODES; - item.pszText = tempBuffer; - ListView_SetItem(hList, &item); + list.SetItemText(i, COL_OPCODES, tempBuffer); swprintf_s(tempBuffer, _countof(tempBuffer),L"%S%S%S",(char*)ProcessAccessHelp::decodedInstructions[i].mnemonic.p, ProcessAccessHelp::decodedInstructions[i].operands.length != 0 ? " " : "", (char*)ProcessAccessHelp::decodedInstructions[i].operands.p); - item.iSubItem = COL_INSTRUCTION; - item.pszText = tempBuffer; - ListView_SetItem(hList, &item); + list.SetItemText(i, COL_INSTRUCTION, tempBuffer); } - - delete [] data; } -void DisassemblerGui::OnContextMenu(int x, int y) -{ - HWND hwnd = 0; - int selection; - POINT pt = { x, y }; // location of mouse click - HTREEITEM selectedTreeNode = 0; - - if ((hwnd = mouseInDialogItem(IDC_LIST_DISASSEMBLER, pt)) != NULL) +void DisassemblerGui::copyToClipboard(const WCHAR * text) +{ + if(OpenClipboard()) { - HMENU hmenuTrackPopup = getCorrectSubMenu(IDR_MENU_DISASSEMBLER, 0); - - BOOL menuItem = TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, 0); - - if (menuItem) + EmptyClipboard(); + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (wcslen(text)+1)*sizeof(WCHAR)); + if(hMem) { - selection = ListView_GetSelectionMark(hwnd); - if (selection != -1) //valid selection? + wcscpy((WCHAR *)GlobalLock(hMem), text); + GlobalUnlock(hMem); + if(!SetClipboardData(CF_UNICODETEXT, hMem)) { - switch (menuItem) - { - case ID__DIS_ADDRESS: - getModuleListItem(COL_ADDRESS,selection,tempBuffer); - copyToClipboard(); - break; - case ID__DIS_SIZE: - getModuleListItem(COL_INSTRUCTION_SIZE,selection,tempBuffer); - copyToClipboard(); - break; - case ID__DIS_OPCODES: - getModuleListItem(COL_OPCODES,selection,tempBuffer); - copyToClipboard(); - break; - case ID__DIS_INSTRUCTIONS: - getModuleListItem(COL_INSTRUCTION,selection,tempBuffer); - copyToClipboard(); - break; - } + GlobalFree(hMem); } } + CloseClipboard(); } - -} - -void DisassemblerGui::copyToClipboard() -{ - HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(tempBuffer)); - LPVOID lock = GlobalLock(hMem); - - CopyMemory(lock,tempBuffer, sizeof(tempBuffer)); - - if (!OpenClipboard(hWndDlg)) - return; - - EmptyClipboard(); - - GlobalUnlock(hMem); - - SetClipboardData(CF_UNICODETEXT, hMem); - CloseClipboard(); - - GlobalFree(hMem); } -void DisassemblerGui::getModuleListItem(int column, int iItem, WCHAR * buffer) +CMenuHandle DisassemblerGui::getCorrectSubMenu(int menuItem, int subMenuItem) { - LVITEM pitem = {0}; - pitem.iItem = iItem; - pitem.iSubItem = column; - pitem.mask = LVIF_TEXT; - pitem.cchTextMax = 256; - pitem.pszText = buffer; - ListView_GetItem(GetDlgItem(hWndDlg, IDC_LIST_DISASSEMBLER),&pitem); -} - + CMenuHandle hmenu; // top-level menu -HMENU DisassemblerGui::getCorrectSubMenu(int menuItem, int subMenuItem) -{ - HMENU hmenu; // top-level menu - HMENU hmenuTrackPopup; // shortcut menu // Load the menu resource. - if ((hmenu = LoadMenu(hInstance, MAKEINTRESOURCE(menuItem))) == NULL) - return 0; + if (!hmenu.LoadMenu(menuItem)) + return NULL; - hmenuTrackPopup = GetSubMenu(hmenu, subMenuItem); - - if (hmenuTrackPopup) - { - return hmenuTrackPopup; - } - else - { - return 0; - } -} - -HWND DisassemblerGui::mouseInDialogItem(int dlgItem, POINT pt) -{ - RECT rc; - HWND hwnd = GetDlgItem(hWndDlg, dlgItem); - if (hwnd) - { - // Get the bounding rectangle of the client area. - GetClientRect(hwnd, &rc); - - // Convert the mouse position to client coordinates. - ScreenToClient(hwnd, &pt); - - // If the position is in the client area, display a - // shortcut menu. - if (PtInRect(&rc, pt)) - { - return hwnd; - } - else - { - return 0; - } - } - else - { - return 0; - } + return hmenu.GetSubMenu(subMenuItem); } diff --git a/Scylla/DisassemblerGui.h b/Scylla/DisassemblerGui.h index 13dd93c..9a769cc 100644 --- a/Scylla/DisassemblerGui.h +++ b/Scylla/DisassemblerGui.h @@ -1,31 +1,68 @@ #pragma once -#include "MainGui.h" +#include +#include "resource.h" -static const enum DisassemblerColumns { - COL_ADDRESS, - COL_INSTRUCTION_SIZE, - COL_OPCODES, - COL_INSTRUCTION -}; - -#define DISASSEMBLER_GUI_MEMORY_SIZE 0x100 +// WTL +#include // base ATL classes +#include // base WTL classes +#include // ATL GUI classes +#include // WTL utility classes like CString +#include // WTL enhanced msg map macros +#include // WTL controls -class DisassemblerGui { +class DisassemblerGui : public CDialogImpl +{ public: - static WCHAR tempBuffer[100]; - static HWND hWndDlg; - static HINSTANCE hInstance; - static DWORD_PTR startAddress; - - static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent, DWORD_PTR address); - static void addColumnsToDisassembler( HWND list ); - static void displayDisassembly(); -private: - static LRESULT CALLBACK disassemblerDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static HWND mouseInDialogItem(int dlgItem, POINT pt); - static void OnContextMenu(int x, int y); - static HMENU getCorrectSubMenu(int menuItem, int subMenuItem); - static void getModuleListItem(int column, int iItem, WCHAR * buffer); - static void copyToClipboard(); -}; \ No newline at end of file + enum { IDD = IDD_DLG_DISASSEMBLER }; + + BEGIN_MSG_MAP(DisassemblerGui) + MSG_WM_INITDIALOG(OnInitDialog) + MSG_WM_CONTEXTMENU(OnContextMenu) + + COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) + END_MSG_MAP() + + DisassemblerGui(DWORD_PTR startAddress) : startAddress(startAddress) { } + +protected: + + // Variables + + static const size_t DISASSEMBLER_GUI_MEMORY_SIZE = 0x100; + + WCHAR tempBuffer[100]; + DWORD_PTR startAddress; + + // Controls + + CListViewCtrl ListDisassembler; + + enum DisassemblerColumns { + COL_ADDRESS, + COL_INSTRUCTION_SIZE, + COL_OPCODES, + COL_INSTRUCTION + }; + +protected: + + // Message handlers + + BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); + void OnContextMenu(CWindow wnd, CPoint point); + void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); + + // GUI functions + + void addColumnsToDisassembler(CListViewCtrl& list); + void displayDisassembly(CListViewCtrl& list); + + // Popup menu functions + + CMenuHandle getCorrectSubMenu(int menuItem, int subMenuItem); + + // Misc + + void copyToClipboard(const WCHAR * text); +}; diff --git a/Scylla/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp index 3ab5c7b..7012139 100644 --- a/Scylla/ImportsHandling.cpp +++ b/Scylla/ImportsHandling.cpp @@ -1,766 +1,767 @@ - #include "ImportsHandling.h" + +#include "Thunks.h" #include "definitions.h" //#define DEBUG_COMMENTS bool ImportModuleThunk::isValid() { std::map::iterator iterator = thunkList.begin(); while (iterator != thunkList.end()) { if (iterator->second.valid == false) { return false; } iterator++; } return true; } DWORD_PTR ImportModuleThunk::getFirstThunk() { if (thunkList.size() > 0) { std::map::iterator iterator = thunkList.begin(); return iterator->first; } else { return 0; } } /*bool ImportsHandling::addModule(WCHAR * moduleName, DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, moduleName); moduleList.insert(std::pair(firstThunk,module)); return true; }*/ /*bool ImportsHandling::addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if (moduleList.size() > 1) { iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleList.end()) { iterator1--; module = &(iterator1->second); break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } } } else { iterator1 = moduleList.begin(); module = &(iterator1->second); } if (!module) { Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(""),rva); return false; } //TODO import.suspect = true; import.valid = false; import.va = va; import.rva = rva; import.ordinal = ordinal; wcscpy_s(import.moduleName, MAX_PATH, moduleName); strcpy_s(import.name, MAX_PATH, name); module->thunkList.insert(std::pair(import.rva, import)); return true; }*/ void ImportsHandling::displayAllImports() { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; CTreeItem module; CTreeItem apiFunction; TreeImports.DeleteAllItems(); iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); module = addDllToTreeView(TreeImports,moduleThunk->moduleName,moduleThunk->firstThunk,moduleThunk->thunkList.size(),moduleThunk->isValid()); moduleThunk->hTreeItem = module; iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); apiFunction = addApiToTreeView(TreeImports,module,importThunk); importThunk->hTreeItem = apiFunction; iterator2++; } iterator1++; } } CTreeItem ImportsHandling::addDllToTreeView(CTreeViewCtrl& idTreeView, const WCHAR * dllName, DWORD_PTR firstThunk, size_t numberOfFunctions, bool valid) { WCHAR validString[4]; if (valid) { wcscpy_s(validString,_countof(validString),TEXT("YES")); } else { wcscpy_s(validString,_countof(validString),TEXT("NO")); } swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" NbThunk: %02X (dec: %02d) valid: %s"),dllName,firstThunk,numberOfFunctions,numberOfFunctions,validString); return idTreeView.InsertItem(stringBuffer, NULL, TVI_ROOT); } -CTreeItem ImportsHandling::addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk) +CTreeItem ImportsHandling::addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk) { if (importThunk->ordinal != 0) { if (importThunk->name[0] != 0x00) { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name); } else { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal); } swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->va,importThunk->rva,importThunk->moduleName,tempString); } else { swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" ptr: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(""),importThunk->va,importThunk->rva,importThunk->apiAddressVA); } return idTreeView.InsertItem(stringBuffer, parentDll, TVI_LAST); } void ImportsHandling::showImports(bool invalid, bool suspect) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; TreeImports.SetFocus(); TreeImports.SelectItem(NULL); //remove selection iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (invalid && !importThunk->valid) { selectItem(TreeImports, importThunk->hTreeItem); setFocus(TreeImports, importThunk->hTreeItem); } else if (suspect && importThunk->suspect) { selectItem(TreeImports, importThunk->hTreeItem); setFocus(TreeImports, importThunk->hTreeItem); } else { unselectItem(TreeImports, importThunk->hTreeItem); } iterator2++; } iterator1++; } } -bool ImportsHandling::isItemSelected(CTreeViewCtrl& hwndTV, CTreeItem hItem) +bool ImportsHandling::isItemSelected(const CTreeViewCtrl& hwndTV, CTreeItem hItem) { const UINT state = TVIS_SELECTED; return ((hwndTV.GetItemState(hItem, state) & state) == state); } void ImportsHandling::unselectItem(CTreeViewCtrl& hwndTV, CTreeItem htItem) { selectItem(hwndTV, htItem, false); } bool ImportsHandling::selectItem(CTreeViewCtrl& hwndTV, CTreeItem hItem, bool select) { const UINT state = TVIS_SELECTED; return FALSE != hwndTV.SetItemState(hItem, (select ? state : 0), state); } void ImportsHandling::setFocus(CTreeViewCtrl& hwndTV, CTreeItem htItem) { // the current focus CTreeItem htFocus = hwndTV.GetSelectedItem(); if ( htItem ) { // set the focus if ( htItem != htFocus ) { // remember the selection state of the item bool wasSelected = isItemSelected(hwndTV, htItem); if ( htFocus && isItemSelected(hwndTV, htFocus) ) { // prevent the tree from unselecting the old focus which it // would do by default (TreeView_SelectItem unselects the // focused item) hwndTV.SelectItem(NULL); selectItem(hwndTV, htFocus); } hwndTV.SelectItem(htItem); if ( !wasSelected ) { // need to clear the selection which TreeView_SelectItem() gave // us unselectItem(hwndTV, htItem); } //else: was selected, still selected - ok } //else: nothing to do, focus already there } else { if ( htFocus ) { bool wasFocusSelected = isItemSelected(hwndTV, htFocus); // just clear the focus hwndTV.SelectItem(NULL); if ( wasFocusSelected ) { // restore the selection state selectItem(hwndTV, htFocus); } } //else: nothing to do, no focus already } } -bool ImportsHandling::invalidateFunction( CTreeItem selectedTreeNode ) +bool ImportsHandling::invalidateFunction(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { importThunk->ordinal = 0; importThunk->hint = 0; importThunk->valid = false; importThunk->suspect = false; importThunk->moduleName[0] = 0; importThunk->name[0] = 0; updateImportInTreeView(importThunk); updateModuleInTreeView(moduleThunk); return true; } iterator2++; } iterator1++; } return false; } void ImportsHandling::updateImportInTreeView(ImportThunk * importThunk) { if (importThunk->ordinal != 0) { if (importThunk->name[0] != 0x00) { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X name: %S"),importThunk->ordinal,importThunk->name); } else { swprintf_s(tempString, _countof(tempString),TEXT("ord: %04X"),importThunk->ordinal); } swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" mod: %s %s"),importThunk->va,importThunk->rva,importThunk->moduleName,tempString); } else { swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("va: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" rva: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" prt: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(""),importThunk->va,importThunk->rva,importThunk->apiAddressVA); } TreeImports.SetItemText(importThunk->hTreeItem, stringBuffer); } void ImportsHandling::updateModuleInTreeView(ImportModuleThunk * importThunk) { WCHAR validString[4]; if (importThunk->isValid()) { wcscpy_s(validString,_countof(validString),TEXT("YES")); } else { wcscpy_s(validString,_countof(validString),TEXT("NO")); } swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%s FThunk: ")TEXT(PRINTF_DWORD_PTR_HALF)TEXT(" NbThunk: %02X (dec: %02d) valid: %s"),importThunk->moduleName,importThunk->firstThunk,importThunk->thunkList.size(),importThunk->thunkList.size(),validString); TreeImports.SetItemText(importThunk->hTreeItem, stringBuffer); } -bool ImportsHandling::cutThunk( CTreeItem selectedTreeNode ) +bool ImportsHandling::cutThunk(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { TreeImports.DeleteItem(importThunk->hTreeItem); moduleThunk->thunkList.erase(iterator2); if (moduleThunk->thunkList.empty()) { TreeImports.DeleteItem(moduleThunk->hTreeItem); moduleList.erase(iterator1); } else { updateModuleInTreeView(moduleThunk); } return true; } iterator2++; } iterator1++; } return false; } -bool ImportsHandling::deleteTreeNode( CTreeItem selectedTreeNode ) +bool ImportsHandling::deleteTreeNode(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); if (moduleThunk->hTreeItem == selectedTreeNode) { TreeImports.DeleteItem(moduleThunk->hTreeItem); moduleThunk->thunkList.clear(); moduleList.erase(iterator1); return true; } else { iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { TreeImports.DeleteItem(moduleThunk->hTreeItem); moduleThunk->thunkList.clear(); moduleList.erase(iterator1); return true; } iterator2++; } } iterator1++; } return false; } -DWORD_PTR ImportsHandling::getApiAddressByNode( CTreeItem selectedTreeNode ) +DWORD_PTR ImportsHandling::getApiAddressByNode(CTreeItem selectedTreeNode) { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->hTreeItem == selectedTreeNode) { return importThunk->apiAddressVA; } iterator2++; } iterator1++; } return 0; } void ImportsHandling::scanAndFixModuleList() { std::map::iterator iterator1; std::map::iterator iterator2; ImportModuleThunk * moduleThunk; ImportThunk * importThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); iterator2 = moduleThunk->thunkList.begin(); while (iterator2 != moduleThunk->thunkList.end()) { importThunk = &(iterator2->second); if (importThunk->moduleName[0] == 0 || importThunk->moduleName[0] == L'?') { addNotFoundApiToModuleList(importThunk); } else { if (isNewModule(importThunk->moduleName)) { addModuleToModuleList(importThunk->moduleName, importThunk->rva); } addFunctionToModuleList(importThunk); } iterator2++; } moduleThunk->thunkList.clear(); iterator1++; } moduleList.clear(); moduleList.insert(moduleListNew.begin(), moduleListNew.end()); moduleListNew.clear(); } -bool ImportsHandling::findNewModules( std::map & thunkList ) +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, MAX_PATH, moduleName); moduleListNew.insert(std::pair(firstThunk,module)); return true; } bool ImportsHandling::isNewModule(const WCHAR * moduleName) { std::map::iterator iterator1; iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (!_wcsicmp(iterator1->second.moduleName, moduleName)) { return false; } iterator1++; } return true; } void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk) { ImportModuleThunk module; module.firstThunk = firstThunk; wcscpy_s(module.moduleName, MAX_PATH, L"?"); moduleListNew.insert(std::pair(firstThunk,module)); } -bool ImportsHandling::addNotFoundApiToModuleList(ImportThunk * apiNotFound) +bool ImportsHandling::addNotFoundApiToModuleList(const ImportThunk * apiNotFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; DWORD_PTR rva = apiNotFound->rva; if (moduleListNew.size() > 0) { iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleListNew.end()) { iterator1--; //new unknown module if (iterator1->second.moduleName[0] == L'?') { module = &(iterator1->second); } else { addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } break; } else if (rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog("Error iterator1 != (*moduleThunkList).end()\r\n"); #endif break; } } } else { //new unknown module addUnknownModuleToModuleList(apiNotFound->rva); module = &(moduleListNew.find(rva)->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva); #endif return false; } import.suspect = true; import.valid = false; import.va = apiNotFound->va; import.rva = apiNotFound->rva; import.apiAddressVA = apiNotFound->apiAddressVA; import.ordinal = 0; wcscpy_s(import.moduleName, MAX_PATH, L"?"); strcpy_s(import.name, MAX_PATH, "?"); module->thunkList.insert(std::pair(import.rva, import)); return true; } -bool ImportsHandling::addFunctionToModuleList(ImportThunk * apiFound) +bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound) { ImportThunk import; ImportModuleThunk * module = 0; std::map::iterator iterator1; if (moduleListNew.size() > 1) { iterator1 = moduleListNew.begin(); while (iterator1 != moduleListNew.end()) { if (apiFound->rva >= iterator1->second.firstThunk) { iterator1++; if (iterator1 == moduleListNew.end()) { iterator1--; module = &(iterator1->second); break; } else if (apiFound->rva < iterator1->second.firstThunk) { iterator1--; module = &(iterator1->second); break; } } else { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("Error iterator1 != moduleListNew.end()\r\n")); #endif break; } } } else { iterator1 = moduleListNew.begin(); module = &(iterator1->second); } if (!module) { #ifdef DEBUG_COMMENTS Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),apiFound->rva); #endif return false; } import.suspect = apiFound->suspect; import.valid = apiFound->valid; import.va = apiFound->va; import.rva = apiFound->rva; import.apiAddressVA = apiFound->apiAddressVA; import.ordinal = apiFound->ordinal; import.hint = apiFound->hint; wcscpy_s(import.moduleName, MAX_PATH, apiFound->moduleName); strcpy_s(import.name, MAX_PATH, apiFound->name); module->thunkList.insert(std::pair(import.rva, import)); return true; } void ImportsHandling::expandAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_EXPAND); } void ImportsHandling::collapseAllTreeNodes() { changeExpandStateOfTreeNodes(TVE_COLLAPSE); } void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag) { std::map::iterator iterator1; ImportModuleThunk * moduleThunk; iterator1 = moduleList.begin(); while (iterator1 != moduleList.end()) { moduleThunk = &(iterator1->second); TreeImports.Expand(moduleThunk->hTreeItem, flag); iterator1++; } } diff --git a/Scylla/ImportsHandling.h b/Scylla/ImportsHandling.h index 5ae9ea3..9499bf8 100644 --- a/Scylla/ImportsHandling.h +++ b/Scylla/ImportsHandling.h @@ -1,58 +1,61 @@ #pragma once -#include "Thunks.h" +#include +// WTL #include #include -#include +#include // CTreeViewCtrl, CTreeItem + +class ImportThunk; +class ImportModuleThunk; class ImportsHandling { public: std::map moduleList; std::map moduleListNew; //bool addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect); //bool addModule(WCHAR * moduleName, DWORD_PTR firstThunk); ImportsHandling(CTreeViewCtrl& TreeImports) : TreeImports(TreeImports) { } void displayAllImports(); void showImports(bool invalid, bool suspect); bool invalidateFunction(CTreeItem selectedTreeNode); - bool cutThunk( CTreeItem selectedTreeNode ); - bool deleteTreeNode( CTreeItem selectedTreeNode ); + bool cutThunk(CTreeItem selectedTreeNode); + bool deleteTreeNode(CTreeItem selectedTreeNode); void updateImportInTreeView(ImportThunk * importThunk); void updateModuleInTreeView(ImportModuleThunk * importThunk); - DWORD_PTR getApiAddressByNode( CTreeItem selectedTreeNode ); + DWORD_PTR getApiAddressByNode(CTreeItem selectedTreeNode); void scanAndFixModuleList(); void expandAllTreeNodes(); void collapseAllTreeNodes(); private: DWORD numberOfFunctions; WCHAR stringBuffer[600]; // o_O - WCHAR tempString[300]; CTreeViewCtrl& TreeImports; CTreeItem addDllToTreeView(CTreeViewCtrl& idTreeView, const WCHAR * dllName, DWORD_PTR firstThunk, size_t numberOfFunctions, bool valid); - CTreeItem addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk); + CTreeItem addApiToTreeView(CTreeViewCtrl& idTreeView, CTreeItem parentDll, const ImportThunk * importThunk); - bool isItemSelected(CTreeViewCtrl& hwndTV, CTreeItem hItem); + bool isItemSelected(const CTreeViewCtrl& hwndTV, CTreeItem hItem); void unselectItem(CTreeViewCtrl& hwndTV, CTreeItem htItem); bool selectItem(CTreeViewCtrl& hwndTV, CTreeItem hItem, bool select = true); void setFocus(CTreeViewCtrl& hwndTV, CTreeItem htItem); - bool findNewModules( std::map & thunkList ); + bool findNewModules(std::map & thunkList); bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk); void addUnknownModuleToModuleList(DWORD_PTR firstThunk); - bool addNotFoundApiToModuleList(ImportThunk * apiNotFound); - bool addFunctionToModuleList(ImportThunk * apiFound); + bool addNotFoundApiToModuleList(const ImportThunk * apiNotFound); + bool addFunctionToModuleList(const ImportThunk * apiFound); bool isNewModule(const WCHAR * moduleName); void changeExpandStateOfTreeNodes(UINT flag); -}; \ No newline at end of file +}; diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp index 0ce1e2a..5438fc7 100644 --- a/Scylla/MainGui.cpp +++ b/Scylla/MainGui.cpp @@ -1,824 +1,826 @@ #include "MainGui.h" #include "definitions.h" #include "PluginLoader.h" #include "ConfigurationHolder.h" #include "PeDump.h" #include "PeRebuild.h" #include "DllInjectionPlugin.h" #include "DisassemblerGui.h" #include "NativeWinApi.h" #include "ImportRebuild.h" #include "SystemInformation.h" #include "AboutGui.h" #include "OptionsGui.h" -MainGui::MainGui(HINSTANCE hInstance) : selectedProcess(0), importsHandling(TreeImports) +MainGui::MainGui() : selectedProcess(0), importsHandling(TreeImports) { - this->hInstance = hInstance; - Logger::getDebugLogFilePath(); ConfigurationHolder::loadConfiguration(); PluginLoader::findAllPlugins(); NativeWinApi::initialize(); SystemInformation::getSystemInformation(); } BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { if (SystemInformation::currenOS == UNKNOWN_OS) { MessageBox(L"Operating System is not supported", L"Error Operating System", MB_ICONERROR); EndDialog(0); return FALSE; } if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue()) { processLister.setDebugPrivileges(); } processAccessHelp.getProcessModules(GetCurrentProcessId(), processAccessHelp.ownModuleList); TreeImports.Attach(GetDlgItem(IDC_TREE_IMPORTS)); ComboProcessList.Attach(GetDlgItem(IDC_CBO_PROCESSLIST)); ListLog.Attach(GetDlgItem(IDC_LIST_LOG)); EditOEPAddress.Attach(GetDlgItem(IDC_EDIT_OEPADDRESS)); EditIATAddress.Attach(GetDlgItem(IDC_EDIT_IATADDRESS)); EditIATSize.Attach(GetDlgItem(IDC_EDIT_IATSIZE)); EditOEPAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); - EditOEPAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); - EditOEPAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); + EditIATAddress.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); + EditIATSize.LimitText(MAX_HEX_VALUE_EDIT_LENGTH); enableDialogButtons(FALSE); setIconAndDialogCaption(); return TRUE; } void MainGui::OnLButtonDown(UINT nFlags, CPoint point) { } void MainGui::OnContextMenu(CWindow wnd, CPoint point) { //TV_ITEM tvi; //WCHAR ttt[260] = {0}; //HTREEITEM selectedTreeNode = 0; if(wnd.GetDlgCtrlID() == IDC_TREE_IMPORTS) { if(TreeImports.GetCount()) //module list should not be empty { /*selectedTreeNode = (HTREEITEM)SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETNEXTITEM,TVGN_CARET,(LPARAM)selectedTreeNode); tvi.mask=TVIF_TEXT; // item text attrivute tvi.pszText=ttt; // Text is the pointer to the text tvi.cchTextMax=260; // size of text to retrieve. tvi.hItem=selectedTreeNode; // the selected item SendDlgItemMessage(hWndMainDlg,IDC_TREE_IMPORTS,TVM_GETITEM,TVGN_CARET,(LPARAM)&tvi); Logger::printfDialog(L"selected %s",tvi.pszText);*/ //CPoint pt = GetMessagePos(); //UINT flags = 0; //if(TreeImports.HitTest(pt, &flags)) //{ DisplayContextMenuImports(wnd, point); //} } return; } //if (PtInRect(&rc, pt)) //{ // ClientToScreen(hwnd, &pt); // DisplayContextMenu(hwnd, pt); // return TRUE; //} } LRESULT MainGui::OnTreeImportsClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_CLICK"); return FALSE; } LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_DBLCLK"); return FALSE; } LRESULT MainGui::OnTreeImportsRightClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_RCLICK"); /* HTREEITEM selectedTreeNode = TreeImports.GetNextItem(NULL, TVGN_DROPHILITE); if(selectedTreeNode != NULL) { TreeImports.Select(selectedTreeNode, TVGN_CARET); } */ return FALSE; } LRESULT MainGui::OnTreeImportsRightDoubleClick(const NMHDR* pnmh) { //Logger::printfDialog(L"NM_RDBLCLK"); return FALSE; } 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) { TreeImports.DeleteAllItems(); importsHandling.moduleList.clear(); } void MainGui::OnClearLog(UINT uNotifyCode, int nID, CWindow wndCtl) { clearOutputLog(); } void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl) { showAboutDialog(); } void MainGui::setIconAndDialogCaption() { CIconHandle hicon; // Resource leak! if(hicon.LoadIcon(IDI_ICON_SCYLLA1)) { SetIcon(hicon, TRUE); SetIcon(hicon, FALSE); } SetWindowText(TEXT(APPNAME)TEXT(" ")TEXT(ARCHITECTURE)TEXT(" ")TEXT(APPVERSION)); } void MainGui::pickDllActionHandler() { - if (PickDllGui::initDialog(hInstance,m_hWnd, processAccessHelp.moduleList)) + PickDllGui dlgPickDll(processAccessHelp.moduleList); + if(dlgPickDll.DoModal()) { //get selected module - processAccessHelp.selectedModule = PickDllGui::selectedModule; + processAccessHelp.selectedModule = dlgPickDll.getSelectedModule(); Logger::printfDialog(TEXT("->>> Module %s selected."), processAccessHelp.selectedModule->getFilename()); Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),processAccessHelp.selectedModule->modBaseAddr,processAccessHelp.selectedModule->modBaseSize); + } else { processAccessHelp.selectedModule = 0; } } void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode) { DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode); if (address) { - DisassemblerGui::initDialog(hInstance,m_hWnd,address); + DisassemblerGui dlgDisassembler(address); + dlgDisassembler.DoModal(); } - } void MainGui::processSelectedActionHandler(int index) { std::vector& processList = processLister.getProcessList(); Process &process = processList.at(index); selectedProcess = &process; enableDialogButtons(TRUE); Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath); if (processAccessHelp.hProcess != 0) { processAccessHelp.closeProcessHandle(); apiReader.clearAll(); } if (!processAccessHelp.openProcessHandle(process.PID)) { Logger::printfDialog(TEXT("Error: Cannot open process handle.")); return; } processAccessHelp.getProcessModules(process.PID, processAccessHelp.moduleList); apiReader.readApisFromModuleList(); Logger::printfDialog(TEXT("Loading modules done.")); //TODO improve processAccessHelp.selectedModule = 0; processAccessHelp.targetSizeOfImage = process.imageSize; processAccessHelp.targetImageBase = process.imageBase; ProcessAccessHelp::getSizeOfImageCurrentProcess(); process.imageSize = (DWORD)processAccessHelp.targetSizeOfImage; Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),process.imageBase, process.imageSize); selectedProcess->entryPoint = ProcessAccessHelp::getEntryPointFromFile(selectedProcess->fullPath); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),selectedProcess->entryPoint + selectedProcess->imageBase); EditOEPAddress.SetWindowText(stringBuffer); } void MainGui::fillProcessListComboBox(CComboBox& hCombo) { hCombo.ResetContent(); std::vector& processList = processLister.getProcessListSnapshot(); for (size_t i = 0; i < processList.size(); i++) { swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("0x%04X - %s - %s"),processList[i].PID,processList[i].filename,processList[i].fullPath); 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(); } } void MainGui::showInvalidImportsActionHandler() { importsHandling.showImports(true, false); } void MainGui::showSuspectImportsActionHandler() { importsHandling.showImports(false, true); } void MainGui::iatAutosearchActionHandler() { DWORD_PTR searchAddress = 0; DWORD_PTR addressIAT = 0; DWORD sizeIAT = 0; IATSearch iatSearch; if(EditOEPAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 1) { searchAddress = stringToDwordPtr(stringBuffer); if (searchAddress) { if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT)) { Logger::printfDialog(TEXT("IAT found at VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d)"),addressIAT, addressIAT - processAccessHelp.targetImageBase,sizeIAT,sizeIAT); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),addressIAT); EditIATAddress.SetWindowText(stringBuffer); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("%08X"),sizeIAT); EditIATSize.SetWindowText(stringBuffer); swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("IAT found! Start Address ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size 0x%04X (%d) "),addressIAT,sizeIAT,sizeIAT); MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION); } else { Logger::printfDialog(TEXT("IAT not found at OEP ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("!"),searchAddress); } } } } void MainGui::getImportsActionHandler() { DWORD_PTR addressIAT = 0; DWORD sizeIAT = 0; if (EditIATAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { addressIAT = stringToDwordPtr(stringBuffer); } if (EditIATSize.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { sizeIAT = wcstoul(stringBuffer, NULL, 16); } if (addressIAT && sizeIAT) { apiReader.readAndParseIAT(addressIAT, sizeIAT,importsHandling.moduleList); importsHandling.displayAllImports(); } } DWORD_PTR MainGui::stringToDwordPtr(WCHAR * hexString) { DWORD_PTR address = 0; #ifdef _WIN64 address = _wcstoui64(hexString, NULL, 16); #else address = wcstoul(hexString, NULL, 16); #endif if (address == 0) { #ifdef DEBUG_COMMENTS Logger::debugLog(L"stringToDwordPtr :: address == 0, %s",hexString); #endif return 0; } else { return address; } } -void MainGui::DisplayContextMenuImports(CWindow hwnd, POINT pt) +void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt) { BOOL menuItem = 0; CTreeItem selectedTreeNode = 0; std::vector &pluginList = PluginLoader::getScyllaPluginList(); CMenuHandle hmenuTrackPopup = getCorrectSubMenu(IDR_MENU_IMPORTS, 0); if (hmenuTrackPopup) { appendPluginListToMenu(hmenuTrackPopup); menuItem = hmenuTrackPopup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); hmenuTrackPopup.DestroyMenu(); if (menuItem) { if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(PluginLoader::getScyllaPluginList().size() + PluginLoader::getImprecPluginList().size() + PLUGIN_MENU_BASE_ID))) { //wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName); //MessageBox(stringBuffer, L"plugin selection"); pluginActionHandler(menuItem); return; } selectedTreeNode = TreeImports.GetSelectedItem(); switch (menuItem) { case ID__INVALIDATEFUNCTION: { importsHandling.invalidateFunction(selectedTreeNode); } break; case ID__DISASSEMBLE: { startDisassemblerGui(selectedTreeNode); } break; case ID__CUTTHUNK: { importsHandling.cutThunk(selectedTreeNode); } break; case ID__DELETETREENODE: { importsHandling.deleteTreeNode(selectedTreeNode); } break; case ID__EXPANDALLNODES: { importsHandling.expandAllTreeNodes(); } break; case ID__COLLAPSEALLNODES: { importsHandling.collapseAllTreeNodes(); } break; } } } } CMenuHandle MainGui::getCorrectSubMenu(int menuItem, int subMenuItem) { - CMenuHandle hmenu; // top-level menu + CMenuHandle hmenu; // top-level menu // Load the menu resource. if (!hmenu.LoadMenu(menuItem)) return NULL; return hmenu.GetSubMenu(subMenuItem); } -void MainGui::DisplayContextMenu(CWindow hwnd, POINT pt) +void MainGui::DisplayContextMenu(CWindow hwnd, CPoint pt) { CMenu hmenu; // top-level menu CMenuHandle hmenuTrackPopup; // shortcut menu int menuItem; // selected menu item // Load the menu resource. if (!hmenu.LoadMenu(IDR_MENU_IMPORTS)) return; // TrackPopupMenu cannot display the menu bar so get // a handle to the first shortcut menu. hmenuTrackPopup = hmenu.GetSubMenu(0); // Display the shortcut menu. Track the right mouse // button. if (!hmenuTrackPopup) { MessageBox(L"hmenuTrackPopup == null", L"hmenuTrackPopup"); } menuItem = hmenuTrackPopup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd); if (menuItem) { /*if (menuItem == ID_LISTCONTROL_SHOWEXPORTS) { MessageBox(L"exports",L"dshhhhh"); }*/ } } void MainGui::appendPluginListToMenu(CMenuHandle hMenuTrackPopup) { std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); std::vector &imprecPluginList = PluginLoader::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); } hMenuTrackPopup.AppendMenu(MF_MENUBARBREAK); hMenuTrackPopup.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); } hMenuTrackPopup.AppendMenu(MF_MENUBARBREAK); hMenuTrackPopup.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins"); } } void MainGui::dumpActionHandler() { WCHAR * targetFile = 0; PeDump peDump; if (processAccessHelp.selectedModule) { targetFile = ProcessAccessHelp::selectFileToSave(0, 0); } else { targetFile = ProcessAccessHelp::selectFileToSave(0, 1); } if (targetFile) { if (processAccessHelp.selectedModule) { //dump DLL peDump.imageBase = processAccessHelp.selectedModule->modBaseAddr; peDump.sizeOfImage = processAccessHelp.selectedModule->modBaseSize; //get it from gui peDump.entryPoint = getOEPFromGui(); wcscpy_s(peDump.fullpath, MAX_PATH, processAccessHelp.selectedModule->fullPath); } else { peDump.imageBase = ProcessAccessHelp::targetImageBase; peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage; //get it from gui peDump.entryPoint = getOEPFromGui(); wcscpy_s(peDump.fullpath, MAX_PATH, selectedProcess->fullPath); } peDump.useHeaderFromDisk = ConfigurationHolder::getConfigObject(USE_PE_HEADER_FROM_DISK)->isTrue(); if (peDump.dumpCompleteProcessToDisk(targetFile)) { Logger::printfDialog(TEXT("Dump success %s"),targetFile); //MessageBox(L"Image dumped successfully.", L"Success"); } else { Logger::printfDialog(TEXT("Error: Cannot dump image.")); MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR); } delete [] targetFile; } } DWORD_PTR MainGui::getOEPFromGui() { if (EditOEPAddress.GetWindowText(stringBuffer, _countof(stringBuffer)) > 0) { return stringToDwordPtr(stringBuffer); } else { return 0; } } void MainGui::peRebuildActionHandler() { DWORD newSize = 0; WCHAR * targetFile = 0; PeRebuild peRebuild; targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 2); if (targetFile) { if (ConfigurationHolder::getConfigObject(CREATE_BACKUP)->isTrue()) { if (!ProcessAccessHelp::createBackupFile(targetFile)) { Logger::printfDialog(TEXT("Creating backup file failed %s"), targetFile); } } LONGLONG fileSize = ProcessAccessHelp::getFileSize(targetFile); LPVOID mapped = peRebuild.createFileMappingViewFull(targetFile); newSize = peRebuild.realignPE(mapped, (DWORD)fileSize); peRebuild.closeAllMappingHandles(); if (newSize < 10) { Logger::printfDialog(TEXT("Rebuild failed %s"), targetFile); MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR); } else { peRebuild.truncateFile(targetFile, newSize); Logger::printfDialog(TEXT("Rebuild success %s"), targetFile); Logger::printfDialog(TEXT("-> Old file size 0x%08X new file size 0x%08X (%d %%)"), (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) ); //MessageBox(L"Image rebuilded successfully.", L"Success", MB_ICONINFORMATION); } delete [] targetFile; } } void MainGui::dumpFixActionHandler() { WCHAR * targetFile = 0; WCHAR newFilePath[MAX_PATH]; ImportRebuild importRebuild; if (TreeImports.GetCount() < 2) { Logger::printfDialog(TEXT("Nothing to rebuild")); return; } if (processAccessHelp.selectedModule) { targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 0); } else { targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 1); } if (targetFile) { wcscpy_s(newFilePath,MAX_PATH,targetFile); WCHAR* dot = wcsrchr(newFilePath, L'.'); if (dot) { *dot = L'\0'; } if (processAccessHelp.selectedModule) { wcscat_s(newFilePath,MAX_PATH, L"_SCY.dll"); } else { wcscat_s(newFilePath,MAX_PATH, L"_SCY.exe"); } if (importRebuild.rebuildImportTable(targetFile,newFilePath,importsHandling.moduleList)) { //MessageBox(L"Imports rebuilding successful", L"Success", MB_ICONINFORMATION); Logger::printfDialog(TEXT("Import Rebuild success %s"), newFilePath); } else { Logger::printfDialog(TEXT("Import Rebuild failed, target %s"), targetFile); MessageBox(L"Imports rebuilding failed", L"Failure", MB_ICONERROR); } delete [] targetFile; } } void MainGui::enableDialogButtons(BOOL value) { GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(value); GetDlgItem(IDC_BTN_DUMP).EnableWindow(value); GetDlgItem(IDC_BTN_DLLINJECT).EnableWindow(value); GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(value); GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(value); GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(value); GetDlgItem(IDC_BTN_OPTIONS).EnableWindow(TRUE); //not yet implemented GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_SAVETREE).EnableWindow(FALSE); GetDlgItem(IDC_BTN_LOADTREE).EnableWindow(FALSE); } void MainGui::showAboutDialog() { - AboutGui::initDialog(hInstance, m_hWnd); + AboutGui dlgAbout; + dlgAbout.DoModal(); } void MainGui::dllInjectActionHandler() { WCHAR * targetFile = 0; HMODULE hMod = 0; DllInjection dllInjection; targetFile = ProcessAccessHelp::selectFileToSave(OFN_FILEMUSTEXIST, 0); if (targetFile) { hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, targetFile); if (hMod && ConfigurationHolder::getConfigObject(DLL_INJECTION_AUTO_UNLOAD)->isTrue()) { if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod)) { Logger::printfDialog(TEXT("DLL unloading failed, target %s"), targetFile); } } if (hMod) { Logger::printfDialog(TEXT("DLL Injection was successful, target %s"), targetFile); } else { Logger::printfDialog(TEXT("DLL Injection failed, target %s"), targetFile); } delete [] targetFile; } } void MainGui::optionsActionHandler() { - OptionsGui::initOptionsDialog(hInstance, m_hWnd); + OptionsGui dlgOptions; + dlgOptions.DoModal(); } void MainGui::pluginActionHandler( int menuItem ) { DllInjectionPlugin dllInjectionPlugin; std::vector &scyllaPluginList = PluginLoader::getScyllaPluginList(); std::vector &imprecPluginList = PluginLoader::getImprecPluginList(); menuItem -= PLUGIN_MENU_BASE_ID; dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess; dllInjectionPlugin.apiReader = &apiReader; if (menuItem < (int)scyllaPluginList.size()) { //scylla plugin dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); } else { #ifndef _WIN64 menuItem -= (int)scyllaPluginList.size(); //imprec plugin dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize); #endif } importsHandling.scanAndFixModuleList(); importsHandling.displayAllImports(); } diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h index ad98403..8ad6154 100644 --- a/Scylla/MainGui.h +++ b/Scylla/MainGui.h @@ -1,169 +1,165 @@ #pragma once -//#define _CRTDBG_MAP_ALLOC -//#include -//#include - #include -#include -#include -#include -#include +#include "resource.h" // WTL - #include // base ATL classes #include // base WTL classes #include // ATL GUI classes -#include // WTL frame window classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros +#include // WTL controls + +//#define _CRTDBG_MAP_ALLOC +//#include +//#include -#include +#include -#include "resource.h" #include "Logger.h" #include "ProcessLister.h" #include "IATSearch.h" #include "PickDllGui.h" - #include "ImportsHandling.h" -//#pragma comment(lib, "comctl32.lib") - -class ImportsHandling; - class MainGui : public CDialogImpl { public: enum { IDD = IDD_DLG_MAIN }; BEGIN_MSG_MAP(MainGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_LBUTTONDOWN(OnLButtonDown) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_CLICK, OnTreeImportsClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_DBLCLK, OnTreeImportsDoubleClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_RCLICK, OnTreeImportsRightClick) NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_RDBLCLK, OnTreeImportsRightDoubleClick) 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_DLLINJECT, OnDLLInject) 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(IDC_BTN_CLEARLOG, OnClearLog) COMMAND_ID_HANDLER_EX(ID_FILE_EXIT, OnExit) COMMAND_ID_HANDLER_EX(ID_MISC_DLLINJECTION, OnDLLInject) COMMAND_ID_HANDLER_EX(ID_MISC_PREFERENCES, OnOptions) COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout) COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) END_MSG_MAP() - MainGui(HINSTANCE hInstance); - - Process * selectedProcess; + MainGui(); //Output Window void addTextToOutputLog(const WCHAR * text); - static DWORD_PTR stringToDwordPtr(WCHAR * hexString); - protected: - HINSTANCE hInstance; - // Controls - CTreeViewCtrl TreeImports; - CComboBox ComboProcessList; - CEdit EditOEPAddress; - CEdit EditIATAddress; - CEdit EditIATSize; - CListBox ListLog; + // Variables ProcessLister processLister; WCHAR stringBuffer[600]; ImportsHandling importsHandling; ProcessAccessHelp processAccessHelp; ApiReader apiReader; -private: + Process * selectedProcess; - //Message handlers + // Controls + + CTreeViewCtrl TreeImports; + CComboBox ComboProcessList; + CEdit EditOEPAddress; + CEdit EditIATAddress; + CEdit EditIATSize; + CListBox ListLog; + +protected: + + // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnLButtonDown(UINT nFlags, CPoint point); void OnContextMenu(CWindow wnd, CPoint point); LRESULT OnTreeImportsClick(const NMHDR* pnmh); LRESULT OnTreeImportsDoubleClick(const NMHDR* pnmh); LRESULT OnTreeImportsRightClick(const NMHDR* pnmh); LRESULT OnTreeImportsRightDoubleClick(const NMHDR* pnmh); 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 OnClearLog(UINT uNotifyCode, int nID, CWindow wndCtl); void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); void OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl); - // --- + // GUI functions void setIconAndDialogCaption(); void fillProcessListComboBox(CComboBox& hCombo); void getModuleListItem(int column, int iItem, char * buffer); - void pickDllActionHandler(); - void processSelectedActionHandler(int index); - //static bool displayModuleList(HWND hWndDlg, HWND hList, LRESULT index); - // POPUP MENU Prototypes - void DisplayContextMenu(CWindow, POINT); - void DisplayContextMenuImports(CWindow, POINT); - CMenuHandle getCorrectSubMenu(int, int); - - void clearOutputLog();//Output Window + // Actions + + void pickDllActionHandler(); + void processSelectedActionHandler(int index); void showInvalidImportsActionHandler(); void showSuspectImportsActionHandler(); void iatAutosearchActionHandler(); void getImportsActionHandler(); void appendPluginListToMenu(CMenuHandle hMenuTrackPopup); void dumpActionHandler(); DWORD_PTR getOEPFromGui(); void peRebuildActionHandler(); - void startDisassemblerGui(CTreeItem selectedTreeNode); void dumpFixActionHandler(); - void enableDialogButtons( BOOL value ); + void enableDialogButtons(BOOL value); void showAboutDialog(); void dllInjectActionHandler(); void optionsActionHandler(); - void pluginActionHandler( int menuItem ); + void pluginActionHandler(int menuItem); + + // Popup menu functions + + void DisplayContextMenu(CWindow, CPoint); + void DisplayContextMenuImports(CWindow, CPoint); + CMenuHandle getCorrectSubMenu(int, int); + + // Misc + + void clearOutputLog();//Output Window + + static DWORD_PTR stringToDwordPtr(WCHAR * hexString); }; diff --git a/Scylla/OptionsGui.cpp b/Scylla/OptionsGui.cpp index 13fbb19..cc3941a 100644 --- a/Scylla/OptionsGui.cpp +++ b/Scylla/OptionsGui.cpp @@ -1,186 +1,162 @@ #include "OptionsGui.h" -#include "ConfigurationHolder.h" -HWND OptionsGui::hWndDlg = 0; +#include "ConfigurationHolder.h" -INT_PTR OptionsGui::initOptionsDialog(HINSTANCE hInstance, HWND hWndParent) +BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { - return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_OPTIONS),hWndParent, (DLGPROC)optionsDlgProc); + EditSectionName.Attach(GetDlgItem(IDC_OPTIONS_SECTIONNAME)); + EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME); + + loadOptions(); + + return TRUE; } -LRESULT CALLBACK OptionsGui::optionsDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { - hWndDlg = hWnd; + saveOptions(); + ConfigurationHolder::saveConfiguration(); - switch (uMsg) - { - case WM_INITDIALOG: - Edit_LimitText(GetDlgItem(hWndDlg,IDC_OPTIONS_SECTIONNAME), IMAGE_SIZEOF_SHORT_NAME); - loadOptions(); - break; - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_BTN_OPTIONS_OK: - { - saveOptions(); - ConfigurationHolder::saveConfiguration(); - EndDialog(hWnd, 0); - } - return TRUE; - case IDC_BTN_OPTIONS_CANCEL: - EndDialog(hWnd, 0); - return TRUE; - case IDCANCEL: - EndDialog(hWnd, 0); - return TRUE; - } - } - return FALSE; + 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++) { getConfigOptionsFromDlg((*mapIter).second); } } void OptionsGui::loadOptions() { std::map::iterator mapIter; for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++) { displayConfigInDlg((*mapIter).second); } } void OptionsGui::setCheckBox( int nIDDlgItem, bool bValue ) { - if (bValue) - { - Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_CHECKED); - } - else - { - Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_UNCHECKED); - } + CButton Button(GetDlgItem(nIDDlgItem)); + Button.SetCheck(bValue ? BST_CHECKED : BST_UNCHECKED); } void OptionsGui::displayConfigInDlg( ConfigObject & config ) { switch (config.configType) { case String: { setEditControl(config.dialogItemValue, config.valueString); } break; case Boolean: { setCheckBox(config.dialogItemValue, config.isTrue()); } break; case Decimal: { #ifdef _WIN64 swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%I64u"),config.valueNumeric); #else swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%u"),config.valueNumeric); #endif setEditControl(config.dialogItemValue, config.valueString); } break; case Hexadecimal: { #ifdef _WIN64 swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%016I64X"),config.valueNumeric); #else swprintf_s(config.valueString, CONFIG_OPTIONS_STRING_LENGTH, TEXT("%08X"),config.valueNumeric); #endif setEditControl(config.dialogItemValue, config.valueString); } break; } } void OptionsGui::setEditControl( int nIDDlgItem, const WCHAR * valueString ) { - SetDlgItemText(hWndDlg,nIDDlgItem,valueString); + CEdit Edit(GetDlgItem(nIDDlgItem)); + Edit.SetWindowText(valueString); } void OptionsGui::getConfigOptionsFromDlg( ConfigObject & config ) { switch (config.configType) { case String: { getEditControl(config.dialogItemValue, config.valueString); } break; case Boolean: { getCheckBox(config.dialogItemValue, &config.valueNumeric); } break; case Decimal: { getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 10); } break; case Hexadecimal: { getEditControlNumeric(config.dialogItemValue, &config.valueNumeric, 16); } break; } } bool OptionsGui::getEditControl( int nIDDlgItem, WCHAR * valueString ) { - if (GetDlgItemText(hWndDlg, nIDDlgItem, valueString, CONFIG_OPTIONS_STRING_LENGTH)) - { - return true; - } - else - { - return false; - } + CEdit Edit(GetDlgItem(nIDDlgItem)); + return (Edit.GetWindowText(valueString, CONFIG_OPTIONS_STRING_LENGTH) > 0); } void OptionsGui::getCheckBox( int nIDDlgItem, DWORD_PTR * valueNumeric ) { - switch (Button_GetCheck(GetDlgItem(hWndDlg, nIDDlgItem))) + CButton Button(GetDlgItem(nIDDlgItem)); + switch (Button.GetCheck()) { case BST_CHECKED: *valueNumeric = 1; return; case BST_UNCHECKED: *valueNumeric = 0; return; default: *valueNumeric = 0; } } void OptionsGui::getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase ) { WCHAR temp[CONFIG_OPTIONS_STRING_LENGTH] = {0}; if (getEditControl(nIDDlgItem, temp)) { #ifdef _WIN64 *valueNumeric = _wcstoui64(temp, NULL, nBase); #else *valueNumeric = wcstoul(temp, NULL, nBase); #endif } else { *valueNumeric = 0; } } diff --git a/Scylla/OptionsGui.h b/Scylla/OptionsGui.h index 21a32cb..fed16c8 100644 --- a/Scylla/OptionsGui.h +++ b/Scylla/OptionsGui.h @@ -1,23 +1,47 @@ #pragma once -#include "MainGui.h" +#include +#include "resource.h" + +// WTL +#include // base ATL classes +#include // base WTL classes +#include // ATL GUI classes +#include // WTL enhanced msg map macros +#include // WTL controls class ConfigObject; -class OptionsGui { +class OptionsGui : public CDialogImpl +{ public: - static HWND hWndDlg; - static INT_PTR initOptionsDialog(HINSTANCE hInstance, HWND hWndParent); + enum { IDD = IDD_DLG_OPTIONS }; + + BEGIN_MSG_MAP(OptionsGui) + MSG_WM_INITDIALOG(OnInitDialog) + + COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_OK, OnOK) + COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_CANCEL, OnCancel) + COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) + END_MSG_MAP() + private: - static LRESULT CALLBACK optionsDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static void saveOptions(); - static void loadOptions(); - static void setCheckBox( int nIDDlgItem, bool bValue ); - static void displayConfigInDlg( ConfigObject & config ); - static void setEditControl( int nIDDlgItem, const WCHAR * valueString ); - static void getConfigOptionsFromDlg( ConfigObject & config ); - - static bool getEditControl( int nIDDlgItem, WCHAR * valueString ); - static void getCheckBox( int dialogItemValue, DWORD_PTR * valueNumeric ); - static void getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase ); -}; \ No newline at end of file + + CEdit EditSectionName; + + BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); + + void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); + void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); + + void saveOptions(); + void loadOptions(); + void setCheckBox( int nIDDlgItem, bool bValue ); + void displayConfigInDlg( ConfigObject & config ); + void setEditControl( int nIDDlgItem, const WCHAR * valueString ); + void getConfigOptionsFromDlg( ConfigObject & config ); + + bool getEditControl( int nIDDlgItem, WCHAR * valueString ); + void getCheckBox( int dialogItemValue, DWORD_PTR * valueNumeric ); + void getEditControlNumeric( int nIDDlgItem, DWORD_PTR * valueNumeric, int nBase ); +}; diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp index 1d749e4..a21dfbc 100644 --- a/Scylla/PickDllGui.cpp +++ b/Scylla/PickDllGui.cpp @@ -1,131 +1,59 @@ #include "PickDllGui.h" +BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) +{ + ListDLLSelect.Attach(GetDlgItem(IDC_LIST_DLLSELECT)); -HWND PickDllGui::hWndDlg; -std::vector * PickDllGui::moduleList = 0; -ModuleInfo * PickDllGui::selectedModule = 0; + addColumnsToModuleList(ListDLLSelect); + displayModuleList(ListDLLSelect); -INT_PTR PickDllGui::initDialog(HINSTANCE hInstance, HWND hWndParent, std::vector &moduleListNew) -{ - moduleList = &moduleListNew; - return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG_PICKDLL),hWndParent, (DLGPROC)pickDllDlgProc); + return TRUE; } -LRESULT CALLBACK PickDllGui::pickDllDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +void PickDllGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { - int index; - hWndDlg = hWnd; - switch (uMsg) + int index = ListDLLSelect.GetSelectionMark(); + if (index != -1) { - case WM_INITDIALOG: - addColumnsToModuleList(GetDlgItem(hWnd, IDC_LIST_DLLSELECT)); - displayModuleList(); - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_BTN_PICKDLL_OK: - index = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_DLLSELECT)); - if (index != -1) - { - selectedModule = &(*moduleList).at(index); - EndDialog(hWnd, 1); - } - - return TRUE; - case IDC_BTN_PICKDLL_CANCEL: - EndDialog(hWnd, 0); - return TRUE; - case IDCANCEL: - EndDialog(hWnd, 0); - return TRUE; - } + selectedModule = &moduleList[index]; + EndDialog(1); } - return FALSE; } -void PickDllGui::addColumnsToModuleList(HWND hList) +void PickDllGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { - if (hList) - { - LVCOLUMN * lvc = (LVCOLUMN*)malloc(sizeof(LVCOLUMN)); - - ListView_SetExtendedListViewStyleEx(hList,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT); - - lvc->mask = LVCF_TEXT | LVCF_WIDTH; - lvc->cx = 210; - lvc->pszText = L"Path"; - ListView_InsertColumn(hList, COL_PATH, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_CENTER; - lvc->cx = 130; - lvc->pszText = L"Name"; - ListView_InsertColumn(hList, COL_NAME, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_CENTER; - lvc->cx = 70; - lvc->pszText = L"ImageBase"; - ListView_InsertColumn(hList, COL_IMAGEBASE, lvc); - - lvc->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc->fmt = LVCFMT_CENTER; - lvc->cx = 70; - lvc->pszText = L"ImageSize"; - ListView_InsertColumn(hList, COL_IMAGESIZE, lvc); - - free(lvc); - } + EndDialog(0); } -void PickDllGui::getModuleListItem(int column, int iItem, WCHAR * buffer) +void PickDllGui::addColumnsToModuleList(CListViewCtrl& list) { - LVITEM pitem = {0}; - pitem.iItem = iItem; - pitem.iSubItem = column; - pitem.mask = LVIF_TEXT; - pitem.cchTextMax = 256; - pitem.pszText = buffer; - ListView_GetItem(GetDlgItem(hWndDlg, IDC_LIST_DLLSELECT),&pitem); + list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + list.InsertColumn(COL_PATH, L"Path", LVCFMT_LEFT, 210); + list.InsertColumn(COL_NAME, L"Name", LVCFMT_CENTER, 130); + list.InsertColumn(COL_IMAGEBASE, L"ImageBase", LVCFMT_CENTER, 70); + list.InsertColumn(COL_IMAGESIZE, L"ImageSize", LVCFMT_CENTER, 70); } -bool PickDllGui::displayModuleList() +void PickDllGui::displayModuleList(CListViewCtrl& list) { - LVITEM item; WCHAR temp[20]; - HWND hList = GetDlgItem(hWndDlg, IDC_LIST_DLLSELECT); - - ListView_DeleteAllItems(hList); - - item.mask = LVIF_TEXT; + list.DeleteAllItems(); - - std::vector::iterator iter; + std::vector::const_iterator iter; int count = 0; - for( iter = (*moduleList).begin(); iter != (*moduleList).end(); iter++ , count++) { - item.iItem = count; - item.iSubItem = COL_PATH; - item.pszText = iter->fullPath; - item.iItem = ListView_InsertItem(hList, &item); + for( iter = moduleList.begin(); iter != moduleList.end(); iter++ , count++) + { + list.InsertItem(count, iter->fullPath); - item.iSubItem = COL_NAME; - item.pszText = iter->getFilename(); - ListView_SetItem(hList, &item); + list.SetItemText(count, COL_NAME, iter->getFilename()); - item.iSubItem = COL_IMAGEBASE; swprintf_s(temp,_countof(temp),L"%08X",iter->modBaseAddr); - item.pszText = temp; - ListView_SetItem(hList, &item); + list.SetItemText(count, COL_IMAGEBASE, temp); - item.iSubItem = COL_IMAGESIZE; swprintf_s(temp,_countof(temp),L"%08X",iter->modBaseSize); - item.pszText = temp; - ListView_SetItem(hList, &item); + list.SetItemText(count, COL_IMAGESIZE, temp); } - - return true; -} \ No newline at end of file +} diff --git a/Scylla/PickDllGui.h b/Scylla/PickDllGui.h index d04f253..e677e0d 100644 --- a/Scylla/PickDllGui.h +++ b/Scylla/PickDllGui.h @@ -1,28 +1,64 @@ #pragma once -#include "MainGui.h" +#include +#include "resource.h" -static const enum ListColumns { - COL_PATH, - COL_NAME, - COL_IMAGEBASE, - COL_IMAGESIZE -}; +// WTL +#include // base ATL classes +#include // base WTL classes +#include // ATL GUI classes +#include // WTL utility classes like CString +#include // WTL enhanced msg map macros +#include // WTL controls + +#include +#include "ProcessAccessHelp.h" -class PickDllGui { +class PickDllGui : public CDialogImpl +{ public: - static HWND hWndDlg; + enum { IDD = IDD_DLG_PICKDLL }; + + BEGIN_MSG_MAP(PickDllGui) + MSG_WM_INITDIALOG(OnInitDialog) + + COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_OK, OnOK) + COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_CANCEL, OnCancel) + COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) + END_MSG_MAP() + + PickDllGui(std::vector &moduleList) : moduleList(moduleList), selectedModule(0) { } + + ModuleInfo* getSelectedModule() const { return selectedModule; } - static std::vector * moduleList; +protected: - static ModuleInfo * selectedModule; + // Variables - static LRESULT CALLBACK pickDllDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent, std::vector &moduleList); + std::vector &moduleList; + ModuleInfo* selectedModule; - static void addColumnsToModuleList(HWND hList); + // Controls - static void getModuleListItem(int column, int iItem, WCHAR * buffer); + CListViewCtrl ListDLLSelect; - static bool displayModuleList(); -}; \ No newline at end of file + enum ListColumns { + COL_PATH, + COL_NAME, + COL_IMAGEBASE, + COL_IMAGESIZE + }; + +protected: + + // Message handlers + + BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); + void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); + void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); + + // GUI functions + + void addColumnsToModuleList(CListViewCtrl& list); + void displayModuleList(CListViewCtrl& list); +}; diff --git a/Scylla/ProcessAccessHelp.h b/Scylla/ProcessAccessHelp.h index 02bfb04..306e007 100644 --- a/Scylla/ProcessAccessHelp.h +++ b/Scylla/ProcessAccessHelp.h @@ -1,217 +1,215 @@ #pragma once #include #include #include #include #include /************************************************************************/ /* distorm */ /************************************************************************/ #include "distorm.h" /* #ifdef _WIN64 #pragma comment(lib, "distorm_x64.lib") #else #pragma comment(lib, "distorm_x86.lib") #endif */ // The number of the array of instructions the decoder function will use to return the disassembled instructions. // Play with this value for performance... #define MAX_INSTRUCTIONS (200) /************************************************************************/ class ApiInfo; class ModuleInfo { public: WCHAR fullPath[MAX_PATH]; DWORD_PTR modBaseAddr; DWORD modBaseSize; bool isAlreadyParsed; bool parsing; /* for iat rebuilding with duplicate entries: ntdll = low priority kernelbase = low priority SHLWAPI = low priority kernel32 = high priority priority = 1 -> normal/high priority priority = 0 -> low priority */ int priority; std::vector apiList; ModuleInfo() { modBaseAddr = 0; modBaseSize = 0; priority = 1; isAlreadyParsed = false; parsing = false; } - WCHAR * getFilename() + const WCHAR * getFilename() const { - for (size_t i = wcslen(fullPath) - 1; i >= 0; i--) + const WCHAR* slash = wcsrchr(fullPath, L'\\'); + if(slash) { - if (fullPath[i] == L'\\') - { - return (&fullPath[i] + 1); - } + return slash+1; } return fullPath; } }; class ApiInfo { public: char name[MAX_PATH]; DWORD hint; DWORD_PTR va; DWORD_PTR rva; DWORD_PTR ordinal; bool isForwarded; ModuleInfo * module; }; class ProcessAccessHelp { public: static HANDLE hProcess; //OpenProcess handle to target process static DWORD_PTR targetImageBase; static DWORD_PTR targetSizeOfImage; static DWORD_PTR maxValidAddress; static ModuleInfo * selectedModule; static std::vector moduleList; //target process module list static std::vector ownModuleList; //own module list static const int PE_HEADER_BYTES_COUNT = 2000; static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; //for decomposer static _DInst decomposerResult[MAX_INSTRUCTIONS]; static unsigned int decomposerInstructionsCount; static _CodeInfo decomposerCi; //distorm :: Decoded instruction information. static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; static unsigned int decodedInstructionsCount; #ifdef _WIN64 static const _DecodeType dt = Decode64Bits; #else static const _DecodeType dt = Decode32Bits; #endif /* * Open a new process handle */ static bool openProcessHandle(DWORD dwPID); static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId); static void closeProcessHandle(); /* * Get all modules from a process */ static bool getProcessModules(DWORD dwPID, std::vector &moduleList); /* * file mapping view with different access level */ static LPVOID createFileMappingViewRead(const WCHAR * filePath); static LPVOID createFileMappingViewFull(const WCHAR * filePath); /* * Create a file mapping view of a file */ static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap); /* * Read memory from target process */ static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); /* * Read memory from file */ static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); /* * Write memory to file */ static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); /* * Write memory to file end */ static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer); /* * Disassemble Memory */ static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset); static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress); /* * Search for pattern */ static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask); /* * Get process ID by process name */ static DWORD getProcessByName(const WCHAR * processName); /* * Get memory region from address */ bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize); /* * Read PE Header from file */ static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath); static bool readHeaderFromCurrentFile(const WCHAR * filePath); /* * Get real sizeOfImage value */ static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase); /* * Get real sizeOfImage value current process */ static bool getSizeOfImageCurrentProcess(); static LONGLONG getFileSize(HANDLE hFile); static LONGLONG getFileSize(const WCHAR * filePath); static WCHAR * selectFileToSave(DWORD flags, int type); static DWORD getEntryPointFromFile(const WCHAR * filePath); static bool createBackupFile(const WCHAR * filePath); }; diff --git a/Scylla/Thunks.h b/Scylla/Thunks.h index 28f540f..2f16d53 100644 --- a/Scylla/Thunks.h +++ b/Scylla/Thunks.h @@ -1,50 +1,38 @@ #pragma once #include #include #include +// WTL #include #include -#include - -class ImportModuleThunk; -class ImportThunk; +#include //CTreeItem class ImportThunk { public: WCHAR moduleName[MAX_PATH]; char name[MAX_PATH]; DWORD_PTR va; DWORD_PTR rva; DWORD_PTR ordinal; DWORD_PTR apiAddressVA; WORD hint; bool valid; bool suspect; CTreeItem hTreeItem; }; - class ImportModuleThunk { public: WCHAR moduleName[MAX_PATH]; std::map thunkList; DWORD_PTR firstThunk; CTreeItem hTreeItem; DWORD_PTR getFirstThunk(); bool isValid(); - - ~ImportModuleThunk() - { - if (!thunkList.empty()) - { - thunkList.clear(); - } - } - -}; \ No newline at end of file +}; diff --git a/Scylla/main.cpp b/Scylla/main.cpp index 9626fed..5cba016 100644 --- a/Scylla/main.cpp +++ b/Scylla/main.cpp @@ -1,40 +1,40 @@ #include // base ATL classes #include // base WTL classes CAppModule _Module; #include "MainGui.h" MainGui* pMainGui = NULL; // for Logger int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HRESULT hRes = CoInitialize(NULL); // If you are running on NT 4.0 or higher you can use the following call instead to // make the EXE free threaded. This means that calls come in on a random RPC thread. //HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ATLASSERT(SUCCEEDED(hRes)); // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used DefWindowProc(NULL, 0, 0, 0L); - AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls + AtlInitCommonControls(ICC_STANDARD_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES); // add flags to support other controls hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); int nRet = 0; // BLOCK: Run application { - MainGui dlgMain(hInstance); + MainGui dlgMain; pMainGui = &dlgMain; // o_O nRet = dlgMain.DoModal(); } _Module.Term(); CoUninitialize(); return nRet; }