diff --git a/Scylla/AboutGui.cpp b/Scylla/AboutGui.cpp
index 3f806e3..53e9674 100644
--- a/Scylla/AboutGui.cpp
+++ b/Scylla/AboutGui.cpp
@@ -1,124 +1,124 @@
#include "AboutGui.h"
#include "Scylla.h"
#include "Architecture.h"
const WCHAR AboutGui::TEXT_VISIT[] = L"Visit http://kickme.to/grn and http://forum.tuts4you.com";
const WCHAR AboutGui::TEXT_DEVELOPED[] = L"Developed with Microsoft Visual Studio, written in pure C/C++";
const WCHAR AboutGui::TEXT_CREDIT_DISTORM[] = L"This tool uses the diStorm disassembler library v3";
const WCHAR AboutGui::TEXT_CREDIT_YODA[] = L"The PE Rebuilder engine is based on Realign DLL v1.5 by yoda";
const WCHAR AboutGui::TEXT_CREDIT_SILK[] = L"The small icons are taken from the Silk icon package";
const WCHAR AboutGui::TEXT_CREDIT_WTL[] = L"Windows Template Library v8 is used for the GUI";
const WCHAR AboutGui::TEXT_GREETINGS[] = L"Greetz: metr0, G36KV and all from the gRn Team";
const WCHAR AboutGui::TEXT_LICENSE[] = L"Scylla is licensed under the GNU General Public License v3";
const WCHAR AboutGui::TEXT_TINYXML[] = L"XML support is provided by TinyXML";
const WCHAR AboutGui::URL_VISIT1[] = L"http://kickme.to/grn";
const WCHAR AboutGui::URL_VISIT2[] = L"http://forum.tuts4you.com";
const WCHAR AboutGui::URL_DISTORM[] = L"http://code.google.com/p/distorm/";
const WCHAR AboutGui::URL_WTL[] = L"http://wtl.sourceforge.net";
const WCHAR AboutGui::URL_SILK[] = L"http://www.famfamfam.com";
const WCHAR AboutGui::URL_LICENSE[] = L"http://www.gnu.org/licenses/gpl-3.0.html";
const WCHAR AboutGui::URL_TINYXML[] = L"http://sourceforge.net/projects/tinyxml/";
BOOL AboutGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
// Create a bold font for the title
LOGFONT lf;
CFontHandle font = StaticTitle.GetFont();
font.GetLogFont(&lf);
lf.lfWeight = FW_BOLD;
FontBold.CreateFontIndirect(&lf);
StaticTitle.SetFont(FontBold, FALSE);
StaticTitle.SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION);
StaticDeveloped.SetWindowText(TEXT_DEVELOPED);
StaticGreetings.SetWindowText(TEXT_GREETINGS);
StaticYoda.SetWindowText(TEXT_CREDIT_YODA);
setupLinks();
CenterWindow();
// Set focus to the OK button
GotoDlgCtrl(GetDlgItem(IDOK));
return FALSE;
}
void AboutGui::OnClose()
{
TooltipDistorm.DestroyWindow();
TooltipWTL.DestroyWindow();
TooltipSilk.DestroyWindow();
TooltipLicense.DestroyWindow();
FontBold.DeleteObject();
EndDialog(0);
}
LRESULT AboutGui::OnLink(NMHDR* pnmh)
{
const NMLINK* link = (NMLINK*)pnmh;
ShellExecute(NULL, L"open", link->item.szUrl, NULL, NULL, SW_SHOW);
return 0;
}
void AboutGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl)
{
SendMessage(WM_CLOSE);
}
void AboutGui::setupLinks()
{
// Set link text (must be set before assigning URLs)
LinkVisit.SetWindowText(TEXT_VISIT);
LinkDistorm.SetWindowText(TEXT_CREDIT_DISTORM);
LinkWTL.SetWindowText(TEXT_CREDIT_WTL);
LinkSilk.SetWindowText(TEXT_CREDIT_SILK);
LinkTinyxml.SetWindowText(TEXT_TINYXML);
LinkLicense.SetWindowText(TEXT_LICENSE);
// Assign URLs to anchors in the link text
setLinkURL(LinkVisit, URL_VISIT1, 0);
setLinkURL(LinkVisit, URL_VISIT2, 1);
setLinkURL(LinkDistorm, URL_DISTORM);
setLinkURL(LinkWTL, URL_WTL);
setLinkURL(LinkSilk, URL_SILK);
setLinkURL(LinkTinyxml, URL_TINYXML);
setLinkURL(LinkLicense, URL_LICENSE);
// Create tooltips for the links
TooltipDistorm.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST);
TooltipWTL.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST);
TooltipSilk.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST);
TooltipTinyxml.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST);
TooltipLicense.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST);
// Assign control and text to the tooltips
setupTooltip(TooltipDistorm, LinkDistorm, URL_DISTORM);
setupTooltip(TooltipWTL, LinkWTL, URL_WTL);
setupTooltip(TooltipSilk, LinkSilk, URL_SILK);
setupTooltip(TooltipTinyxml, LinkTinyxml, URL_TINYXML);
setupTooltip(TooltipLicense, LinkLicense, URL_LICENSE);
}
void AboutGui::setLinkURL(CLinkCtrl& link, const WCHAR* url, int index)
{
LITEM item;
item.mask = LIF_ITEMINDEX | LIF_URL;
item.iLink = index;
- wcscpy_s(item.szUrl, _countof(item.szUrl), url);
+ wcscpy_s(item.szUrl, url);
link.SetItem(&item);
}
void AboutGui::setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text)
{
CToolInfo ti(TTF_SUBCLASS, window);
window.GetClientRect(&ti.rect);
ti.lpszText = const_cast(text);
tooltip.AddTool(ti);
}
diff --git a/Scylla/ApiReader.cpp b/Scylla/ApiReader.cpp
index 9133f4d..b504d4f 100644
--- a/Scylla/ApiReader.cpp
+++ b/Scylla/ApiReader.cpp
@@ -1,1325 +1,1325 @@
#include "ApiReader.h"
#include "Scylla.h"
#include "Architecture.h"
#include "SystemInformation.h"
#include "StringConversion.h"
std::unordered_map ApiReader::apiList; //api look up table
std::map * ApiReader::moduleThunkList; //store found apis
DWORD_PTR ApiReader::minApiAddress = 0xFFFFFFFF;
DWORD_PTR ApiReader::maxApiAddress = 0;
//#define DEBUG_COMMENTS
void ApiReader::readApisFromModuleList()
{
for (unsigned int i = 0; i < moduleList.size();i++)
{
setModulePriority(&moduleList[i]);
if (moduleList[i].modBaseAddr + moduleList[i].modBaseSize > maxValidAddress)
{
maxValidAddress = moduleList[i].modBaseAddr + moduleList[i].modBaseSize;
}
Scylla::windowLog.log(L"Module parsing: %s",moduleList[i].fullPath);
if (!moduleList[i].isAlreadyParsed)
{
parseModule(&moduleList[i]);
}
}
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Address Min " PRINTF_DWORD_PTR_FULL L" Max " PRINTF_DWORD_PTR_FULL L"\nimagebase " PRINTF_DWORD_PTR_FULL L" maxValidAddress " PRINTF_DWORD_PTR_FULL, minApiAddress, maxApiAddress, targetImageBase ,maxValidAddress);
#endif
}
void ApiReader::parseModule(ModuleInfo *module)
{
module->parsing = true;
if (isWinSxSModule(module))
{
parseModuleWithMapping(module);
}
else if (isModuleLoadedInOwnProcess(module))
{
parseModuleWithOwnProcess(module);
}
else
{
parseModuleWithProcess(module);
}
module->isAlreadyParsed = true;
}
void ApiReader::parseModuleWithMapping(ModuleInfo *moduleInfo)
{
LPVOID fileMapping = 0;
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
fileMapping = createFileMappingViewRead(moduleInfo->fullPath);
if (fileMapping == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)fileMapping;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping);
}
UnmapViewOfFile(fileMapping);
}
inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader)
{
if ((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)))
{
return true;
}
else
{
return false;
}
}
void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer,char * functionNameParent, DWORD_PTR rvaParent, WORD ordinalParent, ModuleInfo *moduleParent)
{
size_t dllNameLength = 0;
WORD ordinal = 0;
ModuleInfo *module = 0;
DWORD_PTR vaApi = 0;
DWORD_PTR rvaApi = 0;
char dllName[100] = {0};
WCHAR dllNameW[100] = {0};
char *fordwardedString = (char *)vaStringPointer;
char *searchFunctionName = strchr(fordwardedString, '.');
if (!searchFunctionName)
return;
dllNameLength = searchFunctionName - fordwardedString;
if (dllNameLength >= 99)
{
return;
}
else
{
- strncpy_s(dllName,sizeof(dllName),fordwardedString,dllNameLength);
+ strncpy_s(dllName, fordwardedString, dllNameLength);
}
searchFunctionName++;
//Windows 7
if (!strncmp(dllName,"api-ms-win-", 11))
{
/*
Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html
*/
FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName);
if (addy != 0)
{
addApi(functionNameParent,0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent);
}
return;
}
- strcat_s(dllName, sizeof(dllName), ".dll");
+ strcat_s(dllName, ".dll");
StringConversion::ToUTF16(dllName, dllNameW, _countof(dllNameW));
if (!_wcsicmp(dllNameW, moduleParent->getFilename()))
{
module = moduleParent;
}
else
{
module = findModuleByName(dllNameW);
}
if (module != 0) // module == 0 -> can be ignored
{
/*if ((module->isAlreadyParsed == false) && (module != moduleParent))
{
//do API extract
if (module->parsing == true)
{
//some stupid circle dependency
printf("stupid circle dependency %s\n",module->getFilename());
}
else
{
parseModule(module);
}
}*/
if (strchr(searchFunctionName,'#'))
{
//forwarding by ordinal
searchFunctionName++;
ordinal = (WORD)atoi(searchFunctionName);
findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi);
}
else
{
findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi);
}
if (rvaApi == 0)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"handleForwardedApi :: Api not found, this is really BAD! %S",fordwardedString);
#endif
}
else
{
addApi(functionNameParent,0, ordinalParent, vaApi, rvaApi, true, moduleParent);
}
}
}
ModuleInfo * ApiReader::findModuleByName(WCHAR *name)
{
for (unsigned int i = 0; i < moduleList.size(); i++) {
if (!_wcsicmp(moduleList[i].getFilename(), name))
{
return &moduleList[i];
}
}
return 0;
}
void ApiReader::addApiWithoutName(WORD ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo)
{
addApi(0, 0, ordinal, va, rva, isForwarded, moduleInfo);
}
void ApiReader::addApi(char *functionName, WORD hint, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo)
{
ApiInfo *apiInfo = new ApiInfo();
if ((functionName != 0) && (strlen(functionName) < _countof(apiInfo->name)))
{
- strcpy_s(apiInfo->name, _countof(apiInfo->name), functionName);
+ strcpy_s(apiInfo->name, functionName);
}
else
{
apiInfo->name[0] = 0x00;
}
apiInfo->ordinal = ordinal;
apiInfo->isForwarded = isForwarded;
apiInfo->module = moduleInfo;
apiInfo->rva = rva;
apiInfo->va = va;
apiInfo->hint = hint;
setMinMaxApiAddress(va);
moduleInfo->apiList.push_back(apiInfo);
apiList.insert(API_Pair(va, apiInfo));
}
BYTE * ApiReader::getHeaderFromProcess(ModuleInfo * module)
{
BYTE *bufferHeader = 0;
DWORD readSize = 0;
if (module->modBaseSize < PE_HEADER_BYTES_COUNT)
{
readSize = module->modBaseSize;
}
else
{
readSize = PE_HEADER_BYTES_COUNT;
}
bufferHeader = new BYTE[readSize];
if(!readMemoryFromProcess(module->modBaseAddr, readSize, bufferHeader))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getHeaderFromProcess :: Error reading header");
#endif
delete[] bufferHeader;
return 0;
}
else
{
return bufferHeader;
}
}
BYTE * ApiReader::getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader)
{
DWORD readSize = 0;
BYTE *bufferExportTable = 0;
readSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if (readSize < (sizeof(IMAGE_EXPORT_DIRECTORY) + 8))
{
//Something is wrong with the PE Header
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Something is wrong with the PE Header here Export table size %d", readSize);
#endif
readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100;
}
if (readSize)
{
bufferExportTable = new BYTE[readSize];
if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getExportTableFromProcess :: Error reading export table from process");
#endif
delete[] bufferExportTable;
return 0;
}
else
{
return bufferExportTable;
}
}
else
{
return 0;
}
}
void ApiReader::parseModuleWithProcess(ModuleInfo * module)
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
BYTE *bufferHeader = 0;
BYTE *bufferExportTable = 0;
bufferHeader = getHeaderFromProcess(module);
if (bufferHeader == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
bufferExportTable = getExportTableFromProcess(module, pNtHeader);
if(bufferExportTable)
{
parseExportTable(module,pNtHeader,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
delete[] bufferExportTable;
}
}
delete[] bufferHeader;
}
void ApiReader::parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress)
{
DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
WORD *addressOfNameOrdinalsArray = 0;
char *functionName = 0;
DWORD_PTR RVA = 0, VA = 0;
WORD ordinal = 0;
WORD i = 0, j = 0;
bool withoutName;
addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"parseExportTable :: module %s NumberOfNames %X", module->fullPath, pExportDir->NumberOfNames);
#endif
for (i = 0; i < pExportDir->NumberOfNames; i++)
{
functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
ordinal = (WORD)(addressOfNameOrdinalsArray[i] + pExportDir->Base);
RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"parseExportTable :: api %S ordinal %d imagebase " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" VA " PRINTF_DWORD_PTR_FULL, functionName, ordinal, module->modBaseAddr, RVA, VA);
#endif
if (!isApiBlacklisted(functionName))
{
if (!isApiForwarded(RVA,pNtHeader))
{
addApi(functionName, i, ordinal,VA,RVA,false,module);
}
else
{
//printf("Forwarded: %s\n",functionName);
handleForwardedApi(RVA + deltaAddress,functionName,RVA,ordinal,module);
}
}
}
/*Exports without name*/
if (pExportDir->NumberOfNames != pExportDir->NumberOfFunctions)
{
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
withoutName = true;
for (j = 0; j < pExportDir->NumberOfNames; j++)
{
if(addressOfNameOrdinalsArray[j] == i)
{
withoutName = false;
break;
}
}
if (withoutName && addressOfFunctionsArray[i] != 0)
{
ordinal = (WORD)(i+pExportDir->Base);
RVA = addressOfFunctionsArray[i];
VA = (addressOfFunctionsArray[i] + module->modBaseAddr);
if (!isApiForwarded(RVA,pNtHeader))
{
addApiWithoutName(ordinal,VA,RVA,false,module);
}
else
{
handleForwardedApi(RVA + deltaAddress,0,RVA,ordinal,module);
}
}
}
}
}
void ApiReader::findApiByModuleAndOrdinal(ModuleInfo * module, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
findApiByModule(module,0,ordinal,vaApi,rvaApi);
}
void ApiReader::findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
findApiByModule(module,searchFunctionName,0,vaApi,rvaApi);
}
void ApiReader::findApiByModule(ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
if (isModuleLoadedInOwnProcess(module))
{
HMODULE hModule = GetModuleHandle(module->getFilename());
if (hModule)
{
if (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
Scylla::debugLog.log(L"findApiByModule :: vaApi == NULL, should never happen %S", searchFunctionName);
#endif
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findApiByModule :: hModule == NULL, should never happen %s", module->getFilename());
#endif
}
}
else
{
//search api in extern process
findApiInProcess(module,searchFunctionName,ordinal,vaApi,rvaApi);
}
}
bool ApiReader::isModuleLoadedInOwnProcess(ModuleInfo * module)
{
for (unsigned int i = 0; i < ownModuleList.size(); i++)
{
if (!_wcsicmp(module->fullPath, ownModuleList[i].fullPath))
{
//printf("isModuleLoadedInOwnProcess :: %s %s\n",module->fullPath,ownModuleList[i].fullPath);
return true;
}
}
return false;
}
void ApiReader::parseModuleWithOwnProcess( ModuleInfo * module )
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
HMODULE hModule = GetModuleHandle(module->getFilename());
if (hModule)
{
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)hModule);
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"parseModuleWithOwnProcess :: hModule is NULL");
#endif
}
}
bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader)
{
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
Scylla::windowLog.log(L"-> IMAGE_NT_SIGNATURE doesn't match.");
return false;
}
else if ((pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) || (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0))
{
Scylla::windowLog.log(L"-> No export table.");
return false;
}
else
{
return true;
}
}
void ApiReader::findApiInProcess(ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
BYTE *bufferHeader = 0;
BYTE *bufferExportTable = 0;
bufferHeader = getHeaderFromProcess(module);
if (bufferHeader == 0)
return;
pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew));
if (isPeAndExportTableValid(pNtHeader))
{
bufferExportTable = getExportTableFromProcess(module, pNtHeader);
if(bufferExportTable)
{
findApiInExportTable(module,(PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,searchFunctionName,ordinal,vaApi,rvaApi);
delete[] bufferExportTable;
}
}
delete[] bufferHeader;
}
bool ApiReader::findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi)
{
DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
WORD *addressOfNameOrdinalsArray = 0;
char *functionName = 0;
DWORD i = 0, j = 0;
addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress);
addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress);
addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress);
if (searchFunctionName)
{
for (i = 0; i < pExportDir->NumberOfNames; i++)
{
functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
if (!strcmp(functionName,searchFunctionName))
{
*rvaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]];
*vaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr;
return true;
}
}
}
else
{
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
if (ordinal == (i+pExportDir->Base))
{
*rvaApi = addressOfFunctionsArray[i];
*vaApi = (addressOfFunctionsArray[i] + module->modBaseAddr);
return true;
}
}
}
return false;
}
void ApiReader::setModulePriority(ModuleInfo * module)
{
const WCHAR *moduleFileName = module->getFilename();
//imports by kernelbase don't exist
if (!_wcsicmp(moduleFileName, L"kernelbase.dll"))
{
module->priority = -1;
}
else if (!_wcsicmp(moduleFileName, L"ntdll.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"shlwapi.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"ShimEng.dll"))
{
module->priority = 0;
}
else if (!_wcsicmp(moduleFileName, L"kernel32.dll"))
{
module->priority = 2;
}
else
{
module->priority = 1;
}
}
bool ApiReader::isApiAddressValid(DWORD_PTR virtualAddress)
{
return apiList.count(virtualAddress) > 0;
}
ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect)
{
std::unordered_map::iterator it1, it2;
size_t c = 0;
size_t countDuplicates = apiList.count(virtualAddress);
int countHighPriority = 0;
ApiInfo *apiFound = 0;
if (countDuplicates == 0)
{
Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, virtualAddress);
return 0;
}
else if (countDuplicates == 1)
{
//API is 100% correct
*isSuspect = false;
it1 = apiList.find(virtualAddress); // Find first match.
return (ApiInfo *)((*it1).second);
}
else
{
it1 = apiList.find(virtualAddress); // Find first match.
//any high priority with a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,true,false,false,false,false);
if (apiFound)
return apiFound;
*isSuspect = true;
//high priority with a name and ansi/unicode name
apiFound = getScoredApi(it1,countDuplicates,true,true,false,true,false,false,false,false);
if (apiFound)
return apiFound;
//priority 2 with no underline in name
apiFound = getScoredApi(it1,countDuplicates,true,false,true,false,false,false,true,false);
if (apiFound)
return apiFound;
//priority 1 with a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,false,false,true,false,false);
if (apiFound)
return apiFound;
//With a name
apiFound = getScoredApi(it1,countDuplicates,true,false,false,false,false,false,false,false);
if (apiFound)
return apiFound;
//any with priority, name, ansi/unicode
apiFound = getScoredApi(it1,countDuplicates,true,true,false,true,false,false,false,true);
if (apiFound)
return apiFound;
//any with priority
apiFound = getScoredApi(it1,countDuplicates,false,false,false,true,false,false,false,true);
if (apiFound)
return apiFound;
//has prio 0 and name
apiFound = getScoredApi(it1,countDuplicates,false,false,false,false,true,false,false,true);
if (apiFound)
return apiFound;
}
//is never reached
Scylla::windowLog.log(L"getApiByVirtualAddress :: There is a api resolving bug, VA: " PRINTF_DWORD_PTR_FULL, virtualAddress);
for (size_t c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
Scylla::windowLog.log(L"-> Possible API: %S ord: %d ", apiFound->name, apiFound->ordinal);
}
return (ApiInfo *) 1;
}
/*ApiInfo * ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect)
{
std::unordered_map::iterator it1, it2;
size_t c = 0;
size_t countDuplicates = apiList.count(virtualAddress);
int countHighPriority = 0;
ApiInfo *apiFound = 0;
if (countDuplicates == 0)
{
Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, virtualAddress);
return 0;
}
else if (countDuplicates == 1)
{
//API is 100% correct
*isSuspect = false;
it1 = apiList.find(virtualAddress); // Find first match.
return (ApiInfo *)((*it1).second);
}
else
{
it1 = apiList.find(virtualAddress); // Find first match.
it2 = it1;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
if (apiFound->module->priority >= 1) //1 == high priority
{
countHighPriority++;
}
}
it1 = it2;
This is flawed:
It chooses api(prio:1, name:no) over api(prio:0, name:yes)
(e.g. SHLWAPI.PathCombineW vs SHELL32.#25)
Maybe there should be a check higher up in the code, to see if this API is surrounded
by APIs of a DLL and pick the duplicate from that DLL
if (countHighPriority == 0)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getApiByVirtualAddress :: countHighPriority == 0 " PRINTF_DWORD_PTR_FULL, virtualAddress);
#endif
*isSuspect = true;
return (ApiInfo *)((*it1).second);
}
else if (countHighPriority == 1) // what about kernel32, it has priority 2
{
//API is 100% correct if countHighPriority == 1 and name export
*isSuspect = false;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority
{
return apiFound;
}
}
}
//else // fall through for case api1(priority:1, name:false) <> api2(priority:0, name:true)
{
//API not 100% correct
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getApiByVirtualAddress :: countHighPriority == %d " PRINTF_DWORD_PTR_FULL, countHighPriority, virtualAddress);
#endif
*isSuspect = true;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
Scylla::windowLog.log(L"%s - %s %X %X\n",apiFound->name, apiFound->module->getFilename(), apiFound->rva, apiFound->ordinal);
}
it1 = it2;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
//prefer APIs with a name
if (apiFound->module->priority >= 1 && apiFound->name[0] != 0x00) //1 == high priority
{
//prefer ANSI/UNICODE APIs
if (strrchr(apiFound->name, 'W') || strrchr(apiFound->name, 'A'))
{
return apiFound;
}
}
}
it1 = it2;
for (c = 0; c < countDuplicates; c++, it1++)
{
apiFound = (ApiInfo *)((*it1).second);
//prefer APIs with a name
if (apiFound->module->priority == 2 && !strrchr(apiFound->name, '_')) //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
Scylla::windowLog.log(L"getApiByVirtualAddress :: There is a big bug");
return (ApiInfo *) 1;
}*/
ApiInfo * ApiReader::getScoredApi(std::unordered_map::iterator it1,size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll,bool hasPrio0Dll,bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin )
{
ApiInfo * foundApi = 0;
ApiInfo * foundMatchingApi = 0;
int countFoundApis = 0;
int scoreNeeded = 0;
int scoreValue = 0;
size_t apiNameLength = 0;
if (hasUnicodeAnsiName || hasNoUnderlineInName)
{
hasName = true;
}
if (hasName)
scoreNeeded++;
if (hasUnicodeAnsiName)
scoreNeeded++;
if (hasNoUnderlineInName)
scoreNeeded++;
if (hasPrioDll)
scoreNeeded++;
if (hasPrio0Dll)
scoreNeeded++;
if (hasPrio1Dll)
scoreNeeded++;
if (hasPrio2Dll)
scoreNeeded++;
for (size_t c = 0; c < countDuplicates; c++, it1++)
{
foundApi = (ApiInfo *)((*it1).second);
scoreValue = 0;
if (hasName)
{
if (foundApi->name[0] != 0x00)
{
scoreValue++;
if (hasUnicodeAnsiName)
{
apiNameLength = strlen(foundApi->name);
if ((foundApi->name[apiNameLength - 1] == 'W') || (foundApi->name[apiNameLength - 1] == 'A'))
{
scoreValue++;
}
}
if (hasNoUnderlineInName)
{
if (!strrchr(foundApi->name, '_'))
{
scoreValue++;
}
}
}
}
if (hasPrioDll)
{
if (foundApi->module->priority >= 1)
{
scoreValue++;
}
}
if (hasPrio0Dll)
{
if (foundApi->module->priority == 0)
{
scoreValue++;
}
}
if (hasPrio1Dll)
{
if (foundApi->module->priority == 1)
{
scoreValue++;
}
}
if (hasPrio2Dll)
{
if (foundApi->module->priority == 2)
{
scoreValue++;
}
}
if (scoreValue == scoreNeeded)
{
foundMatchingApi = foundApi;
countFoundApis++;
if (firstWin)
{
return foundMatchingApi;
}
}
}
if (countFoundApis == 1)
{
return foundMatchingApi;
}
else
{
return (ApiInfo *)0;
}
}
void ApiReader::setMinMaxApiAddress(DWORD_PTR virtualAddress)
{
if (virtualAddress < minApiAddress)
{
minApiAddress = virtualAddress - 1;
}
if (virtualAddress > maxApiAddress)
{
maxApiAddress = virtualAddress + 1;
}
}
void ApiReader::readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map &moduleListNew)
{
moduleThunkList = &moduleListNew;
BYTE *dataIat = new BYTE[sizeIAT];
if (readMemoryFromProcess(addressIAT,sizeIAT,dataIat))
{
parseIAT(addressIAT,dataIat,sizeIAT);
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ApiReader::readAndParseIAT :: error reading iat " PRINTF_DWORD_PTR_FULL, addressIAT);
#endif
}
delete[] dataIat;
}
void ApiReader::parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size)
{
ApiInfo *apiFound = 0;
ModuleInfo *module = 0;
bool isSuspect = false;
int countApiFound = 0, countApiNotFound = 0;
DWORD_PTR * pIATAddress = (DWORD_PTR *)iatBuffer;
SIZE_T sizeIAT = size / sizeof(DWORD_PTR);
bool foundModuleBreak = false;
for (SIZE_T i = 0; i < sizeIAT; i++)
{
//Scylla::windowLog.log(L"%08X %08X %d von %d", addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i],i,sizeIAT);
if (pIATAddress[i] == 0 || pIATAddress[i] == -1)
{
/*if (pIATAddress[i+1] != 0)
{
printf("parseIAT :: Module break\n");
}*/
/*else
{
printf("parseIAT :: IAT finished\n");
break;
}*/
foundModuleBreak = true;
}
else if ( (pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress) )
{
apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect);
if (apiFound == (ApiInfo *)1)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"apiFound == (ApiInfo *)1 -> " PRINTF_DWORD_PTR_FULL, pIATAddress[i]);
#endif
}
else if (apiFound)
{
countApiFound++;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" %s %d %s", apiFound->va, apiFound->module->getFilename(), apiFound->ordinal, apiFound->name);
#endif
if (module != apiFound->module)
{
module = apiFound->module;
addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, true, isSuspect);
}
else
{
addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, false, isSuspect);
}
}
else
{
countApiNotFound++;
addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
//printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
}
}
else
{
//printf("parseIAT :: API not found %08X\n", pIATAddress[i]);
countApiNotFound++;
addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]);
}
}
Scylla::windowLog.log(L"IAT parsing finished, found %d valid APIs, missed %d APIs", countApiFound, countApiNotFound);
}
void ApiReader::addFoundApiToModuleList(DWORD_PTR iatAddressVA, ApiInfo * apiFound, bool isNewModule, bool isSuspect)
{
if (isNewModule)
{
addModuleToModuleList(apiFound->module->getFilename(), iatAddressVA - targetImageBase);
}
addFunctionToModuleList(apiFound, iatAddressVA, iatAddressVA - targetImageBase, apiFound->ordinal, true, isSuspect);
}
bool ApiReader::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
- wcscpy_s(module.moduleName, _countof(module.moduleName), moduleName);
+ wcscpy_s(module.moduleName, moduleName);
(*moduleThunkList).insert(std::pair(firstThunk,module));
return true;
}
void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
- wcscpy_s(module.moduleName, _countof(module.moduleName), L"?");
+ wcscpy_s(module.moduleName, L"?");
(*moduleThunkList).insert(std::pair(firstThunk,module));
}
bool ApiReader::addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map::iterator iterator1;
if ((*moduleThunkList).size() > 1)
{
iterator1 = (*moduleThunkList).begin();
while (iterator1 != (*moduleThunkList).end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == (*moduleThunkList).end())
{
iterator1--;
module = &(iterator1->second);
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()");
#endif
break;
}
}
}
else
{
iterator1 = (*moduleThunkList).begin();
module = &(iterator1->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva);
#endif
return false;
}
import.suspect = suspect;
import.valid = valid;
import.va = va;
import.rva = rva;
import.apiAddressVA = apiFound->va;
import.ordinal = ordinal;
import.hint = (WORD)apiFound->hint;
- wcscpy_s(import.moduleName, _countof(import.moduleName), apiFound->module->getFilename());
- strcpy_s(import.name, _countof(import.name), apiFound->name);
+ wcscpy_s(import.moduleName, apiFound->module->getFilename());
+ strcpy_s(import.name, apiFound->name);
module->thunkList.insert(std::pair(import.rva, import));
return true;
}
void ApiReader::clearAll()
{
minApiAddress = -1;
maxApiAddress = 0;
for ( std::unordered_map::iterator it = apiList.begin(); it != apiList.end(); ++it )
{
delete it->second;
}
apiList.clear();
if (moduleThunkList != 0)
{
(*moduleThunkList).clear();
}
}
bool ApiReader::addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map::iterator iterator1;
DWORD_PTR rva = iatAddressVA - targetImageBase;
if ((*moduleThunkList).size() > 0)
{
iterator1 = (*moduleThunkList).begin();
while (iterator1 != (*moduleThunkList).end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == (*moduleThunkList).end())
{
iterator1--;
//new unknown module
if (iterator1->second.moduleName[0] == L'?')
{
module = &(iterator1->second);
}
else
{
addUnknownModuleToModuleList(rva);
module = &((*moduleThunkList).find(rva)->second);
}
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()\r\n");
#endif
break;
}
}
}
else
{
//new unknown module
addUnknownModuleToModuleList(rva);
module = &((*moduleThunkList).find(rva)->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL,rva);
#endif
return false;
}
import.suspect = true;
import.valid = false;
import.va = iatAddressVA;
import.rva = rva;
import.apiAddressVA = apiAddress;
import.ordinal = 0;
- wcscpy_s(import.moduleName, _countof(import.moduleName), L"?");
- strcpy_s(import.name, _countof(import.name), "?");
+ wcscpy_s(import.moduleName, L"?");
+ strcpy_s(import.name, "?");
module->thunkList.insert(std::pair(import.rva, import));
return true;
}
bool ApiReader::isApiBlacklisted( const char * functionName )
{
if (SystemInformation::currenOS < WIN_VISTA_32)
{
if (!strcmp(functionName, "RestoreLastError"))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
/*#ifdef _WIN64
else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer"))
{
return true;
}
#endif*/
}
bool ApiReader::isWinSxSModule( ModuleInfo * module )
{
if (wcsstr(module->fullPath, L"\\WinSxS\\"))
{
return true;
}
else if (wcsstr(module->fullPath, L"\\winsxs\\"))
{
return true;
}
else
{
return false;
}
}
diff --git a/Scylla/DisassemblerGui.cpp b/Scylla/DisassemblerGui.cpp
index a998bf0..569852d 100644
--- a/Scylla/DisassemblerGui.cpp
+++ b/Scylla/DisassemblerGui.cpp
@@ -1,141 +1,141 @@
#include "DisassemblerGui.h"
#include "ProcessAccessHelp.h"
DisassemblerGui::DisassemblerGui(DWORD_PTR startAddress) : startAddress(startAddress)
{
hMenuDisassembler.LoadMenu(IDR_MENU_DISASSEMBLER);
}
BOOL DisassemblerGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
addColumnsToDisassembler(ListDisassembler);
displayDisassembly(ListDisassembler);
CenterWindow();
return TRUE;
}
void DisassemblerGui::OnContextMenu(CWindow wnd, CPoint point)
{
if (wnd.GetDlgCtrlID() == IDC_LIST_DISASSEMBLER)
{
int selection = ListDisassembler.GetSelectionMark();
if(selection == -1) // no item selected
return;
if(point.x == -1 && point.y == -1) // invoked by keyboard
{
ListDisassembler.EnsureVisible(selection, TRUE);
ListDisassembler.GetItemPosition(selection, &point);
ListDisassembler.ClientToScreen(&point);
}
CMenuHandle hSub = hMenuDisassembler.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, wnd);
if (menuItem)
{
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);
}
}
}
}
void DisassemblerGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void DisassemblerGui::addColumnsToDisassembler(CListViewCtrl& list)
{
list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
list.InsertColumn(COL_ADDRESS, L"Address", LVCFMT_LEFT);
list.InsertColumn(COL_INSTRUCTION_SIZE, L"Size", LVCFMT_CENTER);
list.InsertColumn(COL_OPCODES, L"Opcodes", LVCFMT_LEFT);
list.InsertColumn(COL_INSTRUCTION, L"Instructions", LVCFMT_LEFT);
}
void DisassemblerGui::displayDisassembly(CListViewCtrl& list)
{
BYTE data[DISASSEMBLER_GUI_MEMORY_SIZE];
list.DeleteAllItems();
if(!ProcessAccessHelp::readMemoryFromProcess(startAddress, sizeof(data), data))
return;
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);
+ swprintf_s(tempBuffer, L"%016I64X",ProcessAccessHelp::decodedInstructions[i].offset);
#else
- swprintf_s(tempBuffer, _countof(tempBuffer),L"%08X",ProcessAccessHelp::decodedInstructions[i].offset);
+ swprintf_s(tempBuffer, L"%08X",ProcessAccessHelp::decodedInstructions[i].offset);
#endif
list.InsertItem(i, tempBuffer);
- swprintf_s(tempBuffer, _countof(tempBuffer),L"%02d",ProcessAccessHelp::decodedInstructions[i].size);
+ swprintf_s(tempBuffer, L"%02d",ProcessAccessHelp::decodedInstructions[i].size);
list.SetItemText(i, COL_INSTRUCTION_SIZE, tempBuffer);
- swprintf_s(tempBuffer, _countof(tempBuffer),L"%S",(char *)ProcessAccessHelp::decodedInstructions[i].instructionHex.p);
+ swprintf_s(tempBuffer, L"%S", (char *)ProcessAccessHelp::decodedInstructions[i].instructionHex.p);
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);
+ swprintf_s(tempBuffer, L"%S%S%S",(char*)ProcessAccessHelp::decodedInstructions[i].mnemonic.p, ProcessAccessHelp::decodedInstructions[i].operands.length != 0 ? " " : "", (char*)ProcessAccessHelp::decodedInstructions[i].operands.p);
list.SetItemText(i, COL_INSTRUCTION, tempBuffer);
}
list.SetColumnWidth(COL_ADDRESS, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_INSTRUCTION_SIZE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_OPCODES, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_INSTRUCTION, LVSCW_AUTOSIZE_USEHEADER);
}
void DisassemblerGui::copyToClipboard(const WCHAR * text)
{
if(OpenClipboard())
{
EmptyClipboard();
size_t len = wcslen(text);
- HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len+1)*sizeof(WCHAR));
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(WCHAR));
if(hMem)
{
- wcscpy_s((WCHAR *)GlobalLock(hMem), len+1, text);
+ wcscpy_s(static_cast(GlobalLock(hMem)), len + 1, text);
GlobalUnlock(hMem);
if(!SetClipboardData(CF_UNICODETEXT, hMem))
{
GlobalFree(hMem);
}
}
CloseClipboard();
}
}
diff --git a/Scylla/DllInjectionPlugin.cpp b/Scylla/DllInjectionPlugin.cpp
index 75c5d14..0d9332b 100644
--- a/Scylla/DllInjectionPlugin.cpp
+++ b/Scylla/DllInjectionPlugin.cpp
@@ -1,303 +1,303 @@
#include "DllInjectionPlugin.h"
#include "Scylla.h"
const WCHAR * DllInjectionPlugin::FILE_MAPPING_NAME = L"ScyllaPluginExchange";
HANDLE DllInjectionPlugin::hProcess = 0;
//#define DEBUG_COMMENTS
void DllInjectionPlugin::injectPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize)
{
PSCYLLA_EXCHANGE scyllaExchange = 0;
PUNRESOLVED_IMPORT unresImp = 0;
BYTE * dataBuffer = 0;
DWORD_PTR numberOfUnresolvedImports = getNumberOfUnresolvedImports(moduleList);
if (numberOfUnresolvedImports == 0)
{
Scylla::windowLog.log(L"No unresolved Imports");
return;
}
if (!createFileMapping((DWORD)(sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports))))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"injectPlugin :: createFileMapping %X failed",sizeof(SCYLLA_EXCHANGE) + sizeof(UNRESOLVED_IMPORT) + (sizeof(UNRESOLVED_IMPORT) * numberOfUnresolvedImports));
#endif
return;
}
scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
scyllaExchange->status = 0xFF;
scyllaExchange->imageBase = imageBase;
scyllaExchange->imageSize = imageSize;
scyllaExchange->numberOfUnresolvedImports = numberOfUnresolvedImports;
scyllaExchange->offsetUnresolvedImportsArray = sizeof(SCYLLA_EXCHANGE);
unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)lpViewOfFile + sizeof(SCYLLA_EXCHANGE));
addUnresolvedImports(unresImp, moduleList);
UnmapViewOfFile(lpViewOfFile);
lpViewOfFile = 0;
HMODULE hDll = dllInjection(hProcess, plugin.fullpath);
if (hDll)
{
Scylla::windowLog.log(L"Plugin injection was successful");
if (!unloadDllInProcess(hProcess,hDll))
{
Scylla::windowLog.log(L"Plugin unloading failed");
}
lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpViewOfFile)
{
scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
handlePluginResults(scyllaExchange, moduleList);
}
}
else
{
Scylla::windowLog.log(L"Plugin injection failed");
}
closeAllHandles();
}
void DllInjectionPlugin::injectImprecPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize)
{
Plugin newPlugin;
size_t mapSize = (wcslen(plugin.fullpath) + 1) * sizeof(WCHAR);
HANDLE hImprecMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, (DWORD)mapSize, TEXT(PLUGIN_IMPREC_EXCHANGE_DLL_PATH));
if (hImprecMap == NULL)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"injectImprecPlugin :: CreateFileMapping failed 0x%X", GetLastError());
#endif
return;
}
LPVOID lpImprecViewOfFile = MapViewOfFile(hImprecMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpImprecViewOfFile == NULL)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"injectImprecPlugin :: MapViewOfFile failed 0x%X", GetLastError());
#endif
CloseHandle(hImprecMap);
return;
}
CopyMemory(lpImprecViewOfFile,plugin.fullpath, mapSize);
UnmapViewOfFile(lpImprecViewOfFile);
newPlugin.fileSize = plugin.fileSize;
- wcscpy_s(newPlugin.pluginName, _countof(newPlugin.pluginName), plugin.pluginName);
- wcscpy_s(newPlugin.fullpath, _countof(newPlugin.fullpath), Scylla::plugins.imprecWrapperDllPath);
+ wcscpy_s(newPlugin.pluginName, plugin.pluginName);
+ wcscpy_s(newPlugin.fullpath, Scylla::plugins.imprecWrapperDllPath);
injectPlugin(newPlugin,moduleList,imageBase,imageSize);
CloseHandle(hImprecMap);
}
bool DllInjectionPlugin::createFileMapping(DWORD mappingSize)
{
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, mappingSize, FILE_MAPPING_NAME);
if (hMapFile == NULL)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMapping :: CreateFileMapping failed 0x%X", GetLastError());
#endif
return false;
}
lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpViewOfFile == NULL)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMapping :: MapViewOfFile failed 0x%X", GetLastError());
#endif
CloseHandle(hMapFile);
hMapFile = 0;
return false;
}
else
{
return true;
}
}
void DllInjectionPlugin::closeAllHandles()
{
if (lpViewOfFile)
{
UnmapViewOfFile(lpViewOfFile);
lpViewOfFile = 0;
}
if (hMapFile)
{
CloseHandle(hMapFile);
hMapFile = 0;
}
}
DWORD_PTR DllInjectionPlugin::getNumberOfUnresolvedImports( std::map & moduleList )
{
std::map::iterator iterator1;
std::map::iterator iterator2;
ImportModuleThunk * moduleThunk = 0;
ImportThunk * importThunk = 0;
DWORD_PTR dwNumber = 0;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->valid == false)
{
dwNumber++;
}
iterator2++;
}
iterator1++;
}
return dwNumber;
}
void DllInjectionPlugin::addUnresolvedImports( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList )
{
std::map::iterator iterator1;
std::map::iterator iterator2;
ImportModuleThunk * moduleThunk = 0;
ImportThunk * importThunk = 0;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->valid == false)
{
firstUnresImp->InvalidApiAddress = importThunk->apiAddressVA;
firstUnresImp->ImportTableAddressPointer = importThunk->va;
firstUnresImp++;
}
iterator2++;
}
iterator1++;
}
firstUnresImp->InvalidApiAddress = 0;
firstUnresImp->ImportTableAddressPointer = 0;
}
void DllInjectionPlugin::handlePluginResults( PSCYLLA_EXCHANGE scyllaExchange, std::map & moduleList )
{
PUNRESOLVED_IMPORT unresImp = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray);;
switch (scyllaExchange->status)
{
case SCYLLA_STATUS_SUCCESS:
Scylla::windowLog.log(L"Plugin was successful");
updateImportsWithPluginResult(unresImp, moduleList);
break;
case SCYLLA_STATUS_UNKNOWN_ERROR:
Scylla::windowLog.log(L"Plugin reported Unknown Error");
break;
case SCYLLA_STATUS_UNSUPPORTED_PROTECTION:
Scylla::windowLog.log(L"Plugin detected unknown protection");
updateImportsWithPluginResult(unresImp, moduleList);
break;
case SCYLLA_STATUS_IMPORT_RESOLVING_FAILED:
Scylla::windowLog.log(L"Plugin import resolving failed");
updateImportsWithPluginResult(unresImp, moduleList);
break;
case SCYLLA_STATUS_MAPPING_FAILED:
Scylla::windowLog.log(L"Plugin file mapping failed");
break;
default:
Scylla::windowLog.log(L"Plugin failed without reason");
}
}
void DllInjectionPlugin::updateImportsWithPluginResult( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList )
{
std::map::iterator iterator1;
std::map::iterator iterator2;
ImportModuleThunk * moduleThunk = 0;
ImportThunk * importThunk = 0;
ApiInfo * apiInfo = 0;
bool isSuspect = 0;
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
moduleThunk = &(iterator1->second);
iterator2 = moduleThunk->thunkList.begin();
while (iterator2 != moduleThunk->thunkList.end())
{
importThunk = &(iterator2->second);
if (importThunk->valid == false)
{
if (apiReader->isApiAddressValid(firstUnresImp->InvalidApiAddress))
{
apiInfo = apiReader->getApiByVirtualAddress(firstUnresImp->InvalidApiAddress,&isSuspect);
importThunk->suspect = isSuspect;
importThunk->valid = true;
importThunk->apiAddressVA = firstUnresImp->InvalidApiAddress;
importThunk->hint = (WORD)apiInfo->hint;
importThunk->ordinal = apiInfo->ordinal;
- strcpy_s(importThunk->name, _countof(importThunk->name),apiInfo->name);
- wcscpy_s(importThunk->moduleName, _countof(importThunk->moduleName), apiInfo->module->getFilename());
+ strcpy_s(importThunk->name, apiInfo->name);
+ wcscpy_s(importThunk->moduleName, apiInfo->module->getFilename());
if (moduleThunk->moduleName[0] == L'?')
{
wcscpy_s(moduleThunk->moduleName, _countof(importThunk->moduleName), apiInfo->module->getFilename());
}
}
firstUnresImp++;
}
iterator2++;
}
iterator1++;
}
}
diff --git a/Scylla/ImportRebuild.cpp b/Scylla/ImportRebuild.cpp
index 03111e6..888f584 100644
--- a/Scylla/ImportRebuild.cpp
+++ b/Scylla/ImportRebuild.cpp
@@ -1,713 +1,713 @@
#include "ImportRebuild.h"
#include "Scylla.h"
#include "StringConversion.h"
//#define DEBUG_COMMENTS
ImportRebuild::ImportRebuild()
{
imageData = NULL;
sizeOfFile = 0;
pDosStub = NULL;
pOverlay = NULL;
sizeOfOverlay = 0;
pImportDescriptor = NULL;
pThunkData = NULL;
pImportByName = NULL;
numberOfImportDescriptors = 0;
sizeOfImportSection = 0;
sizeOfApiAndModuleNames = 0;
importSectionIndex = 0;
}
ImportRebuild::~ImportRebuild()
{
delete [] pDosStub;
delete [] imageData;
for (size_t i = 0; i < vecSectionData.size(); i++)
{
delete [] vecSectionData[i];
}
delete [] pOverlay;
}
bool ImportRebuild::splitTargetFile()
{
PIMAGE_SECTION_HEADER pSecHeader = 0;
BYTE * data = 0;
DWORD alignment = 0;
DosHeader = *(IMAGE_DOS_HEADER*)imageData;
if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
return false;
}
NTHeader = *(IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew);
if (NTHeader.Signature != IMAGE_NT_SIGNATURE)
{
return false;
}
if (DosHeader.e_lfanew > sizeof(IMAGE_DOS_HEADER))
{
size_t sizeOfStub = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER);
pDosStub = new BYTE[sizeOfStub];
CopyMemory(pDosStub, imageData + sizeof(IMAGE_DOS_HEADER), sizeOfStub);
}
pSecHeader = IMAGE_FIRST_SECTION((IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew));
for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
{
const DWORD SECTION_SIZE_MAX = 300000000;
DWORD sizeOfSection = pSecHeader->SizeOfRawData;
if (sizeOfSection > SECTION_SIZE_MAX)
{
sizeOfSection = SECTION_SIZE_MAX;
}
//TODO better use section alignment because it is better?
alignment = alignValue(sizeOfSection, NTHeader.OptionalHeader.SectionAlignment);
data = new BYTE[alignment];
ZeroMemory(data, alignment);
CopyMemory(data, imageData + pSecHeader->PointerToRawData, sizeOfSection);
vecSectionData.push_back(data);
vecSectionHeaders.push_back(*pSecHeader);
pSecHeader++;
}
if(NTHeader.FileHeader.NumberOfSections > 0) // ??
{
const IMAGE_SECTION_HEADER* pLastSec = &(*vecSectionHeaders.rbegin());
DWORD calcSize = pLastSec->PointerToRawData + pLastSec->SizeOfRawData;
if (calcSize < sizeOfFile)
{
sizeOfOverlay = sizeOfFile - calcSize;
pOverlay = new BYTE[sizeOfOverlay];
memcpy(pOverlay, imageData + calcSize, sizeOfOverlay);
}
}
delete [] imageData;
imageData = 0;
return true;
}
bool ImportRebuild::alignSectionHeaders()
{
for (WORD i = 0; i < vecSectionHeaders.size(); i++)
{
vecSectionHeaders[i].VirtualAddress = alignValue(vecSectionHeaders[i].VirtualAddress, NTHeader.OptionalHeader.SectionAlignment);
vecSectionHeaders[i].Misc.VirtualSize = alignValue(vecSectionHeaders[i].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment);
vecSectionHeaders[i].PointerToRawData = alignValue(vecSectionHeaders[i].PointerToRawData, NTHeader.OptionalHeader.FileAlignment);
vecSectionHeaders[i].SizeOfRawData = alignValue(vecSectionHeaders[i].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment);
}
return true;
}
bool ImportRebuild::saveNewFile(const WCHAR * filepath)
{
DWORD fileOffset = 0;
DWORD dwWriteSize = 0;
size_t i = 0;
if (vecSectionHeaders.size() != vecSectionData.size())
{
return false;
}
HANDLE hFile = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveNewFile :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
return false;
}
//alignSectionHeaders();
updatePeHeader();
fileOffset = 0;
dwWriteSize = sizeof(IMAGE_DOS_HEADER);
ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &DosHeader);
fileOffset += dwWriteSize;
dwWriteSize = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER);
ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pDosStub);
fileOffset += dwWriteSize;
dwWriteSize = sizeof(IMAGE_NT_HEADERS);
ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &NTHeader);
fileOffset += dwWriteSize;
dwWriteSize = sizeof(IMAGE_SECTION_HEADER);
for (i = 0; i < vecSectionHeaders.size(); i++)
{
if (!ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &vecSectionHeaders[i]))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveNewFile :: writeMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize);
#endif
CloseHandle(hFile);
return false;
}
fileOffset += dwWriteSize;
}
for (i = 0; i < vecSectionHeaders.size(); i++)
{
dwWriteSize = vecSectionHeaders[i].PointerToRawData - fileOffset;
if (dwWriteSize)
{
if (!writeZeroMemoryToFile(hFile, fileOffset, dwWriteSize))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveNewFile :: writeZeroMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize);
#endif
CloseHandle(hFile);
return false;
}
fileOffset += dwWriteSize;
}
dwWriteSize = vecSectionHeaders[i].SizeOfRawData;
ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, vecSectionData[i]);
fileOffset += dwWriteSize;
}
if(pOverlay)
{
ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, sizeOfOverlay, pOverlay);
fileOffset += sizeOfOverlay;
}
CloseHandle(hFile);
return true;
}
bool ImportRebuild::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size)
{
bool retValue = false;
PVOID zeromemory = calloc(size, 1);
if (zeromemory)
{
retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory);
free(zeromemory);
}
else
{
retValue = false;
}
return retValue;
}
bool ImportRebuild::addNewSection(char * sectionName, DWORD sectionSize, BYTE * sectionData)
{
BYTE * newBuffer = 0;
IMAGE_SECTION_HEADER pNewSection = {0};
size_t lastSectionIndex = vecSectionHeaders.size() - 1;
size_t nameLength = strlen(sectionName);
if (nameLength > IMAGE_SIZEOF_SHORT_NAME)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"addNewSection :: sectionname is too long %d", nameLength);
#endif
return false;
}
memcpy_s(pNewSection.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength);
pNewSection.SizeOfRawData = alignValue(sectionSize, NTHeader.OptionalHeader.FileAlignment);
pNewSection.Misc.VirtualSize = alignValue(sectionSize, NTHeader.OptionalHeader.SectionAlignment);
pNewSection.PointerToRawData = alignValue(vecSectionHeaders[lastSectionIndex].PointerToRawData + vecSectionHeaders[lastSectionIndex].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment);
pNewSection.VirtualAddress = alignValue(vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment);
pNewSection.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA;
vecSectionHeaders.push_back(pNewSection);
if ( (sectionSize != pNewSection.SizeOfRawData) || (sectionData == 0) )
{
newBuffer = new BYTE[pNewSection.SizeOfRawData];
ZeroMemory(newBuffer, pNewSection.SizeOfRawData);
if (sectionData)
{
CopyMemory(newBuffer, sectionData, sectionSize);
}
}
else
{
newBuffer = sectionData;
}
vecSectionData.push_back(newBuffer);
return true;
}
bool ImportRebuild::loadTargetFile(const WCHAR * filepath)
{
HANDLE hTargetFile = INVALID_HANDLE_VALUE;
DWORD fileSize = 0;
bool retValue = false;
hTargetFile = CreateFile(filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hTargetFile == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"loadTargetFile :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
return false;
}
fileSize = (DWORD)ProcessAccessHelp::getFileSize(hTargetFile);
if (!fileSize)
{
CloseHandle(hTargetFile);
hTargetFile = 0;
return false;
}
imageData = new BYTE[fileSize];
if (!imageData)
{
retValue = false;
}
else
{
sizeOfFile = fileSize;
retValue = ProcessAccessHelp::readMemoryFromFile(hTargetFile, 0, fileSize, imageData);
}
CloseHandle(hTargetFile);
hTargetFile = 0;
return retValue;
}
DWORD ImportRebuild::alignValue(DWORD badValue, DWORD alignTo)
{
return (((badValue + alignTo - 1) / alignTo) * alignTo);
}
DWORD ImportRebuild::convertRVAToOffsetVector(DWORD dwRVA)
{
for (size_t i = 0; i < vecSectionHeaders.size(); i++)
{
if ((vecSectionHeaders[i].VirtualAddress <= dwRVA) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > dwRVA))
{
return ((dwRVA - vecSectionHeaders[i].VirtualAddress) + vecSectionHeaders[i].PointerToRawData);
}
}
return 0;
}
/*
DWORD ImportRebuild::convertRVAToOffset(DWORD dwRVA)
{
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader);
for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
{
if ((pSectionHeader->VirtualAddress <= dwRVA) && ((pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize) > dwRVA))
{
return ((dwRVA - pSectionHeader->VirtualAddress) + pSectionHeader->PointerToRawData);
}
pSectionHeader++;
}
return 0;
}
*/
DWORD_PTR ImportRebuild::convertOffsetToRVAVector(DWORD dwOffset)
{
for (size_t i = 0; i < vecSectionHeaders.size(); i++)
{
if ((vecSectionHeaders[i].PointerToRawData <= dwOffset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > dwOffset))
{
return ((dwOffset - vecSectionHeaders[i].PointerToRawData) + vecSectionHeaders[i].VirtualAddress);
}
}
return 0;
}
/*
DWORD ImportRebuild::convertOffsetToRVA(DWORD dwOffset)
{
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader);
for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
{
if ((pSectionHeader->PointerToRawData <= dwOffset) && ((pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData) > dwOffset))
{
return ((dwOffset - pSectionHeader->PointerToRawData) + pSectionHeader->VirtualAddress);
}
pSectionHeader++;
}
return 0;
}
*/
void ImportRebuild::updatePeHeader()
{
size_t lastSectionIndex = vecSectionHeaders.size() - 1;
NTHeader.FileHeader.NumberOfSections = (WORD)(lastSectionIndex + 1);
NTHeader.OptionalHeader.SizeOfImage = vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize;
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
if (NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress)
{
for (size_t i = 0; i < vecSectionHeaders.size(); i++)
{
if ((vecSectionHeaders[i].VirtualAddress <= NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress))
{
//section must be read and writeable
vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
}
}
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
}
NTHeader.OptionalHeader.NumberOfRvaAndSizes = 0x10;
NTHeader.OptionalHeader.SizeOfHeaders = alignValue(DosHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + NTHeader.FileHeader.SizeOfOptionalHeader + (NTHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), NTHeader.OptionalHeader.FileAlignment);
}
bool ImportRebuild::buildNewImportTable(std::map & moduleList)
{
createNewImportSection(moduleList);
importSectionIndex = vecSectionHeaders.size() - 1;
DWORD dwSize = fillImportSection(moduleList);
if (!dwSize)
{
return false;
}
setFlagToIATSection((*moduleList.begin()).second.firstThunk);
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vecSectionHeaders[importSectionIndex].VirtualAddress;
NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
return true;
}
bool ImportRebuild::createNewImportSection(std::map & moduleList)
{
char sectionName[9] = {0};
//DWORD sectionSize = calculateMinSize(moduleList);
calculateImportSizes(moduleList);
if (wcslen(Scylla::config[IAT_SECTION_NAME].getString()) > IMAGE_SIZEOF_SHORT_NAME)
{
- strcpy_s(sectionName, sizeof(sectionName), ".SCY");
+ strcpy_s(sectionName, ".SCY");
}
else
{
StringConversion::ToASCII(Scylla::config[IAT_SECTION_NAME].getString(), sectionName, _countof(sectionName));
}
return addNewSection(sectionName, (DWORD)sizeOfImportSection, 0);
}
/*DWORD ImportRebuild::calculateMinSize(std::map & moduleList)
{
DWORD dwSize = 0;
std::map::iterator mapIt;
std::map::iterator mapIt2;
dwSize = (DWORD)((moduleList.size() + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)); //last is zero'ed
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
//dwSize += (DWORD)((*mapIt).second.thunkList.size() + sizeof(IMAGE_IMPORT_BY_NAME));
dwSize += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
if((*mapIt2).second.name[0] != '\0')
{
dwSize += sizeof(IMAGE_IMPORT_BY_NAME);
dwSize += (DWORD)strlen((*mapIt2).second.name);
}
}
}
return dwSize;
}*/
BYTE * ImportRebuild::getMemoryPointerFromRVA(DWORD_PTR dwRVA)
{
DWORD_PTR offset = convertRVAToOffsetVector((DWORD)dwRVA);
for (size_t i = 0; i < vecSectionHeaders.size(); i++)
{
if ((vecSectionHeaders[i].PointerToRawData <= offset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > offset))
{
return (BYTE *)((DWORD_PTR)vecSectionData[i] + (offset - vecSectionHeaders[i].PointerToRawData));
}
}
return 0;
}
DWORD ImportRebuild::fillImportSection( std::map & moduleList )
{
std::map::iterator mapIt;
std::map::iterator mapIt2;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
PIMAGE_IMPORT_BY_NAME pImportByName = 0;
PIMAGE_THUNK_DATA pThunk = 0;
ImportModuleThunk * importModuleThunk = 0;
ImportThunk * importThunk = 0;
size_t stringLength = 0;
DWORD_PTR lastRVA = 0;
BYTE * sectionData = vecSectionData[importSectionIndex];
DWORD offset = 0;
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(sectionData);
//skip the IMAGE_IMPORT_DESCRIPTOR
offset += (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
importModuleThunk = &((*mapIt).second);
stringLength = addImportDescriptor(importModuleThunk, offset);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: importDesc.Name %X", pImportDescriptor->Name);
#endif
offset += (DWORD)stringLength; //stringLength has null termination char
pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)sectionData + offset);
//pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importModuleThunk->firstThunk));
lastRVA = importModuleThunk->firstThunk - sizeof(DWORD_PTR);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
importThunk = &((*mapIt2).second);
pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importThunk->rva));
//check wrong iat pointer
if (!pThunk)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: Failed to get pThunk RVA: %X", importThunk->rva);
#endif
return 0;
}
if ((lastRVA + sizeof(DWORD_PTR)) != importThunk->rva)
{
//add additional import desc
addSpecialImportDescriptor(importThunk->rva);
}
lastRVA = importThunk->rva;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X", importThunk,pThunk,pImportByName,offset);
#endif
stringLength = addImportToImportTable(importThunk, pThunk, pImportByName, offset);
offset += (DWORD)stringLength; //is 0 bei import by ordinal
pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + stringLength);
}
pImportDescriptor++;
}
return offset;
}
bool ImportRebuild::rebuildImportTable(const WCHAR * targetFilePath, const WCHAR * newFilePath, std::map & moduleList)
{
bool retValue = false;
if (loadTargetFile(targetFilePath))
{
splitTargetFile();
retValue = buildNewImportTable(moduleList);
if (retValue)
{
retValue = saveNewFile(newFilePath);
}
return retValue;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"rebuildImportTable ::Failed to load target %s", targetFilePath);
#endif
return false;
}
}
void ImportRebuild::setFlagToIATSection(DWORD_PTR iatAddress)
{
for (size_t i = 0; i < vecSectionHeaders.size(); i++)
{
if ((vecSectionHeaders[i].VirtualAddress <= iatAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > iatAddress))
{
//section must be read and writeable
vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
}
}
}
size_t ImportRebuild::addImportToImportTable( ImportThunk * pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset)
{
size_t stringLength = 0;
if(pImport->name[0] == '\0')
{
pThunk->u1.AddressOfData = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG);
}
else
{
pImportByName->Hint = pImport->hint;
stringLength = strlen(pImport->name) + 1;
memcpy(pImportByName->Name, pImport->name, stringLength);
pThunk->u1.AddressOfData = convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
if (!pThunk->u1.AddressOfData)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"addImportToImportTable :: failed to get AddressOfData %X %X", vecSectionHeaders[importSectionIndex].PointerToRawData, sectionOffset);
#endif
}
//next import should be nulled
pThunk++;
pThunk->u1.AddressOfData = 0;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X", pThunk->u1.AddressOfData, pThunk, vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
#endif
stringLength += sizeof(WORD);
}
return stringLength;
}
size_t ImportRebuild::addImportDescriptor(ImportModuleThunk * pImportModule, DWORD sectionOffset)
{
char dllName[MAX_PATH];
StringConversion::ToASCII(pImportModule->moduleName, dllName, _countof(dllName));
size_t stringLength = strlen(dllName);
memcpy((vecSectionData[importSectionIndex] + sectionOffset), dllName, stringLength); //copy module name to section
pImportDescriptor->FirstThunk = (DWORD)pImportModule->firstThunk;
pImportDescriptor->Name = (DWORD)convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
return stringLength;
}
void ImportRebuild::addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk)
{
PIMAGE_IMPORT_DESCRIPTOR oldID = pImportDescriptor;
pImportDescriptor++;
pImportDescriptor->FirstThunk = (DWORD)rvaFirstThunk;
pImportDescriptor->Name = oldID->Name;
}
void ImportRebuild::calculateImportSizes(std::map & moduleList)
{
std::map::iterator mapIt;
std::map::iterator mapIt2;
DWORD_PTR lastRVA = 0;
numberOfImportDescriptors = 0;
sizeOfImportSection = 0;
sizeOfApiAndModuleNames = 0;
numberOfImportDescriptors = moduleList.size() + 1; //last is zero'd
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
lastRVA = (*mapIt).second.firstThunk - sizeof(DWORD_PTR);
sizeOfApiAndModuleNames += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
if ((lastRVA + sizeof(DWORD_PTR)) != (*mapIt2).second.rva)
{
numberOfImportDescriptors++; //add additional import desc
}
if((*mapIt2).second.name[0] != '\0')
{
sizeOfApiAndModuleNames += sizeof(WORD); //Hint from IMAGE_IMPORT_BY_NAME
sizeOfApiAndModuleNames += (DWORD)(strlen((*mapIt2).second.name) + 1);
}
lastRVA = (*mapIt2).second.rva;
}
}
sizeOfImportSection = sizeOfApiAndModuleNames + (numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
}
\ No newline at end of file
diff --git a/Scylla/ImportsHandling.cpp b/Scylla/ImportsHandling.cpp
index a7dcf24..b82511e 100644
--- a/Scylla/ImportsHandling.cpp
+++ b/Scylla/ImportsHandling.cpp
@@ -1,807 +1,807 @@
#include "ImportsHandling.h"
#include "Thunks.h"
#include "Architecture.h"
#include
#include
#include "multitree.h" // CMultiSelectTreeViewCtrl
#include "resource.h"
//#define DEBUG_COMMENTS
void ImportThunk::invalidate()
{
ordinal = 0;
hint = 0;
valid = false;
suspect = false;
moduleName[0] = 0;
name[0] = 0;
}
bool ImportModuleThunk::isValid() const
{
std::map::const_iterator iterator = thunkList.begin();
while (iterator != thunkList.end())
{
if (iterator->second.valid == false)
{
return false;
}
iterator++;
}
return true;
}
DWORD_PTR ImportModuleThunk::getFirstThunk() const
{
if (thunkList.size() > 0)
{
const std::map::const_iterator iterator = thunkList.begin();
return iterator->first;
}
else
{
return 0;
}
}
ImportsHandling::ImportsHandling(CMultiSelectTreeViewCtrl& TreeImports) : TreeImports(TreeImports)
{
hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16);
hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16);
hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16);
CDCHandle dc = CWindow(::GetDesktopWindow()).GetDC();
int bits = dc.GetDeviceCaps(BITSPIXEL);
const UINT FLAGS = bits > 16 ? ILC_COLOR32 : (ILC_COLOR24 | ILC_MASK);
TreeIcons.Create(16, 16, FLAGS, 3, 1);
TreeIcons.AddIcon(hIconCheck);
TreeIcons.AddIcon(hIconWarning);
TreeIcons.AddIcon(hIconError);
m_thunkCount = m_invalidThunkCount = m_suspectThunkCount = 0;
}
ImportsHandling::~ImportsHandling()
{
TreeIcons.Destroy();
}
bool ImportsHandling::isModule(CTreeItem item)
{
return (0 != getModuleThunk(item));
}
bool ImportsHandling::isImport(CTreeItem item)
{
return (0 != getImportThunk(item));
}
ImportModuleThunk * ImportsHandling::getModuleThunk(CTreeItem item)
{
std::unordered_map::const_iterator it;
it = itemData.find(item);
if(it != itemData.end())
{
const TreeItemData * data = &it->second;
if(data->isModule)
{
return data->module;
}
}
return NULL;
}
ImportThunk * ImportsHandling::getImportThunk(CTreeItem item)
{
std::unordered_map::const_iterator it;
TreeItemData * data = getItemData(item);
if(data && !data->isModule)
{
return data->import;
}
return NULL;
}
void ImportsHandling::setItemData(CTreeItem item, const TreeItemData * data)
{
itemData[item] = *data;
}
ImportsHandling::TreeItemData * ImportsHandling::getItemData(CTreeItem item)
{
std::unordered_map::iterator it;
it = itemData.find(item);
if(it != itemData.end())
{
return &it->second;
}
return NULL;
}
void ImportsHandling::updateCounts()
{
std::map::iterator it_module;
std::map::iterator it_import;
m_thunkCount = m_invalidThunkCount = m_suspectThunkCount = 0;
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
ImportModuleThunk &moduleThunk = it_module->second;
it_import = moduleThunk.thunkList.begin();
while (it_import != moduleThunk.thunkList.end())
{
ImportThunk &importThunk = it_import->second;
m_thunkCount++;
if(!importThunk.valid)
m_invalidThunkCount++;
else if(importThunk.suspect)
m_suspectThunkCount++;
it_import++;
}
it_module++;
}
}
/*bool ImportsHandling::addImport(const WCHAR * moduleName, const CHAR * name, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map::iterator iterator1;
if (moduleList.size() > 1)
{
iterator1 = moduleList.begin();
while (iterator1 != moduleList.end())
{
if (rva >= iterator1->second.firstThunk)
{
iterator1++;
if (iterator1 == moduleList.end())
{
iterator1--;
module = &(iterator1->second);
break;
}
else if (rva < iterator1->second.firstThunk)
{
iterator1--;
module = &(iterator1->second);
break;
}
}
}
}
else
{
iterator1 = moduleList.begin();
module = &(iterator1->second);
}
if (!module)
{
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva);
return false;
}
//TODO
import.suspect = true;
import.valid = false;
import.va = va;
import.rva = rva;
import.ordinal = ordinal;
wcscpy_s(import.moduleName, MAX_PATH, moduleName);
strcpy_s(import.name, MAX_PATH, name);
module->thunkList.insert(std::pair(import.rva, import));
return true;
}
*/
/*
bool ImportsHandling::addModule(const WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
wcscpy_s(module.moduleName, MAX_PATH, moduleName);
moduleList.insert(std::pair(firstThunk,module));
return true;
}
*/
void ImportsHandling::displayAllImports()
{
std::map::iterator it_module;
std::map::iterator it_import;
TreeImports.DeleteAllItems();
itemData.clear();
TreeImports.SetImageList(TreeIcons);
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
ImportModuleThunk &moduleThunk = it_module->second;
moduleThunk.key = moduleThunk.firstThunk; // This belongs elsewhere...
moduleThunk.hTreeItem = addDllToTreeView(TreeImports, &moduleThunk);
it_import = moduleThunk.thunkList.begin();
while (it_import != moduleThunk.thunkList.end())
{
ImportThunk &importThunk = it_import->second;
importThunk.key = importThunk.rva; // This belongs elsewhere...
importThunk.hTreeItem = addApiToTreeView(TreeImports, moduleThunk.hTreeItem, &importThunk);
it_import++;
}
it_module++;
}
updateCounts();
}
void ImportsHandling::clearAllImports()
{
TreeImports.DeleteAllItems();
itemData.clear();
moduleList.clear();
updateCounts();
}
CTreeItem ImportsHandling::addDllToTreeView(CMultiSelectTreeViewCtrl& idTreeView, ImportModuleThunk * moduleThunk)
{
CTreeItem item = idTreeView.InsertItem(L"", NULL, TVI_ROOT);
item.SetData(itemData.size());
TreeItemData data;
data.isModule = true;
data.module = moduleThunk;
setItemData(item, &data);
updateModuleInTreeView(moduleThunk, item);
return item;
}
CTreeItem ImportsHandling::addApiToTreeView(CMultiSelectTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk)
{
CTreeItem item = idTreeView.InsertItem(L"", parentDll, TVI_LAST);
item.SetData(itemData.size());
TreeItemData data;
data.isModule = false;
data.import = importThunk;
setItemData(item, &data);
updateImportInTreeView(importThunk, item);
return item;
}
void ImportsHandling::selectImports(bool invalid, bool suspect)
{
std::map::iterator it_module;
std::map::iterator it_import;
TreeImports.SelectAllItems(FALSE); //remove selection
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
ImportModuleThunk &moduleThunk = it_module->second;
it_import = moduleThunk.thunkList.begin();
while (it_import != moduleThunk.thunkList.end())
{
ImportThunk &importThunk = it_import->second;
if ((invalid && !importThunk.valid) || (suspect && importThunk.suspect))
{
TreeImports.SelectItem(importThunk.hTreeItem, TRUE);
importThunk.hTreeItem.EnsureVisible();
}
it_import++;
}
it_module++;
}
}
bool ImportsHandling::invalidateImport(CTreeItem item)
{
ImportThunk * import = getImportThunk(item);
if(import)
{
CTreeItem parent = item.GetParent();
if(!parent.IsNull())
{
const ImportModuleThunk * module = getModuleThunk(parent);
if(module)
{
import->invalidate();
updateImportInTreeView(import, import->hTreeItem);
updateModuleInTreeView(module, module->hTreeItem);
updateCounts();
return true;
}
}
}
return false;
}
bool ImportsHandling::invalidateModule(CTreeItem item)
{
ImportModuleThunk * module = getModuleThunk(item);
if(module)
{
std::map::iterator it_import;
it_import = module->thunkList.begin();
while(it_import != module->thunkList.end())
{
ImportThunk * import = &it_import->second;
import->invalidate();
updateImportInTreeView(import, import->hTreeItem);
it_import++;
}
updateModuleInTreeView(module, module->hTreeItem);
updateCounts();
return true;
}
return false;
}
bool ImportsHandling::setImport(CTreeItem item, const WCHAR * moduleName, const CHAR * apiName, WORD ordinal, WORD hint, bool valid, bool suspect)
{
ImportThunk * import = getImportThunk(item);
if(import)
{
CTreeItem parent = item.GetParent();
if(!parent.IsNull())
{
const ImportModuleThunk * module = getModuleThunk(parent);
if(module)
{
- wcscpy_s(import->moduleName, _countof(import->moduleName), moduleName);
- strcpy_s(import->name, _countof(import->name), apiName);
+ wcscpy_s(import->moduleName, moduleName);
+ strcpy_s(import->name, apiName);
import->ordinal = ordinal;
//import->apiAddressVA = api->va; //??
import->hint = hint;
import->valid = valid;
import->suspect = suspect;
updateImportInTreeView(import, item);
updateModuleInTreeView(module, module->hTreeItem);
updateCounts();
return true;
}
}
}
return false;
}
void ImportsHandling::updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item)
{
if (importThunk->valid)
{
WCHAR tempString[300];
if (importThunk->name[0] != 0x00)
{
- swprintf_s(tempString, _countof(tempString), L"ord: %04X name: %S", importThunk->ordinal, importThunk->name);
+ swprintf_s(tempString, L"ord: %04X name: %S", importThunk->ordinal, importThunk->name);
}
else
{
- swprintf_s(tempString, _countof(tempString), L"ord: %04X", importThunk->ordinal);
+ swprintf_s(tempString, L"ord: %04X", importThunk->ordinal);
}
- swprintf_s(stringBuffer, _countof(stringBuffer), L" rva: " PRINTF_DWORD_PTR_HALF L" mod: %s %s", importThunk->rva, importThunk->moduleName, tempString);
+ swprintf_s(stringBuffer, L" rva: " PRINTF_DWORD_PTR_HALF L" mod: %s %s", importThunk->rva, importThunk->moduleName, tempString);
}
else
{
- swprintf_s(stringBuffer, _countof(stringBuffer), L" rva: " PRINTF_DWORD_PTR_HALF L" ptr: " PRINTF_DWORD_PTR_FULL, importThunk->rva, importThunk->apiAddressVA);
+ swprintf_s(stringBuffer, L" rva: " PRINTF_DWORD_PTR_HALF L" ptr: " PRINTF_DWORD_PTR_FULL, importThunk->rva, importThunk->apiAddressVA);
}
item.SetText(stringBuffer);
Icon icon = getAppropiateIcon(importThunk);
item.SetImage(icon, icon);
}
void ImportsHandling::updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item)
{
- swprintf_s(stringBuffer, _countof(stringBuffer),L"%s (%d) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk);
+ swprintf_s(stringBuffer, L"%s (%d) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->moduleName,importThunk->thunkList.size(), importThunk->firstThunk);
item.SetText(stringBuffer);
Icon icon = getAppropiateIcon(importThunk->isValid());
item.SetImage(icon, icon);
}
ImportsHandling::Icon ImportsHandling::getAppropiateIcon(const ImportThunk * importThunk)
{
if(importThunk->valid)
{
if(importThunk->suspect)
{
return iconWarning;
}
else
{
return iconCheck;
}
}
else
{
return iconError;
}
}
ImportsHandling::Icon ImportsHandling::getAppropiateIcon(bool valid)
{
if(valid)
{
return iconCheck;
}
else
{
return iconError;
}
}
bool ImportsHandling::cutImport(CTreeItem item)
{
ImportThunk * import = getImportThunk(item);
if(import)
{
CTreeItem parent = item.GetParent();
if(!parent.IsNull())
{
ImportModuleThunk * module = getModuleThunk(parent);
if(module)
{
itemData.erase(item);
import->hTreeItem.Delete();
module->thunkList.erase(import->key);
import = 0;
if (module->thunkList.empty())
{
itemData.erase(parent);
module->hTreeItem.Delete();
moduleList.erase(module->key);
module = 0;
}
else
{
if (module->isValid() && module->moduleName[0] == L'?')
{
//update module name
- wcscpy_s(module->moduleName,_countof(module->moduleName),(*module->thunkList.begin()).second.moduleName);
+ wcscpy_s(module->moduleName, module->thunkList.begin()->second.moduleName);
}
- module->firstThunk = (*module->thunkList.begin()).second.rva;
+ module->firstThunk = module->thunkList.begin()->second.rva;
updateModuleInTreeView(module, module->hTreeItem);
}
updateCounts();
return true;
}
}
}
return false;
}
bool ImportsHandling::cutModule(CTreeItem item)
{
ImportModuleThunk * module = getModuleThunk(item);
if(module)
{
CTreeItem child = item.GetChild();
while(!child.IsNull())
{
itemData.erase(child);
child = child.GetNextSibling();
}
itemData.erase(item);
module->hTreeItem.Delete();
moduleList.erase(module->key);
module = 0;
updateCounts();
return true;
}
return false;
}
DWORD_PTR ImportsHandling::getApiAddressByNode(CTreeItem item)
{
const ImportThunk * import = getImportThunk(item);
if(import)
{
return import->apiAddressVA;
}
return 0;
}
void ImportsHandling::scanAndFixModuleList()
{
std::map::iterator it_module;
std::map::iterator it_import;
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
ImportModuleThunk &moduleThunk = it_module->second;
it_import = moduleThunk.thunkList.begin();
while (it_import != moduleThunk.thunkList.end())
{
ImportThunk &importThunk = it_import->second;
if (importThunk.moduleName[0] == 0 || importThunk.moduleName[0] == L'?')
{
addNotFoundApiToModuleList(&importThunk);
}
else
{
if (isNewModule(importThunk.moduleName))
{
addModuleToModuleList(importThunk.moduleName, importThunk.rva);
}
addFunctionToModuleList(&importThunk);
}
it_import++;
}
moduleThunk.thunkList.clear();
it_module++;
}
moduleList = moduleListNew;
moduleListNew.clear();
}
bool ImportsHandling::findNewModules(std::map & thunkList)
{
throw std::exception("The method or operation is not implemented.");
}
bool ImportsHandling::addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
- wcscpy_s(module.moduleName, _countof(module.moduleName), moduleName);
+ wcscpy_s(module.moduleName, moduleName);
module.key = module.firstThunk;
moduleListNew[module.key] = module;
return true;
}
bool ImportsHandling::isNewModule(const WCHAR * moduleName)
{
std::map::iterator it_module;
it_module = moduleListNew.begin();
while (it_module != moduleListNew.end())
{
if (!_wcsicmp(it_module->second.moduleName, moduleName))
{
return false;
}
it_module++;
}
return true;
}
void ImportsHandling::addUnknownModuleToModuleList(DWORD_PTR firstThunk)
{
ImportModuleThunk module;
module.firstThunk = firstThunk;
- wcscpy_s(module.moduleName, _countof(module.moduleName), L"?");
+ wcscpy_s(module.moduleName, L"?");
module.key = module.firstThunk;
moduleListNew[module.key] = module;
}
bool ImportsHandling::addNotFoundApiToModuleList(const ImportThunk * apiNotFound)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map::iterator it_module;
DWORD_PTR rva = apiNotFound->rva;
if (moduleListNew.size() > 0)
{
it_module = moduleListNew.begin();
while (it_module != moduleListNew.end())
{
if (rva >= it_module->second.firstThunk)
{
it_module++;
if (it_module == moduleListNew.end())
{
it_module--;
//new unknown module
if (it_module->second.moduleName[0] == L'?')
{
module = &(it_module->second);
}
else
{
addUnknownModuleToModuleList(apiNotFound->rva);
module = &(moduleListNew.find(rva)->second);
}
break;
}
else if (rva < it_module->second.firstThunk)
{
it_module--;
module = &(it_module->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()");
#endif
break;
}
}
}
else
{
//new unknown module
addUnknownModuleToModuleList(apiNotFound->rva);
module = &(moduleListNew.find(rva)->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva);
#endif
return false;
}
import.suspect = true;
import.valid = false;
import.va = apiNotFound->va;
import.rva = apiNotFound->rva;
import.apiAddressVA = apiNotFound->apiAddressVA;
import.ordinal = 0;
- wcscpy_s(import.moduleName, _countof(import.moduleName), L"?");
- strcpy_s(import.name, _countof(import.name), "?");
+ wcscpy_s(import.moduleName, L"?");
+ strcpy_s(import.name, "?");
import.key = import.rva;
module->thunkList[import.key] = import;
return true;
}
bool ImportsHandling::addFunctionToModuleList(const ImportThunk * apiFound)
{
ImportThunk import;
ImportModuleThunk * module = 0;
std::map::iterator it_module;
if (moduleListNew.size() > 1)
{
it_module = moduleListNew.begin();
while (it_module != moduleListNew.end())
{
if (apiFound->rva >= it_module->second.firstThunk)
{
it_module++;
if (it_module == moduleListNew.end())
{
it_module--;
module = &(it_module->second);
break;
}
else if (apiFound->rva < it_module->second.firstThunk)
{
it_module--;
module = &(it_module->second);
break;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Error iterator1 != moduleListNew.end()");
#endif
break;
}
}
}
else
{
it_module = moduleListNew.begin();
module = &(it_module->second);
}
if (!module)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, apiFound->rva);
#endif
return false;
}
import.suspect = apiFound->suspect;
import.valid = apiFound->valid;
import.va = apiFound->va;
import.rva = apiFound->rva;
import.apiAddressVA = apiFound->apiAddressVA;
import.ordinal = apiFound->ordinal;
import.hint = apiFound->hint;
- wcscpy_s(import.moduleName, _countof(import.moduleName), apiFound->moduleName);
- strcpy_s(import.name, _countof(import.name), apiFound->name);
+ wcscpy_s(import.moduleName, apiFound->moduleName);
+ strcpy_s(import.name, apiFound->name);
import.key = import.rva;
module->thunkList[import.key] = import;
return true;
}
void ImportsHandling::expandAllTreeNodes()
{
changeExpandStateOfTreeNodes(TVE_EXPAND);
}
void ImportsHandling::collapseAllTreeNodes()
{
changeExpandStateOfTreeNodes(TVE_COLLAPSE);
}
void ImportsHandling::changeExpandStateOfTreeNodes(UINT flag)
{
std::map::iterator it_module;
it_module = moduleList.begin();
while (it_module != moduleList.end())
{
ImportModuleThunk &moduleThunk = it_module->second;
moduleThunk.hTreeItem.Expand(flag);
it_module++;
}
}
diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp
index 1391533..7ee228e 100644
--- a/Scylla/MainGui.cpp
+++ b/Scylla/MainGui.cpp
@@ -1,1248 +1,1248 @@
#include "MainGui.h"
#include "Architecture.h"
//#include "PluginLoader.h"
//#include "ConfigurationHolder.h"
#include "PeDump.h"
#include "PeRebuild.h"
#include "DllInjectionPlugin.h"
#include "DisassemblerGui.h"
#include "PickApiGui.h"
//#include "NativeWinApi.h"
#include "ImportRebuild.h"
#include "SystemInformation.h"
#include "Scylla.h"
#include "AboutGui.h"
#include "OptionsGui.h"
#include "TreeImportExport.h"
extern CAppModule _Module; // o_O
const WCHAR MainGui::filterExe[] = L"Executable (*.exe)\0*.exe\0All files\0*.*\0";
const WCHAR MainGui::filterDll[] = L"Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterExeDll[] = L"Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterTxt[] = L"Text file (*.txt)\0*.txt\0All files\0*.*\0";
const WCHAR MainGui::filterXml[] = L"XML file (*.xml)\0*.xml\0All files\0*.*\0";
MainGui::MainGui() : selectedProcess(0), importsHandling(TreeImports), TreeImportsSubclass(this, IDC_TREE_IMPORTS)
{
/*
Logger::getDebugLogFilePath();
ConfigurationHolder::loadConfiguration();
PluginLoader::findAllPlugins();
NativeWinApi::initialize();
SystemInformation::getSystemInformation();
if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue())
{
processLister.setDebugPrivileges();
}
ProcessAccessHelp::getProcessModules(GetCurrentProcessId(), ProcessAccessHelp::ownModuleList);
*/
Scylla::init();
hIcon.LoadIcon(IDI_ICON_SCYLLA);
hMenuImports.LoadMenu(IDR_MENU_IMPORTS);
hMenuLog.LoadMenu(IDR_MENU_LOG);
accelerators.LoadAccelerators(IDR_ACCELERATOR_MAIN);
hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16);
hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16);
hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16);
}
BOOL MainGui::PreTranslateMessage(MSG* pMsg)
{
if(accelerators.TranslateAccelerator(m_hWnd, pMsg))
{
return TRUE; // handled keyboard shortcuts
}
else if(IsDialogMessage(pMsg))
{
return TRUE; // handled dialog messages
}
return FALSE;
}
BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
if (SystemInformation::currenOS == UNKNOWN_OS)
{
if(IDCANCEL == MessageBox(L"Operating System is not supported\r\nContinue anyway?", L"Scylla", MB_ICONWARNING | MB_OKCANCEL))
{
SendMessage(WM_CLOSE);
return FALSE;
}
}
// register ourselves to receive PreTranslateMessage
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->AddMessageFilter(this);
setupStatusBar();
DoDataExchange(); // attach controls
DlgResize_Init(true, true); // init CDialogResize
Scylla::windowLog.setWindow(ListLog);
appendPluginListToMenu(hMenuImports.GetSubMenu(0));
appendPluginListToMenu(CMenuHandle(GetMenu()).GetSubMenu(MenuImportsOffsetTrace));
enableDialogControls(FALSE);
setIconAndDialogCaption();
return TRUE;
}
void MainGui::OnDestroy()
{
PostQuitMessage(0);
}
void MainGui::OnSize(UINT nType, CSize size)
{
StatusBar.SendMessage(WM_SIZE);
SetMsgHandled(FALSE);
}
void MainGui::OnContextMenu(CWindow wnd, CPoint point)
{
switch(wnd.GetDlgCtrlID())
{
case IDC_TREE_IMPORTS:
DisplayContextMenuImports(wnd, point);
return;
case IDC_LIST_LOG:
DisplayContextMenuLog(wnd, point);
return;
}
SetMsgHandled(FALSE);
}
void MainGui::OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// Handle plugin trace menu selection
if(uNotifyCode == 0 && !wndCtl.IsWindow()) // make sure it's a menu
{
if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
pluginActionHandler(nID);
return;
}
}
SetMsgHandled(FALSE);
}
LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh)
{
if(TreeImports.GetCount() < 1)
return 0;
// Get item under cursor
CTreeItem over = findTreeItem(CPoint(GetMessagePos()), true);
if(over && importsHandling.isImport(over))
{
pickApiActionHandler(over);
}
return 0;
}
LRESULT MainGui::OnTreeImportsKeyDown(const NMHDR* pnmh)
{
const NMTVKEYDOWN * tkd = (NMTVKEYDOWN *)pnmh;
switch(tkd->wVKey)
{
case VK_RETURN:
{
CTreeItem selected = TreeImports.GetFocusItem();
if(!selected.IsNull() && importsHandling.isImport(selected))
{
pickApiActionHandler(selected);
}
}
return 1;
case VK_DELETE:
deleteSelectedImportsActionHandler();
return 1;
}
SetMsgHandled(FALSE);
return 0;
}
UINT MainGui::OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg)
{
if(lpMsg)
{
switch(lpMsg->wParam)
{
case VK_RETURN:
return DLGC_WANTMESSAGE;
}
}
SetMsgHandled(FALSE);
return 0;
}
void MainGui::OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_RETURN:
break;
default:
SetMsgHandled(FALSE);
break;
}
}
void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl)
{
fillProcessListComboBox(ComboProcessList);
}
void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
processSelectedActionHandler(ComboProcessList.GetCurSel());
}
void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl)
{
pickDllActionHandler();
}
void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl)
{
optionsActionHandler();
}
void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpActionHandler();
}
void MainGui::OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpFixActionHandler();
}
void MainGui::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl)
{
peRebuildActionHandler();
}
void MainGui::OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dllInjectActionHandler();
}
void MainGui::OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl)
{
iatAutosearchActionHandler();
}
void MainGui::OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
getImportsActionHandler();
}
void MainGui::OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showInvalidImportsActionHandler();
}
void MainGui::OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showSuspectImportsActionHandler();
}
void MainGui::OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
clearImportsActionHandler();
}
void MainGui::OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
invalidateSelectedImportsActionHandler();
}
void MainGui::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
deleteSelectedImportsActionHandler();
}
void MainGui::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
saveTreeActionHandler();
}
void MainGui::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
loadTreeActionHandler();
}
void MainGui::OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// TODO
}
void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl)
{
DestroyWindow();
}
void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showAboutDialog();
}
void MainGui::setupStatusBar()
{
StatusBar.Create(m_hWnd, NULL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_TOOLTIPS, NULL, IDC_STATUS_BAR);
CRect rcMain, rcStatus;
GetClientRect(&rcMain);
StatusBar.GetWindowRect(&rcStatus);
const int PARTS = 4;
int widths[PARTS];
widths[PART_COUNT] = rcMain.Width() / 5;
widths[PART_INVALID] = widths[PART_COUNT] + rcMain.Width() / 5;
widths[PART_IMAGEBASE] = widths[PART_INVALID] + rcMain.Width() / 3;
widths[PART_MODULE] = -1;
StatusBar.SetParts(PARTS, widths);
ResizeClient(rcMain.Width(), rcMain.Height() + rcStatus.Height(), FALSE);
}
void MainGui::updateStatusBar()
{
// Rewrite ImportsHandling so we get these easily
unsigned int totalImports = importsHandling.thunkCount();
unsigned int invalidImports = importsHandling.invalidThunkCount();
// \t = center, \t\t = right-align
- swprintf_s(stringBuffer, _countof(stringBuffer), L"\tImports: %u", totalImports);
+ swprintf_s(stringBuffer, L"\tImports: %u", totalImports);
StatusBar.SetText(PART_COUNT, stringBuffer);
if(invalidImports > 0)
{
StatusBar.SetIcon(PART_INVALID, hIconError);
}
else
{
StatusBar.SetIcon(PART_INVALID, hIconCheck);
}
- swprintf_s(stringBuffer, _countof(stringBuffer), L"\tInvalid: %u", invalidImports);
+ swprintf_s(stringBuffer, L"\tInvalid: %u", invalidImports);
StatusBar.SetText(PART_INVALID, stringBuffer);
if(selectedProcess)
{
DWORD_PTR imageBase = 0;
const WCHAR * fileName = 0;
if(ProcessAccessHelp::selectedModule)
{
imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
fileName = ProcessAccessHelp::selectedModule->getFilename();
}
else
{
imageBase = selectedProcess->imageBase;
fileName = selectedProcess->filename;
}
- swprintf_s(stringBuffer, _countof(stringBuffer), L"\tImagebase: " PRINTF_DWORD_PTR_FULL, imageBase);
+ swprintf_s(stringBuffer, L"\tImagebase: " PRINTF_DWORD_PTR_FULL, imageBase);
StatusBar.SetText(PART_IMAGEBASE, stringBuffer);
StatusBar.SetText(PART_MODULE, fileName);
StatusBar.SetTipText(PART_MODULE, fileName);
}
else
{
StatusBar.SetText(PART_IMAGEBASE, L"");
StatusBar.SetText(PART_MODULE, L"");
}
}
bool MainGui::showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter, const WCHAR * defExtension, const WCHAR * directory)
{
OPENFILENAME ofn = {0};
// WTL doesn't support new explorer styles on Vista and up
// This is because it uses a custom hook, we could remove it or derive
// from CFileDialog but this solution is easier and allows more control anyway (e.g. initial dir)
if(defFileName)
{
wcscpy_s(selectedFile, MAX_PATH, defFileName);
}
else
{
selectedFile[0] = L'\0';
}
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.lpstrFilter = filter;
ofn.lpstrDefExt = defExtension; // only first 3 chars are used, no dots!
ofn.lpstrFile = selectedFile;
ofn.lpstrInitialDir = directory;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
/*
*OFN_EXPLORER is automatically used, it only has to be specified
*if using a custom hook
*OFN_LONGNAMES is automatically used by explorer-style dialogs
*/
if(save)
ofn.Flags |= OFN_OVERWRITEPROMPT;
else
ofn.Flags |= OFN_FILEMUSTEXIST;
if(save)
return 0 != GetSaveFileName(&ofn);
else
return 0 != GetOpenFileName(&ofn);
}
void MainGui::setIconAndDialogCaption()
{
SetIcon(hIcon, TRUE);
SetIcon(hIcon, FALSE);
SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION);
}
void MainGui::pickDllActionHandler()
{
if(!selectedProcess)
return;
PickDllGui dlgPickDll(ProcessAccessHelp::moduleList);
if(dlgPickDll.DoModal())
{
//get selected module
ProcessAccessHelp::selectedModule = dlgPickDll.getSelectedModule();
ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize);
}
else
{
ProcessAccessHelp::selectedModule = 0;
}
updateStatusBar();
}
void MainGui::pickApiActionHandler(CTreeItem item)
{
if(!importsHandling.isImport(item))
return;
// TODO: new node when user picked an API from another DLL?
PickApiGui dlgPickApi(ProcessAccessHelp::moduleList);
if(dlgPickApi.DoModal())
{
const ApiInfo* api = dlgPickApi.getSelectedApi();
if(api && api->module)
{
importsHandling.setImport(item, api->module->getFilename(), api->name, api->ordinal, api->hint, true, api->isForwarded);
}
}
updateStatusBar();
}
void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode)
{
if(!selectedProcess)
return;
DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode);
if (address)
{
BYTE test;
if(!ProcessAccessHelp::readMemoryFromProcess(address, sizeof(test), &test))
{
- swprintf_s(stringBuffer, _countof(stringBuffer), L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address);
+ swprintf_s(stringBuffer, L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address);
MessageBox(stringBuffer, L"Failure", MB_ICONERROR);
}
else
{
DisassemblerGui dlgDisassembler(address);
dlgDisassembler.DoModal();
}
}
}
void MainGui::processSelectedActionHandler(int index)
{
std::vector& processList = Scylla::processLister.getProcessList();
Process &process = processList.at(index);
selectedProcess = 0;
clearImportsActionHandler();
Scylla::windowLog.log(L"Analyzing %s", process.fullPath);
if (ProcessAccessHelp::hProcess != 0)
{
ProcessAccessHelp::closeProcessHandle();
apiReader.clearAll();
}
if (!ProcessAccessHelp::openProcessHandle(process.PID))
{
enableDialogControls(FALSE);
Scylla::windowLog.log(L"Error: Cannot open process handle.");
updateStatusBar();
return;
}
ProcessAccessHelp::getProcessModules(process.PID, ProcessAccessHelp::moduleList);
apiReader.readApisFromModuleList();
Scylla::windowLog.log(L"Loading modules done.");
//TODO improve
ProcessAccessHelp::selectedModule = 0;
ProcessAccessHelp::targetSizeOfImage = process.imageSize;
ProcessAccessHelp::targetImageBase = process.imageBase;
ProcessAccessHelp::getSizeOfImageCurrentProcess();
process.imageSize = (DWORD)ProcessAccessHelp::targetSizeOfImage;
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", process.imageBase, process.imageSize);
process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath);
EditOEPAddress.SetValue(process.entryPoint + process.imageBase);
selectedProcess = &process;
enableDialogControls(TRUE);
updateStatusBar();
}
void MainGui::fillProcessListComboBox(CComboBox& hCombo)
{
hCombo.ResetContent();
std::vector& processList = Scylla::processLister.getProcessListSnapshot();
for (size_t i = 0; i < processList.size(); i++)
{
- swprintf_s(stringBuffer, _countof(stringBuffer), L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
+ swprintf_s(stringBuffer, L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
hCombo.AddString(stringBuffer);
}
}
/*
void MainGui::addTextToOutputLog(const WCHAR * text)
{
if (m_hWnd)
{
ListLog.SetCurSel(ListLog.AddString(text));
}
}
*/
void MainGui::clearOutputLog()
{
if (m_hWnd)
{
ListLog.ResetContent();
}
}
bool MainGui::saveLogToFile(const WCHAR * file)
{
const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian
const WCHAR newLine[] = L"\r\n";
bool success = true;
HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM);
WCHAR * buffer = 0;
size_t bufsize = 0;
for(int i = 0; i < ListLog.GetCount(); i++)
{
size_t size = ListLog.GetTextLen(i);
size += _countof(newLine)-1;
if(size+1 > bufsize)
{
bufsize = size+1;
delete[] buffer;
try
{
buffer = new WCHAR[bufsize];
}
catch(std::bad_alloc&)
{
buffer = 0;
success = false;
break;
}
}
ListLog.GetText(i, buffer);
wcscat_s(buffer, bufsize, newLine);
ProcessAccessHelp::writeMemoryToFileEnd(hFile, (DWORD)(size * sizeof(WCHAR)), buffer);
}
delete[] buffer;
CloseHandle(hFile);
}
return success;
}
void MainGui::showInvalidImportsActionHandler()
{
importsHandling.selectImports(true, false);
GotoDlgCtrl(TreeImports);
}
void MainGui::showSuspectImportsActionHandler()
{
importsHandling.selectImports(false, true);
GotoDlgCtrl(TreeImports);
}
void MainGui::deleteSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isModule(selected))
{
importsHandling.cutModule(selected);
}
else
{
importsHandling.cutImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::invalidateSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isImport(selected))
{
importsHandling.invalidateImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::loadTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
TreeImportExport treeIO;
DWORD_PTR addrOEP = 0;
DWORD_PTR addrIAT = 0;
DWORD sizeIAT = 0;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterXml, NULL, stringBuffer))
{
if(!treeIO.importTreeList(selectedFilePath, importsHandling.moduleList, &addrOEP, &addrIAT, &sizeIAT))
{
Scylla::windowLog.log(L"Loading tree file failed %s", selectedFilePath);
MessageBox(L"Loading tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
EditOEPAddress.SetValue(addrOEP);
EditIATAddress.SetValue(addrIAT);
EditIATSize.SetValue(sizeIAT);
importsHandling.displayAllImports();
updateStatusBar();
Scylla::windowLog.log(L"Loaded tree file %s", selectedFilePath);
Scylla::windowLog.log(L"-> OEP: " PRINTF_DWORD_PTR_FULL, addrOEP);
Scylla::windowLog.log(L"-> IAT: " PRINTF_DWORD_PTR_FULL L" Size: " PRINTF_DWORD_PTR, addrIAT, sizeIAT);
}
}
}
void MainGui::saveTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
TreeImportExport treeIO;
DWORD_PTR addrOEP;
DWORD_PTR addrIAT;
DWORD sizeIAT;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterXml, L"xml", stringBuffer))
{
addrOEP = EditOEPAddress.GetValue();
addrIAT = EditIATAddress.GetValue();
sizeIAT = EditIATSize.GetValue();
if(!treeIO.exportTreeList(selectedFilePath, importsHandling.moduleList, selectedProcess, addrOEP, addrIAT, sizeIAT))
{
Scylla::windowLog.log(L"Saving tree file failed %s", selectedFilePath);
MessageBox(L"Saving tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
Scylla::windowLog.log(L"Saved tree file %s", selectedFilePath);
}
}
}
void MainGui::iatAutosearchActionHandler()
{
DWORD_PTR searchAddress = 0;
DWORD_PTR addressIAT = 0;
DWORD sizeIAT = 0;
IATSearch iatSearch;
if(!selectedProcess)
return;
if(EditOEPAddress.GetWindowTextLength() > 0)
{
searchAddress = EditOEPAddress.GetValue();
if (searchAddress)
{
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT))
{
Scylla::windowLog.log(L"IAT found at VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT);
EditIATAddress.SetValue(addressIAT);
EditIATSize.SetValue(sizeIAT);
- swprintf_s(stringBuffer, _countof(stringBuffer), L"IAT found:\r\n\r\nStart: " PRINTF_DWORD_PTR_FULL L"\r\nSize: 0x%04X (%d) ", addressIAT, sizeIAT, sizeIAT);
+ swprintf_s(stringBuffer, L"IAT found:\r\n\r\nStart: " PRINTF_DWORD_PTR_FULL L"\r\nSize: 0x%04X (%d) ", addressIAT, sizeIAT, sizeIAT);
MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION);
}
else
{
Scylla::windowLog.log(L"IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
}
}
}
void MainGui::getImportsActionHandler()
{
if(!selectedProcess)
return;
DWORD_PTR addressIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
if (addressIAT && sizeIAT)
{
apiReader.readAndParseIAT(addressIAT, sizeIAT, importsHandling.moduleList);
importsHandling.displayAllImports();
updateStatusBar();
}
}
void MainGui::SetupImportsMenuItems(CTreeItem item)
{
bool isItem, isImport = false;
isItem = !item.IsNull();
if(isItem)
{
isImport = importsHandling.isImport(item);
}
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED;
UINT importOnly = isImport ? MF_ENABLED : MF_GRAYED;
hSub.EnableMenuItem(ID__INVALIDATE, itemOnly);
hSub.EnableMenuItem(ID__DISASSEMBLE, importOnly);
hSub.EnableMenuItem(ID__CUTTHUNK, importOnly);
hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly);
}
void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt)
{
if(TreeImports.GetCount() < 1)
return;
CTreeItem over, parent;
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
over = TreeImports.GetFocusItem();
if(over)
{
over.EnsureVisible();
over.GetRect(&pos, TRUE);
TreeImports.ClientToScreen(&pos);
}
else
{
TreeImports.GetWindowRect(&pos);
}
pt = pos.TopLeft();
}
else
{
// Get item under cursor
over = findTreeItem(pt, true);
}
SetupImportsMenuItems(over);
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
//wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName);
//MessageBox(stringBuffer, L"plugin selection");
pluginActionHandler(menuItem);
return;
}
switch (menuItem)
{
case ID__INVALIDATE:
if(importsHandling.isModule(over))
importsHandling.invalidateModule(over);
else
importsHandling.invalidateImport(over);
break;
case ID__DISASSEMBLE:
startDisassemblerGui(over);
break;
case ID__EXPANDALLNODES:
importsHandling.expandAllTreeNodes();
break;
case ID__COLLAPSEALLNODES:
importsHandling.collapseAllTreeNodes();
break;
case ID__CUTTHUNK:
importsHandling.cutImport(over);
break;
case ID__DELETETREENODE:
importsHandling.cutModule(importsHandling.isImport(over) ? over.GetParent() : over);
break;
}
}
updateStatusBar();
}
void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt)
{
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
ListLog.GetWindowRect(&pos);
pt = pos.TopLeft();
}
CMenuHandle hSub = hMenuLog.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
switch (menuItem)
{
case ID__SAVE:
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt", stringBuffer))
{
saveLogToFile(selectedFilePath);
}
break;
case ID__CLEAR:
clearOutputLog();
break;
}
}
}
void MainGui::appendPluginListToMenu(CMenuHandle hMenu)
{
std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList();
if (scyllaPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < scyllaPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins");
}
if (imprecPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < imprecPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins");
}
}
void MainGui::dumpActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
const WCHAR * defExtension;
PeDump peDump;
if (ProcessAccessHelp::selectedModule)
{
fileFilter = filterDll;
defExtension = L"dll";
}
else
{
fileFilter = filterExe;
defExtension = L"exe";
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer))
{
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
peDump.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
peDump.sizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize;
//get it from gui
peDump.entryPoint = EditOEPAddress.GetValue();
- wcscpy_s(peDump.fullpath, _countof(peDump.fullpath), ProcessAccessHelp::selectedModule->fullPath);
+ wcscpy_s(peDump.fullpath, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
peDump.imageBase = ProcessAccessHelp::targetImageBase;
peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage;
//get it from gui
peDump.entryPoint = EditOEPAddress.GetValue();
- wcscpy_s(peDump.fullpath, _countof(peDump.fullpath), selectedProcess->fullPath);
+ wcscpy_s(peDump.fullpath, selectedProcess->fullPath);
}
peDump.useHeaderFromDisk = Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue();
if (peDump.dumpCompleteProcessToDisk(selectedFilePath))
{
Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error: Cannot dump image.");
MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::peRebuildActionHandler()
{
DWORD newSize = 0;
WCHAR selectedFilePath[MAX_PATH];
PeRebuild peRebuild;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL, stringBuffer))
{
if (Scylla::config[CREATE_BACKUP].isTrue())
{
if (!ProcessAccessHelp::createBackupFile(selectedFilePath))
{
Scylla::windowLog.log(L"Creating backup file failed %s", selectedFilePath);
}
}
LONGLONG fileSize = ProcessAccessHelp::getFileSize(selectedFilePath);
LPVOID mapped = peRebuild.createFileMappingViewFull(selectedFilePath);
newSize = peRebuild.realignPE(mapped, (DWORD)fileSize);
peRebuild.closeAllMappingHandles();
if (newSize < 10)
{
Scylla::windowLog.log(L"Rebuild failed %s", selectedFilePath);
MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR);
}
else
{
peRebuild.truncateFile(selectedFilePath, newSize);
Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath);
Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) );
}
}
}
void MainGui::dumpFixActionHandler()
{
if(!selectedProcess)
return;
if (TreeImports.GetCount() < 2)
{
Scylla::windowLog.log(L"Nothing to rebuild");
return;
}
WCHAR newFilePath[MAX_PATH];
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
if (ProcessAccessHelp::selectedModule)
{
fileFilter = filterDll;
}
else
{
fileFilter = filterExe;
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL, stringBuffer))
{
- wcscpy_s(newFilePath,_countof(newFilePath),selectedFilePath);
+ wcscpy_s(newFilePath, selectedFilePath);
const WCHAR * extension = 0;
WCHAR* dot = wcsrchr(newFilePath, L'.');
if (dot)
{
*dot = L'\0';
extension = selectedFilePath + (dot - newFilePath); //wcsrchr(selectedFilePath, L'.');
}
- wcscat_s(newFilePath, _countof(newFilePath), L"_SCY");
+ wcscat_s(newFilePath, L"_SCY");
if(extension)
{
- wcscat_s(newFilePath, _countof(newFilePath), extension);
+ wcscat_s(newFilePath, extension);
}
ImportRebuild importRebuild;
if (importRebuild.rebuildImportTable(selectedFilePath,newFilePath,importsHandling.moduleList))
{
Scylla::windowLog.log(L"Import Rebuild success %s", newFilePath);
}
else
{
Scylla::windowLog.log(L"Import Rebuild failed %s", selectedFilePath);
MessageBox(L"Import Rebuild failed", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::enableDialogControls(BOOL value)
{
BOOL valButton = value ? TRUE : FALSE;
GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(valButton);
GetDlgItem(IDC_BTN_DUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(valButton);
GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(valButton);
CMenuHandle menu = GetMenu();
UINT valMenu = value ? MF_ENABLED : MF_GRAYED;
menu.EnableMenuItem(ID_FILE_DUMP, valMenu);
menu.EnableMenuItem(ID_FILE_FIXDUMP, valMenu);
menu.EnableMenuItem(ID_IMPORTS_INVALIDATESELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_CUTSELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_SAVETREE, valMenu);
menu.EnableMenuItem(ID_IMPORTS_LOADTREE, valMenu);
menu.EnableMenuItem(ID_MISC_DLLINJECTION, valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetScylla, MF_BYPOSITION | valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetImpRec, MF_BYPOSITION | valMenu);
//not yet implemented
GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE);
menu.EnableMenuItem(ID_TRACE_AUTOTRACE, MF_GRAYED);
}
CTreeItem MainGui::findTreeItem(CPoint pt, bool screenCoordinates)
{
if(screenCoordinates)
{
TreeImports.ScreenToClient(&pt);
}
UINT flags;
CTreeItem over = TreeImports.HitTest(pt, &flags);
if(over)
{
if(!(flags & TVHT_ONITEM))
{
over.m_hTreeItem = NULL;
}
}
return over;
}
void MainGui::showAboutDialog()
{
AboutGui dlgAbout;
dlgAbout.DoModal();
}
void MainGui::dllInjectActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
HMODULE hMod = 0;
DllInjection dllInjection;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, filterDll, NULL, stringBuffer))
{
hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, selectedFilePath);
if (hMod && Scylla::config[DLL_INJECTION_AUTO_UNLOAD].isTrue())
{
if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod))
{
Scylla::windowLog.log(L"DLL unloading failed, target %s", selectedFilePath);
}
}
if (hMod)
{
Scylla::windowLog.log(L"DLL Injection was successful, target %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"DLL Injection failed, target %s", selectedFilePath);
}
}
}
void MainGui::optionsActionHandler()
{
OptionsGui dlgOptions;
dlgOptions.DoModal();
}
void MainGui::clearImportsActionHandler()
{
importsHandling.clearAllImports();
updateStatusBar();
}
void MainGui::pluginActionHandler( int menuItem )
{
if(!selectedProcess)
return;
DllInjectionPlugin dllInjectionPlugin;
std::vector &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector &imprecPluginList = Scylla::plugins.getImprecPluginList();
menuItem -= PLUGIN_MENU_BASE_ID;
dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
dllInjectionPlugin.apiReader = &apiReader;
if (menuItem < (int)scyllaPluginList.size())
{
//scylla plugin
dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
}
else
{
#ifndef _WIN64
menuItem -= (int)scyllaPluginList.size();
//imprec plugin
dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
#endif
}
importsHandling.scanAndFixModuleList();
importsHandling.displayAllImports();
updateStatusBar();
}
-bool MainGui::getCurrentModulePath(TCHAR * buffer, size_t bufferSize)
+bool MainGui::getCurrentModulePath(WCHAR * buffer, size_t bufferSize)
{
if(!selectedProcess)
return false;
if(ProcessAccessHelp::selectedModule)
{
wcscpy_s(buffer, bufferSize, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
wcscpy_s(buffer, bufferSize, selectedProcess->fullPath);
}
WCHAR * slash = wcsrchr(buffer, L'\\');
if(slash)
{
*(slash+1) = L'\0';
}
return true;
}
diff --git a/Scylla/MainGui.h b/Scylla/MainGui.h
index abc758e..62d8d2d 100644
--- a/Scylla/MainGui.h
+++ b/Scylla/MainGui.h
@@ -1,295 +1,295 @@
#pragma once
#include
#include "resource.h"
// WTL
#include // base ATL classes
#include // base WTL classes
#include // ATL GUI classes
#include // WTL window frame helpers
#include // WTL utility classes
#include // WTL enhanced msg map macros
#include // WTL controls
#include // WTL dialog data exchange
#include "multitree.h"
#include "hexedit.h"
#include "Logger.h"
#include "ProcessLister.h"
#include "IATSearch.h"
#include "PickDllGui.h"
#include "ImportsHandling.h"
class MainGui : public CDialogImpl, public CWinDataExchange, public CDialogResize, public CMessageFilter
{
public:
enum { IDD = IDD_DLG_MAIN };
// Dialog Data eXchange, attaches/subclasses child controls to wrappers
// DDX_CONTROL : subclass
// DDX_CONTROL_HANDLE : attach
BEGIN_DDX_MAP(MainGui)
DDX_CONTROL(IDC_TREE_IMPORTS, TreeImportsSubclass) // needed for message reflection
DDX_CONTROL(IDC_TREE_IMPORTS, TreeImports)
DDX_CONTROL_HANDLE(IDC_CBO_PROCESSLIST, ComboProcessList)
DDX_CONTROL_HANDLE(IDC_LIST_LOG, ListLog)
DDX_CONTROL(IDC_EDIT_OEPADDRESS, EditOEPAddress)
DDX_CONTROL(IDC_EDIT_IATADDRESS, EditIATAddress)
DDX_CONTROL(IDC_EDIT_IATSIZE, EditIATSize)
END_DDX_MAP()
// Our message map
// Messages are passed from top to bottom
// The first handler that doesn't call SetMsgHandled(FALSE) aborts the chain
// If none signals the message as handled, it will be passed to mixins (CHAIN_MSG_MAP)
// or ultimately passed to DefWindowProc
BEGIN_MSG_MAP_EX(MainGui)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_SIZE(OnSize)
MSG_WM_CONTEXTMENU(OnContextMenu)
MSG_WM_COMMAND(OnCommand)
NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, NM_DBLCLK, OnTreeImportsDoubleClick)
NOTIFY_HANDLER_EX(IDC_TREE_IMPORTS, TVN_KEYDOWN, OnTreeImportsKeyDown)
COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_DROPDOWN, OnProcessListDrop)
COMMAND_HANDLER_EX(IDC_CBO_PROCESSLIST, CBN_SELENDOK, OnProcessListSelected)
COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL, OnPickDLL)
COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS, OnOptions)
COMMAND_ID_HANDLER_EX(IDC_BTN_DUMP, OnDump)
COMMAND_ID_HANDLER_EX(IDC_BTN_FIXDUMP, OnFixDump)
COMMAND_ID_HANDLER_EX(IDC_BTN_PEREBUILD, OnPERebuild)
COMMAND_ID_HANDLER_EX(IDC_BTN_IATAUTOSEARCH, OnIATAutoSearch)
COMMAND_ID_HANDLER_EX(IDC_BTN_GETIMPORTS, OnGetImports)
COMMAND_ID_HANDLER_EX(IDC_BTN_INVALIDIMPORTS, OnInvalidImports)
COMMAND_ID_HANDLER_EX(IDC_BTN_SUSPECTIMPORTS, OnSuspectImports)
COMMAND_ID_HANDLER_EX(IDC_BTN_CLEARIMPORTS, OnClearImports)
COMMAND_ID_HANDLER_EX(ID_FILE_DUMP, OnDump)
COMMAND_ID_HANDLER_EX(ID_FILE_PEREBUILD, OnPERebuild)
COMMAND_ID_HANDLER_EX(ID_FILE_FIXDUMP, OnFixDump)
COMMAND_ID_HANDLER_EX(ID_FILE_EXIT, OnExit)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWINVALID, OnInvalidImports)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOWSUSPECT, OnSuspectImports)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_INVALIDATESELECTED, OnInvalidateSelected)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_CUTSELECTED, OnCutSelected)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_CLEARIMPORTS, OnClearImports)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SAVETREE, OnSaveTree)
COMMAND_ID_HANDLER_EX(ID_IMPORTS_LOADTREE, OnLoadTree)
COMMAND_ID_HANDLER_EX(ID_TRACE_AUTOTRACE, OnAutotrace)
COMMAND_ID_HANDLER_EX(ID_MISC_DLLINJECTION, OnDLLInject)
COMMAND_ID_HANDLER_EX(ID_MISC_OPTIONS, OnOptions)
COMMAND_ID_HANDLER_EX(ID_HELP_ABOUT, OnAbout)
COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit)
REFLECT_NOTIFY_ID(IDC_TREE_IMPORTS) // pass WM_NOTIFY to child control
CHAIN_MSG_MAP(CDialogResize)
// Message map for subclassed treeview
// CContainedWindow forwards all messages to this map
ALT_MSG_MAP(IDC_TREE_IMPORTS)
MSG_WM_GETDLGCODE(OnTreeImportsSubclassGetDlgCode)
MSG_WM_CHAR(OnTreeImportsSubclassChar)
END_MSG_MAP()
// Dialog resize 'table'
// States if child controls move or resize or center in a specific direction
// when the parent dialog is resized
BEGIN_DLGRESIZE_MAP(MainGui)
DLGRESIZE_CONTROL(IDC_GROUP_ATTACH, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_CBO_PROCESSLIST, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_BTN_PICKDLL, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_GROUP_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_TREE_IMPORTS, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_BTN_INVALIDIMPORTS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_SUSPECTIMPORTS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_CLEARIMPORTS, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_GROUP_IATINFO, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_STATIC_OEPADDRESS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_STATIC_IATADDRESS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_STATIC_IATSIZE, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_EDIT_OEPADDRESS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_EDIT_IATADDRESS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_EDIT_IATSIZE, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_IATAUTOSEARCH, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_GETIMPORTS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_GROUP_ACTIONS, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_AUTOTRACE, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_GROUP_DUMP, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_DUMP, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_PEREBUILD, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BTN_FIXDUMP, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_GROUP_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_LIST_LOG, DLSZ_MOVE_Y | DLSZ_SIZE_X)
END_DLGRESIZE_MAP()
MainGui();
//void addTextToOutputLog(const WCHAR * text);
//CWindow getLogListboxHandle() const { return ListLog; }
protected:
// Variables
WCHAR stringBuffer[600];
ImportsHandling importsHandling;
//ProcessAccessHelp processAccessHelp;
ApiReader apiReader;
Process * selectedProcess;
// File selection filters
static const WCHAR filterExe[];
static const WCHAR filterDll[];
static const WCHAR filterExeDll[];
static const WCHAR filterTxt[];
static const WCHAR filterXml[];
// Controls
CMultiSelectTreeViewCtrl TreeImports;
CComboBox ComboProcessList;
CHexEdit EditOEPAddress;
CHexEdit EditIATAddress;
CHexEdit EditIATSize;
CListBox ListLog;
CStatusBarCtrl StatusBar;
enum StatusParts {
PART_COUNT = 0,
PART_INVALID,
PART_IMAGEBASE,
PART_MODULE
};
CContainedWindow TreeImportsSubclass;
// Handles
CIcon hIcon;
CMenu hMenuImports;
CMenu hMenuLog;
CAccelerator accelerators;
CIcon hIconCheck;
CIcon hIconWarning;
CIcon hIconError;
static const int MenuImportsOffsetTrace = 2;
static const int MenuImportsTraceOffsetScylla = 2;
static const int MenuImportsTraceOffsetImpRec = 4;
static const int PLUGIN_MENU_BASE_ID = 0x10;
protected:
virtual BOOL PreTranslateMessage(MSG* pMsg);
// Message handlers
BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
void OnDestroy();
void OnSize(UINT nType, CSize size);
void OnContextMenu(CWindow wnd, CPoint point);
void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl);
// WM_NOTIFY handlers
LRESULT OnTreeImportsDoubleClick(const NMHDR* pnmh);
LRESULT OnTreeImportsKeyDown(const NMHDR* pnmh);
// Forwarded messages from subclassed treeview
UINT OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg);
void OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags);
// WM_COMMAND handlers
void OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnDump(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl);
// GUI functions
bool showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter = NULL, const WCHAR * defExtension = NULL, const WCHAR * directory = NULL);
void setupStatusBar();
void updateStatusBar();
void fillProcessListComboBox(CComboBox& hCombo);
void setIconAndDialogCaption();
void enableDialogControls(BOOL value);
CTreeItem findTreeItem(CPoint pt, bool screenCoordinates);
// Actions
void pickDllActionHandler();
void pickApiActionHandler(CTreeItem item);
void processSelectedActionHandler(int index);
void showInvalidImportsActionHandler();
void showSuspectImportsActionHandler();
void deleteSelectedImportsActionHandler();
void invalidateSelectedImportsActionHandler();
void loadTreeActionHandler();
void saveTreeActionHandler();
void iatAutosearchActionHandler();
void getImportsActionHandler();
void dumpActionHandler();
void peRebuildActionHandler();
void startDisassemblerGui(CTreeItem selectedTreeNode);
void dumpFixActionHandler();
void showAboutDialog();
void dllInjectActionHandler();
void optionsActionHandler();
void clearImportsActionHandler();
void pluginActionHandler(int menuItem);
// Popup menu functions
void SetupImportsMenuItems(CTreeItem item);
void appendPluginListToMenu(CMenuHandle hMenuTrackPopup);
void DisplayContextMenuImports(CWindow, CPoint);
void DisplayContextMenuLog(CWindow, CPoint);
// Log
void clearOutputLog();
bool saveLogToFile(const WCHAR * file);
// Misc
- bool getCurrentModulePath(TCHAR * buffer, size_t bufferSize);
+ bool getCurrentModulePath(WCHAR * buffer, size_t bufferSize);
};
diff --git a/Scylla/OptionsGui.cpp b/Scylla/OptionsGui.cpp
index f56795a..1fc51e4 100644
--- a/Scylla/OptionsGui.cpp
+++ b/Scylla/OptionsGui.cpp
@@ -1,48 +1,49 @@
#include "OptionsGui.h"
#include "Scylla.h"
BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
loadOptions();
DoDataExchange(DDX_LOAD); // show settings
EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME);
CenterWindow();
return TRUE;
}
void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
DoDataExchange(DDX_SAVE);
saveOptions();
Scylla::config.saveConfiguration();
EndDialog(0);
}
void OptionsGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void OptionsGui::saveOptions() const
{
Scylla::config[USE_PE_HEADER_FROM_DISK].setBool(usePEHeaderFromDisk);
Scylla::config[DEBUG_PRIVILEGE].setBool(debugPrivilege);
Scylla::config[CREATE_BACKUP].setBool(createBackup);
Scylla::config[DLL_INJECTION_AUTO_UNLOAD].setBool(dllInjectionAutoUnload);
Scylla::config[UPDATE_HEADER_CHECKSUM].setBool(updateHeaderChecksum);
Scylla::config[IAT_SECTION_NAME].setString(iatSectionName);
}
void OptionsGui::loadOptions()
{
usePEHeaderFromDisk = Scylla::config[USE_PE_HEADER_FROM_DISK].getBool();
debugPrivilege = Scylla::config[DEBUG_PRIVILEGE].getBool();
createBackup = Scylla::config[CREATE_BACKUP].getBool();
dllInjectionAutoUnload = Scylla::config[DLL_INJECTION_AUTO_UNLOAD].getBool();
updateHeaderChecksum = Scylla::config[UPDATE_HEADER_CHECKSUM].getBool();
wcsncpy_s(iatSectionName, Scylla::config[IAT_SECTION_NAME].getString(), _countof(iatSectionName)-1);
+ iatSectionName[_countof(iatSectionName) - 1] = L'\0';
}
diff --git a/Scylla/PickApiGui.cpp b/Scylla/PickApiGui.cpp
index dc6775c..1e9a74f 100644
--- a/Scylla/PickApiGui.cpp
+++ b/Scylla/PickApiGui.cpp
@@ -1,140 +1,140 @@
#include "PickApiGui.h"
#include // string conversion
PickApiGui::PickApiGui(const std::vector &moduleList) : moduleList(moduleList)
{
selectedApi = 0;
}
BOOL PickApiGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
DlgResize_Init(true, true);
fillDllComboBox(ComboDllSelect);
CenterWindow();
return TRUE;
}
void PickApiGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
actionApiSelected();
}
void PickApiGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void PickApiGui::OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
int indexDll = ComboDllSelect.GetCurSel();
if (indexDll != CB_ERR)
{
fillApiListBox(ListApiSelect, moduleList[indexDll].apiList);
EditApiFilter.SetWindowText(L"");
}
}
void PickApiGui::OnApiListDoubleClick(UINT uNotifyCode, int nID, CWindow wndCtl)
{
actionApiSelected();
}
void PickApiGui::OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl)
{
int indexDll = ComboDllSelect.GetCurSel();
if (indexDll == CB_ERR)
return;
std::vector newApis;
WCHAR filter[MAX_PATH];
int lenFilter = EditApiFilter.GetWindowText(filter, _countof(filter));
if(lenFilter > 0)
{
const std::vector &apis = moduleList[indexDll].apiList;
for (size_t i = 0; i < apis.size(); i++)
{
ApiInfo* api = apis[i];
if(api->name[0] != '\0')
{
CA2WEX wStr(api->name);
if(!_wcsnicmp(wStr, filter, lenFilter))
{
newApis.push_back(api);
}
}
else
{
WCHAR buf[6];
- swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal);
+ swprintf_s(buf, L"#%04X", api->ordinal);
if(!_wcsnicmp(buf, filter, lenFilter))
{
newApis.push_back(api);
}
}
}
}
else
{
newApis = moduleList[indexDll].apiList;
}
fillApiListBox(ListApiSelect, newApis);
}
void PickApiGui::actionApiSelected()
{
int indexDll = ComboDllSelect.GetCurSel();
int indexApi;
if(ListApiSelect.GetCount() == 1)
{
indexApi = 0;
}
else
{
indexApi = ListApiSelect.GetCurSel();
}
if (indexDll != CB_ERR && indexApi != LB_ERR)
{
selectedApi = (ApiInfo *)ListApiSelect.GetItemData(indexApi);
EndDialog(1);
}
}
void PickApiGui::fillDllComboBox(CComboBox& combo)
{
combo.ResetContent();
for (size_t i = 0; i < moduleList.size(); i++)
{
combo.AddString(moduleList[i].fullPath);
}
}
void PickApiGui::fillApiListBox(CListBox& list, const std::vector &apis)
{
list.ResetContent();
for (size_t i = 0; i < apis.size(); i++)
{
const ApiInfo* api = apis[i];
int item;
if(api->name[0] != '\0')
{
CA2WEX wStr(api->name);
item = list.AddString(wStr);
}
else
{
WCHAR buf[6];
- swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal);
+ swprintf_s(buf, L"#%04X", api->ordinal);
item = list.AddString(buf);
}
list.SetItemData(item, (DWORD_PTR)api);
}
}
diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp
index 5fc07b3..dcf1516 100644
--- a/Scylla/PickDllGui.cpp
+++ b/Scylla/PickDllGui.cpp
@@ -1,145 +1,145 @@
#include "PickDllGui.h"
PickDllGui::PickDllGui(std::vector &moduleList) : moduleList(moduleList)
{
selectedModule = 0;
prevColumn = -1;
ascending = true;
}
BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
DlgResize_Init(true, true);
addColumnsToModuleList(ListDLLSelect);
displayModuleList(ListDLLSelect);
CenterWindow();
return TRUE;
}
LRESULT PickDllGui::OnListDllColumnClicked(NMHDR* pnmh)
{
NMLISTVIEW* list = (NMLISTVIEW*)pnmh;
int column = list->iSubItem;
if(column == prevColumn)
{
ascending = !ascending;
}
else
{
prevColumn = column;
ascending = true;
}
// lo-byte: column, hi-byte: sort-order
ListDLLSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending));
return 0;
}
LRESULT PickDllGui::OnListDllDoubleClick(NMHDR* pnmh)
{
NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh;
LVHITTESTINFO hti;
hti.pt = ia->ptAction;
int clicked = ListDLLSelect.HitTest(&hti);
if(clicked != -1)
{
selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(clicked);
EndDialog(1);
}
return 0;
}
void PickDllGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
int index = ListDLLSelect.GetSelectionMark();
if (index != -1)
{
selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(index);
EndDialog(1);
}
}
void PickDllGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void PickDllGui::addColumnsToModuleList(CListViewCtrl& list)
{
list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
list.InsertColumn(COL_NAME, L"Name", LVCFMT_LEFT);
list.InsertColumn(COL_IMAGEBASE, L"ImageBase", LVCFMT_CENTER);
list.InsertColumn(COL_IMAGESIZE, L"ImageSize", LVCFMT_CENTER);
list.InsertColumn(COL_PATH, L"Path", LVCFMT_LEFT);
}
void PickDllGui::displayModuleList(CListViewCtrl& list)
{
WCHAR temp[20];
list.DeleteAllItems();
std::vector::const_iterator iter;
int count = 0;
for( iter = moduleList.begin(); iter != moduleList.end(); iter++ , count++)
{
list.InsertItem(count, iter->getFilename());
#ifdef _WIN64
- swprintf_s(temp, _countof(temp), L"%016I64X", iter->modBaseAddr);
+ swprintf_s(temp, L"%016I64X", iter->modBaseAddr);
#else
- swprintf_s(temp, _countof(temp), L"%08X", iter->modBaseAddr);
+ swprintf_s(temp, L"%08X", iter->modBaseAddr);
#endif
list.SetItemText(count, COL_IMAGEBASE, temp);
- swprintf_s(temp, _countof(temp),L"%08X",iter->modBaseSize);
+ swprintf_s(temp, L"%08X",iter->modBaseSize);
list.SetItemText(count, COL_IMAGESIZE, temp);
list.SetItemText(count, COL_PATH, iter->fullPath);
list.SetItemData(count, (DWORD_PTR)&(*iter));
}
list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_IMAGEBASE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_IMAGESIZE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_PATH, LVSCW_AUTOSIZE_USEHEADER);
}
// lParamSort - lo-byte: column, hi-byte: sort-order
int PickDllGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
const ModuleInfo * module1 = (ModuleInfo *)lParam1;
const ModuleInfo * module2 = (ModuleInfo *)lParam2;
int column = LOBYTE(lParamSort);
bool ascending = (HIBYTE(lParamSort) == TRUE);
int diff = 0;
switch(column)
{
case COL_NAME:
diff = _wcsicmp(module1->getFilename(), module2->getFilename());
break;
case COL_IMAGEBASE:
diff = module1->modBaseAddr < module2->modBaseAddr ? -1 : 1;
break;
case COL_IMAGESIZE:
diff = module1->modBaseSize < module2->modBaseSize ? -1 : 1;
break;
case COL_PATH:
diff = _wcsicmp(module1->fullPath, module2->fullPath);
break;
}
return ascending ? diff : -diff;
}
diff --git a/Scylla/PluginLoader.cpp b/Scylla/PluginLoader.cpp
index 3e03b8c..4c8a168 100644
--- a/Scylla/PluginLoader.cpp
+++ b/Scylla/PluginLoader.cpp
@@ -1,360 +1,353 @@
#include "PluginLoader.h"
#include "Logger.h"
#include "ProcessAccessHelp.h"
#include "StringConversion.h"
#include
const WCHAR PluginLoader::PLUGIN_DIR[] = L"Plugins\\";
const WCHAR PluginLoader::PLUGIN_SEARCH_STRING[] = L"*.dll";
const WCHAR PluginLoader::PLUGIN_IMPREC_DIR[] = L"ImpRec_Plugins\\";
const WCHAR PluginLoader::PLUGIN_IMPREC_WRAPPER_DLL[] = L"Imprec_Wrapper_DLL.dll";
//#define DEBUG_COMMENTS
std::vector & PluginLoader::getScyllaPluginList()
{
return scyllaPluginList;
}
std::vector & PluginLoader::getImprecPluginList()
{
return imprecPluginList;
}
bool PluginLoader::findAllPlugins()
{
if (!scyllaPluginList.empty())
{
scyllaPluginList.clear();
}
if (!imprecPluginList.empty())
{
imprecPluginList.clear();
}
if (!buildSearchString())
{
return false;
}
if (!searchForPlugin(scyllaPluginList, dirSearchString, true))
{
return false;
}
#ifndef _WIN64
if (!buildSearchStringImprecPlugins())
{
return false;
}
if (!searchForPlugin(imprecPluginList, dirSearchString, false))
{
return false;
}
#endif
return true;
}
bool PluginLoader::searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin)
{
WIN32_FIND_DATA ffd;
HANDLE hFind = 0;
DWORD dwError = 0;
Plugin pluginData;
hFind = FindFirstFile(searchPath, &ffd);
dwError = GetLastError();
if (dwError == ERROR_FILE_NOT_FOUND)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: No files found");
#endif
return true;
}
if (hFind == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: FindFirstFile failed %d", dwError);
#endif
return false;
}
do
{
if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
if ((ffd.nFileSizeHigh != 0) || (ffd.nFileSizeLow < 200))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: Plugin invalid file size: %s", ffd.cFileName);
#endif
}
else
{
pluginData.fileSize = ffd.nFileSizeLow;
- wcscpy_s(pluginData.fullpath, _countof(baseDirPath), baseDirPath);
- wcscat_s(pluginData.fullpath, _countof(baseDirPath), ffd.cFileName);
+ wcscpy_s(pluginData.fullpath, baseDirPath);
+ wcscat_s(pluginData.fullpath, ffd.cFileName);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: Plugin %s", pluginData.fullpath);
#endif
if (isValidDllFile(pluginData.fullpath))
{
if (isScyllaPlugin)
{
if (getScyllaPluginName(&pluginData))
{
//add valid plugin
newPluginList.push_back(pluginData);
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Cannot get scylla plugin name %s", pluginData.fullpath);
#endif
}
}
else
{
if (isValidImprecPlugin(pluginData.fullpath))
{
- wcscpy_s(pluginData.pluginName, MAX_PATH, ffd.cFileName);
+ wcscpy_s(pluginData.pluginName, ffd.cFileName);
newPluginList.push_back(pluginData);
}
}
}
}
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
FindClose(hFind);
if (dwError == ERROR_NO_MORE_FILES)
{
return true;
}
else
{
return false;
}
}
bool PluginLoader::getScyllaPluginName(Plugin * pluginData)
{
bool retValue = false;
char * pluginName = 0;
def_ScyllaPluginNameW ScyllaPluginNameW = 0;
def_ScyllaPluginNameA ScyllaPluginNameA = 0;
HMODULE hModule = LoadLibraryEx(pluginData->fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
if (hModule)
{
ScyllaPluginNameW = (def_ScyllaPluginNameW)GetProcAddress(hModule, "ScyllaPluginNameW");
if (ScyllaPluginNameW)
{
- wcscpy_s(pluginData->pluginName, MAX_PATH, ScyllaPluginNameW());
+ wcscpy_s(pluginData->pluginName, ScyllaPluginNameW());
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: Plugin name %s", pluginData->pluginName);
#endif
retValue = true;
}
else
{
ScyllaPluginNameA = (def_ScyllaPluginNameA)GetProcAddress(hModule, "ScyllaPluginNameA");
if (ScyllaPluginNameA)
{
pluginName = ScyllaPluginNameA();
StringConversion::ToUTF16(pluginName, pluginData->pluginName, _countof(pluginData->pluginName));
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: Plugin name mbstowcs_s %s", pluginData->pluginName);
#endif
if (wcslen(pluginData->pluginName) > 1)
{
retValue = true;
}
else
{
retValue = false;
}
}
else
{
retValue = false;
}
}
FreeLibrary(hModule);
return retValue;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: LoadLibraryEx failed %s", pluginData->fullpath);
#endif
return false;
}
}
bool PluginLoader::buildSearchString()
{
ZeroMemory(dirSearchString, sizeof(dirSearchString));
ZeroMemory(baseDirPath, sizeof(baseDirPath));
if (!GetModuleFileName(0, dirSearchString, _countof(dirSearchString)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"buildSearchString :: GetModuleFileName failed %d", GetLastError());
#endif
return false;
}
//wprintf(L"dirSearchString 1 %s\n\n", dirSearchString);
PathRemoveFileSpec(dirSearchString);
//wprintf(L"dirSearchString 2 %s\n\n", dirSearchString);
PathAppend(dirSearchString, PLUGIN_DIR);
- wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString);
- wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_SEARCH_STRING);
+ wcscpy_s(baseDirPath, dirSearchString);
+ wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING);
//wprintf(L"dirSearchString 3 %s\n\n", dirSearchString);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dirSearchString final %s", dirSearchString);
#endif
return true;
}
bool PluginLoader::isValidDllFile( const WCHAR * fullpath )
{
BYTE * data = 0;
DWORD lpNumberOfBytesRead = 0;
PIMAGE_DOS_HEADER pDos = 0;
PIMAGE_NT_HEADERS pNT = 0;
bool retValue = false;
HANDLE hFile = CreateFile(fullpath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
data = new BYTE[sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100];
if (ReadFile(hFile, data, sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + 0x100, &lpNumberOfBytesRead, 0))
{
pDos = (PIMAGE_DOS_HEADER)data;
if (pDos->e_magic == IMAGE_DOS_SIGNATURE)
{
pNT = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew);
if (pNT->Signature == IMAGE_NT_SIGNATURE)
{
#ifdef _WIN64
if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
#else
if (pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
#endif
{
retValue = true;
}
}
}
}
delete [] data;
CloseHandle(hFile);
}
return retValue;
}
bool PluginLoader::isValidImprecPlugin(const WCHAR * fullpath)
{
def_Imprec_Trace Imprec_Trace = 0;
bool retValue = false;
HMODULE hModule = LoadLibraryEx(fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
if (hModule)
{
Imprec_Trace = (def_Imprec_Trace)GetProcAddress(hModule, "Trace");
if (Imprec_Trace)
{
retValue = true;
}
else
{
retValue = false;
}
FreeLibrary(hModule);
return retValue;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"isValidImprecPlugin :: LoadLibraryEx failed %s", pluginData->fullpath);
#endif
return false;
}
}
bool PluginLoader::buildSearchStringImprecPlugins()
{
- wcscpy_s(dirSearchString, _countof(dirSearchString), baseDirPath);
+ wcscpy_s(dirSearchString, baseDirPath);
- wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_IMPREC_DIR);
+ wcscat_s(dirSearchString, PLUGIN_IMPREC_DIR);
- wcscpy_s(baseDirPath, _countof(baseDirPath), dirSearchString);
+ wcscpy_s(baseDirPath, dirSearchString);
//build imprec wrapper dll path
- wcscpy_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), dirSearchString);
- wcscat_s(imprecWrapperDllPath, _countof(imprecWrapperDllPath), PLUGIN_IMPREC_WRAPPER_DLL);
+ wcscpy_s(imprecWrapperDllPath, dirSearchString);
+ wcscat_s(imprecWrapperDllPath, PLUGIN_IMPREC_WRAPPER_DLL);
if (!fileExists(imprecWrapperDllPath))
{
return false;
}
- wcscat_s(dirSearchString, _countof(dirSearchString), PLUGIN_SEARCH_STRING);
+ wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING);
return true;
}
bool PluginLoader::fileExists(const WCHAR * fileName)
{
- if (GetFileAttributesW(fileName) == INVALID_FILE_ATTRIBUTES)
- {
- return false;
- }
- else
- {
- return true;
- }
+ return (GetFileAttributesW(fileName) != INVALID_FILE_ATTRIBUTES);
}
diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp
index cfb7f3d..6f191a4 100644
--- a/Scylla/ProcessAccessHelp.cpp
+++ b/Scylla/ProcessAccessHelp.cpp
@@ -1,715 +1,715 @@
#include "ProcessAccessHelp.h"
#include "Scylla.h"
#include "NativeWinApi.h"
HANDLE ProcessAccessHelp::hProcess = 0;
ModuleInfo * ProcessAccessHelp::selectedModule;
DWORD_PTR ProcessAccessHelp::targetImageBase = 0;
DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0;
DWORD_PTR ProcessAccessHelp::maxValidAddress = 0;
std::vector ProcessAccessHelp::moduleList; //target process module list
std::vector ProcessAccessHelp::ownModuleList; //own module list
_DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS];
unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0;
_CodeInfo ProcessAccessHelp::decomposerCi = {0};
_DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS];
unsigned int ProcessAccessHelp::decodedInstructionsCount = 0;
BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
//#define DEBUG_COMMENTS
bool ProcessAccessHelp::openProcessHandle(DWORD dwPID)
{
if (dwPID > 0)
{
if (hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", hProcess);
#endif
return false;
}
else
{
//hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID);
//if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid)))
hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID);
if (hProcess)
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID);
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Wrong PID, PID %X", dwPID);
#endif
return false;
}
}
HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId)
{
HANDLE hProcess = 0;
CLIENT_ID cid = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntStatus = 0;
InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
cid.UniqueProcess = (HANDLE)dwProcessId;
ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid);
if (NT_SUCCESS(ntStatus))
{
return hProcess;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus));
#endif
return 0;
}
}
void ProcessAccessHelp::closeProcessHandle()
{
CloseHandle(hProcess);
hProcess = 0;
moduleList.clear();
targetImageBase = 0;
selectedModule = 0;
}
bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
SIZE_T lpNumberOfBytesRead = 0;
DWORD dwProtect = 0;
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL");
#endif
return returnValue;
}
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u", address,size, GetLastError());
#endif
returnValue = false;
}
else
{
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError());
#endif
returnValue = false;
}
else
{
returnValue = true;
}
VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect);
}
}
else
{
returnValue = true;
}
if (returnValue)
{
if (size != lpNumberOfBytesRead)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes", lpNumberOfBytesRead, size);
#endif
returnValue = false;
}
else
{
returnValue = true;
}
}
return returnValue;
}
bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress)
{
ZeroMemory(&decomposerCi, sizeof(_CodeInfo));
decomposerCi.code = dataBuffer;
decomposerCi.codeLen = (int)bufferSize;
decomposerCi.dt = dt;
decomposerCi.codeOffset = startAddress;
decomposerInstructionsCount = 0;
if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"decomposeMemory :: distorm_decompose == DECRES_INPUTERR");
#endif
return false;
}
else
{
return true;
}
}
bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
{
// Holds the result of the decoding.
_DecodeResult res;
// next is used for instruction's offset synchronization.
// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
decodedInstructionsCount = 0;
_OffsetType offset = startOffset;
res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
/* for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
#ifdef SUPPORT_64BIT_OFFSET
printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#else
printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#endif
}*/
if (res == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR");
#endif
return false;
}
else if (res == DECRES_SUCCESS)
{
//printf("disassembleMemory :: res == DECRES_SUCCESS\n");
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == %d", res);
#endif
return false;
}
}
DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask)
{
DWORD pos = 0;
size_t searchLen = strlen(mask) - 1;
for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++)
{
if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' )
{
if(mask[pos+1] == 0x00)
{
return (retAddress - searchLen);
}
pos++;
} else {
pos = 0;
}
}
return 0;
}
bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath)
{
return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath);
}
LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath)
{
LONGLONG fileSize = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
fileSize = getFileSize(hFile);
CloseHandle(hFile);
hFile = 0;
}
return fileSize;
}
LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile)
{
LARGE_INTEGER lpFileSize = {0};
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
if (!GetFileSizeEx(hFile, &lpFileSize))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError());
#endif
return 0;
}
else
{
return lpFileSize.QuadPart;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid");
#endif
return 0;
}
}
bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesRead = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
SetFilePointer(hFile, 0, 0, FILE_END);
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath)
{
DWORD lpNumberOfBytesRead = 0;
LONGLONG fileSize = 0;
DWORD dwSize = 0;
bool returnValue = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readHeaderFromFile :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
returnValue = false;
}
else
{
fileSize = getFileSize(hFile);
if (fileSize > 0)
{
if (fileSize > bufferSize)
{
dwSize = bufferSize;
}
else
{
dwSize = (DWORD)(fileSize - 1);
}
returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer);
}
CloseHandle(hFile);
}
return returnValue;
}
LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ);
}
LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS);
}
LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap)
{
HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
return NULL;
}
HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
CloseHandle(hFile);
if( hMappedFile == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL");
#endif
return NULL;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS);
#endif
return NULL;
}
LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0);
if( addrMappedDll == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL");
#endif
CloseHandle(hMappedFile);
return NULL;
}
CloseHandle(hMappedFile);
return addrMappedDll;
}
DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName)
{
DWORD dwPID = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(PROCESSENTRY32W);
if( !Process32FirstW( hProcessSnap, &pe32 ) )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getProcessByName :: Error getting first Process");
#endif
CloseHandle( hProcessSnap );
return 0;
}
do
{
if(!_wcsicmp(pe32.szExeFile, processName))
{
dwPID = pe32.th32ProcessID;
break;
}
} while(Process32NextW(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return dwPID;
}
bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector &moduleList)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
ModuleInfo module;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return false;
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap );
return false;
}
// Now walk the module list of the process,
// and display information about each module
//the first is always the .exe
if (!Module32Next(hModuleSnap, &me32))
{
CloseHandle( hModuleSnap );
return false;
}
moduleList.reserve(20);
do
{
//printf(L"\n MODULE NAME: %s", me32.szModule);
module.modBaseAddr = (DWORD_PTR)me32.modBaseAddr;
module.modBaseSize = me32.modBaseSize;
module.isAlreadyParsed = false;
module.parsing = false;
- wcscpy_s(module.fullPath, MAX_PATH, me32.szExePath);
+ wcscpy_s(module.fullPath, me32.szExePath);
moduleList.push_back(module);
} while(Module32Next(hModuleSnap, &me32));
CloseHandle( hModuleSnap );
return true;
}
bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize)
{
MEMORY_BASIC_INFORMATION memBasic;
if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", GetLastError());
#endif
return false;
}
else
{
*memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress;
*memoryRegionSize = memBasic.RegionSize;
return true;
}
}
bool ProcessAccessHelp::getSizeOfImageCurrentProcess()
{
DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
if (newSizeOfImage != 0)
{
ProcessAccessHelp::targetSizeOfImage = newSizeOfImage;
return true;
}
else
{
return false;
}
}
SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase)
{
SIZE_T sizeOfImage = 0;
MEMORY_BASIC_INFORMATION lpBuffer = {0};
SIZE_T dwLength = sizeof(MEMORY_BASIC_INFORMATION);
do
{
moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize);
sizeOfImage += lpBuffer.RegionSize;
//printf("Query 0x"PRINTF_DWORD_PTR_FULL" size 0x%08X\n",moduleBase,sizeOfImage);
if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, dwLength))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", GetLastError());
#endif
lpBuffer.Type = 0;
sizeOfImage = 0;
}
/*else
{
printf("\nAllocationBase %X\n",lpBuffer.AllocationBase);
printf("AllocationProtect %X\n",lpBuffer.AllocationProtect);
printf("BaseAddress %X\n",lpBuffer.BaseAddress);
printf("Protect %X\n",lpBuffer.Protect);
printf("RegionSize %X\n",lpBuffer.RegionSize);
printf("State %X\n",lpBuffer.State);
printf("Type %X\n",lpBuffer.Type);
}*/
} while (lpBuffer.Type == MEM_IMAGE);
//printf("Real sizeOfImage %X\n",sizeOfImage);
return sizeOfImage;
}
DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath)
{
PIMAGE_NT_HEADERS pNtHeader = 0;
PIMAGE_DOS_HEADER pDosHeader = 0;
readHeaderFromCurrentFile(filePath);
pDosHeader = (PIMAGE_DOS_HEADER)fileHeaderFromDisk;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return 0;
}
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileHeaderFromDisk + (DWORD_PTR)(pDosHeader->e_lfanew));
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
return 0;
}
return pNtHeader->OptionalHeader.AddressOfEntryPoint;
}
bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath)
{
size_t fileNameLength = wcslen(filePath) + 5; //.bak + null
BOOL retValue = 0;
WCHAR * backupFile = new WCHAR[fileNameLength];
wcscpy_s(backupFile, fileNameLength, filePath);
wcscat_s(backupFile, fileNameLength, L".bak");
retValue = CopyFile(filePath, backupFile, FALSE);
if (!retValue)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError());
#endif
}
delete [] backupFile;
return retValue != 0;
}
diff --git a/Scylla/ProcessLister.cpp b/Scylla/ProcessLister.cpp
index c48274f..b078316 100644
--- a/Scylla/ProcessLister.cpp
+++ b/Scylla/ProcessLister.cpp
@@ -1,364 +1,364 @@
#include "ProcessLister.h"
#include "SystemInformation.h"
#include "Logger.h"
#include "ProcessAccessHelp.h"
//#define DEBUG_COMMENTS
def_IsWow64Process ProcessLister::_IsWow64Process = 0;
std::vector& ProcessLister::getProcessList()
{
return processList;
}
bool ProcessLister::isWindows64()
{
#ifdef _WIN64
//compiled 64bit application
return true;
#else
//32bit exe, check wow64
BOOL bIsWow64 = FALSE;
//not available in all windows operating systems
//Minimum supported client: Windows Vista, Windows XP with SP2
//Minimum supported server: Windows Server 2008, Windows Server 2003 with SP1
if (_IsWow64Process)
{
_IsWow64Process(GetCurrentProcess(), &bIsWow64);
if (bIsWow64 == TRUE)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
#endif
}
void ProcessLister::initDeviceNameList()
{
TCHAR shortName[3] = {0};
TCHAR longName[MAX_PATH] = {0};
HardDisk hardDisk;
shortName[1] = L':';
for ( WCHAR shortD = L'a'; shortD < L'z'; shortD++ )
{
shortName[0] = shortD;
if (QueryDosDeviceW( shortName, longName, MAX_PATH ) > 0)
{
hardDisk.shortName[0] = towupper(shortD);
hardDisk.shortName[1] = L':';
hardDisk.shortName[2] = 0;
hardDisk.longNameLength = wcslen(longName);
- wcscpy_s(hardDisk.longName, MAX_PATH, longName);
+ wcscpy_s(hardDisk.longName, longName);
deviceNameList.push_back(hardDisk);
}
}
}
//only needed in windows xp
DWORD ProcessLister::setDebugPrivileges()
{
DWORD err = 0;
HANDLE hToken = 0;
TOKEN_PRIVILEGES Debug_Privileges = {0};
if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Debug_Privileges.Privileges[0].Luid))
{
return GetLastError();
}
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
err = GetLastError();
if(hToken) CloseHandle(hToken);
return err;
}
Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
Debug_Privileges.PrivilegeCount = 1;
AdjustTokenPrivileges(hToken, false, &Debug_Privileges, 0, NULL, NULL);
CloseHandle(hToken);
return GetLastError();
}
/************************************************************************/
/* Check if a process is 32 or 64bit */
/************************************************************************/
ProcessType ProcessLister::checkIsProcess64(DWORD dwPID)
{
HANDLE hProcess;
BOOL bIsWow64 = FALSE;
if (dwPID == 0)
{
//unknown
return PROCESS_UNKNOWN;
}
//hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, NULL, dwPID);
hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, dwPID);
if(!hProcess)
{
//missing rights
return PROCESS_MISSING_RIGHTS;
}
if (!isWindows64())
{
//32bit win can only run 32bit process
CloseHandle(hProcess);
return PROCESS_32;
}
_IsWow64Process(hProcess, &bIsWow64);
CloseHandle(hProcess);
if (bIsWow64 == FALSE)
{
//process not running under wow
return PROCESS_64;
}
else
{
//process running under wow -> 32bit
return PROCESS_32;
}
}
bool ProcessLister::getAbsoluteFilePath(Process * process)
{
WCHAR processPath[MAX_PATH];
HANDLE hProcess;
//hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, NULL, process->PID);
hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION, process->PID);
if(!hProcess)
{
//missing rights
return false;
}
if (GetProcessImageFileName(hProcess, processPath, _countof(processPath)) > 0)
{
CloseHandle(hProcess);
if (!resolveDeviceLongNameToShort(processPath, process->fullPath))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s", processPath);
#endif
}
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getAbsoluteFilePath :: GetProcessImageFileName failed %u", GetLastError());
#endif
CloseHandle(hProcess);
return false;
}
}
std::vector& ProcessLister::getProcessListSnapshot()
{
HANDLE hProcessSnap;
ProcessType processType;
PROCESSENTRY32 pe32;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32 = {0};
Process process;
processList.reserve(34);
if (!processList.empty())
{
processList.clear();
}
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
return processList;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if(!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap);
return processList;
}
do
{
//filter process list
if (pe32.th32ProcessID > 4)
{
processType = checkIsProcess64(pe32.th32ProcessID);
if (processType != PROCESS_MISSING_RIGHTS)
{
#ifdef _WIN64
if (processType == PROCESS_64)
#else
if (processType == PROCESS_32)
#endif
{
process.PID = pe32.th32ProcessID;
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process.PID);
if(hModuleSnap != INVALID_HANDLE_VALUE)
{
me32.dwSize = sizeof(MODULEENTRY32);
Module32First(hModuleSnap, &me32);
process.imageBase = (DWORD_PTR)me32.hModule;
process.imageSize = me32.modBaseSize;
CloseHandle(hModuleSnap);
}
- wcscpy_s(process.filename, MAX_PATH, pe32.szExeFile);
+ wcscpy_s(process.filename, pe32.szExeFile);
getAbsoluteFilePath(&process);
processList.push_back(process);
}
}
}
} while(Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
//get module informations
//getAllModuleInformation();
return processList;
}
void ProcessLister::getAllModuleInformation()
{
/*for (std::size_t i = 0; i < processList.size(); i++)
{
getModuleInformationByProcess(&processList[i]);
}*/
}
void ProcessLister::getModuleInformationByProcess(Process *process)
{
/* MODULEENTRY32 me32 = {0};
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
char temp[111];
if (process->PID == 0)
{
MessageBox(0, "PID == NULL","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING);
return;
}
#ifdef _WIN64
if (!process->is64BitProcess)
{
//MessageBox(hWndDlg, "I'm a x64 process and you're trying to access a 32-bit process!","displayModuleList", MB_OK);
return;
}
#else
if (process->is64BitProcess)
{
//MessageBox(hWndDlg, "I'm a 32-bit process and you're trying to access a x64 process!","displayModuleList", MB_OK);
return;
}
#endif
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process->PID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
- sprintf_s(temp,sizeof(temp),"GetLastError %d",GetLastError());
+ sprintf_s(temp, "GetLastError %d",GetLastError());
MessageBox(0, temp,"ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING);
return;
}
me32.dwSize = sizeof(MODULEENTRY32);
if(!Module32First(hModuleSnap, &me32))
{
MessageBox(0, "Module32First error","ProcessLister::getModuleInformationByProcess", MB_OK|MB_ICONWARNING);
CloseHandle(hModuleSnap);
return;
}
do {
ModuleInfo moduleInfo;
if (!_strnicmp(me32.szExePath,"\\Systemroot",11))
{
char * path = (char *)malloc(MAX_PATH);
- sprintf_s(path,MAX_PATH,"%s\\%s",getenv("SystemRoot"),(me32.szExePath + 12));
+ sprintf_s(path"%s\\%s",getenv("SystemRoot"),(me32.szExePath + 12));
strcpy_s(moduleInfo.fullPath,MAX_PATH, path);
free(path);
}
else if(!_strnicmp(me32.szExePath,"\\??\\",4))
{
strcpy_s(moduleInfo.fullPath,MAX_PATH, (me32.szExePath + 4));
}
else
{
strcpy_s(moduleInfo.fullPath,MAX_PATH,me32.szExePath);
}
moduleInfo.hModule = (DWORD_PTR)me32.hModule;
moduleInfo.modBaseSize = me32.modBaseSize;
moduleInfo.modBaseAddr = (DWORD_PTR)me32.modBaseAddr;
process->moduleList[moduleInfo.hModule] = moduleInfo;
} while(Module32Next(hModuleSnap, &me32));
CloseHandle(hModuleSnap);*/
}
bool ProcessLister::resolveDeviceLongNameToShort( WCHAR * sourcePath, WCHAR * targetPath )
{
for (unsigned int i = 0; i < deviceNameList.size(); i++)
{
if (!_wcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength))
{
wcscpy_s(targetPath, MAX_PATH,deviceNameList[i].shortName);
wcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength);
return true;
}
}
return false;
}
diff --git a/Scylla/TreeImportExport.cpp b/Scylla/TreeImportExport.cpp
index 43eb64c..e17c027 100644
--- a/Scylla/TreeImportExport.cpp
+++ b/Scylla/TreeImportExport.cpp
@@ -1,337 +1,337 @@
#include "TreeImportExport.h"
#include "Architecture.h"
#include "Scylla.h"
#include "StringConversion.h"
bool TreeImportExport::exportTreeList(const WCHAR * targetXmlFile, std::map & moduleList, const Process * process, const DWORD_PTR addressOEP, const DWORD_PTR addressIAT, const DWORD sizeIAT)
{
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "");
doc.LinkEndChild(decl);
TiXmlElement * rootElement = new TiXmlElement("target");
setTargetInformation(rootElement, process,addressOEP,addressIAT,sizeIAT);
addModuleListToRootElement(rootElement, moduleList);
doc.LinkEndChild(rootElement);
return saveXmlToFile(doc,targetXmlFile);
}
bool TreeImportExport::importTreeList(const WCHAR * targetXmlFile, std::map & moduleList, DWORD_PTR * addressOEP, DWORD_PTR * addressIAT, DWORD * sizeIAT)
{
TiXmlElement * targetElement;
TiXmlDocument doc;
char * buffer = readXmlFile(targetXmlFile);
int count = 0;
moduleList.clear();
if (buffer)
{
doc.Parse(buffer);
if (doc.Error())
{
Scylla::windowLog.log(L"Load Tree :: Error parsing xml %S: %S\r\n", doc.Value(), doc.ErrorDesc());
delete [] buffer;
return false;
}
targetElement = doc.FirstChildElement();
*addressOEP = ConvertStringToDwordPtr(targetElement->Attribute("oep_va"));
*addressIAT = ConvertStringToDwordPtr(targetElement->Attribute("iat_va"));
*sizeIAT = (DWORD)ConvertStringToDwordPtr(targetElement->Attribute("iat_size"));
//test = targetElement->Attribute("filename");
parseAllElementModules(targetElement, moduleList);
delete [] buffer;
}
return true;
}
void TreeImportExport::setTargetInformation(TiXmlElement * rootElement, const Process * process, const DWORD_PTR addressOEP, const DWORD_PTR addressIAT, const DWORD sizeIAT)
{
StringConversion::ToASCII(process->filename, xmlStringBuffer, _countof(xmlStringBuffer));
rootElement->SetAttribute("filename", xmlStringBuffer);
ConvertDwordPtrToString(addressOEP);
rootElement->SetAttribute("oep_va", xmlStringBuffer);
ConvertDwordPtrToString(addressIAT);
rootElement->SetAttribute("iat_va", xmlStringBuffer);
ConvertDwordPtrToString(sizeIAT);
rootElement->SetAttribute("iat_size", xmlStringBuffer);
}
char * TreeImportExport::readXmlFile(const WCHAR * xmlFilePath)
{
FILE * pFile = 0;
long lSize = 0;
char * buffer = 0;
- if (_wfopen_s(&pFile,xmlFilePath,L"r") == NULL)
+ if (_wfopen_s(&pFile, xmlFilePath, L"r") == NULL)
{
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
if (lSize > 2)
{
buffer = new char[lSize + sizeof(char)];
ZeroMemory(buffer, lSize + sizeof(char));
fread(buffer, sizeof(char), lSize, pFile);
if (!feof(pFile) || ferror(pFile))
{
delete [] buffer;
buffer = 0;
}
}
fclose (pFile);
return buffer;
}
else
{
return 0;
}
}
bool TreeImportExport::saveXmlToFile(TiXmlDocument doc, const WCHAR * xmlFilePath)
{
FILE * pFile = 0;
- if (_wfopen_s(&pFile,xmlFilePath,L"w") == NULL)
+ if (_wfopen_s(&pFile, xmlFilePath, L"w") == NULL)
{
doc.Print(pFile);
fclose (pFile);
return true;
}
else
{
return false;
}
}
void TreeImportExport::addModuleListToRootElement( TiXmlElement * rootElement, std::map & moduleList )
{
std::map::iterator mapIt;
std::map::iterator mapIt2;
ImportModuleThunk * importModuleThunk = 0;
ImportThunk * importThunk = 0;
TiXmlElement * moduleElement;
TiXmlElement * importElement;
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
importModuleThunk = &((*mapIt).second);
moduleElement = getModuleXmlElement(importModuleThunk);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
importThunk = &((*mapIt2).second);
importElement = getImportXmlElement(importThunk);
moduleElement->LinkEndChild(importElement);
}
rootElement->LinkEndChild(moduleElement);
}
}
TiXmlElement * TreeImportExport::getModuleXmlElement(const ImportModuleThunk * importModuleThunk)
{
TiXmlElement * moduleElement = new TiXmlElement("module");
StringConversion::ToASCII(importModuleThunk->moduleName, xmlStringBuffer, _countof(xmlStringBuffer));
moduleElement->SetAttribute("filename", xmlStringBuffer);
ConvertDwordPtrToString(importModuleThunk->getFirstThunk());
moduleElement->SetAttribute("first_thunk_rva",xmlStringBuffer);
return moduleElement;
}
TiXmlElement * TreeImportExport::getImportXmlElement(const ImportThunk * importThunk)
{
TiXmlElement * importElement = 0;
if (importThunk->valid)
{
importElement = new TiXmlElement("import_valid");
if(importThunk->name[0] != '\0')
{
importElement->SetAttribute("name",importThunk->name);
}
ConvertWordToString(importThunk->ordinal);
importElement->SetAttribute("ordinal",xmlStringBuffer);
ConvertWordToString(importThunk->hint);
importElement->SetAttribute("hint",xmlStringBuffer);
ConvertBoolToString(importThunk->suspect);
importElement->SetAttribute("suspect", xmlStringBuffer);
}
else
{
importElement = new TiXmlElement("import_invalid");
}
ConvertDwordPtrToString(importThunk->rva);
importElement->SetAttribute("iat_rva", xmlStringBuffer);
ConvertDwordPtrToString(importThunk->apiAddressVA);
importElement->SetAttribute("address_va",xmlStringBuffer);
return importElement;
}
void TreeImportExport::ConvertBoolToString(const bool boolValue)
{
if (boolValue)
{
- strcpy_s(xmlStringBuffer,_countof(xmlStringBuffer), "1");
+ strcpy_s(xmlStringBuffer, "1");
}
else
{
- strcpy_s(xmlStringBuffer,_countof(xmlStringBuffer), "0");
+ strcpy_s(xmlStringBuffer, "0");
}
}
bool TreeImportExport::ConvertStringToBool(const char * strValue)
{
if (strValue)
{
if (strValue[0] == '1')
{
return true;
}
}
return false;
}
void TreeImportExport::ConvertDwordPtrToString(const DWORD_PTR dwValue)
{
- sprintf_s(xmlStringBuffer, _countof(xmlStringBuffer), PRINTF_DWORD_PTR_FULL_S, dwValue);
+ sprintf_s(xmlStringBuffer, PRINTF_DWORD_PTR_FULL_S, dwValue);
}
DWORD_PTR TreeImportExport::ConvertStringToDwordPtr(const char * strValue)
{
DWORD_PTR result = 0;
if (strValue)
{
#ifdef _WIN64
result = _strtoi64(strValue, NULL, 16);
#else
result = strtoul(strValue, NULL, 16);
#endif
}
return result;
}
void TreeImportExport::ConvertWordToString(const WORD dwValue)
{
- sprintf_s(xmlStringBuffer, _countof(xmlStringBuffer), "%04X", dwValue);
+ sprintf_s(xmlStringBuffer, "%04X", dwValue);
}
WORD TreeImportExport::ConvertStringToWord(const char * strValue)
{
WORD result = 0;
if (strValue)
{
result = (WORD)strtoul(strValue, NULL, 16);
}
return result;
}
void TreeImportExport::parseAllElementModules( TiXmlElement * targetElement, std::map & moduleList )
{
TiXmlElement * moduleElement = 0;
ImportModuleThunk importModuleThunk;
const char * filename = 0;
for(moduleElement = targetElement->FirstChildElement(); moduleElement; moduleElement = moduleElement->NextSiblingElement())
{
filename = moduleElement->Attribute("filename");
if (filename)
{
StringConversion::ToUTF16(filename, importModuleThunk.moduleName, _countof(importModuleThunk.moduleName));
importModuleThunk.firstThunk = ConvertStringToDwordPtr(moduleElement->Attribute("first_thunk_rva"));
importModuleThunk.thunkList.clear();
parseAllElementImports(moduleElement, &importModuleThunk);
moduleList.insert(std::pair(importModuleThunk.firstThunk, importModuleThunk));
}
}
}
void TreeImportExport::parseAllElementImports( TiXmlElement * moduleElement, ImportModuleThunk * importModuleThunk )
{
TiXmlElement * importElement = 0;
ImportThunk importThunk;
const char * temp = 0;
for(importElement = moduleElement->FirstChildElement(); importElement; importElement = importElement->NextSiblingElement())
{
temp = importElement->Value();
if (!strcmp(temp, "import_valid"))
{
temp = importElement->Attribute("name");
if (temp)
{
- strcpy_s(importThunk.name, _countof(importThunk.name),temp);
+ strcpy_s(importThunk.name, temp);
}
else
{
importThunk.name[0] = 0;
}
- wcscpy_s(importThunk.moduleName,_countof(importThunk.moduleName), importModuleThunk->moduleName);
+ wcscpy_s(importThunk.moduleName, importModuleThunk->moduleName);
importThunk.suspect = ConvertStringToBool(importElement->Attribute("suspect"));
importThunk.ordinal = ConvertStringToWord(importElement->Attribute("ordinal"));
importThunk.hint = ConvertStringToWord(importElement->Attribute("hint"));
importThunk.valid = true;
}
else
{
importThunk.valid = false;
importThunk.suspect = true;
}
importThunk.apiAddressVA = ConvertStringToDwordPtr(importElement->Attribute("address_va"));
importThunk.rva = ConvertStringToDwordPtr(importElement->Attribute("iat_rva"));
if (importThunk.rva != 0)
{
importModuleThunk->thunkList.insert(std::pair(importThunk.rva, importThunk));
}
}
}