Page MenuHomedesp's stash

No OneTemporary

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 <windows.h>
+#include "resource.h"
+// WTL
+#include <atlbase.h> // base ATL classes
+#include <atlapp.h> // base WTL classes
+#include <atlwin.h> // ATL GUI classes
+#include <atlcrack.h> // WTL enhanced msg map macros
+#include <atlctrls.h> // WTL controls
-class AboutGui {
+class AboutGui : public CDialogImpl<AboutGui>
+{
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<DWORD_PTR, ApiInfo *> ApiReader::apiList; //api look up table
std::map<DWORD_PTR, ImportModuleThunk> * ApiReader::moduleThunkList; //store found apis
DWORD_PTR ApiReader::minApiAddress = 0xFFFFFFFF;
DWORD_PTR ApiReader::maxApiAddress = 0;
//#define DEBUG_COMMENTS
void ApiReader::readApisFromModuleList()
{
for (unsigned int i = 0; i < moduleList.size();i++)
{
setModulePriority(&moduleList[i]);
if (moduleList[i].modBaseAddr + moduleList[i].modBaseSize > maxValidAddress)
{
maxValidAddress = moduleList[i].modBaseAddr + moduleList[i].modBaseSize;
}
Logger::printfDialog(TEXT("Module parsing: %s"),moduleList[i].fullPath);
if (!moduleList[i].isAlreadyParsed)
{
parseModule(&moduleList[i]);
}
}
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("Address Min ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Max ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\nimagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" maxValidAddress ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),minApiAddress,maxApiAddress,targetImageBase,maxValidAddress);
#endif
}
void ApiReader::parseModule(ModuleInfo *module)
{
module->parsing = true;
if (isWinSxSModule(module))
{
parseModuleWithMapping(module);
}
else if (isModuleLoadedInOwnProcess(module))
{
parseModuleWithOwnProcess(module);
}
else
{
parseModuleWithProcess(module);
}
module->isAlreadyParsed = true;
}
void ApiReader::parseModuleWithMapping(ModuleInfo *moduleInfo)
{
LPVOID fileMapping = 0;
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
fileMapping = createFileMappingViewRead(moduleInfo->fullPath);
if (fileMapping == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)fileMapping;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping);
}
UnmapViewOfFile(fileMapping);
}
inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader)
{
if ((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)))
{
return true;
}
else
{
return false;
}
}
void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer,char * functionNameParent, DWORD_PTR rvaParent, DWORD_PTR ordinalParent, ModuleInfo *moduleParent)
{
size_t dllNameLength = 0;
DWORD_PTR ordinal = 0;
ModuleInfo *module = 0;
DWORD_PTR vaApi = 0;
DWORD_PTR rvaApi = 0;
char dllName[100] = {0};
WCHAR dllNameW[100] = {0};
char *fordwardedString = (char *)vaStringPointer;
char *searchFunctionName = strchr(fordwardedString, '.');
if (!searchFunctionName)
return;
dllNameLength = searchFunctionName - fordwardedString;
if (dllNameLength >= 99)
{
return;
}
else
{
strncpy_s(dllName,sizeof(dllName),fordwardedString,dllNameLength);
}
searchFunctionName++;
//Windows 7
if (!strncmp(dllName,"api-ms-win-", 11))
{
/*
Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html
*/
FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName);
if (addy != 0)
{
addApi(functionNameParent,0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent);
}
return;
}
strcat_s(dllName,sizeof(dllName),".dll");
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, dllNameW, strlen(dllName) + 1, dllName, _TRUNCATE);
if (!_wcsicmp(dllNameW, moduleParent->getFilename()))
{
module = moduleParent;
}
else
{
module = findModuleByName(dllNameW);
}
if (module != 0) // module == 0 -> can be ignored
{
/*if ((module->isAlreadyParsed == false) && (module != moduleParent))
{
//do API extract
if (module->parsing == true)
{
//some stupid circle dependency
printf("stupid circle dependency %s\n",module->getFilename());
}
else
{
parseModule(module);
}
}*/
if (strchr(searchFunctionName,'#'))
{
//forwarding by ordinal
searchFunctionName++;
ordinal = atoi(searchFunctionName);
findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi);
}
else
{
findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi);
}
if (rvaApi == 0)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(L"handleForwardedApi :: Api not found, this is really BAD! %S\r\n",fordwardedString);
#endif
}
else
{
addApi(functionNameParent,0, ordinalParent, vaApi, rvaApi, true, moduleParent);
}
}
}
ModuleInfo * ApiReader::findModuleByName(WCHAR *name)
{
for (unsigned int i = 0; i < moduleList.size(); i++) {
if (!_wcsicmp(moduleList[i].getFilename(), name))
{
return &moduleList[i];
}
}
return 0;
}
void ApiReader::addApiWithoutName(DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo)
{
addApi(0, 0, ordinal, va, rva, isForwarded, moduleInfo);
}
void ApiReader::addApi(char *functionName, WORD hint, DWORD_PTR ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo)
{
ApiInfo *apiInfo = new ApiInfo();
if ((functionName != 0) && (strlen(functionName) < MAX_PATH))
{
strcpy_s(apiInfo->name, MAX_PATH, functionName);
}
else
{
apiInfo->name[0] = 0x00;
}
apiInfo->ordinal = ordinal;
apiInfo->isForwarded = isForwarded;
apiInfo->module = moduleInfo;
apiInfo->rva = rva;
apiInfo->va = va;
apiInfo->hint = hint;
setMinMaxApiAddress(va);
moduleInfo->apiList.push_back(apiInfo);
apiList.insert(API_Pair(va, apiInfo));
}
BYTE * ApiReader::getHeaderFromProcess(ModuleInfo * module)
{
BYTE *bufferHeader = 0;
DWORD readSize = 0;
if (module->modBaseSize < PE_HEADER_BYTES_COUNT)
{
readSize = module->modBaseSize;
}
else
{
readSize = PE_HEADER_BYTES_COUNT;
}
bufferHeader = new BYTE[readSize];
if(!readMemoryFromProcess(module->modBaseAddr, readSize, bufferHeader))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(L"getHeaderFromProcess :: Error reading header\r\n");
#endif
delete[] bufferHeader;
return 0;
}
else
{
return bufferHeader;
}
}
BYTE * ApiReader::getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader)
{
DWORD readSize = 0;
BYTE *bufferExportTable = 0;
readSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if (readSize < (sizeof(IMAGE_EXPORT_DIRECTORY) + 8))
{
//Something is wrong with the PE Header
#ifdef DEBUG_COMMENTS
Logger::debugLog(L"Something is wrong with the PE Header here Export table size %d\r\n",readSize);
#endif
readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100;
}
if (readSize)
{
bufferExportTable = new BYTE[readSize];
if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(L"getExportTableFromProcess :: Error reading export table from process\r\n");
#endif
delete[] bufferExportTable;
return 0;
}
else
{
return bufferExportTable;
}
}
else
{
return 0;
}
}
void ApiReader::parseModuleWithProcess(ModuleInfo * module)
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
BYTE *bufferHeader = 0;
BYTE *bufferExportTable = 0;
bufferHeader = getHeaderFromProcess(module);
if (bufferHeader == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
bufferExportTable = getExportTableFromProcess(module, pNtHeader);
if(bufferExportTable)
{
parseExportTable(module,pNtHeader,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
delete[] bufferExportTable;
}
}
delete[] bufferHeader;
}
void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress)
{
DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
WORD *addressOfNameOrdinalsArray = 0;
char *functionName = 0;
DWORD_PTR RVA = 0, VA = 0, ordinal = 0;
DWORD i = 0, j = 0;
bool withoutName;
addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
#ifdef DEBUG_COMMENTS
Logger::debugLog(L"parseExportTable :: module %s NumberOfNames %X\r\n",module->fullPath,pExportDir->NumberOfNames);
#endif
for (i = 0; i < pExportDir->NumberOfNames; i++)
{
functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
ordinal = (addressOfNameOrdinalsArray[i] + pExportDir->Base);
RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("parseExportTable :: api %S ")TEXT(" ordinal %d imagebase ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" RVA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" VA ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),functionName,ordinal,module->modBaseAddr,RVA,VA);
#endif
if (!isApiBlacklisted(functionName))
{
if (!isApiForwarded(RVA,pNtHeader))
{
addApi(functionName, (WORD)i, ordinal,VA,RVA,false,module);
}
else
{
//printf("Forwarded: %s\n",functionName);
handleForwardedApi(RVA + deltaAddress,functionName,RVA,ordinal,module);
}
}
}
/*Exports without name*/
if (pExportDir->NumberOfNames != pExportDir->NumberOfFunctions)
{
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
withoutName = true;
for (j = 0; j < pExportDir->NumberOfNames; j++)
{
if(addressOfNameOrdinalsArray[j] == i)
{
withoutName = false;
break;
}
}
if (withoutName && addressOfFunctionsArray[i] != 0)
{
ordinal = (i+pExportDir->Base);
RVA = addressOfFunctionsArray[i];
VA = (addressOfFunctionsArray[i] + module->modBaseAddr);
if (!isApiForwarded(RVA,pNtHeader))
{
addApiWithoutName(ordinal,VA,RVA,false,module);
}
else
{
handleForwardedApi(RVA + deltaAddress,0,RVA,ordinal,module);
}
}
}
}
}
void ApiReader::findApiByModuleAndOrdinal(ModuleInfo * module, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
findApiByModule(module,0,ordinal,vaApi,rvaApi);
}
void ApiReader::findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
findApiByModule(module,searchFunctionName,0,vaApi,rvaApi);
}
void ApiReader::findApiByModule(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
if (isModuleLoadedInOwnProcess(module))
{
HMODULE hModule = GetModuleHandle(module->getFilename());
if (hModule)
{
if (ordinal)
{
*vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal);
}
else
{
*vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName);
}
if (vaApi)
{
*rvaApi = (*vaApi) - (DWORD_PTR)hModule;
*vaApi = (*rvaApi) + module->modBaseAddr;
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("findApiByModule :: vaApi == NULL, should never happen %S\r\n"),searchFunctionName);
#endif
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("findApiByModule :: hModule == NULL, should never happen %s\r\n"),module->getFilename());
#endif
}
}
else
{
//search api in extern process
findApiInProcess(module,searchFunctionName,ordinal,vaApi,rvaApi);
}
}
bool ApiReader::isModuleLoadedInOwnProcess(ModuleInfo * module)
{
for (unsigned int i = 0; i < ownModuleList.size(); i++)
{
if (!_wcsicmp(module->fullPath, ownModuleList[i].fullPath))
{
//printf("isModuleLoadedInOwnProcess :: %s %s\n",module->fullPath,ownModuleList[i].fullPath);
return true;
}
}
return false;
}
void ApiReader::parseModuleWithOwnProcess( ModuleInfo * module )
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
HMODULE hModule = GetModuleHandle(module->getFilename());
if (hModule)
{
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)hModule);
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("parseModuleWithOwnProcess :: hModule is NULL\r\n"));
#endif
}
}
bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader)
{
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
Logger::printfDialog(TEXT("-> IMAGE_NT_SIGNATURE doesn't match."));
return false;
}
else if ((pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) || (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0))
{
Logger::printfDialog(TEXT("-> No export table."));
return false;
}
else
{
return true;
}
}
void ApiReader::findApiInProcess(ModuleInfo * module, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
BYTE *bufferHeader = 0;
BYTE *bufferExportTable = 0;
bufferHeader = getHeaderFromProcess(module);
if (bufferHeader == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
bufferExportTable = getExportTableFromProcess(module, pNtHeader);
if(bufferExportTable)
{
findApiInExportTable(module,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,searchFunctionName,ordinal,vaApi,rvaApi);
delete[] bufferExportTable;
}
}
delete[] bufferHeader;
}
bool ApiReader::findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, DWORD_PTR ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
WORD *addressOfNameOrdinalsArray = 0;
char *functionName = 0;
DWORD i = 0, j = 0;
addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
if (searchFunctionName)
{
for (i = 0; i < pExportDir->NumberOfNames; i++)
{
functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
if (!strcmp(functionName,searchFunctionName))
{
*rvaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
*vaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
return true;
}
}
}
else
{
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
if (ordinal == (i+pExportDir->Base))
{
*rvaApi = addressOfFunctionsArray[i];
*vaApi = (addressOfFunctionsArray[i] + module->modBaseAddr);
return true;
}
}
}
return false;
}
void ApiReader::setModulePriority(ModuleInfo * module)
{
- WCHAR *moduleFileName = module->getFilename();
+ 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<DWORD_PTR, ApiInfo *>::iterator it1, it2;
size_t c = 0;
size_t countDuplicates = apiList.count(virtualAddress);
int countHighPriority = 0;
ApiInfo *apiFound = 0;
if (countDuplicates == 0)
{
Logger::printfDialog(TEXT("getApiByVirtualAddress :: No Api found ")TEXT(PRINTF_DWORD_PTR_FULL),virtualAddress);
return 0;
}
else if (countDuplicates == 1)
{
//API is 100% correct
*isSuspect = false;
it1 = apiList.find(virtualAddress); // Find first match.
return (ApiInfo *)((*it1).second);
}
else
{
it1 = apiList.find(virtualAddress); // Find first match.
it2 = it1;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
if (apiFound->module->priority >= 1) //1 == high priority
{
countHighPriority++;
}
}
it1 = it2;
if (countHighPriority == 0)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("getApiByVirtualAddress :: countHighPriority == 0 ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),virtualAddress);
#endif
*isSuspect = true;
return (ApiInfo *)((*it1).second);
}
else if (countHighPriority == 1)
{
//API is 100% correct if countHighPriority == 1 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<DWORD_PTR, ImportModuleThunk> &moduleListNew)
{
moduleThunkList = &moduleListNew;
BYTE *dataIat = new BYTE[sizeIAT];
if (readMemoryFromProcess(addressIAT,sizeIAT,dataIat))
{
parseIAT(addressIAT,dataIat,sizeIAT);
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ApiReader::readAndParseIAT :: error reading iat ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),addressIAT);
#endif
}
delete[] dataIat;
}
void ApiReader::parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size)
{
ApiInfo *apiFound = 0;
ModuleInfo *module = 0;
bool isSuspect = false;
int countApiFound = 0, countApiNotFound = 0;
DWORD_PTR * pIATAddress = (DWORD_PTR *)iatBuffer;
SIZE_T sizeIAT = size / sizeof(DWORD_PTR);
bool foundModuleBreak = false;
for (SIZE_T i = 0; i < sizeIAT; i++)
{
//Logger::printfDialog("%08X %08X %d von %d",addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer,pIATAddress[i],i,sizeIAT);
if (pIATAddress[i] == 0 || pIATAddress[i] == -1)
{
/*if (pIATAddress[i+1] != 0)
{
printf("parseIAT :: Module break\n");
}*/
/*else
{
printf("parseIAT :: IAT finished\n");
break;
}*/
foundModuleBreak = true;
}
else if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) )
{
apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect);
if (apiFound == (ApiInfo *)1)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("apiFound == (ApiInfo *)1 -> ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),pIATAddress[i]);
#endif
}
else if (apiFound)
{
countApiFound++;
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" %s %d %s\r\n"),apiFound->va, apiFound->module->getFilename(), apiFound->ordinal,apiFound->name);
#endif
if (module != apiFound->module)
{
module = apiFound->module;
addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, true, isSuspect);
}
else
{
addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, false, isSuspect);
}
}
else
{
countApiNotFound++;
addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
//printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
}
}
else
{
//printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
countApiNotFound++;
addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
}
}
Logger::printfDialog(TEXT("IAT parsing finished, found %d valid APIs, missed %d APIs"),countApiFound,countApiNotFound);
}
void ApiReader::addFoundApiToModuleList(DWORD_PTR iatAddressVA, ApiInfo * apiFound, bool isNewModule, bool isSuspect)
{
if (isNewModule)
{
addModuleToModuleList(apiFound->module->getFilename(), iatAddressVA - targetImageBase);
}
addFunctionToModuleList(apiFound, iatAddressVA, iatAddressVA - targetImageBase, apiFound->ordinal, true, isSuspect);
}
bool ApiReader::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, moduleName);
(*moduleThunkList).insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
return true;
}
void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, TEXT("?"));
(*moduleThunkList).insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
}
bool ApiReader::addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
if ((*moduleThunkList).size() > 1)
{
iterator1 = (*moduleThunkList).begin();
while (iterator1 != (*moduleThunkList).end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == (*moduleThunkList).end())
{
iterator1--;
module = &(iterator1->second);
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n"));
#endif
break;
}
}
}
else
{
iterator1 = (*moduleThunkList).begin();
module = &(iterator1->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
#endif
return false;
}
import.suspect = suspect;
import.valid = valid;
import.va = va;
import.rva = rva;
import.apiAddressVA = apiFound->va;
import.ordinal = ordinal;
import.hint = (WORD)apiFound->hint;
wcscpy_s(import.moduleName, MAX_PATH, apiFound->module->getFilename());
strcpy_s(import.name, MAX_PATH, apiFound->name);
module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
return true;
}
void ApiReader::clearAll()
{
minApiAddress = -1;
maxApiAddress = 0;
for ( stdext::hash_multimap<DWORD_PTR, ApiInfo *>::iterator it = apiList.begin(); it != apiList.end(); ++it )
{
delete it->second;
}
apiList.clear();
if (moduleThunkList != 0)
{
(*moduleThunkList).clear();
}
}
bool ApiReader::addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
DWORD_PTR rva = iatAddressVA - targetImageBase;
if ((*moduleThunkList).size() > 0)
{
iterator1 = (*moduleThunkList).begin();
while (iterator1 != (*moduleThunkList).end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == (*moduleThunkList).end())
{
iterator1--;
//new unknown module
if (iterator1->second.moduleName[0] == L'?')
{
module = &(iterator1->second);
}
else
{
addUnknownModuleToModuleList(rva);
module = &((*moduleThunkList).find(rva)->second);
}
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("Error iterator1 != (*moduleThunkList).end()\r\n"));
#endif
break;
}
}
}
else
{
//new unknown module
addUnknownModuleToModuleList(rva);
module = &((*moduleThunkList).find(rva)->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
#endif
return false;
}
import.suspect = true;
import.valid = false;
import.va = iatAddressVA;
import.rva = rva;
import.apiAddressVA = apiAddress;
import.ordinal = 0;
wcscpy_s(import.moduleName, MAX_PATH, TEXT("?"));
strcpy_s(import.name, MAX_PATH, "?");
module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
return true;
}
bool ApiReader::isApiBlacklisted( const char * functionName )
{
if (SystemInformation::currenOS < WIN_VISTA_32)
{
if (!strcmp(functionName, "RestoreLastError"))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
/*#ifdef _WIN64
else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer"))
{
return true;
}
#endif*/
}
bool ApiReader::isWinSxSModule( ModuleInfo * module )
{
if (wcsstr(module->fullPath, TEXT("\\WinSxS\\")))
{
return true;
}
else if (wcsstr(module->fullPath, TEXT("\\winsxs\\")))
{
return true;
}
else
{
return false;
}
}
diff --git a/Scylla/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 <windows.h>
+#include "resource.h"
-static const enum DisassemblerColumns {
- COL_ADDRESS,
- COL_INSTRUCTION_SIZE,
- COL_OPCODES,
- COL_INSTRUCTION
-};
-
-#define DISASSEMBLER_GUI_MEMORY_SIZE 0x100
+// WTL
+#include <atlbase.h> // base ATL classes
+#include <atlapp.h> // base WTL classes
+#include <atlwin.h> // ATL GUI classes
+#include <atlmisc.h> // WTL utility classes like CString
+#include <atlcrack.h> // WTL enhanced msg map macros
+#include <atlctrls.h> // WTL controls
-class DisassemblerGui {
+class DisassemblerGui : public CDialogImpl<DisassemblerGui>
+{
public:
- static WCHAR tempBuffer[100];
- static HWND hWndDlg;
- static HINSTANCE hInstance;
- static DWORD_PTR startAddress;
-
- static INT_PTR initDialog(HINSTANCE hInstance, HWND hWndParent, DWORD_PTR address);
- static void addColumnsToDisassembler( HWND list );
- static void displayDisassembly();
-private:
- static LRESULT CALLBACK disassemblerDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- static HWND mouseInDialogItem(int dlgItem, POINT pt);
- static void OnContextMenu(int x, int y);
- static HMENU getCorrectSubMenu(int menuItem, int subMenuItem);
- static void getModuleListItem(int column, int iItem, WCHAR * buffer);
- static void copyToClipboard();
-};
\ No newline at end of file
+ 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<DWORD_PTR, ImportThunk>::iterator iterator = thunkList.begin();
while (iterator != thunkList.end())
{
if (iterator->second.valid == false)
{
return false;
}
iterator++;
}
return true;
}
DWORD_PTR ImportModuleThunk::getFirstThunk()
{
if (thunkList.size() > 0)
{
std::map<DWORD_PTR, ImportThunk>::iterator iterator = thunkList.begin();
return iterator->first;
}
else
{
return 0;
}
}
/*bool ImportsHandling::addModule(WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, moduleName);
moduleList.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
return true;
}*/
/*bool ImportsHandling::addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
if (moduleList.size() > 1)
{
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == moduleList.end())
{
iterator1--;
module = &(iterator1->second);
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
}
}
else
{
iterator1 = moduleList.begin();
module = &(iterator1->second);
}
if (!module)
{
Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(""),rva);
return false;
}
//TODO
import.suspect = true;
import.valid = false;
import.va = va;
import.rva = rva;
import.ordinal = ordinal;
wcscpy_s(import.moduleName, MAX_PATH, moduleName);
strcpy_s(import.name, MAX_PATH, name);
module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
return true;
}*/
void ImportsHandling::displayAllImports()
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
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<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::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<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->hTreeItem == selectedTreeNode)
{
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<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->hTreeItem == selectedTreeNode)
{
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<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
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<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->hTreeItem == selectedTreeNode)
{
return importThunk->apiAddressVA;
}
iterator2++;
}
iterator1++;
}
return 0;
}
void ImportsHandling::scanAndFixModuleList()
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
std::map<DWORD_PTR, ImportThunk>::iterator iterator2;
ImportModuleThunk * moduleThunk;
ImportThunk * importThunk;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->moduleName[0] == 0 || importThunk->moduleName[0] == L'?')
{
addNotFoundApiToModuleList(importThunk);
}
else
{
if (isNewModule(importThunk->moduleName))
{
addModuleToModuleList(importThunk->moduleName, importThunk->rva);
}
addFunctionToModuleList(importThunk);
}
iterator2++;
}
moduleThunk->thunkList.clear();
iterator1++;
}
moduleList.clear();
moduleList.insert(moduleListNew.begin(), moduleListNew.end());
moduleListNew.clear();
}
-bool ImportsHandling::findNewModules( std::map<DWORD_PTR, ImportThunk> & thunkList )
+bool ImportsHandling::findNewModules(std::map<DWORD_PTR, ImportThunk> & thunkList)
{
throw std::exception("The method or operation is not implemented.");
}
bool ImportsHandling::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, moduleName);
moduleListNew.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
return true;
}
bool ImportsHandling::isNewModule(const WCHAR * moduleName)
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
iterator1 = moduleListNew.begin();
while (iterator1 != moduleListNew.end())
{
if (!_wcsicmp(iterator1->second.moduleName, moduleName))
{
return false;
}
iterator1++;
}
return true;
}
void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, L"?");
moduleListNew.insert(std::pair<DWORD_PTR,ImportModuleThunk>(firstThunk,module));
}
-bool ImportsHandling::addNotFoundApiToModuleList(ImportThunk * apiNotFound)
+bool ImportsHandling::addNotFoundApiToModuleList(const ImportThunk * apiNotFound)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
DWORD_PTR rva = apiNotFound->rva;
if (moduleListNew.size() > 0)
{
iterator1 = moduleListNew.begin();
while (iterator1 != moduleListNew.end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == moduleListNew.end())
{
iterator1--;
//new unknown module
if (iterator1->second.moduleName[0] == L'?')
{
module = &(iterator1->second);
}
else
{
addUnknownModuleToModuleList(apiNotFound->rva);
module = &(moduleListNew.find(rva)->second);
}
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("Error iterator1 != (*moduleThunkList).end()\r\n");
#endif
break;
}
}
}
else
{
//new unknown module
addUnknownModuleToModuleList(apiNotFound->rva);
module = &(moduleListNew.find(rva)->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),rva);
#endif
return false;
}
import.suspect = true;
import.valid = false;
import.va = apiNotFound->va;
import.rva = apiNotFound->rva;
import.apiAddressVA = apiNotFound->apiAddressVA;
import.ordinal = 0;
wcscpy_s(import.moduleName, MAX_PATH, L"?");
strcpy_s(import.name, MAX_PATH, "?");
module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
return true;
}
-bool ImportsHandling::addFunctionToModuleList(ImportThunk * apiFound)
+bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
if (moduleListNew.size() > 1)
{
iterator1 = moduleListNew.begin();
while (iterator1 != moduleListNew.end())
{
if (apiFound->rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == moduleListNew.end())
{
iterator1--;
module = &(iterator1->second);
break;
}
else if (apiFound->rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("Error iterator1 != moduleListNew.end()\r\n"));
#endif
break;
}
}
}
else
{
iterator1 = moduleListNew.begin();
module = &(iterator1->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog(TEXT("ImportsHandling::addFunction module not found rva ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT("\r\n"),apiFound->rva);
#endif
return false;
}
import.suspect = apiFound->suspect;
import.valid = apiFound->valid;
import.va = apiFound->va;
import.rva = apiFound->rva;
import.apiAddressVA = apiFound->apiAddressVA;
import.ordinal = apiFound->ordinal;
import.hint = apiFound->hint;
wcscpy_s(import.moduleName, MAX_PATH, apiFound->moduleName);
strcpy_s(import.name, MAX_PATH, apiFound->name);
module->thunkList.insert(std::pair<DWORD_PTR,ImportThunk>(import.rva, import));
return true;
}
void ImportsHandling::expandAllTreeNodes()
{
changeExpandStateOfTreeNodes(TVE_EXPAND);
}
void ImportsHandling::collapseAllTreeNodes()
{
changeExpandStateOfTreeNodes(TVE_COLLAPSE);
}
void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag)
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator iterator1;
ImportModuleThunk * moduleThunk;
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 <map>
+// WTL
#include <atlbase.h>
#include <atlapp.h>
-#include <atlctrls.h>
+#include <atlctrls.h> // CTreeViewCtrl, CTreeItem
+
+class ImportThunk;
+class ImportModuleThunk;
class ImportsHandling
{
public:
std::map<DWORD_PTR, ImportModuleThunk> moduleList;
std::map<DWORD_PTR, ImportModuleThunk> moduleListNew;
//bool addFunction(WCHAR * moduleName, char * name, DWORD_PTR va, DWORD_PTR rva, DWORD_PTR ordinal, bool valid, bool suspect);
//bool addModule(WCHAR * moduleName, DWORD_PTR firstThunk);
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<DWORD_PTR, ImportThunk> & thunkList );
+ bool findNewModules(std::map<DWORD_PTR, ImportThunk> & thunkList);
bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk);
void addUnknownModuleToModuleList(DWORD_PTR firstThunk);
- bool addNotFoundApiToModuleList(ImportThunk * apiNotFound);
- bool addFunctionToModuleList(ImportThunk * apiFound);
+ bool 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<Process>& processList = processLister.getProcessList();
Process &process = processList.at(index);
selectedProcess = &process;
enableDialogButtons(TRUE);
Logger::printfDialog(TEXT("Analyzing %s"),process.fullPath);
if (processAccessHelp.hProcess != 0)
{
processAccessHelp.closeProcessHandle();
apiReader.clearAll();
}
if (!processAccessHelp.openProcessHandle(process.PID))
{
Logger::printfDialog(TEXT("Error: Cannot open process handle."));
return;
}
processAccessHelp.getProcessModules(process.PID, processAccessHelp.moduleList);
apiReader.readApisFromModuleList();
Logger::printfDialog(TEXT("Loading modules done."));
//TODO improve
processAccessHelp.selectedModule = 0;
processAccessHelp.targetSizeOfImage = process.imageSize;
processAccessHelp.targetImageBase = process.imageBase;
ProcessAccessHelp::getSizeOfImageCurrentProcess();
process.imageSize = (DWORD)processAccessHelp.targetSizeOfImage;
Logger::printfDialog(TEXT("Imagebase: ")TEXT(PRINTF_DWORD_PTR_FULL)TEXT(" Size: %08X"),process.imageBase, process.imageSize);
selectedProcess->entryPoint = ProcessAccessHelp::getEntryPointFromFile(selectedProcess->fullPath);
swprintf_s(stringBuffer, _countof(stringBuffer),TEXT(PRINTF_DWORD_PTR_FULL),selectedProcess->entryPoint + selectedProcess->imageBase);
EditOEPAddress.SetWindowText(stringBuffer);
}
void MainGui::fillProcessListComboBox(CComboBox& hCombo)
{
hCombo.ResetContent();
std::vector<Process>& processList = processLister.getProcessListSnapshot();
for (size_t i = 0; i < processList.size(); i++)
{
swprintf_s(stringBuffer, _countof(stringBuffer),TEXT("0x%04X - %s - %s"),processList[i].PID,processList[i].filename,processList[i].fullPath);
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<Plugin> &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<Plugin> &scyllaPluginList = PluginLoader::getScyllaPluginList();
std::vector<Plugin> &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<Plugin> &scyllaPluginList = PluginLoader::getScyllaPluginList();
std::vector<Plugin> &imprecPluginList = PluginLoader::getImprecPluginList();
menuItem -= PLUGIN_MENU_BASE_ID;
dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
dllInjectionPlugin.apiReader = &apiReader;
if (menuItem < (int)scyllaPluginList.size())
{
//scylla plugin
dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
}
else
{
#ifndef _WIN64
menuItem -= (int)scyllaPluginList.size();
//imprec plugin
dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
#endif
}
importsHandling.scanAndFixModuleList();
importsHandling.displayAllImports();
}
diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h
index ad98403..8ad6154 100644
--- a/Scylla/MainGui.h
+++ b/Scylla/MainGui.h
@@ -1,169 +1,165 @@
#pragma once
-//#define _CRTDBG_MAP_ALLOC
-//#include <stdlib.h>
-//#include <crtdbg.h>
-
#include <windows.h>
-#include <Commctrl.h>
-#include <stdio.h>
-#include <map>
-#include <Windowsx.h>
+#include "resource.h"
// WTL
-
#include <atlbase.h> // base ATL classes
#include <atlapp.h> // base WTL classes
#include <atlwin.h> // ATL GUI classes
-#include <atlframe.h> // WTL frame window classes
#include <atlmisc.h> // WTL utility classes like CString
#include <atlcrack.h> // WTL enhanced msg map macros
+#include <atlctrls.h> // WTL controls
+
+//#define _CRTDBG_MAP_ALLOC
+//#include <cstdlib>
+//#include <crtdbg.h>
-#include <atlctrls.h>
+#include <cstdio>
-#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<MainGui>
{
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<Configuration, ConfigObject>::iterator mapIter;
for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++)
{
getConfigOptionsFromDlg((*mapIter).second);
}
}
void OptionsGui::loadOptions()
{
std::map<Configuration, ConfigObject>::iterator mapIter;
for (mapIter = ConfigurationHolder::getConfigList().begin() ; mapIter != ConfigurationHolder::getConfigList().end(); mapIter++)
{
displayConfigInDlg((*mapIter).second);
}
}
void OptionsGui::setCheckBox( int nIDDlgItem, bool bValue )
{
- if (bValue)
- {
- Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_CHECKED);
- }
- else
- {
- Button_SetCheck(GetDlgItem(hWndDlg, nIDDlgItem),BST_UNCHECKED);
- }
+ 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 <windows.h>
+#include "resource.h"
+
+// WTL
+#include <atlbase.h> // base ATL classes
+#include <atlapp.h> // base WTL classes
+#include <atlwin.h> // ATL GUI classes
+#include <atlcrack.h> // WTL enhanced msg map macros
+#include <atlctrls.h> // WTL controls
class ConfigObject;
-class OptionsGui {
+class OptionsGui : public CDialogImpl<OptionsGui>
+{
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<ModuleInfo> * PickDllGui::moduleList = 0;
-ModuleInfo * PickDllGui::selectedModule = 0;
+ addColumnsToModuleList(ListDLLSelect);
+ displayModuleList(ListDLLSelect);
-INT_PTR PickDllGui::initDialog(HINSTANCE hInstance, HWND hWndParent, std::vector<ModuleInfo> &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<ModuleInfo>::iterator iter;
+ std::vector<ModuleInfo>::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 <windows.h>
+#include "resource.h"
-static const enum ListColumns {
- COL_PATH,
- COL_NAME,
- COL_IMAGEBASE,
- COL_IMAGESIZE
-};
+// WTL
+#include <atlbase.h> // base ATL classes
+#include <atlapp.h> // base WTL classes
+#include <atlwin.h> // ATL GUI classes
+#include <atlmisc.h> // WTL utility classes like CString
+#include <atlcrack.h> // WTL enhanced msg map macros
+#include <atlctrls.h> // WTL controls
+
+#include <vector>
+#include "ProcessAccessHelp.h"
-class PickDllGui {
+class PickDllGui : public CDialogImpl<PickDllGui>
+{
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<ModuleInfo> &moduleList) : moduleList(moduleList), selectedModule(0) { }
+
+ ModuleInfo* getSelectedModule() const { return selectedModule; }
- static std::vector<ModuleInfo> * 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<ModuleInfo> &moduleList);
+ std::vector<ModuleInfo> &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 <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
#include <hash_map>
#include <map>
/************************************************************************/
/* distorm */
/************************************************************************/
#include "distorm.h"
/*
#ifdef _WIN64
#pragma comment(lib, "distorm_x64.lib")
#else
#pragma comment(lib, "distorm_x86.lib")
#endif
*/
// The number of the array of instructions the decoder function will use to return the disassembled instructions.
// Play with this value for performance...
#define MAX_INSTRUCTIONS (200)
/************************************************************************/
class ApiInfo;
class ModuleInfo {
public:
WCHAR fullPath[MAX_PATH];
DWORD_PTR modBaseAddr;
DWORD modBaseSize;
bool isAlreadyParsed;
bool parsing;
/*
for iat rebuilding with duplicate entries:
ntdll = low priority
kernelbase = low priority
SHLWAPI = low priority
kernel32 = high priority
priority = 1 -> normal/high priority
priority = 0 -> low priority
*/
int priority;
std::vector<ApiInfo *> apiList;
ModuleInfo()
{
modBaseAddr = 0;
modBaseSize = 0;
priority = 1;
isAlreadyParsed = false;
parsing = false;
}
- WCHAR * getFilename()
+ 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<ModuleInfo> moduleList; //target process module list
static std::vector<ModuleInfo> ownModuleList; //own module list
static const int PE_HEADER_BYTES_COUNT = 2000;
static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
//for decomposer
static _DInst decomposerResult[MAX_INSTRUCTIONS];
static unsigned int decomposerInstructionsCount;
static _CodeInfo decomposerCi;
//distorm :: Decoded instruction information.
static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
static unsigned int decodedInstructionsCount;
#ifdef _WIN64
static const _DecodeType dt = Decode64Bits;
#else
static const _DecodeType dt = Decode32Bits;
#endif
/*
* Open a new process handle
*/
static bool openProcessHandle(DWORD dwPID);
static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId);
static void closeProcessHandle();
/*
* Get all modules from a process
*/
static bool getProcessModules(DWORD dwPID, std::vector<ModuleInfo> &moduleList);
/*
* file mapping view with different access level
*/
static LPVOID createFileMappingViewRead(const WCHAR * filePath);
static LPVOID createFileMappingViewFull(const WCHAR * filePath);
/*
* Create a file mapping view of a file
*/
static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap);
/*
* Read memory from target process
*/
static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer);
/*
* Read memory from file
*/
static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer);
/*
* Write memory to file
*/
static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer);
/*
* Write memory to file end
*/
static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPVOID dataBuffer);
/*
* Disassemble Memory
*/
static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset);
static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress);
/*
* Search for pattern
*/
static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask);
/*
* Get process ID by process name
*/
static DWORD getProcessByName(const WCHAR * processName);
/*
* Get memory region from address
*/
bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize);
/*
* Read PE Header from file
*/
static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath);
static bool readHeaderFromCurrentFile(const WCHAR * filePath);
/*
* Get real sizeOfImage value
*/
static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase);
/*
* Get real sizeOfImage value current process
*/
static bool getSizeOfImageCurrentProcess();
static LONGLONG getFileSize(HANDLE hFile);
static LONGLONG getFileSize(const WCHAR * filePath);
static WCHAR * selectFileToSave(DWORD flags, int type);
static DWORD getEntryPointFromFile(const WCHAR * filePath);
static bool createBackupFile(const WCHAR * filePath);
};
diff --git a/Scylla/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 <windows.h>
#include <Commctrl.h>
#include <map>
+// WTL
#include <atlbase.h>
#include <atlapp.h>
-#include <atlctrls.h>
-
-class ImportModuleThunk;
-class ImportThunk;
+#include <atlctrls.h> //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<DWORD_PTR, ImportThunk> 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 <atlbase.h> // base ATL classes
#include <atlapp.h> // 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;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 21, 9:40 PM (1 d, 21 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b4/48/e35ac9a3a8be7b20df83af4135de

Event Timeline