├── .gitignore ├── COMPILING ├── LICENSE ├── Plugins ├── ImpRec_Plugins │ ├── Imprec_Wrapper_DLL.dll │ └── PECompact 2.7.x.dll ├── Include_Headers │ └── ScyllaPlugin.h ├── PECompact.dll ├── PESpin_x64_v1.dll └── Sources │ ├── Imprec_Wrapper_DLL.cpp │ ├── PECompact.cpp │ ├── PESpin_x64_v1.cpp │ └── scyllatoimprectree.rar ├── README.md ├── Scylla.sln ├── Scylla ├── AboutGui.cpp ├── AboutGui.h ├── ApiReader.cpp ├── ApiReader.h ├── Architecture.cpp ├── Architecture.h ├── Configuration.cpp ├── Configuration.h ├── ConfigurationHolder.cpp ├── ConfigurationHolder.h ├── DeviceNameResolver.cpp ├── DeviceNameResolver.h ├── DisassemblerGui.cpp ├── DisassemblerGui.h ├── DllInjection.cpp ├── DllInjection.h ├── DllInjectionPlugin.cpp ├── DllInjectionPlugin.h ├── DonateGui.cpp ├── DonateGui.h ├── DumpMemoryGui.cpp ├── DumpMemoryGui.h ├── DumpSectionGui.cpp ├── DumpSectionGui.h ├── FunctionExport.cpp ├── FunctionExport.h ├── IATReferenceScan.cpp ├── IATReferenceScan.h ├── IATSearch.cpp ├── IATSearch.h ├── ImportRebuilder.cpp ├── ImportRebuilder.h ├── ImportsHandling.cpp ├── ImportsHandling.h ├── Logger.cpp ├── Logger.h ├── MainGui.cpp ├── MainGui.h ├── MainGui.rc ├── NativeWinApi.cpp ├── NativeWinApi.h ├── OptionsGui.cpp ├── OptionsGui.h ├── PeParser.cpp ├── PeParser.h ├── PeRebuild.cpp ├── PeRebuild.h ├── PickApiGui.cpp ├── PickApiGui.h ├── PickDllGui.cpp ├── PickDllGui.h ├── PluginLoader.cpp ├── PluginLoader.h ├── ProcessAccessHelp.cpp ├── ProcessAccessHelp.h ├── ProcessLister.cpp ├── ProcessLister.h ├── Scylla.cpp ├── Scylla.h ├── Scylla.vcxproj ├── Scylla.vcxproj.filters ├── StringConversion.cpp ├── StringConversion.h ├── SystemInformation.cpp ├── SystemInformation.h ├── Thunks.h ├── TreeImportExport.cpp ├── TreeImportExport.h ├── check.ico ├── error.ico ├── hexedit.h ├── main.cpp ├── multitree.h ├── resource.h ├── scylla.ico ├── scylla_export_functions.def └── warning.ico ├── ScyllaDllTest ├── ScyllaDllTest.sln ├── ScyllaDllTest │ ├── ScyllaDllTest.vcxproj │ └── Source.cpp └── ScyllaTestExe │ ├── ScyllaTestExe.vcxproj │ └── main.cpp ├── Scylla_Exports.txt ├── WTL └── README ├── diStorm ├── README ├── diStorm.vcxproj ├── diStorm.vcxproj.filters ├── diStorm.vcxproj.user ├── include │ ├── distorm.h │ └── mnemonics.h └── src │ ├── config.h │ ├── decoder.c │ ├── decoder.h │ ├── distorm.c │ ├── instructions.c │ ├── instructions.h │ ├── insts.c │ ├── insts.h │ ├── mnemonics.c │ ├── operands.c │ ├── operands.h │ ├── prefix.c │ ├── prefix.h │ ├── textdefs.c │ ├── textdefs.h │ ├── wstring.c │ ├── wstring.h │ └── x86defs.h ├── scylla_release.bat └── tinyxml ├── README ├── tinyxml.vcxproj ├── tinyxml.vcxproj.filters └── tinyxml.vcxproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | #generic files/directories to ignore 2 | Win32/ 3 | x64/ 4 | ipch/ 5 | *.opensdf 6 | *.sdf 7 | *.aps 8 | *.suo 9 | Scylla.vcxproj.user 10 | 11 | #tinyxml ignore + exceptions 12 | tinyxml/* 13 | !tinyxml/README 14 | !tinyxml/tinyxml.vcxproj* 15 | 16 | #WTL ignore + exceptions 17 | WTL/* 18 | !WTL/README -------------------------------------------------------------------------------- /COMPILING: -------------------------------------------------------------------------------- 1 | To compile Scylla you need to have VS2008 installed. 2 | In addition to that you need source codes for the following libraries: 3 | diStorm 4 | tinyxml 5 | WTL 6 | 7 | See the corresponding README files for installation instructions. -------------------------------------------------------------------------------- /Plugins/ImpRec_Plugins/Imprec_Wrapper_DLL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Plugins/ImpRec_Plugins/Imprec_Wrapper_DLL.dll -------------------------------------------------------------------------------- /Plugins/ImpRec_Plugins/PECompact 2.7.x.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Plugins/ImpRec_Plugins/PECompact 2.7.x.dll -------------------------------------------------------------------------------- /Plugins/Include_Headers/ScyllaPlugin.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | const char FILE_MAPPING_NAME[] = "ScyllaPluginExchange"; 5 | 6 | #define SCYLLA_STATUS_SUCCESS 0 7 | #define SCYLLA_STATUS_UNKNOWN_ERROR 1 8 | #define SCYLLA_STATUS_UNSUPPORTED_PROTECTION 2 9 | #define SCYLLA_STATUS_IMPORT_RESOLVING_FAILED 3 10 | #define SCYLLA_STATUS_MAPPING_FAILED 0xFF 11 | 12 | /* Important note: 13 | * 14 | * If you write a plugin for the x86 (32-Bit) edition: DWORD_PTR address has 32 bit (4 byte) 15 | * If you write a plugin for the x64 (64-Bit) edition: DWORD_PTR address has 64 bit (8 byte) 16 | */ 17 | typedef struct _UNRESOLVED_IMPORT { // Scylla Plugin exchange format 18 | DWORD_PTR ImportTableAddressPointer; //in VA, address in IAT which points to an invalid api address 19 | DWORD_PTR InvalidApiAddress; //in VA, invalid api address that needs to be resolved 20 | } UNRESOLVED_IMPORT, *PUNRESOLVED_IMPORT; 21 | 22 | typedef struct _SCYLLA_EXCHANGE { 23 | BYTE status; //return a status, default 0xFF == SCYLLA_STATUS_MAPPING_FAILED 24 | DWORD_PTR imageBase; //image base 25 | DWORD_PTR imageSize; //size of the image 26 | DWORD_PTR numberOfUnresolvedImports; //number of unresolved imports in this structure 27 | BYTE offsetUnresolvedImportsArray; 28 | } SCYLLA_EXCHANGE, *PSCYLLA_EXCHANGE; 29 | 30 | 31 | 32 | #define DllExport __declspec(dllexport) 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #ifdef UNICODE 39 | DllExport wchar_t * __cdecl ScyllaPluginNameW(); 40 | #else 41 | DllExport char * __cdecl ScyllaPluginNameA(); 42 | #endif 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif -------------------------------------------------------------------------------- /Plugins/PECompact.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Plugins/PECompact.dll -------------------------------------------------------------------------------- /Plugins/PESpin_x64_v1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Plugins/PESpin_x64_v1.dll -------------------------------------------------------------------------------- /Plugins/Sources/PECompact.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "ScyllaPlugin.h" 3 | 4 | //remove c runtime library 5 | //#pragma comment(linker, "/ENTRY:DllMain") 6 | 7 | 8 | const char logFileName[] = "logfile_scylla_plugin.txt"; 9 | BOOL writeToLogFile(const char * text); 10 | 11 | 12 | HANDLE hMapFile = 0; 13 | LPVOID lpViewOfFile = 0; 14 | 15 | BOOL getMappedView(); 16 | void cleanUp(); 17 | 18 | void resolveImports(); 19 | 20 | 21 | #define PLUGIN_NAME "PECompact v2.x" 22 | 23 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved) 24 | { 25 | switch(fdwReason) 26 | { 27 | case DLL_PROCESS_ATTACH: 28 | // Initialize once for each new process. 29 | // Return FALSE to fail DLL load. 30 | 31 | writeToLogFile("DLL attached - Injection successful\r\n"); 32 | if (getMappedView()) //open file mapping 33 | { 34 | writeToLogFile("Open mapping successful\r\n"); 35 | resolveImports(); //resolve imports 36 | cleanUp(); //clean up handles 37 | } 38 | break; 39 | 40 | case DLL_THREAD_ATTACH: 41 | // Do thread-specific initialization. 42 | break; 43 | 44 | case DLL_THREAD_DETACH: 45 | // Do thread-specific cleanup. 46 | break; 47 | 48 | case DLL_PROCESS_DETACH: 49 | // Perform any necessary cleanup. 50 | writeToLogFile("DLL successfully detached\r\n"); 51 | break; 52 | } 53 | return TRUE; // Successful DLL_PROCESS_ATTACH. 54 | } 55 | 56 | BOOL getMappedView() 57 | { 58 | hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, FILE_MAPPING_NAME); //open named file mapping object 59 | 60 | if (hMapFile == 0) 61 | { 62 | writeToLogFile("OpenFileMappingA failed\r\n"); 63 | return FALSE; 64 | } 65 | 66 | lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); //map the view with full access 67 | 68 | if (lpViewOfFile == 0) 69 | { 70 | CloseHandle(hMapFile); //close mapping handle 71 | hMapFile = 0; 72 | writeToLogFile("MapViewOfFile failed\r\n"); 73 | return FALSE; 74 | } 75 | else 76 | { 77 | return TRUE; 78 | } 79 | } 80 | 81 | void cleanUp() 82 | { 83 | if (lpViewOfFile != 0) 84 | { 85 | UnmapViewOfFile(lpViewOfFile); //close map view 86 | } 87 | if (hMapFile != 0) 88 | { 89 | CloseHandle(hMapFile); //close mapping handle 90 | } 91 | } 92 | 93 | 94 | void resolveImports() 95 | { 96 | DWORD_PTR invalidApiAddress = 0; 97 | PSCYLLA_EXCHANGE scyllaExchange = 0; 98 | PUNRESOLVED_IMPORT unresolvedImport = 0; 99 | 100 | scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile; 101 | unresolvedImport = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray); 102 | 103 | scyllaExchange->status = SCYLLA_STATUS_SUCCESS; 104 | 105 | while (unresolvedImport->ImportTableAddressPointer != 0) //last element is a nulled struct 106 | { 107 | //get real WINAPI address 108 | 109 | //overwrite the existing wrong value with the good api address 110 | invalidApiAddress = unresolvedImport->InvalidApiAddress; 111 | 112 | //PECompact example 113 | //01BF01FF B8 45128275 MOV EAX,kernel32.GetModuleHandleA 114 | //01BF0204 - FFE0 JMP EAX 115 | 116 | if (*((BYTE *)invalidApiAddress) == 0xB8) //is it pe compact? 117 | { 118 | invalidApiAddress++; //increase 1 opcode 119 | 120 | //write right value to struct 121 | unresolvedImport->InvalidApiAddress = *((DWORD_PTR *)invalidApiAddress); 122 | } 123 | else 124 | { 125 | writeToLogFile("Unsupported opcode found\r\n"); 126 | scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION; 127 | break; 128 | } 129 | 130 | unresolvedImport++; //next pointer to struct 131 | } 132 | } 133 | 134 | BOOL writeToLogFile(const char * text) 135 | { 136 | DWORD lpNumberOfBytesWritten = 0; 137 | size_t i = 0; 138 | BOOL wfRet = 0; 139 | HANDLE hFile = 0; 140 | char buffer[260]; 141 | 142 | if (!GetModuleFileNameA(0, buffer, sizeof(buffer))) //get full path of exe 143 | { 144 | return FALSE; 145 | } 146 | 147 | for (i = (lstrlenA(buffer) - 1); i >= 0; i--) //remove the exe file name from full path 148 | { 149 | if (buffer[i] == '\\') 150 | { 151 | buffer[i+1] = 0x00; 152 | break; 153 | } 154 | } 155 | 156 | if (lstrcatA(buffer,logFileName) == 0) //append log file name to path 157 | { 158 | return FALSE; 159 | } 160 | 161 | hFile = CreateFileA(buffer, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); //open log file for writing 162 | 163 | if (hFile == INVALID_HANDLE_VALUE) 164 | { 165 | return FALSE; 166 | } 167 | 168 | SetFilePointer(hFile, 0, 0, FILE_END); //set file pointer to the end of file 169 | 170 | if (WriteFile(hFile, text, (DWORD)lstrlenA(text), &lpNumberOfBytesWritten, 0)) //write message to logfile 171 | { 172 | wfRet = TRUE; 173 | } 174 | else 175 | { 176 | wfRet = FALSE; 177 | } 178 | 179 | CloseHandle(hFile); 180 | return wfRet; 181 | } 182 | 183 | 184 | #ifdef UNICODE 185 | DllExport wchar_t * __cdecl ScyllaPluginNameW() 186 | { 187 | return TEXT(PLUGIN_NAME); 188 | } 189 | #else 190 | DllExport char * __cdecl ScyllaPluginNameA() 191 | { 192 | return PLUGIN_NAME; 193 | } 194 | #endif -------------------------------------------------------------------------------- /Plugins/Sources/scyllatoimprectree.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Plugins/Sources/scyllatoimprectree.rar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Scylla - x64/x86 Imports Reconstruction 2 | ======================================= 3 | 4 | ImpREC, CHimpREC, Imports Fixer... this are all great tools to rebuild an import table, 5 | but they all have some major disadvantages, so I decided to create my own tool for this job. 6 | 7 | Scylla's key benefits are: 8 | 9 | - x64 and x86 support 10 | - full unicode support 11 | - written in C/C++ 12 | - plugin support 13 | - works great with Windows 7 14 | 15 | This tool was designed to be used with Windows 7 x64, so it is recommend to use this operating system. 16 | But it may work with XP and Vista, too. 17 | 18 | Source code is licensed under GNU GENERAL PUBLIC LICENSE v3.0 19 | 20 | 21 | Known Bugs 22 | ---------- 23 | 24 | ### Windows 7 x64 25 | 26 | Sometimes the API kernel32.dll GetProcAddress cannot be resolved, because the IAT has an entry from apphelp.dll 27 | Solution? I don't know 28 | 29 | ### Only Windows XP x64: 30 | 31 | Windows XP x64 has some API bugs. 100% correct imports reconstruction is impossible. 32 | If you still want to use XP x64, here are some hints: 33 | 34 | * EncodePointer/DecodePointer exported by kernel32.dll have both the same VA. 35 | Scylla, CHimpREC and other tools cannot know which API is correct. You need to fix this manually. 36 | Your fixed dump will probably run fine on XP but crash on Vista/7. 37 | 38 | ### ImpREC plugin support: 39 | 40 | Some ImpREC Plugins don't work with Windows Vista/7 because they don't "return 1" in the DllMain function. 41 | 42 | 43 | Keyboard Shortcuts 44 | ------------------ 45 | 46 | - CTRL + D: [D]ump 47 | - CTRL + F: [F]ix Dump 48 | - CTRL + R: PE [R]ebuild 49 | - CTRL + O: L[o]ad Tree 50 | - CTRL + S: [S]ave Tree 51 | - CTRL + T: Auto[t]race 52 | - CTRL + G: [G]et Imports 53 | - CTRL + I: [I]AT Autosearch 54 | 55 | 56 | Changelog 57 | --------- 58 | 59 | Version 0.9.8 60 | 61 | - Bugfixes for x64, IAT Search 62 | - diStorm3 update from Jan 3rd 2015 63 | 64 | Version 0.9.7 65 | 66 | - Fixed bug bad allocation https://forum.tuts4you.com/topic/36458-scylla-097b-crash-on-pep-50-unpackme/ 67 | - Fixed bug https://forum.tuts4you.com/topic/35352-scylla-themida-v2180-iat-problem/ 68 | - Fixed bug with api selection https://forum.tuts4you.com/topic/35912-scylla-097-problem-acprotect/ 69 | - Included .NET binary + source, ScyllaToImprecTree to convert the api export to imprec 70 | 71 | Version 0.9.6 72 | 73 | - improved iat search 74 | - fixed bug in api resolve engine 75 | - new option: parse APIs always from disk -> slower, useful against pe header modifications 76 | 77 | Version 0.9.5 78 | 79 | - Fixed virtual device bug caused by QueryDosDeviceW bug 80 | - improved process lister 81 | - improved module lister 82 | - improved dump name 83 | - improved IAT parser 84 | 85 | Version 0.9.4 Final 86 | 87 | - direct import scanner (LEA, MOV, PUSH, CALL, JMP) + fixer with 2 fix methods 88 | - create new iat in section 89 | - fixed various bugs 90 | 91 | Version 0.9.3 92 | 93 | - new dll function: iat search 94 | - new dll function: iat fix auto 95 | 96 | Version 0.9.2 97 | 98 | - Pick DLL -> Set DLL Entrypoint 99 | - Advanced IAT Search Algorithm (Enable/Disable it in Options), thanks to ahmadmansoor 100 | - Fixed bug in Options 101 | - Added donate information, please feel free to donate some BTC to support this project 102 | 103 | Version 0.9.1 104 | 105 | - Fixed virtual device bug 106 | - Fixed 2 minor bugs 107 | 108 | Version 0.9 109 | 110 | - updated to distorm v3.3 111 | - added application exception handler 112 | - fixed bug in dump engine 113 | - improved "suspend process" feature, messagebox on exit 114 | 115 | Version 0.8 116 | 117 | - added OriginalFirstThunk support. Thanks to p0c 118 | - fixed malformed dos header bug 119 | - NtCreateThreadEx added infos from waliedassar, thanks! 120 | 121 | Version 0.7 Beta 122 | 123 | - fixed bug Overlapped Headers 124 | - fixed bug SizeOfOptionalHeader 125 | - added feature: suspend process for dumping, more information 126 | - improved disassembler 127 | - fixed various bugs 128 | 129 | Version 0.6b 130 | 131 | - internal code changes 132 | - added option: fix iat and oep 133 | 134 | Version 0.6a 135 | 136 | - fixed buffer to small bug in dump memory 137 | 138 | Version 0.6 139 | 140 | - added dump memory regions 141 | - added dump pe sections -> you can edit some values in the dialog 142 | - improved dump engine with intelligent dumping 143 | - improved pe rebuild engine -> removed yoda's code 144 | - fixed various bugs 145 | 146 | Version 0.5a: 147 | 148 | - fixed memory leak 149 | - improved IAT search 150 | 151 | Version 0.5: 152 | 153 | - added save/load import tree feature 154 | - multi-select in tree view 155 | - fixed black icons problem in tree view 156 | - added keyboard shortcuts 157 | - dll dump + dll dump fix now working 158 | - added support for scattered IATs 159 | - pre select target path in open file dialogs 160 | - improved import resolving engine with api scoring 161 | - api selection dialog 162 | - minor bug fixes and improvements 163 | 164 | Version 0.4: 165 | 166 | - GUI code improvements 167 | - bug fixes 168 | - imports by ordinal 169 | 170 | Version 0.3a: 171 | 172 | - Improved import resolving 173 | - fixed buffer overflow errors 174 | 175 | Version 0.3: 176 | 177 | - ImpREC plugin support 178 | - minor bug fix 179 | -------------------------------------------------------------------------------- /Scylla.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scylla", "Scylla\Scylla.vcxproj", "{710434C9-FC4B-4F1D-B318-E10ADC78499F}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {187A751B-B47D-4A95-9F24-55D3D7ABB570} = {187A751B-B47D-4A95-9F24-55D3D7ABB570} 7 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1} = {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1} 8 | EndProjectSection 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "diStorm", "diStorm\diStorm.vcxproj", "{A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4814523D-1988-4131-A72B-32C7881F3A32}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml", "tinyxml\tinyxml.vcxproj", "{187A751B-B47D-4A95-9F24-55D3D7ABB570}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Win32 = Debug|Win32 19 | Debug|x64 = Debug|x64 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|Win32.Build.0 = Debug|Win32 26 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|x64.ActiveCfg = Debug|x64 27 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Debug|x64.Build.0 = Debug|x64 28 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|Win32.ActiveCfg = Release|Win32 29 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|Win32.Build.0 = Release|Win32 30 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|x64.ActiveCfg = Release|x64 31 | {710434C9-FC4B-4F1D-B318-E10ADC78499F}.Release|x64.Build.0 = Release|x64 32 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Debug|Win32.Build.0 = Debug|Win32 34 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Debug|x64.ActiveCfg = Debug|x64 35 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Debug|x64.Build.0 = Debug|x64 36 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Release|Win32.ActiveCfg = Release|Win32 37 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Release|Win32.Build.0 = Release|Win32 38 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Release|x64.ActiveCfg = Release|x64 39 | {A4B94DE4-BE0E-4E7D-95E7-7B84E6F117A1}.Release|x64.Build.0 = Release|x64 40 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Debug|Win32.Build.0 = Debug|Win32 42 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Debug|x64.ActiveCfg = Debug|x64 43 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Debug|x64.Build.0 = Debug|x64 44 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Release|Win32.ActiveCfg = Release|Win32 45 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Release|Win32.Build.0 = Release|Win32 46 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Release|x64.ActiveCfg = Release|x64 47 | {187A751B-B47D-4A95-9F24-55D3D7ABB570}.Release|x64.Build.0 = Release|x64 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /Scylla/AboutGui.cpp: -------------------------------------------------------------------------------- 1 | #include "AboutGui.h" 2 | 3 | #include "Scylla.h" 4 | #include "Architecture.h" 5 | 6 | const WCHAR AboutGui::TEXT_VISIT[] = L"Visit German Reversing Newbies and Seek n Destroy"; 7 | const WCHAR AboutGui::TEXT_DEVELOPED[] = L"Developed with Microsoft Visual Studio, written in pure C/C++"; 8 | const WCHAR AboutGui::TEXT_CREDIT_DISTORM[] = L"This tool uses the diStorm disassembler library v3"; 9 | const WCHAR AboutGui::TEXT_CREDIT_YODA[] = L"Thanks yoda for your PE Rebuilder engine"; 10 | const WCHAR AboutGui::TEXT_CREDIT_SILK[] = L"The small icons are taken from the Silk icon package"; 11 | const WCHAR AboutGui::TEXT_CREDIT_WTL[] = L"Windows Template Library v8 is used for the GUI"; 12 | const WCHAR AboutGui::TEXT_GREETINGS[] = L"Greetz: metr0, G36KV and all from the gRn Team"; 13 | const WCHAR AboutGui::TEXT_LICENSE[] = L"Scylla is licensed under the GNU General Public License v3"; 14 | const WCHAR AboutGui::TEXT_TINYXML[] = L"XML support is provided by TinyXML"; 15 | 16 | const WCHAR AboutGui::URL_VISIT1[] = L"http://www.c0rk.org/portal/a/"; 17 | const WCHAR AboutGui::URL_VISIT2[] = L"http://forum.tuts4you.com"; 18 | const WCHAR AboutGui::URL_DISTORM[] = L"http://code.google.com/p/distorm/"; 19 | const WCHAR AboutGui::URL_WTL[] = L"http://wtl.sourceforge.net"; 20 | const WCHAR AboutGui::URL_SILK[] = L"http://www.famfamfam.com"; 21 | const WCHAR AboutGui::URL_LICENSE[] = L"http://www.gnu.org/licenses/gpl-3.0.html"; 22 | const WCHAR AboutGui::URL_TINYXML[] = L"http://sourceforge.net/projects/tinyxml/"; 23 | 24 | BOOL AboutGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) 25 | { 26 | DoDataExchange(); // attach controls 27 | 28 | // Create a bold font for the title 29 | LOGFONT lf; 30 | CFontHandle font = StaticTitle.GetFont(); 31 | font.GetLogFont(&lf); 32 | lf.lfWeight = FW_BOLD; 33 | FontBold.CreateFontIndirect(&lf); 34 | 35 | StaticTitle.SetFont(FontBold, FALSE); 36 | 37 | StaticTitle.SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION); 38 | StaticDeveloped.SetWindowText(TEXT_DEVELOPED); 39 | StaticGreetings.SetWindowText(TEXT_GREETINGS); 40 | StaticYoda.SetWindowText(TEXT_CREDIT_YODA); 41 | 42 | setupLinks(); 43 | 44 | CenterWindow(); 45 | 46 | // Set focus to the OK button 47 | GotoDlgCtrl(GetDlgItem(IDOK)); 48 | return FALSE; 49 | } 50 | 51 | void AboutGui::OnClose() 52 | { 53 | TooltipDistorm.DestroyWindow(); 54 | TooltipWTL.DestroyWindow(); 55 | TooltipSilk.DestroyWindow(); 56 | TooltipLicense.DestroyWindow(); 57 | FontBold.DeleteObject(); 58 | EndDialog(0); 59 | } 60 | 61 | LRESULT AboutGui::OnLink(NMHDR* pnmh) 62 | { 63 | const NMLINK* link = (NMLINK*)pnmh; 64 | ShellExecute(NULL, L"open", link->item.szUrl, NULL, NULL, SW_SHOW); 65 | return 0; 66 | } 67 | 68 | void AboutGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) 69 | { 70 | SendMessage(WM_CLOSE); 71 | } 72 | 73 | void AboutGui::setupLinks() 74 | { 75 | // Set link text (must be set before assigning URLs) 76 | LinkVisit.SetWindowText(TEXT_VISIT); 77 | LinkDistorm.SetWindowText(TEXT_CREDIT_DISTORM); 78 | LinkWTL.SetWindowText(TEXT_CREDIT_WTL); 79 | LinkSilk.SetWindowText(TEXT_CREDIT_SILK); 80 | LinkTinyxml.SetWindowText(TEXT_TINYXML); 81 | LinkLicense.SetWindowText(TEXT_LICENSE); 82 | 83 | // Assign URLs to anchors in the link text 84 | setLinkURL(LinkVisit, URL_VISIT1, 0); 85 | setLinkURL(LinkVisit, URL_VISIT2, 1); 86 | setLinkURL(LinkDistorm, URL_DISTORM); 87 | setLinkURL(LinkWTL, URL_WTL); 88 | setLinkURL(LinkSilk, URL_SILK); 89 | setLinkURL(LinkTinyxml, URL_TINYXML); 90 | setLinkURL(LinkLicense, URL_LICENSE); 91 | 92 | // Create tooltips for the links 93 | TooltipDistorm.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); 94 | TooltipWTL.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); 95 | TooltipSilk.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); 96 | TooltipTinyxml.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); 97 | TooltipLicense.Create(m_hWnd, NULL, NULL, TTS_NOPREFIX, WS_EX_TOPMOST); 98 | 99 | // Assign control and text to the tooltips 100 | setupTooltip(TooltipDistorm, LinkDistorm, URL_DISTORM); 101 | setupTooltip(TooltipWTL, LinkWTL, URL_WTL); 102 | setupTooltip(TooltipSilk, LinkSilk, URL_SILK); 103 | setupTooltip(TooltipTinyxml, LinkTinyxml, URL_TINYXML); 104 | setupTooltip(TooltipLicense, LinkLicense, URL_LICENSE); 105 | } 106 | 107 | void AboutGui::setLinkURL(CLinkCtrl& link, const WCHAR* url, int index) 108 | { 109 | LITEM item; 110 | item.mask = LIF_ITEMINDEX | LIF_URL; 111 | item.iLink = index; 112 | 113 | wcscpy_s(item.szUrl, url); 114 | link.SetItem(&item); 115 | } 116 | 117 | void AboutGui::setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text) 118 | { 119 | CToolInfo ti(TTF_SUBCLASS, window); 120 | 121 | window.GetClientRect(&ti.rect); 122 | ti.lpszText = const_cast(text); 123 | tooltip.AddTool(ti); 124 | } 125 | -------------------------------------------------------------------------------- /Scylla/AboutGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL enhanced msg map macros 11 | #include // WTL controls 12 | #include // WTL dialog data exchange 13 | 14 | class AboutGui : public CDialogImpl, public CWinDataExchange 15 | { 16 | public: 17 | enum { IDD = IDD_DLG_ABOUT }; 18 | 19 | BEGIN_DDX_MAP(AboutGui) 20 | DDX_CONTROL_HANDLE(IDC_STATIC_ABOUT_TITLE, StaticTitle) 21 | DDX_CONTROL_HANDLE(IDC_STATIC_DEVELOPED, StaticDeveloped) 22 | DDX_CONTROL_HANDLE(IDC_STATIC_GREETINGS, StaticGreetings) 23 | DDX_CONTROL_HANDLE(IDC_STATIC_YODA, StaticYoda) 24 | DDX_CONTROL_HANDLE(IDC_SYSLINK_VISIT, LinkVisit) 25 | DDX_CONTROL_HANDLE(IDC_SYSLINK_DISTORM, LinkDistorm) 26 | DDX_CONTROL_HANDLE(IDC_SYSLINK_WTL, LinkWTL) 27 | DDX_CONTROL_HANDLE(IDC_SYSLINK_SILK, LinkSilk) 28 | DDX_CONTROL_HANDLE(IDC_SYSLINK_TINYXML, LinkTinyxml) 29 | DDX_CONTROL_HANDLE(IDC_SYSLINK_LICENSE, LinkLicense) 30 | END_DDX_MAP() 31 | 32 | BEGIN_MSG_MAP(AboutGui) 33 | MSG_WM_INITDIALOG(OnInitDialog) 34 | MSG_WM_CLOSE(OnClose) 35 | 36 | NOTIFY_HANDLER_EX(IDC_SYSLINK_DISTORM, NM_CLICK, OnLink) 37 | NOTIFY_HANDLER_EX(IDC_SYSLINK_DISTORM, NM_RETURN, OnLink) 38 | NOTIFY_HANDLER_EX(IDC_SYSLINK_WTL, NM_CLICK, OnLink) 39 | NOTIFY_HANDLER_EX(IDC_SYSLINK_WTL, NM_RETURN, OnLink) 40 | NOTIFY_HANDLER_EX(IDC_SYSLINK_SILK, NM_CLICK, OnLink) 41 | NOTIFY_HANDLER_EX(IDC_SYSLINK_SILK, NM_RETURN, OnLink) 42 | NOTIFY_HANDLER_EX(IDC_SYSLINK_TINYXML, NM_CLICK, OnLink) 43 | NOTIFY_HANDLER_EX(IDC_SYSLINK_TINYXML, NM_RETURN, OnLink) 44 | NOTIFY_HANDLER_EX(IDC_SYSLINK_VISIT, NM_CLICK, OnLink) 45 | NOTIFY_HANDLER_EX(IDC_SYSLINK_VISIT, NM_RETURN, OnLink) 46 | NOTIFY_HANDLER_EX(IDC_SYSLINK_LICENSE, NM_CLICK, OnLink) 47 | NOTIFY_HANDLER_EX(IDC_SYSLINK_LICENSE, NM_RETURN, OnLink) 48 | COMMAND_ID_HANDLER_EX(IDOK, OnExit) 49 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) 50 | END_MSG_MAP() 51 | 52 | protected: 53 | 54 | // Controls 55 | 56 | CStatic StaticTitle; 57 | CStatic StaticDeveloped; 58 | CStatic StaticGreetings; 59 | CStatic StaticYoda; 60 | 61 | CLinkCtrl LinkVisit; 62 | CLinkCtrl LinkDistorm; 63 | CLinkCtrl LinkWTL; 64 | CLinkCtrl LinkSilk; 65 | CLinkCtrl LinkTinyxml; 66 | CLinkCtrl LinkLicense; 67 | 68 | CToolTipCtrl TooltipDistorm; 69 | CToolTipCtrl TooltipWTL; 70 | CToolTipCtrl TooltipSilk; 71 | CToolTipCtrl TooltipTinyxml; 72 | CToolTipCtrl TooltipLicense; 73 | 74 | // Handles 75 | 76 | CFontHandle FontBold; 77 | 78 | // Texts 79 | 80 | static const WCHAR TEXT_VISIT[]; 81 | static const WCHAR TEXT_DEVELOPED[]; 82 | static const WCHAR TEXT_CREDIT_DISTORM[]; 83 | static const WCHAR TEXT_CREDIT_YODA[]; 84 | static const WCHAR TEXT_CREDIT_WTL[]; 85 | static const WCHAR TEXT_CREDIT_SILK[]; 86 | static const WCHAR TEXT_GREETINGS[]; 87 | static const WCHAR TEXT_LICENSE[]; 88 | static const WCHAR TEXT_TINYXML[]; 89 | 90 | // URLs 91 | 92 | static const WCHAR URL_VISIT1[]; 93 | static const WCHAR URL_VISIT2[]; 94 | static const WCHAR URL_DISTORM[]; 95 | static const WCHAR URL_WTL[]; 96 | static const WCHAR URL_SILK[]; 97 | static const WCHAR URL_LICENSE[]; 98 | static const WCHAR URL_TINYXML[]; 99 | 100 | protected: 101 | 102 | // Message handlers 103 | 104 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 105 | void OnClose(); 106 | LRESULT OnLink(NMHDR* pnmh); 107 | void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); 108 | 109 | // GUI helpers 110 | 111 | void setupLinks(); 112 | void setLinkURL(CLinkCtrl& link, const WCHAR* url, int index = 0); 113 | void setupTooltip(CToolTipCtrl tooltip, CWindow window, const WCHAR* text); 114 | }; 115 | -------------------------------------------------------------------------------- /Scylla/ApiReader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "ProcessAccessHelp.h" 7 | #include "Thunks.h" 8 | 9 | typedef std::pair API_Pair; 10 | 11 | class ApiReader : public ProcessAccessHelp 12 | { 13 | public: 14 | static stdext::hash_multimap apiList; //api look up table 15 | 16 | static std::map * moduleThunkList; //store found apis 17 | 18 | static DWORD_PTR minApiAddress; 19 | static DWORD_PTR maxApiAddress; 20 | 21 | /* 22 | * Read all APIs from target process 23 | */ 24 | void readApisFromModuleList(); 25 | 26 | bool isApiAddressValid(DWORD_PTR virtualAddress); 27 | ApiInfo * getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect); 28 | void readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map &moduleListNew ); 29 | void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo * apiFound, bool isNewModule, bool isSuspect); 30 | void clearAll(); 31 | bool isInvalidMemoryForIat( DWORD_PTR address ); 32 | private: 33 | bool readExportTableAlwaysFromDisk; 34 | void parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size); 35 | 36 | void addApi(char *functionName, WORD hint, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo); 37 | void addApiWithoutName(WORD ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo); 38 | inline bool isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader); 39 | void handleForwardedApi(DWORD_PTR vaStringPointer,char *functionNameParent,DWORD_PTR rvaParent, WORD ordinalParent, ModuleInfo *moduleParent); 40 | void parseModule(ModuleInfo *module); 41 | void parseModuleWithProcess(ModuleInfo * module); 42 | 43 | void parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress); 44 | 45 | ModuleInfo * findModuleByName(WCHAR *name); 46 | 47 | void findApiByModuleAndOrdinal(ModuleInfo * module, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi); 48 | void findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi); 49 | void findApiByModule(ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi); 50 | 51 | bool isModuleLoadedInOwnProcess( ModuleInfo * module ); 52 | void parseModuleWithOwnProcess( ModuleInfo * module ); 53 | bool isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader); 54 | void findApiInProcess( ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi ); 55 | bool findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi); 56 | 57 | BYTE * getHeaderFromProcess(ModuleInfo * module); 58 | BYTE * getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader); 59 | 60 | void setModulePriority(ModuleInfo * module); 61 | void setMinMaxApiAddress(DWORD_PTR virtualAddress); 62 | 63 | void parseModuleWithMapping(ModuleInfo *moduleInfo); //not used 64 | 65 | bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk); 66 | bool addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect); 67 | bool addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress); 68 | 69 | void addUnknownModuleToModuleList(DWORD_PTR firstThunk); 70 | bool isApiBlacklisted( const char * functionName ); 71 | bool isWinSxSModule( ModuleInfo * module ); 72 | 73 | ApiInfo * getScoredApi(stdext::hash_map::iterator it1,size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll,bool hasPrio0Dll,bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin ); 74 | 75 | }; 76 | -------------------------------------------------------------------------------- /Scylla/Architecture.cpp: -------------------------------------------------------------------------------- 1 | #include "Architecture.h" 2 | 3 | /* 4 | #ifdef _WIN64 5 | 6 | const WCHAR Architecture::NAME[] = L"x64"; 7 | 8 | const WCHAR Architecture::PRINTF_DWORD_PTR[] = L"%I64X"; 9 | const WCHAR Architecture::PRINTF_DWORD_PTR_FULL[] = L"%016I64X"; 10 | const WCHAR Architecture::PRINTF_DWORD_PTR_HALF[] = L"%08I64X"; 11 | const WCHAR Architecture::PRINTF_INTEGER[] = L"%I64u"; 12 | 13 | #else 14 | 15 | const WCHAR Architecture::NAME[] = L"x86"; 16 | 17 | const WCHAR Architecture::PRINTF_DWORD_PTR[] = L"%X"; 18 | const WCHAR Architecture::PRINTF_DWORD_PTR_FULL[] = L"%08X"; 19 | const WCHAR Architecture::PRINTF_DWORD_PTR_HALF[] = L"%08X"; 20 | const WCHAR Architecture::PRINTF_INTEGER[] = L"%u"; 21 | 22 | #endif 23 | */ 24 | -------------------------------------------------------------------------------- /Scylla/Architecture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef _WIN64 6 | 7 | #define ARCHITECTURE_S "x64" 8 | #define PRINTF_DWORD_PTR_S "%I64X" 9 | #define PRINTF_DWORD_PTR_FULL_S "%016I64X" 10 | #define PRINTF_DWORD_PTR_HALF_S "%08I64X" 11 | #define PRINTF_INTEGER_S "%I64u" 12 | 13 | #else 14 | 15 | #define ARCHITECTURE_S "x86" 16 | #define PRINTF_DWORD_PTR_S "%X" 17 | #define PRINTF_DWORD_PTR_FULL_S "%08X" 18 | #define PRINTF_DWORD_PTR_HALF_S "%08X" 19 | #define PRINTF_INTEGER_S "%u" 20 | 21 | #endif 22 | 23 | #define ARCHITECTURE TEXT(ARCHITECTURE_S) 24 | #define PRINTF_DWORD_PTR TEXT(PRINTF_DWORD_PTR_S) 25 | #define PRINTF_DWORD_PTR_FULL TEXT(PRINTF_DWORD_PTR_FULL_S) 26 | #define PRINTF_DWORD_PTR_HALF TEXT(PRINTF_DWORD_PTR_HALF_S) 27 | #define PRINTF_INTEGER TEXT(PRINTF_INTEGER_S) 28 | -------------------------------------------------------------------------------- /Scylla/Configuration.cpp: -------------------------------------------------------------------------------- 1 | #include "Configuration.h" 2 | 3 | Configuration::Configuration(const WCHAR* name, Type type) 4 | { 5 | wcscpy_s(this->name, name); 6 | this->type = type; 7 | valueNumeric = 0; 8 | valueString[0] = L'\0'; 9 | } 10 | 11 | const WCHAR* Configuration::getName() const 12 | { 13 | return name; 14 | } 15 | 16 | Configuration::Type Configuration::getType() const 17 | { 18 | return type; 19 | } 20 | 21 | DWORD_PTR Configuration::getNumeric() const 22 | { 23 | return valueNumeric; 24 | } 25 | 26 | void Configuration::setNumeric(DWORD_PTR value) 27 | { 28 | valueNumeric = value; 29 | } 30 | 31 | const WCHAR* Configuration::getString() const 32 | { 33 | return valueString; 34 | } 35 | 36 | void Configuration::setString(const WCHAR* str) 37 | { 38 | wcsncpy_s(valueString, str, _countof(valueString)); 39 | } 40 | 41 | bool Configuration::getBool() const 42 | { 43 | return getNumeric() == 1; 44 | } 45 | 46 | void Configuration::setBool(bool flag) 47 | { 48 | setNumeric(flag ? 1 : 0); 49 | } 50 | 51 | bool Configuration::isTrue() const 52 | { 53 | return getBool(); 54 | } 55 | 56 | void Configuration::setTrue() 57 | { 58 | setBool(true); 59 | } 60 | 61 | void Configuration::setFalse() 62 | { 63 | setBool(false); 64 | } 65 | -------------------------------------------------------------------------------- /Scylla/Configuration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Configuration 6 | { 7 | public: 8 | 9 | enum Type { 10 | String, 11 | Decimal, 12 | Hexadecimal, 13 | Boolean 14 | }; 15 | 16 | static const size_t CONFIG_NAME_LENGTH = 100; 17 | static const size_t CONFIG_STRING_LENGTH = 100; 18 | 19 | Configuration(const WCHAR* name = L"", Type type = String); 20 | 21 | const WCHAR* getName() const; 22 | Type getType() const; 23 | 24 | DWORD_PTR getNumeric() const; 25 | void setNumeric(DWORD_PTR value); 26 | 27 | const WCHAR* getString() const; 28 | void setString(const WCHAR* str); 29 | 30 | bool getBool() const; 31 | void setBool(bool flag); 32 | 33 | // Redundant (we have getBool and setBool), but easier on the eye 34 | bool isTrue() const; 35 | void setTrue(); 36 | void setFalse(); 37 | 38 | private: 39 | 40 | WCHAR name[CONFIG_NAME_LENGTH]; 41 | Type type; 42 | 43 | DWORD_PTR valueNumeric; 44 | WCHAR valueString[CONFIG_STRING_LENGTH]; 45 | }; 46 | -------------------------------------------------------------------------------- /Scylla/ConfigurationHolder.cpp: -------------------------------------------------------------------------------- 1 | #include "ConfigurationHolder.h" 2 | 3 | #include 4 | #include "Architecture.h" 5 | 6 | const WCHAR ConfigurationHolder::CONFIG_FILE_SECTION_NAME[] = L"SCYLLA_CONFIG"; 7 | 8 | //#define DEBUG_COMMENTS 9 | 10 | ConfigurationHolder::ConfigurationHolder(const WCHAR* fileName) 11 | { 12 | config[USE_PE_HEADER_FROM_DISK] = Configuration(L"USE_PE_HEADER_FROM_DISK", Configuration::Boolean); 13 | config[DEBUG_PRIVILEGE] = Configuration(L"DEBUG_PRIVILEGE", Configuration::Boolean); 14 | config[CREATE_BACKUP] = Configuration(L"CREATE_BACKUP", Configuration::Boolean); 15 | config[DLL_INJECTION_AUTO_UNLOAD] = Configuration(L"DLL_INJECTION_AUTO_UNLOAD", Configuration::Boolean); 16 | config[UPDATE_HEADER_CHECKSUM] = Configuration(L"UPDATE_HEADER_CHECKSUM", Configuration::Boolean); 17 | config[IAT_SECTION_NAME] = Configuration(L"IAT_SECTION_NAME", Configuration::String); 18 | config[REMOVE_DOS_HEADER_STUB] = Configuration(L"REMOVE_DOS_HEADER_STUB", Configuration::Boolean); 19 | config[IAT_FIX_AND_OEP_FIX] = Configuration(L"IAT_FIX_AND_OEP_FIX", Configuration::Boolean); 20 | config[SUSPEND_PROCESS_FOR_DUMPING] = Configuration(L"SUSPEND_PROCESS_FOR_DUMPING", Configuration::Boolean); 21 | config[OriginalFirstThunk_SUPPORT] = Configuration(L"OriginalFirstThunk_SUPPORT", Configuration::Boolean); 22 | config[USE_ADVANCED_IAT_SEARCH] = Configuration(L"USE_ADVANCED_IAT_SEARCH", Configuration::Boolean); 23 | config[SCAN_DIRECT_IMPORTS] = Configuration(L"SCAN_DIRECT_IMPORTS", Configuration::Boolean); 24 | config[FIX_DIRECT_IMPORTS_NORMAL] = Configuration(L"FIX_DIRECT_IMPORTS_NORMAL", Configuration::Boolean); 25 | config[FIX_DIRECT_IMPORTS_UNIVERSAL] = Configuration(L"FIX_DIRECT_IMPORTS_UNIVERSAL", Configuration::Boolean); 26 | config[CREATE_NEW_IAT_IN_SECTION] = Configuration(L"CREATE_NEW_IAT_IN_SECTION", Configuration::Boolean); 27 | config[DONT_CREATE_NEW_SECTION] = Configuration(L"DONT_CREATE_NEW_SECTION", Configuration::Boolean); 28 | config[APIS_ALWAYS_FROM_DISK] = Configuration(L"APIS_ALWAYS_FROM_DISK", Configuration::Boolean); 29 | buildConfigFilePath(fileName); 30 | } 31 | 32 | bool ConfigurationHolder::loadConfiguration() 33 | { 34 | std::map::iterator mapIter; 35 | 36 | if (configPath[0] == '\0') 37 | { 38 | return false; 39 | } 40 | 41 | for (mapIter = config.begin() ; mapIter != config.end(); mapIter++) 42 | { 43 | Configuration& configObject = mapIter->second; 44 | loadConfig(configObject); 45 | } 46 | 47 | return true; 48 | } 49 | 50 | bool ConfigurationHolder::saveConfiguration() const 51 | { 52 | std::map::const_iterator mapIter; 53 | 54 | if (configPath[0] == '\0') 55 | { 56 | return false; 57 | } 58 | 59 | for (mapIter = config.begin() ; mapIter != config.end(); mapIter++) 60 | { 61 | const Configuration& configObject = mapIter->second; 62 | if (!saveConfig(configObject)) 63 | { 64 | return false; 65 | } 66 | } 67 | 68 | return true; 69 | } 70 | 71 | Configuration& ConfigurationHolder::operator[](ConfigOption option) 72 | { 73 | return config[option]; 74 | } 75 | 76 | const Configuration& ConfigurationHolder::operator[](ConfigOption option) const 77 | { 78 | static const Configuration dummy; 79 | 80 | std::map::const_iterator found = config.find(option); 81 | if(found != config.end()) 82 | { 83 | return found->second; 84 | } 85 | else 86 | { 87 | return dummy; 88 | } 89 | } 90 | 91 | bool ConfigurationHolder::saveNumericToConfigFile(const Configuration & configObject, int nBase) const 92 | { 93 | WCHAR buf[21]; // UINT64_MAX in dec has 20 digits 94 | 95 | if (nBase == 16) 96 | { 97 | swprintf_s(buf, PRINTF_DWORD_PTR_FULL, configObject.getNumeric()); 98 | } 99 | else 100 | { 101 | swprintf_s(buf, PRINTF_INTEGER, configObject.getNumeric()); 102 | } 103 | 104 | BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), buf, configPath); 105 | return !!ret; 106 | } 107 | 108 | bool ConfigurationHolder::readNumericFromConfigFile(Configuration & configObject, int nBase) 109 | { 110 | WCHAR buf[21]; // UINT64_MAX in dec has 20 digits 111 | DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), L"", buf, _countof(buf), configPath); 112 | 113 | if (read > 0 && wcslen(buf) > 0) 114 | { 115 | #ifdef _WIN64 116 | configObject.setNumeric(_wcstoui64(buf, NULL, nBase)); 117 | #else 118 | configObject.setNumeric(wcstoul(buf, NULL, nBase)); 119 | #endif 120 | return true; 121 | } 122 | 123 | return false; 124 | } 125 | 126 | bool ConfigurationHolder::saveStringToConfigFile(const Configuration & configObject) const 127 | { 128 | BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), configObject.getString(), configPath); 129 | return !!ret; 130 | } 131 | 132 | bool ConfigurationHolder::readStringFromConfigFile(Configuration & configObject) 133 | { 134 | WCHAR buf[Configuration::CONFIG_STRING_LENGTH]; 135 | DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), L"", buf, _countof(buf), configPath); 136 | if(read > 0 && wcslen(buf) > 0) 137 | { 138 | configObject.setString(buf); 139 | return true; 140 | } 141 | 142 | return false; 143 | } 144 | 145 | bool ConfigurationHolder::readBooleanFromConfigFile(Configuration & configObject) 146 | { 147 | UINT val = GetPrivateProfileInt(CONFIG_FILE_SECTION_NAME, configObject.getName(), 0, configPath); 148 | configObject.setBool(val != 0); 149 | return true; 150 | } 151 | 152 | bool ConfigurationHolder::saveBooleanToConfigFile(const Configuration & configObject) const 153 | { 154 | const WCHAR *boolValue = configObject.isTrue() ? L"1" : L"0"; 155 | BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), boolValue, configPath); 156 | return !!ret; 157 | } 158 | 159 | bool ConfigurationHolder::loadConfig(Configuration & configObject) 160 | { 161 | switch (configObject.getType()) 162 | { 163 | case Configuration::String: 164 | return readStringFromConfigFile(configObject); 165 | case Configuration::Boolean: 166 | return readBooleanFromConfigFile(configObject); 167 | case Configuration::Decimal: 168 | return readNumericFromConfigFile(configObject, 10); 169 | case Configuration::Hexadecimal: 170 | return readNumericFromConfigFile(configObject, 16); 171 | default: 172 | return false; 173 | } 174 | } 175 | 176 | bool ConfigurationHolder::saveConfig(const Configuration & configObject) const 177 | { 178 | switch (configObject.getType()) 179 | { 180 | case Configuration::String: 181 | return saveStringToConfigFile(configObject); 182 | case Configuration::Boolean: 183 | return saveBooleanToConfigFile(configObject); 184 | case Configuration::Decimal: 185 | return saveNumericToConfigFile(configObject, 10); 186 | case Configuration::Hexadecimal: 187 | return saveNumericToConfigFile(configObject, 16); 188 | default: 189 | return false; 190 | } 191 | } 192 | 193 | bool ConfigurationHolder::buildConfigFilePath(const WCHAR* fileName) 194 | { 195 | ZeroMemory(configPath, sizeof(configPath)); 196 | 197 | if (!GetModuleFileName(0, configPath, _countof(configPath))) 198 | { 199 | #ifdef DEBUG_COMMENTS 200 | Scylla::debugLog.log(L"buildConfigFilePath :: GetModuleFileName failed %d", GetLastError()); 201 | #endif 202 | return false; 203 | } 204 | 205 | PathRemoveFileSpec(configPath); 206 | PathAppend(configPath, fileName); 207 | 208 | return true; 209 | } 210 | -------------------------------------------------------------------------------- /Scylla/ConfigurationHolder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Configuration.h" 6 | 7 | enum ConfigOption 8 | { 9 | USE_PE_HEADER_FROM_DISK, 10 | DEBUG_PRIVILEGE, 11 | CREATE_BACKUP, 12 | DLL_INJECTION_AUTO_UNLOAD, 13 | IAT_SECTION_NAME, 14 | UPDATE_HEADER_CHECKSUM, 15 | REMOVE_DOS_HEADER_STUB, 16 | IAT_FIX_AND_OEP_FIX, 17 | SUSPEND_PROCESS_FOR_DUMPING, 18 | OriginalFirstThunk_SUPPORT, 19 | USE_ADVANCED_IAT_SEARCH, 20 | SCAN_DIRECT_IMPORTS, 21 | FIX_DIRECT_IMPORTS_NORMAL, 22 | FIX_DIRECT_IMPORTS_UNIVERSAL, 23 | CREATE_NEW_IAT_IN_SECTION, 24 | DONT_CREATE_NEW_SECTION, 25 | APIS_ALWAYS_FROM_DISK 26 | }; 27 | 28 | class ConfigurationHolder 29 | { 30 | public: 31 | 32 | ConfigurationHolder(const WCHAR* fileName); 33 | 34 | bool loadConfiguration(); 35 | bool saveConfiguration() const; 36 | 37 | Configuration& operator[](ConfigOption option); 38 | const Configuration& operator[](ConfigOption option) const; 39 | 40 | private: 41 | 42 | static const WCHAR CONFIG_FILE_SECTION_NAME[]; 43 | 44 | WCHAR configPath[MAX_PATH]; 45 | std::map config; 46 | 47 | bool buildConfigFilePath(const WCHAR* fileName); 48 | 49 | bool readStringFromConfigFile(Configuration & configObject); 50 | bool readBooleanFromConfigFile(Configuration & configObject); 51 | bool readNumericFromConfigFile(Configuration & configObject, int nBase); 52 | 53 | bool saveStringToConfigFile(const Configuration & configObject) const; 54 | bool saveBooleanToConfigFile(const Configuration & configObject) const; 55 | bool saveNumericToConfigFile(const Configuration & configObject, int nBase) const; 56 | 57 | bool loadConfig(Configuration & configObject); 58 | bool saveConfig(const Configuration & configObject) const; 59 | }; 60 | -------------------------------------------------------------------------------- /Scylla/DeviceNameResolver.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "DeviceNameResolver.h" 3 | #include "NativeWinApi.h" 4 | 5 | DeviceNameResolver::DeviceNameResolver() 6 | { 7 | NativeWinApi::initialize(); 8 | initDeviceNameList(); 9 | } 10 | 11 | DeviceNameResolver::~DeviceNameResolver() 12 | { 13 | deviceNameList.clear(); 14 | } 15 | 16 | void DeviceNameResolver::initDeviceNameList() 17 | { 18 | TCHAR shortName[3] = {0}; 19 | TCHAR longName[MAX_PATH] = {0}; 20 | HardDisk hardDisk; 21 | 22 | shortName[1] = TEXT(':'); 23 | 24 | deviceNameList.reserve(3); 25 | 26 | for ( TCHAR shortD = TEXT('a'); shortD <= TEXT('z'); shortD++ ) 27 | { 28 | shortName[0] = shortD; 29 | if (QueryDosDevice( shortName, longName, MAX_PATH ) > 0) 30 | { 31 | hardDisk.shortName[0] = _totupper(shortD); 32 | hardDisk.shortName[1] = TEXT(':'); 33 | hardDisk.shortName[2] = 0; 34 | 35 | hardDisk.longNameLength = _tcslen(longName); 36 | 37 | 38 | _tcscpy_s(hardDisk.longName, longName); 39 | deviceNameList.push_back(hardDisk); 40 | } 41 | } 42 | 43 | fixVirtualDevices(); 44 | } 45 | 46 | bool DeviceNameResolver::resolveDeviceLongNameToShort(const TCHAR * sourcePath, TCHAR * targetPath) 47 | { 48 | for (unsigned int i = 0; i < deviceNameList.size(); i++) 49 | { 50 | if (!_tcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength) && sourcePath[deviceNameList[i].longNameLength] == TEXT('\\')) 51 | { 52 | _tcscpy_s(targetPath, MAX_PATH, deviceNameList[i].shortName); 53 | _tcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength); 54 | return true; 55 | } 56 | } 57 | 58 | return false; 59 | } 60 | 61 | void DeviceNameResolver::fixVirtualDevices() 62 | { 63 | const USHORT BufferSize = MAX_PATH * 2 * sizeof(WCHAR); 64 | WCHAR longCopy[MAX_PATH] = {0}; 65 | OBJECT_ATTRIBUTES oa = {0}; 66 | UNICODE_STRING unicodeInput = {0}; 67 | UNICODE_STRING unicodeOutput = {0}; 68 | HANDLE hFile = 0; 69 | ULONG retLen = 0; 70 | HardDisk hardDisk; 71 | 72 | unicodeOutput.Buffer = (PWSTR)malloc(BufferSize); 73 | if (!unicodeOutput.Buffer) 74 | return; 75 | 76 | for (unsigned int i = 0; i < deviceNameList.size(); i++) 77 | { 78 | wcscpy_s(longCopy, deviceNameList[i].longName); 79 | 80 | NativeWinApi::RtlInitUnicodeString(&unicodeInput, longCopy); 81 | InitializeObjectAttributes(&oa, &unicodeInput, 0, 0, 0); 82 | 83 | if(NT_SUCCESS(NativeWinApi::NtOpenSymbolicLinkObject(&hFile, SYMBOLIC_LINK_QUERY, &oa))) 84 | { 85 | unicodeOutput.Length = BufferSize; 86 | unicodeOutput.MaximumLength = unicodeOutput.Length; 87 | ZeroMemory(unicodeOutput.Buffer, unicodeOutput.Length); 88 | 89 | if (NT_SUCCESS(NativeWinApi::NtQuerySymbolicLinkObject(hFile, &unicodeOutput, &retLen))) 90 | { 91 | hardDisk.longNameLength = wcslen(unicodeOutput.Buffer); 92 | wcscpy_s(hardDisk.shortName, deviceNameList[i].shortName); 93 | wcscpy_s(hardDisk.longName, unicodeOutput.Buffer); 94 | deviceNameList.push_back(hardDisk); 95 | } 96 | 97 | NativeWinApi::NtClose(hFile); 98 | } 99 | } 100 | 101 | free(unicodeOutput.Buffer); 102 | } 103 | 104 | -------------------------------------------------------------------------------- /Scylla/DeviceNameResolver.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class HardDisk { 11 | public: 12 | TCHAR shortName[3]; 13 | TCHAR longName[MAX_PATH]; 14 | size_t longNameLength; 15 | }; 16 | 17 | class DeviceNameResolver 18 | { 19 | public: 20 | DeviceNameResolver(); 21 | ~DeviceNameResolver(); 22 | bool resolveDeviceLongNameToShort(const TCHAR * sourcePath, TCHAR * targetPath); 23 | private: 24 | std::vector deviceNameList; 25 | 26 | void initDeviceNameList(); 27 | void fixVirtualDevices(); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /Scylla/DisassemblerGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL window frame helpers 11 | #include // WTL utility classes like CString 12 | #include // WTL enhanced msg map macros 13 | #include // WTL controls 14 | #include // WTL dialog data exchange 15 | #include 16 | #include "hexedit.h" 17 | 18 | #include "ApiReader.h" 19 | 20 | enum DisassemblerAddressType { 21 | ADDRESS_TYPE_MODULE, 22 | ADDRESS_TYPE_API, 23 | ADDRESS_TYPE_SPECIAL 24 | }; 25 | 26 | class DisassemblerAddressComment 27 | { 28 | public: 29 | DWORD_PTR address; 30 | WCHAR comment[MAX_PATH]; 31 | DisassemblerAddressType type; 32 | DWORD moduleSize; 33 | 34 | bool operator<(const DisassemblerAddressComment& rhs) { return address < rhs.address; } 35 | }; 36 | 37 | class DisassemblerGui : public CDialogImpl, public CWinDataExchange, public CDialogResize 38 | { 39 | public: 40 | enum { IDD = IDD_DLG_DISASSEMBLER }; 41 | 42 | BEGIN_DDX_MAP(DisassemblerGui) 43 | DDX_CONTROL_HANDLE(IDC_LIST_DISASSEMBLER, ListDisassembler) 44 | DDX_CONTROL(IDC_EDIT_ADDRESS_DISASSEMBLE, EditAddress) 45 | END_DDX_MAP() 46 | 47 | BEGIN_MSG_MAP(DisassemblerGui) 48 | MSG_WM_INITDIALOG(OnInitDialog) 49 | MSG_WM_CONTEXTMENU(OnContextMenu) 50 | 51 | NOTIFY_HANDLER_EX(IDC_LIST_DISASSEMBLER, NM_CUSTOMDRAW, OnNMCustomdraw) 52 | 53 | COMMAND_ID_HANDLER_EX(IDC_BUTTON_DISASSEMBLE, OnDisassemble) 54 | COMMAND_ID_HANDLER_EX(IDC_BUTTON_DISASSEMBLER_BACK, OnDisassembleBack) 55 | COMMAND_ID_HANDLER_EX(IDC_BUTTON_DISASSEMBLER_FORWARD, OnDisassembleForward) 56 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) 57 | COMMAND_ID_HANDLER_EX(IDOK, OnExit) 58 | 59 | CHAIN_MSG_MAP(CDialogResize) 60 | END_MSG_MAP() 61 | 62 | BEGIN_DLGRESIZE_MAP(DisassemblerGui) 63 | DLGRESIZE_CONTROL(IDC_LIST_DISASSEMBLER, DLSZ_SIZE_X | DLSZ_SIZE_Y) 64 | DLGRESIZE_CONTROL(IDC_BUTTON_DISASSEMBLE, DLSZ_MOVE_X | DLSZ_MOVE_Y) 65 | DLGRESIZE_CONTROL(IDC_BUTTON_DISASSEMBLER_BACK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 66 | DLGRESIZE_CONTROL(IDC_BUTTON_DISASSEMBLER_FORWARD, DLSZ_MOVE_X | DLSZ_MOVE_Y) 67 | DLGRESIZE_CONTROL(IDC_EDIT_ADDRESS_DISASSEMBLE, DLSZ_MOVE_Y) 68 | DLGRESIZE_CONTROL(IDC_STATIC_ADDRESS_DISASSEMBLE, DLSZ_MOVE_Y) 69 | END_DLGRESIZE_MAP() 70 | 71 | DisassemblerGui(DWORD_PTR startAddress, ApiReader * apiReaderObject); 72 | 73 | protected: 74 | 75 | // Variables 76 | 77 | static const size_t DISASSEMBLER_GUI_MEMORY_SIZE = 0x120; 78 | 79 | WCHAR tempBuffer[500]; 80 | int addressHistoryIndex; 81 | 82 | std::vector addressHistory; 83 | 84 | std::vector addressCommentList; 85 | 86 | // Controls 87 | 88 | CListViewCtrl ListDisassembler; 89 | CHexEdit EditAddress; 90 | 91 | enum DisassemblerColumns { 92 | COL_ADDRESS = 0, 93 | COL_INSTRUCTION_SIZE, 94 | COL_OPCODES, 95 | COL_INSTRUCTION, 96 | COL_COMMENT 97 | }; 98 | 99 | // Handles 100 | 101 | CMenu hMenuDisassembler; 102 | 103 | // Message handlers 104 | 105 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 106 | void OnContextMenu(CWindow wnd, CPoint point); 107 | void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); 108 | LRESULT OnNMCustomdraw(NMHDR* pnmh); 109 | void OnDisassemble(UINT uNotifyCode, int nID, CWindow wndCtl); 110 | void OnDisassembleBack(UINT uNotifyCode, int nID, CWindow wndCtl); 111 | void OnDisassembleForward(UINT uNotifyCode, int nID, CWindow wndCtl); 112 | // GUI functions 113 | 114 | void addColumnsToDisassembler(CListViewCtrl& list); 115 | bool displayDisassembly(); 116 | 117 | // Misc 118 | 119 | void copyToClipboard(const WCHAR * text); 120 | 121 | private: 122 | ApiReader * apiReader; 123 | BYTE data[DISASSEMBLER_GUI_MEMORY_SIZE]; 124 | 125 | void toUpperCase(WCHAR * lowercase); 126 | void doColorInstruction( LPNMLVCUSTOMDRAW lpLVCustomDraw, DWORD_PTR itemIndex ); 127 | void followInstruction(int index); 128 | bool getDisassemblyComment(unsigned int index); 129 | 130 | void disassembleNewAddress(DWORD_PTR address); 131 | void initAddressCommentList(); 132 | void addModuleAddressCommentEntry( DWORD_PTR address, DWORD moduleSize, const WCHAR * modulePath ); 133 | void analyzeAddress( DWORD_PTR address, WCHAR * comment ); 134 | }; 135 | -------------------------------------------------------------------------------- /Scylla/DllInjection.cpp: -------------------------------------------------------------------------------- 1 | #include "DllInjection.h" 2 | #include 3 | #include "Scylla.h" 4 | 5 | #include "NativeWinApi.h" 6 | #include "ProcessAccessHelp.h" 7 | 8 | #pragma comment(lib, "Psapi.lib") 9 | 10 | //#define DEBUG_COMMENTS 11 | 12 | HMODULE DllInjection::dllInjection(HANDLE hProcess, const WCHAR * filename) 13 | { 14 | LPVOID remoteMemory = 0; 15 | SIZE_T memorySize = 0; 16 | HANDLE hThread = 0; 17 | HMODULE hModule = 0; 18 | 19 | memorySize = (wcslen(filename) + 1) * sizeof(WCHAR); 20 | 21 | if (memorySize < 7) 22 | { 23 | #ifdef DEBUG_COMMENTS 24 | Scylla::debugLog.log(L"dllInjection :: memorySize invalid"); 25 | #endif 26 | return 0; 27 | } 28 | 29 | remoteMemory = VirtualAllocEx(hProcess, NULL, memorySize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 30 | 31 | if (remoteMemory == 0) 32 | { 33 | #ifdef DEBUG_COMMENTS 34 | Scylla::debugLog.log(L"dllInjection :: VirtualAllocEx failed 0x%X", GetLastError()); 35 | #endif 36 | return 0; 37 | } 38 | 39 | if (WriteProcessMemory(hProcess, remoteMemory, filename, memorySize, &memorySize)) 40 | { 41 | hThread = startRemoteThread(hProcess,LoadLibraryW,remoteMemory); 42 | 43 | if (hThread) 44 | { 45 | WaitForSingleObject(hThread, INFINITE); 46 | 47 | #ifdef _WIN64 48 | 49 | hModule = getModuleHandleByFilename(hProcess, filename); 50 | 51 | #else 52 | //returns only 32 bit values -> design bug by microsoft 53 | if (!GetExitCodeThread(hThread, (LPDWORD) &hModule)) 54 | { 55 | #ifdef DEBUG_COMMENTS 56 | Scylla::debugLog.log(L"dllInjection :: GetExitCodeThread failed 0x%X", GetLastError()); 57 | #endif 58 | hModule = 0; 59 | } 60 | #endif 61 | 62 | CloseHandle(hThread); 63 | } 64 | else 65 | { 66 | #ifdef DEBUG_COMMENTS 67 | Scylla::debugLog.log(L"dllInjection :: CreateRemoteThread failed 0x%X", GetLastError()); 68 | #endif 69 | } 70 | } 71 | else 72 | { 73 | #ifdef DEBUG_COMMENTS 74 | Scylla::debugLog.log(L"dllInjection :: WriteProcessMemory failed 0x%X", GetLastError()); 75 | #endif 76 | } 77 | 78 | 79 | VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); 80 | 81 | return hModule; 82 | } 83 | 84 | bool DllInjection::unloadDllInProcess(HANDLE hProcess, HMODULE hModule) 85 | { 86 | HANDLE hThread = 0; 87 | DWORD lpThreadId = 0; 88 | BOOL freeLibraryRet = 0; 89 | 90 | 91 | hThread = startRemoteThread(hProcess,FreeLibrary,hModule); 92 | 93 | if (hThread) 94 | { 95 | WaitForSingleObject(hThread, INFINITE); 96 | 97 | if (!GetExitCodeThread(hThread, (LPDWORD) &freeLibraryRet)) 98 | { 99 | #ifdef DEBUG_COMMENTS 100 | Scylla::debugLog.log(L"unloadDllInProcess :: GetExitCodeThread failed 0x%X", GetLastError()); 101 | #endif 102 | freeLibraryRet = 0; 103 | } 104 | 105 | CloseHandle(hThread); 106 | } 107 | else 108 | { 109 | #ifdef DEBUG_COMMENTS 110 | Scylla::debugLog.log(L"unloadDllInProcess :: CreateRemoteThread failed 0x%X", GetLastError()); 111 | #endif 112 | } 113 | 114 | return freeLibraryRet != 0; 115 | } 116 | 117 | HMODULE DllInjection::getModuleHandleByFilename( HANDLE hProcess, const WCHAR * filename ) 118 | { 119 | HMODULE * hMods = 0; 120 | HMODULE hModResult = 0; 121 | WCHAR target[MAX_PATH]; 122 | 123 | DWORD numHandles = ProcessAccessHelp::getModuleHandlesFromProcess(hProcess, &hMods); 124 | if (numHandles == 0) 125 | { 126 | return 0; 127 | } 128 | 129 | for (DWORD i = 0; i < numHandles; i++) 130 | { 131 | if (GetModuleFileNameExW(hProcess, hMods[i], target, _countof(target))) 132 | { 133 | if (!_wcsicmp(target, filename)) 134 | { 135 | hModResult = hMods[i]; 136 | break; 137 | } 138 | } 139 | else 140 | { 141 | #ifdef DEBUG_COMMENTS 142 | Scylla::debugLog.log(L"DllInjection::getModuleHandle :: GetModuleFileNameExW failed 0x%X", GetLastError()); 143 | #endif 144 | } 145 | } 146 | 147 | if (!hModResult) 148 | { 149 | #ifdef DEBUG_COMMENTS 150 | Scylla::debugLog.log(L"DllInjection::getModuleHandle :: Handle not found"); 151 | #endif 152 | } 153 | 154 | delete [] hMods; 155 | 156 | return hModResult; 157 | } 158 | 159 | void DllInjection::specialThreadSettings( HANDLE hThread ) 160 | { 161 | if (hThread) 162 | { 163 | if (!SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL)) 164 | { 165 | #ifdef DEBUG_COMMENTS 166 | Scylla::debugLog.log(L"specialThreadSettings :: SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL) failed 0x%X", GetLastError()); 167 | #endif 168 | } 169 | 170 | if (NativeWinApi::NtSetInformationThread) 171 | { 172 | if (NativeWinApi::NtSetInformationThread(hThread, ThreadHideFromDebugger, 0, 0) != STATUS_SUCCESS) 173 | { 174 | #ifdef DEBUG_COMMENTS 175 | Scylla::debugLog.log(L"specialThreadSettings :: NtSetInformationThread ThreadHideFromDebugger failed"); 176 | #endif 177 | } 178 | } 179 | } 180 | } 181 | 182 | HANDLE DllInjection::startRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter) 183 | { 184 | HANDLE hThread = 0; 185 | 186 | hThread = customCreateRemoteThread(hProcess, lpStartAddress, lpParameter); 187 | 188 | if (hThread) 189 | { 190 | specialThreadSettings(hThread); 191 | ResumeThread(hThread); 192 | } 193 | 194 | return hThread; 195 | } 196 | 197 | HANDLE DllInjection::customCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter) 198 | { 199 | DWORD lpThreadId = 0; 200 | HANDLE hThread = 0; 201 | NTSTATUS ntStatus = 0; 202 | 203 | if (NativeWinApi::NtCreateThreadEx) 204 | { 205 | #define THREAD_ALL_ACCESS_VISTA_7 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF) 206 | 207 | //for windows vista/7 208 | ntStatus = NativeWinApi::NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS_VISTA_7, 0, hProcess, (LPTHREAD_START_ROUTINE)lpStartAddress, (LPVOID)lpParameter, NtCreateThreadExFlagCreateSuspended|NtCreateThreadExFlagHideFromDebugger, 0, 0, 0, 0); 209 | if (NT_SUCCESS(ntStatus)) 210 | { 211 | return hThread; 212 | } 213 | else 214 | { 215 | #ifdef DEBUG_COMMENTS 216 | Scylla::debugLog.log(L"customCreateRemoteThread :: NtCreateThreadEx failed 0x%X", NativeWinApi::RtlNtStatusToDosError(ntStatus)); 217 | #endif 218 | return 0; 219 | } 220 | } 221 | else 222 | { 223 | return CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)lpStartAddress,lpParameter,CREATE_SUSPENDED,&lpThreadId); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /Scylla/DllInjection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class DllInjection 6 | { 7 | public: 8 | 9 | HMODULE dllInjection(HANDLE hProcess, const WCHAR * filename); 10 | bool unloadDllInProcess(HANDLE hProcess, HMODULE hModule); 11 | HANDLE startRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter); 12 | 13 | private: 14 | 15 | HANDLE customCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter); 16 | void specialThreadSettings(HANDLE hThread); 17 | HMODULE getModuleHandleByFilename(HANDLE hProcess, const WCHAR * filename); 18 | }; 19 | -------------------------------------------------------------------------------- /Scylla/DllInjectionPlugin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DllInjection.h" 4 | #include "PluginLoader.h" 5 | #include "Thunks.h" 6 | #include "ApiReader.h" 7 | 8 | #define PLUGIN_IMPREC_EXCHANGE_DLL_PATH "ScyllaImprecPluginExchangePath" 9 | 10 | #define SCYLLA_STATUS_SUCCESS 0 11 | #define SCYLLA_STATUS_UNKNOWN_ERROR 1 12 | #define SCYLLA_STATUS_UNSUPPORTED_PROTECTION 2 13 | #define SCYLLA_STATUS_IMPORT_RESOLVING_FAILED 3 14 | #define SCYLLA_STATUS_MAPPING_FAILED 0xFF 15 | 16 | /* Important note: 17 | * 18 | * If you write a plugin for the x86 (32-Bit) edition: DWORD_PTR address has 32 bit (4 byte) 19 | * If you write a plugin for the x64 (64-Bit) edition: DWORD_PTR address has 64 bit (8 byte) 20 | */ 21 | typedef struct _UNRESOLVED_IMPORT { // Scylla Plugin exchange format 22 | DWORD_PTR ImportTableAddressPointer; //in VA, address in IAT which points to an invalid api address 23 | DWORD_PTR InvalidApiAddress; //in VA, invalid api address that needs to be resolved 24 | } UNRESOLVED_IMPORT, *PUNRESOLVED_IMPORT; 25 | 26 | typedef struct _SCYLLA_EXCHANGE { 27 | BYTE status; //return a status, default 0xFF 28 | DWORD_PTR imageBase; //image base 29 | DWORD_PTR imageSize; //size of the image 30 | DWORD_PTR numberOfUnresolvedImports; //number of unresolved imports in this structure 31 | BYTE offsetUnresolvedImportsArray; 32 | } SCYLLA_EXCHANGE, *PSCYLLA_EXCHANGE; 33 | 34 | class DllInjectionPlugin : public DllInjection { 35 | 36 | public: 37 | static const WCHAR * FILE_MAPPING_NAME; 38 | static HANDLE hProcess; 39 | 40 | ApiReader * apiReader; 41 | HANDLE hMapFile; 42 | LPVOID lpViewOfFile; 43 | 44 | DllInjectionPlugin() 45 | { 46 | hMapFile = 0; 47 | lpViewOfFile = 0; 48 | apiReader = 0; 49 | } 50 | 51 | ~DllInjectionPlugin() 52 | { 53 | closeAllHandles(); 54 | } 55 | 56 | void injectPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize); 57 | void injectImprecPlugin(Plugin & plugin, std::map & moduleList, DWORD_PTR imageBase, DWORD_PTR imageSize); 58 | 59 | private: 60 | bool createFileMapping(DWORD mappingSize); 61 | void closeAllHandles(); 62 | DWORD_PTR getNumberOfUnresolvedImports( std::map & moduleList ); 63 | void addUnresolvedImports( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList ); 64 | void handlePluginResults( PSCYLLA_EXCHANGE scyllaExchange, std::map & moduleList ); 65 | void updateImportsWithPluginResult( PUNRESOLVED_IMPORT firstUnresImp, std::map & moduleList ); 66 | }; 67 | -------------------------------------------------------------------------------- /Scylla/DonateGui.cpp: -------------------------------------------------------------------------------- 1 | #include "DonateGui.h" 2 | 3 | #include "Scylla.h" 4 | #include "Architecture.h" 5 | 6 | const WCHAR DonateGui::TEXT_DONATE[] = L"If you like this tool, please feel free to donate some Bitcoins to support this project.\n\n\nBTC Address:\n\n" TEXT(DONATE_BTC_ADDRESS); 7 | 8 | 9 | BOOL DonateGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) 10 | { 11 | DoDataExchange(); // attach controls 12 | 13 | DonateInfo.SetWindowText(TEXT_DONATE); 14 | 15 | CenterWindow(); 16 | 17 | // Set focus to button 18 | GotoDlgCtrl(GetDlgItem(IDC_BUTTON_COPYBTC)); 19 | return FALSE; 20 | } 21 | 22 | void DonateGui::OnClose() 23 | { 24 | EndDialog(0); 25 | } 26 | 27 | void DonateGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl) 28 | { 29 | SendMessage(WM_CLOSE); 30 | } 31 | 32 | void DonateGui::CopyBtcAddress(UINT uNotifyCode, int nID, CWindow wndCtl) 33 | { 34 | if(OpenClipboard()) 35 | { 36 | EmptyClipboard(); 37 | size_t len = strlen(DONATE_BTC_ADDRESS); 38 | HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(CHAR)); 39 | if(hMem) 40 | { 41 | strcpy_s(static_cast(GlobalLock(hMem)), len + 1, DONATE_BTC_ADDRESS); 42 | GlobalUnlock(hMem); 43 | if(!SetClipboardData(CF_TEXT, hMem)) 44 | { 45 | GlobalFree(hMem); 46 | } 47 | } 48 | CloseClipboard(); 49 | } 50 | } -------------------------------------------------------------------------------- /Scylla/DonateGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL enhanced msg map macros 11 | #include // WTL controls 12 | #include // WTL dialog data exchange 13 | 14 | class DonateGui : public CDialogImpl, public CWinDataExchange 15 | { 16 | public: 17 | enum { IDD = IDD_DLG_DONATE }; 18 | 19 | BEGIN_DDX_MAP(DonateGui) 20 | DDX_CONTROL_HANDLE(IDC_STATIC_DONATEINFO, DonateInfo) 21 | END_DDX_MAP() 22 | 23 | BEGIN_MSG_MAP(DonateGui) 24 | MSG_WM_INITDIALOG(OnInitDialog) 25 | MSG_WM_CLOSE(OnClose) 26 | COMMAND_ID_HANDLER_EX(IDC_BUTTON_COPYBTC, CopyBtcAddress) 27 | 28 | COMMAND_ID_HANDLER_EX(IDOK, OnExit) 29 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnExit) 30 | END_MSG_MAP() 31 | 32 | protected: 33 | 34 | // Controls 35 | 36 | CStatic DonateInfo; 37 | 38 | // Texts 39 | static const WCHAR TEXT_DONATE[]; 40 | 41 | protected: 42 | 43 | // Message handlers 44 | void CopyBtcAddress(UINT uNotifyCode, int nID, CWindow wndCtl); 45 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 46 | void OnClose(); 47 | void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); 48 | 49 | }; -------------------------------------------------------------------------------- /Scylla/DumpMemoryGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL window frame helpers 11 | #include // WTL utility classes 12 | #include // WTL enhanced msg map macros 13 | #include // WTL controls 14 | #include // WTL dialog data exchange 15 | 16 | #include 17 | #include "hexedit.h" 18 | #include "DeviceNameResolver.h" 19 | 20 | class Memory 21 | { 22 | public: 23 | DWORD_PTR address; 24 | DWORD size; 25 | WCHAR filename[MAX_PATH]; 26 | WCHAR mappedFilename[MAX_PATH]; 27 | WCHAR peSection[IMAGE_SIZEOF_SHORT_NAME * 20]; 28 | DWORD state; 29 | DWORD protect; 30 | DWORD type; 31 | }; 32 | 33 | class DumpMemoryGui : public CDialogImpl, public CWinDataExchange, public CDialogResize 34 | { 35 | public: 36 | enum { IDD = IDD_DLG_DUMPMEMORY }; 37 | 38 | BEGIN_DDX_MAP(DumpMemoryGui) 39 | DDX_CONTROL_HANDLE(IDC_LIST_DUMPMEMORY, ListMemorySelect) 40 | DDX_CONTROL(IDC_EDIT_DUMPADDRESS, EditMemoryAddress) 41 | DDX_CONTROL(IDC_EDIT_DUMPSIZE, EditMemorySize) 42 | DDX_CHECK(IDC_CHECK_FORCEDUMP, forceDump) 43 | END_DDX_MAP() 44 | 45 | BEGIN_MSG_MAP(DumpMemoryGui) 46 | MSG_WM_INITDIALOG(OnInitDialog) 47 | 48 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPMEMORY, LVN_COLUMNCLICK, OnListMemoryColumnClicked) 49 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPMEMORY, NM_CLICK, OnListMemoryClick) 50 | 51 | COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPMEMORY_OK, OnOK) 52 | COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPMEMORY_CANCEL, OnCancel) 53 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 54 | 55 | CHAIN_MSG_MAP(CDialogResize) 56 | END_MSG_MAP() 57 | 58 | BEGIN_DLGRESIZE_MAP(DumpMemoryGui) 59 | DLGRESIZE_CONTROL(IDC_LIST_DUMPMEMORY, DLSZ_SIZE_X | DLSZ_SIZE_Y) 60 | DLGRESIZE_CONTROL(IDC_BTN_DUMPMEMORY_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 61 | DLGRESIZE_CONTROL(IDC_BTN_DUMPMEMORY_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) 62 | DLGRESIZE_CONTROL(IDC_EDIT_DUMPADDRESS, DLSZ_MOVE_Y) 63 | DLGRESIZE_CONTROL(IDC_EDIT_DUMPSIZE, DLSZ_MOVE_Y) 64 | DLGRESIZE_CONTROL(IDC_STATIC_SIZE, DLSZ_MOVE_Y) 65 | DLGRESIZE_CONTROL(IDC_STATIC_ADDRESS, DLSZ_MOVE_Y) 66 | DLGRESIZE_CONTROL(IDC_CHECK_FORCEDUMP, DLSZ_MOVE_Y) 67 | END_DLGRESIZE_MAP() 68 | 69 | DumpMemoryGui(); 70 | ~DumpMemoryGui(); 71 | 72 | BYTE * dumpedMemory; 73 | DWORD dumpedMemorySize; 74 | WCHAR dumpFilename[39]; 75 | 76 | protected: 77 | CListViewCtrl ListMemorySelect; 78 | CHexEdit EditMemoryAddress; 79 | CHexEdit EditMemorySize; 80 | 81 | std::vector memoryList; 82 | Memory * selectedMemory; 83 | 84 | DeviceNameResolver * deviceNameResolver; 85 | 86 | enum ListColumns { 87 | COL_ADDRESS = 0, 88 | COL_SIZE, 89 | COL_FILENAME, 90 | COL_PESECTION, 91 | COL_TYPE, 92 | COL_PROTECTION, 93 | COL_STATE, 94 | COL_MAPPED_FILE 95 | }; 96 | 97 | int prevColumn; 98 | bool ascending; 99 | 100 | bool forceDump; 101 | 102 | // Message handlers 103 | 104 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 105 | 106 | LRESULT OnListMemoryColumnClicked(NMHDR* pnmh); 107 | LRESULT OnListMemoryClick(NMHDR* pnmh); 108 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 109 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 110 | 111 | // GUI functions 112 | 113 | void addColumnsToMemoryList(CListViewCtrl& list); 114 | void displayMemoryList(CListViewCtrl& list); 115 | 116 | static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 117 | 118 | private: 119 | 120 | enum enumMemoryStateValues { 121 | STATE_COMMIT = 0, 122 | STATE_FREE, 123 | STATE_RESERVE 124 | }; 125 | 126 | //"IMAGE",L"MAPPED",L"PRIVATE" 127 | enum enumMemoryTypeValues { 128 | TYPE_IMAGE = 0, 129 | TYPE_MAPPED, 130 | TYPE_PRIVATE 131 | }; 132 | 133 | //"EXECUTE",L"EXECUTE_READ",L"EXECUTE_READWRITE",L"EXECUTE_WRITECOPY",L"NOACCESS",L"READONLY",L"READWRITE",L"WRITECOPY",L"GUARD",L"NOCACHE",L"WRITECOMBINE" 134 | enum enumMemoryProtectionValues { 135 | PROT_EXECUTE = 0, 136 | PROT_EXECUTE_READ, 137 | PROT_EXECUTE_READWRITE, 138 | PROT_EXECUTE_WRITECOPY, 139 | PROT_NOACCESS, 140 | PROT_READONLY, 141 | PROT_READWRITE, 142 | PROT_WRITECOPY, 143 | PROT_GUARD, 144 | PROT_NOCACHE, 145 | PROT_WRITECOMBINE 146 | }; 147 | 148 | static const WCHAR * MemoryStateValues[]; 149 | static const WCHAR * MemoryTypeValues[]; 150 | static const WCHAR * MemoryProtectionValues[]; 151 | static const WCHAR MemoryUnknown[]; 152 | static const WCHAR MemoryUndefined[]; 153 | 154 | static WCHAR protectionString[100]; 155 | 156 | static const WCHAR * getMemoryTypeString(DWORD value); 157 | static const WCHAR * getMemoryStateString(DWORD value); 158 | static WCHAR * getMemoryProtectionString(DWORD value); 159 | 160 | void updateAddressAndSize( Memory * selectedMemory ); 161 | void getMemoryList(); 162 | SIZE_T getSizeOfImage(DWORD_PTR moduleBase); 163 | void setModuleName(DWORD_PTR moduleBase, const WCHAR * moduleName); 164 | void setAllSectionNames( DWORD_PTR moduleBase, WCHAR * moduleName ); 165 | 166 | void setSectionName(DWORD_PTR sectionAddress, DWORD sectionSize, const WCHAR * sectionName); 167 | bool dumpMemory(); 168 | bool getMappedFilename( Memory* memory ); 169 | }; 170 | -------------------------------------------------------------------------------- /Scylla/DumpSectionGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL window frame helpers 11 | #include // WTL utility classes 12 | #include // WTL enhanced msg map macros 13 | #include // WTL controls 14 | #include // WTL dialog data exchange 15 | 16 | #include 17 | #include "hexedit.h" 18 | 19 | 20 | class PeSection 21 | { 22 | public: 23 | WCHAR name[IMAGE_SIZEOF_SHORT_NAME + 1]; 24 | DWORD_PTR virtualAddress; 25 | DWORD virtualSize; 26 | DWORD rawAddress; 27 | DWORD rawSize; 28 | DWORD characteristics; 29 | 30 | bool isDumped; 31 | 32 | bool highlightVirtualSize(); 33 | }; 34 | 35 | class DumpSectionGui : public CDialogImpl, public CWinDataExchange, public CDialogResize 36 | { 37 | public: 38 | enum { IDD = IDD_DLG_DUMPSECTION }; 39 | 40 | BEGIN_DDX_MAP(DumpSectionGui) 41 | DDX_CONTROL_HANDLE(IDC_LIST_DUMPSECTION, ListSectionSelect) 42 | DDX_CONTROL(IDC_EDIT_LISTCONTROL, EditListControl) 43 | END_DDX_MAP() 44 | 45 | BEGIN_MSG_MAP(DumpSectionGui) 46 | MSG_WM_INITDIALOG(OnInitDialog) 47 | 48 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, LVN_COLUMNCLICK, OnListSectionColumnClicked) 49 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_CLICK, OnListSectionClick) 50 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_CUSTOMDRAW, OnNMCustomdraw) 51 | NOTIFY_HANDLER_EX(IDC_LIST_DUMPSECTION, NM_DBLCLK, OnListDoubleClick) 52 | 53 | COMMAND_ID_HANDLER_EX(IDC_BUTTON_SELECT_DESELECT, OnSectionSelectAll) 54 | COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPSECTION_OK, OnOK) 55 | COMMAND_ID_HANDLER_EX(IDC_EDIT_LISTCONTROL, OnEditList) 56 | COMMAND_ID_HANDLER_EX(IDC_BTN_DUMPSECTION_CANCEL, OnCancel) 57 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 58 | 59 | CHAIN_MSG_MAP(CDialogResize) 60 | END_MSG_MAP() 61 | 62 | BEGIN_DLGRESIZE_MAP(DumpSectionGui) 63 | DLGRESIZE_CONTROL(IDC_LIST_DUMPSECTION, DLSZ_SIZE_X | DLSZ_SIZE_Y) 64 | DLGRESIZE_CONTROL(IDC_BTN_DUMPSECTION_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 65 | DLGRESIZE_CONTROL(IDC_BTN_DUMPSECTION_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) 66 | DLGRESIZE_CONTROL(IDC_BUTTON_SELECT_DESELECT, DLSZ_MOVE_Y) 67 | END_DLGRESIZE_MAP() 68 | 69 | DumpSectionGui(); 70 | ~DumpSectionGui(); 71 | 72 | DWORD_PTR imageBase; //VA 73 | DWORD_PTR entryPoint; 74 | WCHAR fullpath[MAX_PATH]; 75 | 76 | std::vector & getSectionList(); 77 | 78 | private: 79 | CListViewCtrl ListSectionSelect; 80 | CHexEdit EditListControl; 81 | 82 | std::vector sectionList; 83 | 84 | PeSection *selectedSection; 85 | 86 | bool isEditing; 87 | int editingSubItem; 88 | DWORD valueBeforeEditing; 89 | 90 | enum ListColumns { 91 | COL_NAME = 0, 92 | COL_VA, 93 | COL_VSize, 94 | COL_RVA, 95 | COL_RSize, 96 | COL_Characteristics 97 | }; 98 | 99 | int prevColumn; 100 | bool ascending; 101 | 102 | // Message handlers 103 | 104 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 105 | 106 | LRESULT OnListSectionColumnClicked(NMHDR* pnmh); 107 | LRESULT OnListSectionClick(NMHDR* pnmh); 108 | LRESULT OnNMCustomdraw(NMHDR* pnmh); 109 | LRESULT OnListDoubleClick(NMHDR* pnmh); 110 | 111 | void OnSectionSelectAll(UINT uNotifyCode, int nID, CWindow wndCtl); 112 | void OnEditList(UINT uNotifyCode, int nID, CWindow wndCtl); 113 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 114 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 115 | 116 | // GUI functions 117 | 118 | void addColumnsToSectionList(CListViewCtrl& list); 119 | void displaySectionList(CListViewCtrl& list); 120 | 121 | static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 122 | WCHAR * getCharacteristicsString( DWORD characteristics ); 123 | void getAllSectionsFromFile(); 124 | void updateEditedItem(); 125 | void updateCheckState(); 126 | void selectOrDeselectAll(); 127 | }; -------------------------------------------------------------------------------- /Scylla/FunctionExport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | const int SCY_ERROR_SUCCESS = 0; 6 | const int SCY_ERROR_PROCOPEN = -1; 7 | const int SCY_ERROR_IATWRITE = -2; 8 | const int SCY_ERROR_IATSEARCH = -3; 9 | const int SCY_ERROR_IATNOTFOUND = -4; 10 | const int SCY_ERROR_PIDNOTFOUND = -5; 11 | 12 | 13 | typedef struct _GUI_DLL_PARAMETER { 14 | DWORD dwProcessId; 15 | HINSTANCE mod; 16 | DWORD_PTR entrypoint; 17 | } GUI_DLL_PARAMETER, *PGUI_DLL_PARAMETER; 18 | 19 | int InitializeGui(HINSTANCE hInstance, LPARAM param); 20 | 21 | 22 | //function to export in DLL 23 | 24 | BOOL DumpProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 25 | 26 | BOOL WINAPI ScyllaDumpCurrentProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 27 | BOOL WINAPI ScyllaDumpCurrentProcessA(const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 28 | 29 | BOOL WINAPI ScyllaDumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 30 | BOOL WINAPI ScyllaDumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 31 | 32 | BOOL WINAPI ScyllaRebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 33 | BOOL WINAPI ScyllaRebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 34 | 35 | const WCHAR * WINAPI ScyllaVersionInformationW(); 36 | const char * WINAPI ScyllaVersionInformationA(); 37 | DWORD WINAPI ScyllaVersionInformationDword(); 38 | 39 | int WINAPI ScyllaStartGui(DWORD dwProcessId, HINSTANCE mod); 40 | 41 | int WINAPI ScyllaIatSearch(DWORD dwProcessId, DWORD_PTR * iatStart, DWORD * iatSize, DWORD_PTR searchStart, BOOL advancedSearch); 42 | int WINAPI ScyllaIatFixAutoW(DWORD_PTR iatAddr, DWORD iatSize, DWORD dwProcessId, const WCHAR * dumpFile, const WCHAR * iatFixFile); 43 | 44 | 45 | /* 46 | C/C++ Prototyps 47 | 48 | typedef const WCHAR * (WINAPI * def_ScyllaVersionInformationW)(); 49 | typedef const char * (WINAPI * def_ScyllaVersionInformationA)(); 50 | typedef DWORD (WINAPI * def_ScyllaVersionInformationDword)(); 51 | typedef int (WINAPI * def_ScyllaIatSearch)(DWORD dwProcessId, DWORD_PTR * iatStart, DWORD * iatSize, DWORD_PTR searchStart, BOOL advancedSearch); 52 | typedef int (WINAPI * def_ScyllaStartGui)(DWORD dwProcessId, HINSTANCE mod); 53 | 54 | */ 55 | -------------------------------------------------------------------------------- /Scylla/IATReferenceScan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "ProcessAccessHelp.h" 4 | #include "PeParser.h" 5 | #include "Logger.h" 6 | #include "ApiReader.h" 7 | 8 | enum IATReferenceType { 9 | IAT_REFERENCE_PTR_JMP, 10 | IAT_REFERENCE_PTR_CALL, 11 | IAT_REFERENCE_DIRECT_JMP, 12 | IAT_REFERENCE_DIRECT_CALL, 13 | IAT_REFERENCE_DIRECT_MOV, 14 | IAT_REFERENCE_DIRECT_PUSH, 15 | IAT_REFERENCE_DIRECT_LEA 16 | }; 17 | 18 | class IATReference 19 | { 20 | public: 21 | DWORD_PTR addressVA; //Address of reference 22 | DWORD_PTR targetPointer; //Place inside IAT 23 | DWORD_PTR targetAddressInIat; //WIN API? 24 | BYTE instructionSize; 25 | IATReferenceType type; 26 | }; 27 | 28 | 29 | class IATReferenceScan 30 | { 31 | public: 32 | 33 | IATReferenceScan() 34 | { 35 | apiReader = 0; 36 | IatAddressVA = 0; 37 | IatSize = 0; 38 | ImageBase = 0; 39 | ImageSize = 0; 40 | iatBackup = 0; 41 | ScanForDirectImports = false; 42 | ScanForNormalImports = true; 43 | } 44 | 45 | ~IATReferenceScan() 46 | { 47 | iatReferenceList.clear(); 48 | iatDirectImportList.clear(); 49 | 50 | if (iatBackup) 51 | { 52 | free(iatBackup); 53 | } 54 | } 55 | 56 | bool ScanForDirectImports; 57 | bool ScanForNormalImports; 58 | bool JunkByteAfterInstruction; 59 | ApiReader * apiReader; 60 | 61 | void startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR iatAddress, DWORD iatSize); 62 | //void patchNewIatBaseMemory(DWORD_PTR newIatBaseAddress); 63 | //void patchNewIatBaseFile(DWORD_PTR newIatBaseAddress); 64 | 65 | void patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseAddress, PeParser * peParser); 66 | void patchDirectJumpTable( DWORD_PTR imageBase, DWORD directImportsJumpTableRVA, PeParser * peParser, BYTE * jmpTableMemory, DWORD newIatBase); 67 | void patchDirectImportsMemory(bool junkByteAfterInstruction); 68 | int numberOfFoundDirectImports(); 69 | int numberOfFoundUniqueDirectImports(); 70 | int numberOfDirectImportApisNotInIat(); 71 | int getSizeInBytesOfJumpTableInSection(); 72 | static FileLog directImportLog; 73 | void printDirectImportLog(); 74 | void changeIatBaseOfDirectImports( DWORD newIatBaseAddressRVA ); 75 | DWORD addAdditionalApisToList(); 76 | private: 77 | DWORD_PTR NewIatAddressRVA; 78 | 79 | DWORD_PTR IatAddressVA; 80 | DWORD IatSize; 81 | DWORD_PTR ImageBase; 82 | DWORD ImageSize; 83 | 84 | 85 | DWORD_PTR * iatBackup; 86 | 87 | std::vector iatReferenceList; 88 | std::vector iatDirectImportList; 89 | 90 | void scanMemoryPage( PVOID BaseAddress, SIZE_T RegionSize ); 91 | void analyzeInstruction( _DInst * instruction ); 92 | void findNormalIatReference( _DInst * instruction ); 93 | void getIatEntryAddress( IATReference* ref ); 94 | void findDirectIatReferenceCallJmp( _DInst * instruction ); 95 | bool isAddressValidImageMemory( DWORD_PTR address ); 96 | void patchReferenceInMemory( IATReference * ref ); 97 | void patchReferenceInFile( IATReference* ref ); 98 | void patchDirectImportInMemory( IATReference * iter ); 99 | DWORD_PTR lookUpIatForPointer( DWORD_PTR addr ); 100 | void findDirectIatReferenceMov( _DInst * instruction ); 101 | void findDirectIatReferencePush( _DInst * instruction ); 102 | void checkMemoryRangeAndAddToList( IATReference * ref, _DInst * instruction ); 103 | void findDirectIatReferenceLea( _DInst * instruction ); 104 | void patchDirectImportInDump32( int patchPreFixBytes, int instructionSize, DWORD patchBytes, BYTE * memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA ); 105 | void patchDirectImportInDump64( int patchPreFixBytes, int instructionSize, DWORD_PTR patchBytes, BYTE * memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA ); 106 | void patchDirectJumpTableEntry(DWORD_PTR targetIatPointer, DWORD_PTR stdImagebase, DWORD directImportsJumpTableRVA, PeParser * peParser, BYTE * jmpTableMemory, DWORD newIatBase ); 107 | 108 | 109 | }; 110 | 111 | /* 112 | PE64 113 | ---------- 114 | 000000013FF82D87 FF15 137C0A00 CALL QWORD [RIP+0xA7C13] 115 | Result: 000000014002A9A0 116 | 117 | 000000013F65C952 FF25 F8EA0B00 JMP QWORD [RIP+0xBEAF8] 118 | Result: 000000013F71B450 119 | 120 | PE32 121 | ---------- 122 | 0120FFA5 FF15 8C6D2601 CALL DWORD [0x01266D8C] 123 | 124 | 0120FF52 FF25 D4722601 JMP DWORD [0x012672D4] 125 | */ 126 | 127 | -------------------------------------------------------------------------------- /Scylla/IATSearch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ApiReader.h" 4 | #include 5 | 6 | class IATSearch : protected ApiReader 7 | { 8 | public: 9 | 10 | DWORD_PTR memoryAddress; 11 | SIZE_T memorySize; 12 | 13 | bool searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT, bool advanced); 14 | 15 | private: 16 | 17 | DWORD_PTR findAPIAddressInIAT(DWORD_PTR startAddress); 18 | bool findIATAdvanced(DWORD_PTR startAddress,DWORD_PTR* addressIAT, DWORD* sizeIAT); 19 | DWORD_PTR findNextFunctionAddress(); 20 | DWORD_PTR findIATPointer(); 21 | //DWORD_PTR findAddressFromWORDString(char * stringBuffer); 22 | //DWORD_PTR findAddressFromNormalCALLString(char * stringBuffer); 23 | bool isIATPointerValid(DWORD_PTR iatPointer, bool checkRedirects); 24 | 25 | bool findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT); 26 | 27 | DWORD_PTR findIATStartAddress( DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE * dataBuffer ); 28 | DWORD findIATSize( DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE * dataBuffer, DWORD bufferSize ); 29 | 30 | void findIATPointers(std::set & iatPointers); 31 | void findExecutableMemoryPagesByStartAddress( DWORD_PTR startAddress, DWORD_PTR* baseAddress, SIZE_T* memorySize ); 32 | void filterIATPointersList( std::set & iatPointers ); 33 | void getMemoryBaseAndSizeForIat( DWORD_PTR address, DWORD_PTR* baseAddress, DWORD* baseSize ); 34 | }; 35 | -------------------------------------------------------------------------------- /Scylla/ImportRebuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "PeParser.h" 5 | #include "Thunks.h" 6 | #include "IATReferenceScan.h" 7 | 8 | 9 | class ImportRebuilder : public PeParser { 10 | public: 11 | ImportRebuilder(const WCHAR * file) : PeParser(file, true) 12 | { 13 | pImportDescriptor = 0; 14 | pThunkData = 0; 15 | pImportByName = 0; 16 | 17 | numberOfImportDescriptors = 0; 18 | sizeOfImportSection = 0; 19 | sizeOfApiAndModuleNames = 0; 20 | importSectionIndex = 0; 21 | useOFT = false; 22 | sizeOfOFTArray = 0; 23 | newIatInSection = false; 24 | BuildDirectImportsJumpTable = false; 25 | sizeOfJumpTable = 0; 26 | } 27 | 28 | bool rebuildImportTable(const WCHAR * newFilePath, std::map & moduleList); 29 | void enableOFTSupport(); 30 | void enableNewIatInSection(DWORD_PTR iatAddress, DWORD iatSize); 31 | 32 | IATReferenceScan * iatReferenceScan; 33 | bool BuildDirectImportsJumpTable; 34 | private: 35 | PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; 36 | PIMAGE_THUNK_DATA pThunkData; 37 | PIMAGE_IMPORT_BY_NAME pImportByName; 38 | 39 | size_t numberOfImportDescriptors; 40 | size_t sizeOfImportSection; 41 | size_t sizeOfApiAndModuleNames; 42 | size_t importSectionIndex; 43 | 44 | //OriginalFirstThunk Array in Import Section 45 | size_t sizeOfOFTArray; 46 | bool useOFT; 47 | bool newIatInSection; 48 | DWORD_PTR IatAddress; 49 | 50 | DWORD IatSize; 51 | 52 | DWORD sizeOfJumpTable; 53 | 54 | DWORD directImportsJumpTableRVA; 55 | BYTE * JMPTableMemory; 56 | DWORD newIatBaseAddressRVA; 57 | 58 | 59 | DWORD fillImportSection(std::map & moduleList); 60 | BYTE * getMemoryPointerFromRVA(DWORD_PTR dwRVA); 61 | 62 | bool createNewImportSection(std::map & moduleList); 63 | bool buildNewImportTable(std::map & moduleList); 64 | void setFlagToIATSection(DWORD_PTR iatAddress); 65 | size_t addImportToImportTable( ImportThunk * pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset); 66 | size_t addImportDescriptor(ImportModuleThunk * pImportModule, DWORD sectionOffset, DWORD sectionOffsetOFTArray); 67 | 68 | void calculateImportSizes(std::map & moduleList); 69 | 70 | void addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk, DWORD sectionOffsetOFTArray); 71 | void patchFileForNewIatLocation(); 72 | void changeIatBaseAddress( std::map & moduleList ); 73 | void patchFileForDirectImportJumpTable(); 74 | }; -------------------------------------------------------------------------------- /Scylla/ImportsHandling.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // WTL 7 | #include 8 | #include 9 | #include // CTreeItem 10 | 11 | class CMultiSelectTreeViewCtrl; 12 | 13 | class ImportThunk; 14 | class ImportModuleThunk; 15 | 16 | class ImportsHandling 17 | { 18 | public: 19 | std::map moduleList; 20 | std::map moduleListNew; 21 | 22 | ImportsHandling(CMultiSelectTreeViewCtrl& TreeImports); 23 | ~ImportsHandling(); 24 | 25 | unsigned int thunkCount() const { return m_thunkCount; } 26 | unsigned int invalidThunkCount() const { return m_invalidThunkCount; } 27 | unsigned int suspectThunkCount() const { return m_suspectThunkCount; } 28 | 29 | bool isModule(CTreeItem item); 30 | bool isImport(CTreeItem item); 31 | 32 | ImportModuleThunk * getModuleThunk(CTreeItem item); 33 | ImportThunk * getImportThunk(CTreeItem item); 34 | 35 | void displayAllImports(); 36 | void clearAllImports(); 37 | void selectImports(bool invalid, bool suspect); 38 | 39 | bool invalidateImport(CTreeItem item); 40 | bool invalidateModule(CTreeItem item); 41 | bool setImport(CTreeItem item, const WCHAR * moduleName, const CHAR * apiName, WORD ordinal = 0, WORD hint = 0, bool valid = true, bool suspect = false); 42 | bool cutImport(CTreeItem item); 43 | bool cutModule(CTreeItem item); 44 | //bool addImport(const WCHAR * moduleName, const CHAR * name, DWORD_PTR va, DWORD_PTR rva, WORD ordinal = 0, bool valid = true, bool suspect = false); 45 | //bool addModule(const WCHAR * moduleName, DWORD_PTR firstThunk); 46 | 47 | DWORD_PTR getApiAddressByNode(CTreeItem selectedTreeNode); 48 | void scanAndFixModuleList(); 49 | void expandAllTreeNodes(); 50 | void collapseAllTreeNodes(); 51 | 52 | private: 53 | DWORD numberOfFunctions; 54 | 55 | unsigned int m_thunkCount; 56 | unsigned int m_invalidThunkCount; 57 | unsigned int m_suspectThunkCount; 58 | 59 | struct TreeItemData 60 | { 61 | bool isModule; 62 | union 63 | { 64 | ImportModuleThunk * module; 65 | ImportThunk * import; 66 | }; 67 | }; 68 | 69 | stdext::hash_map itemData; 70 | 71 | void setItemData(CTreeItem item, const TreeItemData * data); 72 | TreeItemData * getItemData(CTreeItem item); 73 | 74 | WCHAR stringBuffer[600]; 75 | 76 | CMultiSelectTreeViewCtrl& TreeImports; 77 | CImageList TreeIcons; 78 | CIcon hIconCheck; 79 | CIcon hIconWarning; 80 | CIcon hIconError; 81 | 82 | // They have to be added to the image list in that order! 83 | enum Icon { 84 | iconCheck = 0, 85 | iconWarning, 86 | iconError 87 | }; 88 | 89 | void updateCounts(); 90 | 91 | CTreeItem addDllToTreeView(CMultiSelectTreeViewCtrl& idTreeView, ImportModuleThunk * moduleThunk); 92 | CTreeItem addApiToTreeView(CMultiSelectTreeViewCtrl& idTreeView, CTreeItem parentDll, ImportThunk * importThunk); 93 | 94 | void updateImportInTreeView(const ImportThunk * importThunk, CTreeItem item); 95 | void updateModuleInTreeView(const ImportModuleThunk * importThunk, CTreeItem item); 96 | 97 | //bool isItemSelected(CTreeItem hItem); 98 | //void unselectItem(CTreeItem htItem); 99 | //bool selectItem(CTreeItem hItem, bool select = true); 100 | bool findNewModules(std::map & thunkList); 101 | 102 | Icon getAppropiateIcon(const ImportThunk * importThunk); 103 | Icon getAppropiateIcon(bool valid); 104 | 105 | bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk); 106 | void addUnknownModuleToModuleList(DWORD_PTR firstThunk); 107 | bool addNotFoundApiToModuleList(const ImportThunk * apiNotFound); 108 | bool addFunctionToModuleList(const ImportThunk * apiFound); 109 | bool isNewModule(const WCHAR * moduleName); 110 | 111 | void changeExpandStateOfTreeNodes(UINT flag); 112 | 113 | }; 114 | -------------------------------------------------------------------------------- /Scylla/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.h" 2 | 3 | #include 4 | //#include 5 | #include 6 | #include 7 | #include 8 | 9 | extern bool IsDllMode; 10 | 11 | void Logger::log(const WCHAR * format, ...) 12 | { 13 | static WCHAR buf[300]; 14 | 15 | if(!format) 16 | return; 17 | 18 | va_list va_alist; 19 | va_start (va_alist, format); 20 | _vsnwprintf_s(buf, _countof(buf) - 1, format, va_alist); 21 | va_end (va_alist); 22 | 23 | write(buf); 24 | } 25 | 26 | void Logger::log(const char * format, ...) 27 | { 28 | static char buf[300]; 29 | 30 | if(!format) 31 | return; 32 | 33 | va_list va_alist; 34 | va_start (va_alist, format); 35 | _vsnprintf_s(buf, _countof(buf) - 1, format, va_alist); 36 | va_end (va_alist); 37 | 38 | write(buf); 39 | } 40 | 41 | void Logger::write(const CHAR * str) 42 | { 43 | write(ATL::CA2W(str)); 44 | } 45 | 46 | FileLog::FileLog(const WCHAR * fileName) 47 | { 48 | GetModuleFileName(0, this->filePath, _countof(this->filePath)); 49 | PathRemoveFileSpec(this->filePath); 50 | PathAppend(this->filePath, fileName); 51 | } 52 | 53 | void FileLog::write(const CHAR * str) 54 | { 55 | /* 56 | std::wofstream file(filePath, std::wofstream::app); 57 | if(!file.fail()) 58 | { 59 | file << str << std::endl; 60 | } 61 | */ 62 | 63 | FILE * pFile = 0; 64 | if (_wfopen_s(&pFile, filePath, L"a") == 0) 65 | { 66 | fputs(str, pFile); 67 | fputs("\r\n", pFile); 68 | fclose(pFile); 69 | } 70 | } 71 | 72 | void FileLog::write(const WCHAR * str) 73 | { 74 | /* 75 | std::wofstream file(filePath, std::wofstream::app); 76 | if(!file.fail()) 77 | { 78 | file << str << std::endl; 79 | } 80 | */ 81 | 82 | FILE * pFile = 0; 83 | if (_wfopen_s(&pFile, filePath, L"a") == 0) 84 | { 85 | fputws(str, pFile); 86 | fputws(L"\r\n", pFile); 87 | fclose(pFile); 88 | } 89 | } 90 | 91 | void ListboxLog::setWindow(HWND window) 92 | { 93 | this->window = window; 94 | } 95 | 96 | void ListboxLog::write(const WCHAR* str) 97 | { 98 | if (IsDllMode == false) 99 | { 100 | LRESULT index = SendMessageW(window, LB_ADDSTRING, 0, reinterpret_cast(str)); 101 | SendMessage(window, LB_SETCURSEL, index, 0); 102 | UpdateWindow(window); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Scylla/Logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Logger 6 | { 7 | public: 8 | 9 | virtual void log(const WCHAR * format, ...); 10 | virtual void log(const CHAR * format, ...); 11 | 12 | protected: 13 | 14 | virtual void write(const WCHAR * str) = 0; 15 | virtual void write(const CHAR * str); 16 | }; 17 | 18 | class FileLog : public Logger 19 | { 20 | public: 21 | 22 | FileLog(const WCHAR * fileName); 23 | 24 | private: 25 | 26 | void write(const WCHAR * str); 27 | void write(const CHAR * str); 28 | 29 | WCHAR filePath[MAX_PATH]; 30 | }; 31 | 32 | class ListboxLog : public Logger 33 | { 34 | public: 35 | 36 | ListboxLog() : window(0) { } 37 | ListboxLog(HWND window); 38 | 39 | void setWindow(HWND window); 40 | 41 | private: 42 | 43 | void write(const WCHAR * str); 44 | //void write(const CHAR * str); 45 | 46 | HWND window; 47 | }; 48 | -------------------------------------------------------------------------------- /Scylla/MainGui.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/MainGui.rc -------------------------------------------------------------------------------- /Scylla/NativeWinApi.cpp: -------------------------------------------------------------------------------- 1 | #include "NativeWinApi.h" 2 | 3 | def_NtCreateThreadEx NativeWinApi::NtCreateThreadEx = 0; 4 | def_NtDuplicateObject NativeWinApi::NtDuplicateObject = 0; 5 | def_NtOpenProcess NativeWinApi::NtOpenProcess = 0; 6 | def_NtOpenThread NativeWinApi::NtOpenThread = 0; 7 | def_NtQueryObject NativeWinApi::NtQueryObject = 0; 8 | def_NtQueryInformationFile NativeWinApi::NtQueryInformationFile = 0; 9 | def_NtQueryInformationProcess NativeWinApi::NtQueryInformationProcess = 0; 10 | def_NtQueryInformationThread NativeWinApi::NtQueryInformationThread = 0; 11 | def_NtQuerySystemInformation NativeWinApi::NtQuerySystemInformation = 0; 12 | def_NtQueryVirtualMemory NativeWinApi::NtQueryVirtualMemory = 0; 13 | def_NtResumeProcess NativeWinApi::NtResumeProcess = 0; 14 | def_NtResumeThread NativeWinApi::NtResumeThread = 0; 15 | def_NtSetInformationThread NativeWinApi::NtSetInformationThread = 0; 16 | def_NtSuspendProcess NativeWinApi::NtSuspendProcess = 0; 17 | def_NtTerminateProcess NativeWinApi::NtTerminateProcess = 0; 18 | 19 | def_NtOpenSymbolicLinkObject NativeWinApi::NtOpenSymbolicLinkObject = 0; 20 | def_NtQuerySymbolicLinkObject NativeWinApi::NtQuerySymbolicLinkObject = 0; 21 | 22 | def_RtlNtStatusToDosError NativeWinApi::RtlNtStatusToDosError = 0; 23 | def_NtClose NativeWinApi::NtClose = 0; 24 | 25 | void NativeWinApi::initialize() 26 | { 27 | if (RtlNtStatusToDosError) 28 | { 29 | return; 30 | } 31 | 32 | HMODULE hModuleNtdll = GetModuleHandle(L"ntdll.dll"); 33 | 34 | if (!hModuleNtdll) 35 | { 36 | return; 37 | } 38 | 39 | NtCreateThreadEx = (def_NtCreateThreadEx)GetProcAddress(hModuleNtdll, "NtCreateThreadEx"); 40 | NtDuplicateObject = (def_NtDuplicateObject)GetProcAddress(hModuleNtdll, "NtDuplicateObject"); 41 | NtOpenProcess = (def_NtOpenProcess)GetProcAddress(hModuleNtdll, "NtOpenProcess"); 42 | NtOpenThread = (def_NtOpenThread)GetProcAddress(hModuleNtdll, "NtOpenThread"); 43 | NtQueryObject = (def_NtQueryObject)GetProcAddress(hModuleNtdll, "NtQueryObject"); 44 | NtQueryInformationFile = (def_NtQueryInformationFile)GetProcAddress(hModuleNtdll, "NtQueryInformationFile"); 45 | NtQueryInformationProcess = (def_NtQueryInformationProcess)GetProcAddress(hModuleNtdll, "NtQueryInformationProcess"); 46 | NtQueryInformationThread = (def_NtQueryInformationThread)GetProcAddress(hModuleNtdll, "NtQueryInformationThread"); 47 | NtQuerySystemInformation = (def_NtQuerySystemInformation)GetProcAddress(hModuleNtdll, "NtQuerySystemInformation"); 48 | NtQueryVirtualMemory = (def_NtQueryVirtualMemory)GetProcAddress(hModuleNtdll, "NtQueryVirtualMemory"); 49 | NtResumeProcess = (def_NtResumeProcess)GetProcAddress(hModuleNtdll, "NtResumeProcess"); 50 | NtResumeThread = (def_NtResumeThread)GetProcAddress(hModuleNtdll, "NtResumeThread"); 51 | NtSetInformationThread = (def_NtSetInformationThread)GetProcAddress(hModuleNtdll, "NtSetInformationThread"); 52 | NtSuspendProcess = (def_NtSuspendProcess)GetProcAddress(hModuleNtdll, "NtSuspendProcess"); 53 | NtTerminateProcess = (def_NtTerminateProcess)GetProcAddress(hModuleNtdll, "NtTerminateProcess"); 54 | NtOpenSymbolicLinkObject = (def_NtOpenSymbolicLinkObject)GetProcAddress(hModuleNtdll, "NtOpenSymbolicLinkObject"); 55 | NtQuerySymbolicLinkObject = (def_NtQuerySymbolicLinkObject)GetProcAddress(hModuleNtdll, "NtQuerySymbolicLinkObject"); 56 | 57 | RtlNtStatusToDosError = (def_RtlNtStatusToDosError)GetProcAddress(hModuleNtdll, "RtlNtStatusToDosError"); 58 | NtClose = (def_NtClose)GetProcAddress(hModuleNtdll, "NtClose"); 59 | } 60 | 61 | 62 | PPEB NativeWinApi::getCurrentProcessEnvironmentBlock() 63 | { 64 | return getProcessEnvironmentBlockAddress(GetCurrentProcess()); 65 | } 66 | 67 | PPEB NativeWinApi::getProcessEnvironmentBlockAddress(HANDLE processHandle) 68 | { 69 | ULONG lReturnLength = 0; 70 | PROCESS_BASIC_INFORMATION processBasicInformation; 71 | 72 | if ((NtQueryInformationProcess(processHandle,ProcessBasicInformation,&processBasicInformation,sizeof(PROCESS_BASIC_INFORMATION),&lReturnLength) >= 0) && (lReturnLength == sizeof(PROCESS_BASIC_INFORMATION))) 73 | { 74 | //printf("NtQueryInformationProcess success %d\n",sizeof(PROCESS_BASIC_INFORMATION)); 75 | 76 | return processBasicInformation.PebBaseAddress; 77 | } 78 | else 79 | { 80 | //printf("NtQueryInformationProcess failed %d vs %d\n",lReturnLength,sizeof(PROCESS_BASIC_INFORMATION)); 81 | return 0; 82 | } 83 | } -------------------------------------------------------------------------------- /Scylla/OptionsGui.cpp: -------------------------------------------------------------------------------- 1 | #include "OptionsGui.h" 2 | #include "Scylla.h" 3 | 4 | BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) 5 | { 6 | loadOptions(); 7 | DoDataExchange(DDX_LOAD); // show settings 8 | 9 | EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME); 10 | 11 | CenterWindow(); 12 | 13 | return TRUE; 14 | } 15 | 16 | void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) 17 | { 18 | DoDataExchange(DDX_SAVE); 19 | saveOptions(); 20 | Scylla::config.saveConfiguration(); 21 | 22 | EndDialog(0); 23 | } 24 | 25 | void OptionsGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) 26 | { 27 | EndDialog(0); 28 | } 29 | 30 | void OptionsGui::saveOptions() const 31 | { 32 | Scylla::config[USE_PE_HEADER_FROM_DISK].setBool(usePEHeaderFromDisk); 33 | Scylla::config[DEBUG_PRIVILEGE].setBool(debugPrivilege); 34 | Scylla::config[CREATE_BACKUP].setBool(createBackup); 35 | Scylla::config[DLL_INJECTION_AUTO_UNLOAD].setBool(dllInjectionAutoUnload); 36 | Scylla::config[UPDATE_HEADER_CHECKSUM].setBool(updateHeaderChecksum); 37 | Scylla::config[IAT_SECTION_NAME].setString(iatSectionName); 38 | Scylla::config[REMOVE_DOS_HEADER_STUB].setBool(removeDosHeaderStub); 39 | Scylla::config[IAT_FIX_AND_OEP_FIX].setBool(fixIatAndOep); 40 | Scylla::config[SUSPEND_PROCESS_FOR_DUMPING].setBool(suspendProcessForDumping); 41 | Scylla::config[OriginalFirstThunk_SUPPORT].setBool(oftSupport); 42 | Scylla::config[USE_ADVANCED_IAT_SEARCH].setBool(useAdvancedIatSearch); 43 | Scylla::config[SCAN_DIRECT_IMPORTS].setBool(scanDirectImports); 44 | Scylla::config[FIX_DIRECT_IMPORTS_NORMAL].setBool(fixDirectImportsNormal); 45 | Scylla::config[FIX_DIRECT_IMPORTS_UNIVERSAL].setBool(fixDirectImportsUniversal); 46 | Scylla::config[CREATE_NEW_IAT_IN_SECTION].setBool(createNewIatInSection); 47 | Scylla::config[DONT_CREATE_NEW_SECTION].setBool(dontCreateNewSection); 48 | Scylla::config[APIS_ALWAYS_FROM_DISK].setBool(readApisAlwaysFromDisk); 49 | } 50 | 51 | void OptionsGui::loadOptions() 52 | { 53 | usePEHeaderFromDisk = Scylla::config[USE_PE_HEADER_FROM_DISK].getBool(); 54 | debugPrivilege = Scylla::config[DEBUG_PRIVILEGE].getBool(); 55 | createBackup = Scylla::config[CREATE_BACKUP].getBool(); 56 | dllInjectionAutoUnload = Scylla::config[DLL_INJECTION_AUTO_UNLOAD].getBool(); 57 | updateHeaderChecksum = Scylla::config[UPDATE_HEADER_CHECKSUM].getBool(); 58 | wcsncpy_s(iatSectionName, Scylla::config[IAT_SECTION_NAME].getString(), _countof(iatSectionName)-1); 59 | iatSectionName[_countof(iatSectionName) - 1] = L'\0'; 60 | 61 | removeDosHeaderStub = Scylla::config[REMOVE_DOS_HEADER_STUB].getBool(); 62 | fixIatAndOep = Scylla::config[IAT_FIX_AND_OEP_FIX].getBool(); 63 | suspendProcessForDumping = Scylla::config[SUSPEND_PROCESS_FOR_DUMPING].getBool(); 64 | oftSupport = Scylla::config[OriginalFirstThunk_SUPPORT].getBool(); 65 | useAdvancedIatSearch = Scylla::config[USE_ADVANCED_IAT_SEARCH].getBool(); 66 | scanDirectImports = Scylla::config[SCAN_DIRECT_IMPORTS].getBool(); 67 | fixDirectImportsNormal = Scylla::config[FIX_DIRECT_IMPORTS_NORMAL].getBool(); 68 | fixDirectImportsUniversal = Scylla::config[FIX_DIRECT_IMPORTS_UNIVERSAL].getBool(); 69 | createNewIatInSection = Scylla::config[CREATE_NEW_IAT_IN_SECTION].getBool(); 70 | dontCreateNewSection = Scylla::config[DONT_CREATE_NEW_SECTION].getBool(); 71 | readApisAlwaysFromDisk = Scylla::config[APIS_ALWAYS_FROM_DISK].getBool(); 72 | } 73 | -------------------------------------------------------------------------------- /Scylla/OptionsGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL enhanced msg map macros 11 | #include // WTL controls 12 | #include // WTL dialog data exchange 13 | 14 | class OptionsGui : public CDialogImpl, public CWinDataExchange 15 | { 16 | public: 17 | enum { IDD = IDD_DLG_OPTIONS }; 18 | 19 | BEGIN_DDX_MAP(OptionsGui) 20 | DDX_CONTROL_HANDLE(IDC_OPTIONS_SECTIONNAME, EditSectionName) 21 | DDX_TEXT(IDC_OPTIONS_SECTIONNAME, iatSectionName) 22 | DDX_CHECK(IDC_CHECK_HEADER_CHECKSUM, updateHeaderChecksum) 23 | DDX_CHECK(IDC_CHECK_CREATE_BACKUP, createBackup) 24 | DDX_CHECK(IDC_CHECK_UNLOAD_DLL, dllInjectionAutoUnload) 25 | DDX_CHECK(IDC_CHECK_PE_HEADER_FROM_DISK, usePEHeaderFromDisk) 26 | DDX_CHECK(IDC_CHECK_DEBUG_PRIVILEGES, debugPrivilege) 27 | DDX_CHECK(IDC_CHECK_REMOVE_DOS_STUB, removeDosHeaderStub) 28 | DDX_CHECK(IDC_CHECK_FIX_IAT_AND_OEP, fixIatAndOep) 29 | DDX_CHECK(IDC_CHECK_SUSPEND_PROCESS, suspendProcessForDumping) 30 | DDX_CHECK(IDC_CHECKOFTSUPPORT, oftSupport) 31 | DDX_CHECK(IDC_CHECK_USEADVANCEDIATSEARCH, useAdvancedIatSearch) 32 | DDX_CHECK(IDC_SCANDIRECTIMPORT, scanDirectImports) 33 | DDX_CHECK(IDC_FIXDIRECTIMPORTSNORMAL, fixDirectImportsNormal) 34 | DDX_CHECK(IDC_FIXDIRECTIMPORTSUNIVERSAL, fixDirectImportsUniversal) 35 | DDX_CHECK(IDC_NEWIATINSECTION, createNewIatInSection) 36 | DDX_CHECK(IDC_CHECKNOSECTION, dontCreateNewSection) 37 | DDX_CHECK(IDC_CHECKAPIALWAYSDISK, readApisAlwaysFromDisk) 38 | END_DDX_MAP() 39 | 40 | BEGIN_MSG_MAP(OptionsGui) 41 | MSG_WM_INITDIALOG(OnInitDialog) 42 | 43 | COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_OK, OnOK) 44 | COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_CANCEL, OnCancel) 45 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 46 | END_MSG_MAP() 47 | 48 | protected: 49 | 50 | // Settings (filled by DDX) 51 | 52 | WCHAR iatSectionName[IMAGE_SIZEOF_SHORT_NAME+1]; 53 | bool updateHeaderChecksum; 54 | bool createBackup; 55 | bool dllInjectionAutoUnload; 56 | bool usePEHeaderFromDisk; 57 | bool debugPrivilege; 58 | bool removeDosHeaderStub; 59 | bool fixIatAndOep; 60 | bool suspendProcessForDumping; 61 | bool oftSupport; 62 | bool useAdvancedIatSearch; 63 | bool scanDirectImports; 64 | bool fixDirectImportsNormal; 65 | bool fixDirectImportsUniversal; 66 | bool createNewIatInSection; 67 | bool dontCreateNewSection; 68 | bool readApisAlwaysFromDisk; 69 | // Controls 70 | 71 | CEdit EditSectionName; 72 | 73 | // Message handlers 74 | 75 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 76 | 77 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 78 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 79 | 80 | // Gui helpers 81 | 82 | void saveOptions() const; 83 | void loadOptions(); 84 | }; 85 | -------------------------------------------------------------------------------- /Scylla/PeParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "DumpSectionGui.h" 6 | 7 | class PeFileSection { 8 | public: 9 | IMAGE_SECTION_HEADER sectionHeader; 10 | BYTE * data; 11 | DWORD dataSize; 12 | DWORD normalSize; 13 | 14 | PeFileSection() 15 | { 16 | ZeroMemory(§ionHeader, sizeof(IMAGE_SECTION_HEADER)); 17 | data = 0; 18 | dataSize = 0; 19 | normalSize = 0; 20 | } 21 | }; 22 | 23 | class PeParser 24 | { 25 | public: 26 | PeParser(const WCHAR * file, bool readSectionHeaders = true); 27 | PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders = true); 28 | 29 | ~PeParser(); 30 | 31 | bool isValidPeFile(); 32 | bool isPE64(); 33 | bool isPE32(); 34 | 35 | bool isTargetFileSamePeFormat(); 36 | 37 | WORD getNumberOfSections(); 38 | std::vector & getSectionHeaderList(); 39 | 40 | bool hasExportDirectory(); 41 | bool hasTLSDirectory(); 42 | bool hasRelocationDirectory(); 43 | bool hasOverlayData(); 44 | 45 | DWORD getEntryPoint(); 46 | 47 | bool getSectionNameUnicode(const int sectionIndex, WCHAR * output, const int outputLen); 48 | 49 | DWORD getSectionHeaderBasedFileSize(); 50 | DWORD getSectionHeaderBasedSizeOfImage(); 51 | 52 | bool readPeSectionsFromProcess(); 53 | bool readPeSectionsFromFile(); 54 | bool savePeFileToDisk(const WCHAR * newFile); 55 | void removeDosStub(); 56 | void alignAllSectionHeaders(); 57 | void fixPeHeader(); 58 | void setDefaultFileAlignment(); 59 | bool dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR * dumpFilePath); 60 | bool dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR * dumpFilePath, std::vector & sectionList); 61 | 62 | void setEntryPointVa(DWORD_PTR entryPoint); 63 | void setEntryPointRva(DWORD entryPoint); 64 | 65 | static bool updatePeHeaderChecksum(const WCHAR * targetFile, DWORD fileSize); 66 | BYTE * getSectionMemoryByIndex(int index); 67 | DWORD getSectionMemorySizeByIndex(int index); 68 | int convertRVAToOffsetVectorIndex(DWORD_PTR dwRVA); 69 | DWORD_PTR convertOffsetToRVAVector(DWORD_PTR dwOffset); 70 | DWORD_PTR convertRVAToOffsetVector(DWORD_PTR dwRVA); 71 | DWORD_PTR convertRVAToOffsetRelative(DWORD_PTR dwRVA); 72 | DWORD getSectionAddressRVAByIndex( int index ); 73 | 74 | PIMAGE_NT_HEADERS getCurrentNtHeader(); 75 | protected: 76 | PeParser(); 77 | 78 | 79 | static const DWORD FileAlignmentConstant = 0x200; 80 | 81 | const WCHAR * filename; 82 | DWORD_PTR moduleBaseAddress; 83 | 84 | /************************************************************************/ 85 | /* PE FILE */ 86 | /* */ 87 | /* IMAGE_DOS_HEADER 64 0x40 */ 88 | /* IMAGE_NT_HEADERS32 248 0xF8 */ 89 | /* IMAGE_NT_HEADERS64 264 0x108 */ 90 | /* IMAGE_SECTION_HEADER 40 0x28 */ 91 | /************************************************************************/ 92 | 93 | PIMAGE_DOS_HEADER pDosHeader; 94 | BYTE * pDosStub; //between dos header and section header 95 | DWORD dosStubSize; 96 | PIMAGE_NT_HEADERS32 pNTHeader32; 97 | PIMAGE_NT_HEADERS64 pNTHeader64; 98 | std::vector listPeSection; 99 | BYTE * overlayData; 100 | DWORD overlaySize; 101 | /************************************************************************/ 102 | 103 | BYTE * fileMemory; 104 | BYTE * headerMemory; 105 | 106 | HANDLE hFile; 107 | DWORD fileSize; 108 | 109 | bool readPeHeaderFromFile(bool readSectionHeaders); 110 | bool readPeHeaderFromProcess(bool readSectionHeaders); 111 | 112 | bool hasDirectory(const int directoryIndex); 113 | bool getSectionHeaders(); 114 | void getDosAndNtHeader(BYTE * memory, LONG size); 115 | DWORD calcCorrectPeHeaderSize( bool readSectionHeaders ); 116 | DWORD getInitialHeaderReadSize( bool readSectionHeaders ); 117 | bool openFileHandle(); 118 | void closeFileHandle(); 119 | void initClass(); 120 | 121 | DWORD isMemoryNotNull( BYTE * data, int dataSize ); 122 | bool openWriteFileHandle( const WCHAR * newFile ); 123 | bool writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size); 124 | 125 | bool readPeSectionFromFile( DWORD readOffset, PeFileSection & peFileSection ); 126 | bool readPeSectionFromProcess( DWORD_PTR readOffset, PeFileSection & peFileSection ); 127 | 128 | bool readSectionFromProcess(const DWORD_PTR readOffset, PeFileSection & peFileSection ); 129 | bool readSectionFromFile(const DWORD readOffset, PeFileSection & peFileSection ); 130 | bool readSectionFrom(const DWORD_PTR readOffset, PeFileSection & peFileSection, const bool isProcess); 131 | 132 | 133 | DWORD_PTR getStandardImagebase(); 134 | 135 | bool addNewLastSection(const CHAR * sectionName, DWORD sectionSize, BYTE * sectionData); 136 | DWORD alignValue(DWORD badValue, DWORD alignTo); 137 | 138 | void setNumberOfSections(WORD numberOfSections); 139 | 140 | void removeIatDirectory(); 141 | bool getFileOverlay(); 142 | 143 | }; 144 | 145 | -------------------------------------------------------------------------------- /Scylla/PeRebuild.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | enum ReBaseErr 7 | { 8 | RB_OK = 0, 9 | RB_INVALIDPE, 10 | RB_NORELOCATIONINFO, 11 | RB_INVALIDRVA, 12 | RB_INVALIDNEWBASE, 13 | RB_ACCESSVIOLATION 14 | }; 15 | 16 | /***************************************************************************** 17 | Improved Realign DLL version 1.5 by yoda 18 | *****************************************************************************/ 19 | 20 | class PeRebuild 21 | { 22 | public: 23 | 24 | bool truncateFile(WCHAR * szFilePath, DWORD dwNewFsize); 25 | DWORD realignPE(LPVOID AddressOfMapFile,DWORD dwFsize); 26 | DWORD wipeReloc(void* pMap, DWORD dwFsize); 27 | bool validatePE(void* pPEImage, DWORD dwFileSize); 28 | ReBaseErr reBasePEImage(void* pPE, DWORD_PTR dwNewBase); 29 | 30 | bool updatePeHeaderChecksum(LPVOID AddressOfMapFile, DWORD dwFsize); 31 | 32 | LPVOID createFileMappingViewFull(const WCHAR * filePath); 33 | void closeAllMappingHandles(); 34 | 35 | private: 36 | 37 | // constants 38 | static const size_t MAX_SEC_NUM = 30; 39 | 40 | static const DWORD ScanStartDS = 0x40; 41 | static const int MinSectionTerm = 5; 42 | static const int FileAlignmentConstant = 0x200; 43 | 44 | // variables 45 | DWORD_PTR dwMapBase; 46 | LPVOID pMap; 47 | DWORD dwTmpNum,dwSectionBase; 48 | WORD wTmpNum; 49 | CHAR * pCH; 50 | WORD * pW; 51 | DWORD * pDW; 52 | LPVOID pSections[MAX_SEC_NUM]; 53 | 54 | //my vars 55 | HANDLE hFileToMap; 56 | HANDLE hMappedFile; 57 | LPVOID addrMappedDll; 58 | 59 | 60 | DWORD validAlignment(DWORD BadSize); 61 | DWORD validAlignmentNew(DWORD badAddress); 62 | bool isRoundedTo(DWORD_PTR dwTarNum, DWORD_PTR dwRoundNum); 63 | 64 | void cleanSectionPointer(); 65 | bool validatePeHeaders( PIMAGE_DOS_HEADER pDosh ); 66 | }; 67 | -------------------------------------------------------------------------------- /Scylla/PickApiGui.cpp: -------------------------------------------------------------------------------- 1 | #include "PickApiGui.h" 2 | 3 | #include // string conversion 4 | 5 | PickApiGui::PickApiGui(const std::vector &moduleList) : moduleList(moduleList) 6 | { 7 | selectedApi = 0; 8 | } 9 | 10 | BOOL PickApiGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) 11 | { 12 | DoDataExchange(); // attach controls 13 | DlgResize_Init(true, true); 14 | 15 | fillDllComboBox(ComboDllSelect); 16 | 17 | CenterWindow(); 18 | return TRUE; 19 | } 20 | 21 | void PickApiGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) 22 | { 23 | actionApiSelected(); 24 | } 25 | 26 | void PickApiGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) 27 | { 28 | EndDialog(0); 29 | } 30 | 31 | void PickApiGui::OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) 32 | { 33 | int indexDll = ComboDllSelect.GetCurSel(); 34 | if (indexDll != CB_ERR) 35 | { 36 | fillApiListBox(ListApiSelect, moduleList[indexDll].apiList); 37 | EditApiFilter.SetWindowText(L""); 38 | } 39 | } 40 | 41 | void PickApiGui::OnApiListDoubleClick(UINT uNotifyCode, int nID, CWindow wndCtl) 42 | { 43 | actionApiSelected(); 44 | } 45 | 46 | void PickApiGui::OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl) 47 | { 48 | int indexDll = ComboDllSelect.GetCurSel(); 49 | if (indexDll == CB_ERR) 50 | return; 51 | 52 | std::vector newApis; 53 | WCHAR filter[MAX_PATH]; 54 | 55 | int lenFilter = EditApiFilter.GetWindowText(filter, _countof(filter)); 56 | if(lenFilter > 0) 57 | { 58 | const std::vector &apis = moduleList[indexDll].apiList; 59 | 60 | for (size_t i = 0; i < apis.size(); i++) 61 | { 62 | ApiInfo* api = apis[i]; 63 | if(api->name[0] != '\0') 64 | { 65 | CA2WEX wStr(api->name); 66 | if(!_wcsnicmp(wStr, filter, lenFilter)) 67 | { 68 | newApis.push_back(api); 69 | } 70 | } 71 | else 72 | { 73 | WCHAR buf[6]; 74 | swprintf_s(buf, L"#%04X", api->ordinal); 75 | if(!_wcsnicmp(buf, filter, lenFilter)) 76 | { 77 | newApis.push_back(api); 78 | } 79 | } 80 | } 81 | } 82 | else 83 | { 84 | newApis = moduleList[indexDll].apiList; 85 | } 86 | 87 | fillApiListBox(ListApiSelect, newApis); 88 | } 89 | 90 | void PickApiGui::actionApiSelected() 91 | { 92 | int indexDll = ComboDllSelect.GetCurSel(); 93 | int indexApi; 94 | if(ListApiSelect.GetCount() == 1) 95 | { 96 | indexApi = 0; 97 | } 98 | else 99 | { 100 | indexApi = ListApiSelect.GetCurSel(); 101 | } 102 | if (indexDll != CB_ERR && indexApi != LB_ERR) 103 | { 104 | selectedApi = (ApiInfo *)ListApiSelect.GetItemData(indexApi); 105 | EndDialog(1); 106 | } 107 | } 108 | 109 | void PickApiGui::fillDllComboBox(CComboBox& combo) 110 | { 111 | combo.ResetContent(); 112 | 113 | for (size_t i = 0; i < moduleList.size(); i++) 114 | { 115 | combo.AddString(moduleList[i].fullPath); 116 | } 117 | } 118 | 119 | void PickApiGui::fillApiListBox(CListBox& list, const std::vector &apis) 120 | { 121 | list.ResetContent(); 122 | 123 | for (size_t i = 0; i < apis.size(); i++) 124 | { 125 | const ApiInfo* api = apis[i]; 126 | int item; 127 | if(api->name[0] != '\0') 128 | { 129 | CA2WEX wStr(api->name); 130 | item = list.AddString(wStr); 131 | } 132 | else 133 | { 134 | WCHAR buf[6]; 135 | swprintf_s(buf, L"#%04X", api->ordinal); 136 | item = list.AddString(buf); 137 | } 138 | list.SetItemData(item, (DWORD_PTR)api); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Scylla/PickApiGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL window frame helpers 11 | #include // WTL utility classes 12 | #include // WTL enhanced msg map macros 13 | #include // WTL controls 14 | #include // WTL dialog data exchange 15 | 16 | #include 17 | #include "ProcessAccessHelp.h" // ModuleInfo, ApiInfo 18 | 19 | class PickApiGui : public CDialogImpl, public CWinDataExchange, public CDialogResize 20 | { 21 | public: 22 | enum { IDD = IDD_DLG_PICKAPI }; 23 | 24 | BEGIN_DDX_MAP(PickApiGui) 25 | DDX_CONTROL_HANDLE(IDC_CBO_DLLSELECT, ComboDllSelect) 26 | DDX_CONTROL_HANDLE(IDC_LIST_APISELECT, ListApiSelect) 27 | DDX_CONTROL_HANDLE(IDC_EDIT_APIFILTER, EditApiFilter) 28 | END_DDX_MAP() 29 | 30 | BEGIN_MSG_MAP(PickDllGui) 31 | MSG_WM_INITDIALOG(OnInitDialog) 32 | 33 | COMMAND_HANDLER_EX(IDC_CBO_DLLSELECT, CBN_SELENDOK, OnDllListSelected) 34 | COMMAND_HANDLER_EX(IDC_LIST_APISELECT, LBN_DBLCLK, OnApiListDoubleClick) 35 | COMMAND_HANDLER_EX(IDC_EDIT_APIFILTER, EN_UPDATE, OnApiFilterUpdated) 36 | 37 | COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_OK, OnOK) 38 | COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_CANCEL, OnCancel) 39 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 40 | 41 | CHAIN_MSG_MAP(CDialogResize) 42 | END_MSG_MAP() 43 | 44 | BEGIN_DLGRESIZE_MAP(PickApiGui) 45 | DLGRESIZE_CONTROL(IDC_GROUP_DLL, DLSZ_SIZE_X) 46 | DLGRESIZE_CONTROL(IDC_CBO_DLLSELECT, DLSZ_SIZE_X) 47 | 48 | DLGRESIZE_CONTROL(IDC_GROUP_APIS, DLSZ_SIZE_X | DLSZ_SIZE_Y) 49 | DLGRESIZE_CONTROL(IDC_LIST_APISELECT, DLSZ_SIZE_X | DLSZ_SIZE_Y) 50 | DLGRESIZE_CONTROL(IDC_STATIC_APIFILTER, DLSZ_MOVE_Y) 51 | DLGRESIZE_CONTROL(IDC_EDIT_APIFILTER, DLSZ_MOVE_Y | DLSZ_SIZE_X) 52 | 53 | DLGRESIZE_CONTROL(IDC_BTN_PICKAPI_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 54 | DLGRESIZE_CONTROL(IDC_BTN_PICKAPI_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) 55 | END_DLGRESIZE_MAP() 56 | 57 | PickApiGui(const std::vector &moduleList); 58 | 59 | ApiInfo* getSelectedApi() const { return selectedApi; } 60 | 61 | protected: 62 | 63 | // Variables 64 | 65 | const std::vector &moduleList; 66 | ApiInfo* selectedApi; 67 | 68 | // Controls 69 | 70 | CComboBox ComboDllSelect; 71 | CListBox ListApiSelect; 72 | CEdit EditApiFilter; 73 | 74 | protected: 75 | 76 | // Message handlers 77 | 78 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 79 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 80 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 81 | 82 | void OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); 83 | void OnApiListDoubleClick(UINT uNotifyCode, int nID, CWindow wndCtl); 84 | void OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl); 85 | 86 | // Actions 87 | 88 | void actionApiSelected(); 89 | 90 | // GUI functions 91 | 92 | void fillDllComboBox(CComboBox& combo); 93 | void fillApiListBox(CListBox& list, const std::vector &apis); 94 | }; 95 | -------------------------------------------------------------------------------- /Scylla/PickDllGui.cpp: -------------------------------------------------------------------------------- 1 | #include "PickDllGui.h" 2 | 3 | #include "Architecture.h" 4 | 5 | PickDllGui::PickDllGui(std::vector &moduleList) : moduleList(moduleList) 6 | { 7 | selectedModule = 0; 8 | 9 | prevColumn = -1; 10 | ascending = true; 11 | } 12 | 13 | BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) 14 | { 15 | DoDataExchange(); // attach controls 16 | DlgResize_Init(true, true); 17 | 18 | addColumnsToModuleList(ListDLLSelect); 19 | displayModuleList(ListDLLSelect); 20 | 21 | CenterWindow(); 22 | return TRUE; 23 | } 24 | 25 | LRESULT PickDllGui::OnListDllColumnClicked(NMHDR* pnmh) 26 | { 27 | NMLISTVIEW* list = (NMLISTVIEW*)pnmh; 28 | int column = list->iSubItem; 29 | 30 | if(column == prevColumn) 31 | { 32 | ascending = !ascending; 33 | } 34 | else 35 | { 36 | prevColumn = column; 37 | ascending = true; 38 | } 39 | 40 | // lo-byte: column, hi-byte: sort-order 41 | ListDLLSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); 42 | 43 | return 0; 44 | } 45 | 46 | LRESULT PickDllGui::OnListDllDoubleClick(NMHDR* pnmh) 47 | { 48 | NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh; 49 | LVHITTESTINFO hti; 50 | hti.pt = ia->ptAction; 51 | int clicked = ListDLLSelect.HitTest(&hti); 52 | if(clicked != -1) 53 | { 54 | selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(clicked); 55 | EndDialog(1); 56 | } 57 | return 0; 58 | } 59 | 60 | void PickDllGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) 61 | { 62 | int index = ListDLLSelect.GetSelectionMark(); 63 | if (index != -1) 64 | { 65 | selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(index); 66 | EndDialog(1); 67 | } 68 | } 69 | 70 | void PickDllGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) 71 | { 72 | EndDialog(0); 73 | } 74 | 75 | void PickDllGui::addColumnsToModuleList(CListViewCtrl& list) 76 | { 77 | list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); 78 | 79 | list.InsertColumn(COL_NAME, L"Name", LVCFMT_LEFT); 80 | list.InsertColumn(COL_IMAGEBASE, L"ImageBase", LVCFMT_CENTER); 81 | list.InsertColumn(COL_IMAGESIZE, L"ImageSize", LVCFMT_CENTER); 82 | list.InsertColumn(COL_PATH, L"Path", LVCFMT_LEFT); 83 | } 84 | 85 | void PickDllGui::displayModuleList(CListViewCtrl& list) 86 | { 87 | WCHAR temp[20]; 88 | 89 | list.DeleteAllItems(); 90 | 91 | std::vector::const_iterator iter; 92 | int count = 0; 93 | 94 | for( iter = moduleList.begin(); iter != moduleList.end(); iter++ , count++) 95 | { 96 | list.InsertItem(count, iter->getFilename()); 97 | 98 | swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->modBaseAddr); 99 | 100 | list.SetItemText(count, COL_IMAGEBASE, temp); 101 | 102 | swprintf_s(temp, L"%08X",iter->modBaseSize); 103 | list.SetItemText(count, COL_IMAGESIZE, temp); 104 | 105 | list.SetItemText(count, COL_PATH, iter->fullPath); 106 | 107 | list.SetItemData(count, (DWORD_PTR)&(*iter)); 108 | } 109 | 110 | list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER); 111 | list.SetColumnWidth(COL_IMAGEBASE, LVSCW_AUTOSIZE_USEHEADER); 112 | list.SetColumnWidth(COL_IMAGESIZE, LVSCW_AUTOSIZE_USEHEADER); 113 | list.SetColumnWidth(COL_PATH, LVSCW_AUTOSIZE_USEHEADER); 114 | } 115 | 116 | // lParamSort - lo-byte: column, hi-byte: sort-order 117 | int PickDllGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 118 | { 119 | const ModuleInfo * module1 = (ModuleInfo *)lParam1; 120 | const ModuleInfo * module2 = (ModuleInfo *)lParam2; 121 | 122 | int column = LOBYTE(lParamSort); 123 | bool ascending = (HIBYTE(lParamSort) == TRUE); 124 | 125 | int diff = 0; 126 | 127 | switch(column) 128 | { 129 | case COL_NAME: 130 | diff = _wcsicmp(module1->getFilename(), module2->getFilename()); 131 | break; 132 | case COL_IMAGEBASE: 133 | diff = module1->modBaseAddr < module2->modBaseAddr ? -1 : 1; 134 | break; 135 | case COL_IMAGESIZE: 136 | diff = module1->modBaseSize < module2->modBaseSize ? -1 : 1; 137 | break; 138 | case COL_PATH: 139 | diff = _wcsicmp(module1->fullPath, module2->fullPath); 140 | break; 141 | } 142 | 143 | return ascending ? diff : -diff; 144 | } 145 | -------------------------------------------------------------------------------- /Scylla/PickDllGui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "resource.h" 5 | 6 | // WTL 7 | #include // base ATL classes 8 | #include // base WTL classes 9 | #include // ATL GUI classes 10 | #include // WTL window frame helpers 11 | #include // WTL utility classes 12 | #include // WTL enhanced msg map macros 13 | #include // WTL controls 14 | #include // WTL dialog data exchange 15 | 16 | #include 17 | #include "ProcessAccessHelp.h" // ModuleInfo 18 | 19 | class PickDllGui : public CDialogImpl, public CWinDataExchange, public CDialogResize 20 | { 21 | public: 22 | enum { IDD = IDD_DLG_PICKDLL }; 23 | 24 | BEGIN_DDX_MAP(PickDllGui) 25 | DDX_CONTROL_HANDLE(IDC_LIST_DLLSELECT, ListDLLSelect) 26 | END_DDX_MAP() 27 | 28 | BEGIN_MSG_MAP(PickDllGui) 29 | MSG_WM_INITDIALOG(OnInitDialog) 30 | 31 | NOTIFY_HANDLER_EX(IDC_LIST_DLLSELECT, LVN_COLUMNCLICK, OnListDllColumnClicked) 32 | NOTIFY_HANDLER_EX(IDC_LIST_DLLSELECT, NM_DBLCLK, OnListDllDoubleClick) 33 | 34 | COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_OK, OnOK) 35 | COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_CANCEL, OnCancel) 36 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 37 | 38 | CHAIN_MSG_MAP(CDialogResize) 39 | END_MSG_MAP() 40 | 41 | BEGIN_DLGRESIZE_MAP(PickDllGui) 42 | DLGRESIZE_CONTROL(IDC_LIST_DLLSELECT, DLSZ_SIZE_X | DLSZ_SIZE_Y) 43 | DLGRESIZE_CONTROL(IDC_BTN_PICKDLL_OK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 44 | DLGRESIZE_CONTROL(IDC_BTN_PICKDLL_CANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y) 45 | END_DLGRESIZE_MAP() 46 | 47 | PickDllGui(std::vector &moduleList); 48 | 49 | ModuleInfo* getSelectedModule() const { return selectedModule; } 50 | 51 | protected: 52 | 53 | // Variables 54 | 55 | std::vector &moduleList; 56 | ModuleInfo* selectedModule; 57 | 58 | // Controls 59 | 60 | CListViewCtrl ListDLLSelect; 61 | 62 | enum ListColumns { 63 | COL_NAME = 0, 64 | COL_IMAGEBASE, 65 | COL_IMAGESIZE, 66 | COL_PATH 67 | }; 68 | 69 | int prevColumn; 70 | bool ascending; 71 | 72 | protected: 73 | 74 | // Message handlers 75 | 76 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 77 | 78 | LRESULT OnListDllColumnClicked(NMHDR* pnmh); 79 | LRESULT OnListDllDoubleClick(NMHDR* pnmh); 80 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 81 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 82 | 83 | // GUI functions 84 | 85 | void addColumnsToModuleList(CListViewCtrl& list); 86 | void displayModuleList(CListViewCtrl& list); 87 | 88 | static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 89 | }; 90 | -------------------------------------------------------------------------------- /Scylla/PluginLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "PluginLoader.h" 2 | #include "Logger.h" 3 | 4 | #include "ProcessAccessHelp.h" 5 | #include "StringConversion.h" 6 | #include 7 | 8 | #include "PeParser.h" 9 | 10 | const WCHAR PluginLoader::PLUGIN_DIR[] = L"Plugins\\"; 11 | const WCHAR PluginLoader::PLUGIN_SEARCH_STRING[] = L"*.dll"; 12 | const WCHAR PluginLoader::PLUGIN_IMPREC_DIR[] = L"ImpRec_Plugins\\"; 13 | const WCHAR PluginLoader::PLUGIN_IMPREC_WRAPPER_DLL[] = L"Imprec_Wrapper_DLL.dll"; 14 | 15 | //#define DEBUG_COMMENTS 16 | 17 | std::vector & PluginLoader::getScyllaPluginList() 18 | { 19 | return scyllaPluginList; 20 | } 21 | 22 | std::vector & PluginLoader::getImprecPluginList() 23 | { 24 | return imprecPluginList; 25 | } 26 | 27 | bool PluginLoader::findAllPlugins() 28 | { 29 | 30 | if (!scyllaPluginList.empty()) 31 | { 32 | scyllaPluginList.clear(); 33 | } 34 | 35 | if (!imprecPluginList.empty()) 36 | { 37 | imprecPluginList.clear(); 38 | } 39 | 40 | if (!buildSearchString()) 41 | { 42 | return false; 43 | } 44 | 45 | if (!searchForPlugin(scyllaPluginList, dirSearchString, true)) 46 | { 47 | return false; 48 | } 49 | 50 | #ifndef _WIN64 51 | if (!buildSearchStringImprecPlugins()) 52 | { 53 | return false; 54 | } 55 | 56 | if (!searchForPlugin(imprecPluginList, dirSearchString, false)) 57 | { 58 | return false; 59 | } 60 | #endif 61 | 62 | return true; 63 | } 64 | 65 | bool PluginLoader::searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin) 66 | { 67 | WIN32_FIND_DATA ffd; 68 | HANDLE hFind = 0; 69 | DWORD dwError = 0; 70 | Plugin pluginData; 71 | 72 | hFind = FindFirstFile(searchPath, &ffd); 73 | 74 | dwError = GetLastError(); 75 | 76 | if (dwError == ERROR_FILE_NOT_FOUND) 77 | { 78 | #ifdef DEBUG_COMMENTS 79 | Scylla::debugLog.log(L"findAllPlugins :: No files found"); 80 | #endif 81 | return true; 82 | } 83 | 84 | if (hFind == INVALID_HANDLE_VALUE) 85 | { 86 | #ifdef DEBUG_COMMENTS 87 | Scylla::debugLog.log(L"findAllPlugins :: FindFirstFile failed %d", dwError); 88 | #endif 89 | return false; 90 | } 91 | 92 | do 93 | { 94 | if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 95 | { 96 | 97 | if ((ffd.nFileSizeHigh != 0) || (ffd.nFileSizeLow < 200)) 98 | { 99 | #ifdef DEBUG_COMMENTS 100 | Scylla::debugLog.log(L"findAllPlugins :: Plugin invalid file size: %s", ffd.cFileName); 101 | #endif 102 | } 103 | else 104 | { 105 | pluginData.fileSize = ffd.nFileSizeLow; 106 | wcscpy_s(pluginData.fullpath, baseDirPath); 107 | wcscat_s(pluginData.fullpath, ffd.cFileName); 108 | 109 | #ifdef DEBUG_COMMENTS 110 | Scylla::debugLog.log(L"findAllPlugins :: Plugin %s", pluginData.fullpath); 111 | #endif 112 | if (isValidDllFile(pluginData.fullpath)) 113 | { 114 | if (isScyllaPlugin) 115 | { 116 | if (getScyllaPluginName(&pluginData)) 117 | { 118 | //add valid plugin 119 | newPluginList.push_back(pluginData); 120 | } 121 | else 122 | { 123 | #ifdef DEBUG_COMMENTS 124 | Scylla::debugLog.log(L"Cannot get scylla plugin name %s", pluginData.fullpath); 125 | #endif 126 | } 127 | } 128 | else 129 | { 130 | if (isValidImprecPlugin(pluginData.fullpath)) 131 | { 132 | wcscpy_s(pluginData.pluginName, ffd.cFileName); 133 | newPluginList.push_back(pluginData); 134 | } 135 | } 136 | 137 | } 138 | 139 | } 140 | 141 | } 142 | } 143 | while (FindNextFile(hFind, &ffd) != 0); 144 | 145 | dwError = GetLastError(); 146 | 147 | FindClose(hFind); 148 | 149 | return (dwError == ERROR_NO_MORE_FILES); 150 | } 151 | 152 | bool PluginLoader::getScyllaPluginName(Plugin * pluginData) 153 | { 154 | bool retValue = false; 155 | char * pluginName = 0; 156 | def_ScyllaPluginNameW ScyllaPluginNameW = 0; 157 | def_ScyllaPluginNameA ScyllaPluginNameA = 0; 158 | 159 | HMODULE hModule = LoadLibraryEx(pluginData->fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain 160 | 161 | if (hModule) 162 | { 163 | ScyllaPluginNameW = (def_ScyllaPluginNameW)GetProcAddress(hModule, "ScyllaPluginNameW"); 164 | 165 | if (ScyllaPluginNameW) 166 | { 167 | wcscpy_s(pluginData->pluginName, ScyllaPluginNameW()); 168 | 169 | #ifdef DEBUG_COMMENTS 170 | Scylla::debugLog.log(L"getPluginName :: Plugin name %s", pluginData->pluginName); 171 | #endif 172 | 173 | retValue = true; 174 | } 175 | else 176 | { 177 | ScyllaPluginNameA = (def_ScyllaPluginNameA)GetProcAddress(hModule, "ScyllaPluginNameA"); 178 | 179 | if (ScyllaPluginNameA) 180 | { 181 | pluginName = ScyllaPluginNameA(); 182 | 183 | StringConversion::ToUTF16(pluginName, pluginData->pluginName, _countof(pluginData->pluginName)); 184 | 185 | #ifdef DEBUG_COMMENTS 186 | Scylla::debugLog.log(L"getPluginName :: Plugin name mbstowcs_s %s", pluginData->pluginName); 187 | #endif 188 | 189 | if (wcslen(pluginData->pluginName) > 1) 190 | { 191 | retValue = true; 192 | } 193 | } 194 | } 195 | 196 | FreeLibrary(hModule); 197 | 198 | return retValue; 199 | } 200 | else 201 | { 202 | #ifdef DEBUG_COMMENTS 203 | Scylla::debugLog.log(L"getPluginName :: LoadLibraryEx failed %s", pluginData->fullpath); 204 | #endif 205 | return false; 206 | } 207 | } 208 | 209 | bool PluginLoader::buildSearchString() 210 | { 211 | ZeroMemory(dirSearchString, sizeof(dirSearchString)); 212 | ZeroMemory(baseDirPath, sizeof(baseDirPath)); 213 | 214 | if (!GetModuleFileName(0, dirSearchString, _countof(dirSearchString))) 215 | { 216 | #ifdef DEBUG_COMMENTS 217 | Scylla::debugLog.log(L"buildSearchString :: GetModuleFileName failed %d", GetLastError()); 218 | #endif 219 | return false; 220 | } 221 | 222 | //wprintf(L"dirSearchString 1 %s\n\n", dirSearchString); 223 | PathRemoveFileSpec(dirSearchString); 224 | //wprintf(L"dirSearchString 2 %s\n\n", dirSearchString); 225 | PathAppend(dirSearchString, PLUGIN_DIR); 226 | 227 | wcscpy_s(baseDirPath, dirSearchString); 228 | wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING); 229 | 230 | //wprintf(L"dirSearchString 3 %s\n\n", dirSearchString); 231 | 232 | #ifdef DEBUG_COMMENTS 233 | Scylla::debugLog.log(L"dirSearchString final %s", dirSearchString); 234 | #endif 235 | 236 | 237 | return true; 238 | } 239 | 240 | bool PluginLoader::isValidDllFile( const WCHAR * fullpath ) 241 | { 242 | PeParser peFile(fullpath, false); 243 | 244 | return (peFile.isTargetFileSamePeFormat() && peFile.hasExportDirectory()); 245 | } 246 | 247 | bool PluginLoader::isValidImprecPlugin(const WCHAR * fullpath) 248 | { 249 | def_Imprec_Trace Imprec_Trace = 0; 250 | bool retValue = false; 251 | 252 | HMODULE hModule = LoadLibraryEx(fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain 253 | 254 | if (hModule) 255 | { 256 | Imprec_Trace = (def_Imprec_Trace)GetProcAddress(hModule, "Trace"); 257 | if (Imprec_Trace) 258 | { 259 | retValue = true; 260 | } 261 | else 262 | { 263 | retValue = false; 264 | } 265 | 266 | FreeLibrary(hModule); 267 | return retValue; 268 | } 269 | else 270 | { 271 | #ifdef DEBUG_COMMENTS 272 | Scylla::debugLog.log(L"isValidImprecPlugin :: LoadLibraryEx failed %s", pluginData->fullpath); 273 | #endif 274 | return false; 275 | } 276 | } 277 | 278 | bool PluginLoader::buildSearchStringImprecPlugins() 279 | { 280 | wcscpy_s(dirSearchString, baseDirPath); 281 | 282 | wcscat_s(dirSearchString, PLUGIN_IMPREC_DIR); 283 | 284 | wcscpy_s(baseDirPath, dirSearchString); 285 | 286 | //build imprec wrapper dll path 287 | wcscpy_s(imprecWrapperDllPath, dirSearchString); 288 | wcscat_s(imprecWrapperDllPath, PLUGIN_IMPREC_WRAPPER_DLL); 289 | 290 | if (!fileExists(imprecWrapperDllPath)) 291 | { 292 | return false; 293 | } 294 | 295 | wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING); 296 | 297 | return true; 298 | } 299 | 300 | bool PluginLoader::fileExists(const WCHAR * fileName) 301 | { 302 | return (GetFileAttributesW(fileName) != INVALID_FILE_ATTRIBUTES); 303 | } 304 | -------------------------------------------------------------------------------- /Scylla/PluginLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class Plugin { 7 | public: 8 | DWORD fileSize; 9 | WCHAR fullpath[MAX_PATH]; 10 | WCHAR pluginName[MAX_PATH]; 11 | }; 12 | 13 | typedef wchar_t * (__cdecl * def_ScyllaPluginNameW)(); 14 | typedef char * (__cdecl * def_ScyllaPluginNameA)(); 15 | 16 | typedef DWORD ( * def_Imprec_Trace)(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall); 17 | 18 | class PluginLoader { 19 | public: 20 | WCHAR imprecWrapperDllPath[MAX_PATH]; 21 | 22 | bool findAllPlugins(); 23 | 24 | std::vector & getScyllaPluginList(); 25 | std::vector & getImprecPluginList(); 26 | 27 | private: 28 | 29 | static const WCHAR PLUGIN_DIR[]; 30 | static const WCHAR PLUGIN_SEARCH_STRING[]; 31 | static const WCHAR PLUGIN_IMPREC_DIR[]; 32 | static const WCHAR PLUGIN_IMPREC_WRAPPER_DLL[]; 33 | 34 | std::vector scyllaPluginList; 35 | std::vector imprecPluginList; 36 | 37 | WCHAR dirSearchString[MAX_PATH]; 38 | WCHAR baseDirPath[MAX_PATH]; 39 | 40 | bool buildSearchString(); 41 | bool buildSearchStringImprecPlugins(); 42 | 43 | bool getScyllaPluginName(Plugin * pluginData); 44 | bool searchForPlugin(std::vector & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin); 45 | 46 | static bool fileExists(const WCHAR * fileName); 47 | static bool isValidDllFile(const WCHAR * fullpath); 48 | static bool isValidImprecPlugin(const WCHAR * fullpath); 49 | }; 50 | -------------------------------------------------------------------------------- /Scylla/ProcessAccessHelp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /************************************************************************/ 8 | /* distorm */ 9 | /************************************************************************/ 10 | #include 11 | #include 12 | 13 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 14 | // Play with this value for performance... 15 | #define MAX_INSTRUCTIONS (200) 16 | 17 | /************************************************************************/ 18 | 19 | class ApiInfo; 20 | 21 | class ModuleInfo 22 | { 23 | public: 24 | 25 | WCHAR fullPath[MAX_PATH]; 26 | DWORD_PTR modBaseAddr; 27 | DWORD modBaseSize; 28 | 29 | bool isAlreadyParsed; 30 | bool parsing; 31 | 32 | /* 33 | for iat rebuilding with duplicate entries: 34 | 35 | ntdll = low priority 36 | kernelbase = low priority 37 | SHLWAPI = low priority 38 | 39 | kernel32 = high priority 40 | 41 | priority = 1 -> normal/high priority 42 | priority = 0 -> low priority 43 | */ 44 | int priority; 45 | 46 | std::vector apiList; 47 | 48 | ModuleInfo() 49 | { 50 | modBaseAddr = 0; 51 | modBaseSize = 0; 52 | priority = 1; 53 | isAlreadyParsed = false; 54 | parsing = false; 55 | } 56 | 57 | const WCHAR * getFilename() const 58 | { 59 | const WCHAR* slash = wcsrchr(fullPath, L'\\'); 60 | if(slash) 61 | { 62 | return slash+1; 63 | } 64 | return fullPath; 65 | } 66 | }; 67 | 68 | class ApiInfo 69 | { 70 | public: 71 | 72 | char name[MAX_PATH]; 73 | WORD hint; 74 | DWORD_PTR va; 75 | DWORD_PTR rva; 76 | WORD ordinal; 77 | bool isForwarded; 78 | ModuleInfo * module; 79 | }; 80 | 81 | class ProcessAccessHelp 82 | { 83 | public: 84 | 85 | static HANDLE hProcess; //OpenProcess handle to target process 86 | 87 | static DWORD_PTR targetImageBase; 88 | static DWORD_PTR targetSizeOfImage; 89 | static DWORD_PTR maxValidAddress; 90 | 91 | static ModuleInfo * selectedModule; 92 | 93 | static std::vector moduleList; //target process module list 94 | static std::vector ownModuleList; //own module list 95 | 96 | static const size_t PE_HEADER_BYTES_COUNT = 2000; 97 | 98 | static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; 99 | 100 | 101 | //for decomposer 102 | static _DInst decomposerResult[MAX_INSTRUCTIONS]; 103 | static unsigned int decomposerInstructionsCount; 104 | static _CodeInfo decomposerCi; 105 | 106 | //distorm :: Decoded instruction information. 107 | static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; 108 | static unsigned int decodedInstructionsCount; 109 | #ifdef _WIN64 110 | static const _DecodeType dt = Decode64Bits; 111 | #else 112 | static const _DecodeType dt = Decode32Bits; 113 | #endif 114 | 115 | /* 116 | * Open a new process handle 117 | */ 118 | static bool openProcessHandle(DWORD dwPID); 119 | 120 | static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId); 121 | 122 | static void closeProcessHandle(); 123 | 124 | /* 125 | * Get all modules from a process 126 | */ 127 | static bool getProcessModules(HANDLE hProcess, std::vector &moduleList); 128 | 129 | 130 | /* 131 | * file mapping view with different access level 132 | */ 133 | static LPVOID createFileMappingViewRead(const WCHAR * filePath); 134 | static LPVOID createFileMappingViewFull(const WCHAR * filePath); 135 | 136 | /* 137 | * Create a file mapping view of a file 138 | */ 139 | static LPVOID createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap); 140 | 141 | /* 142 | * Read memory from target process 143 | */ 144 | static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); 145 | static bool writeMemoryToProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); 146 | 147 | /* 148 | * Read memory from target process and ignore no data pages 149 | */ 150 | static bool readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); 151 | 152 | /* 153 | * Read memory from file 154 | */ 155 | static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); 156 | 157 | /* 158 | * Write memory to file 159 | */ 160 | static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer); 161 | 162 | 163 | /* 164 | * Write memory to new file 165 | */ 166 | static bool writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer); 167 | 168 | /* 169 | * Write memory to file end 170 | */ 171 | static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer); 172 | 173 | /* 174 | * Disassemble Memory 175 | */ 176 | static bool disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset); 177 | 178 | static bool decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress); 179 | 180 | /* 181 | * Search for pattern 182 | */ 183 | static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask); 184 | 185 | /* 186 | * Get process ID by process name 187 | */ 188 | static DWORD getProcessByName(const WCHAR * processName); 189 | 190 | /* 191 | * Get memory region from address 192 | */ 193 | static bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize); 194 | 195 | 196 | /* 197 | * Read PE Header from file 198 | */ 199 | static bool readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath); 200 | 201 | static bool readHeaderFromCurrentFile(const WCHAR * filePath); 202 | 203 | /* 204 | * Get real sizeOfImage value 205 | */ 206 | static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase); 207 | 208 | /* 209 | * Get real sizeOfImage value current process 210 | */ 211 | static bool getSizeOfImageCurrentProcess(); 212 | 213 | static LONGLONG getFileSize(HANDLE hFile); 214 | static LONGLONG getFileSize(const WCHAR * filePath); 215 | 216 | static DWORD getEntryPointFromFile(const WCHAR * filePath); 217 | 218 | static bool createBackupFile(const WCHAR * filePath); 219 | 220 | static DWORD getModuleHandlesFromProcess(const HANDLE hProcess, HMODULE ** hMods ); 221 | 222 | static void setCurrentProcessAsTarget(); 223 | 224 | static bool suspendProcess(); 225 | static bool resumeProcess(); 226 | static bool terminateProcess(); 227 | static bool isPageExecutable( DWORD Protect ); 228 | static bool isPageAccessable( DWORD Protect ); 229 | static SIZE_T getSizeOfImageProcessNative( HANDLE processHandle, DWORD_PTR moduleBase ); 230 | }; 231 | -------------------------------------------------------------------------------- /Scylla/ProcessLister.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "NativeWinApi.h" 9 | #include "DeviceNameResolver.h" 10 | 11 | typedef BOOL (WINAPI *def_IsWow64Process)(HANDLE hProcess,PBOOL Wow64Process); 12 | 13 | class Process { 14 | public: 15 | DWORD PID; 16 | DWORD sessionId; 17 | DWORD_PTR imageBase; 18 | DWORD_PTR pebAddress; 19 | DWORD entryPoint; //RVA without imagebase 20 | DWORD imageSize; 21 | WCHAR filename[MAX_PATH]; 22 | WCHAR fullPath[MAX_PATH]; 23 | 24 | Process() 25 | { 26 | PID = 0; 27 | } 28 | }; 29 | 30 | enum ProcessType { 31 | PROCESS_UNKNOWN, 32 | PROCESS_MISSING_RIGHTS, 33 | PROCESS_32, 34 | PROCESS_64 35 | }; 36 | 37 | class ProcessLister { 38 | public: 39 | 40 | static def_IsWow64Process _IsWow64Process; 41 | 42 | ProcessLister() 43 | { 44 | deviceNameResolver = new DeviceNameResolver(); 45 | _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"); 46 | } 47 | ~ProcessLister() 48 | { 49 | delete deviceNameResolver; 50 | } 51 | 52 | std::vector& getProcessList(); 53 | static bool isWindows64(); 54 | static DWORD setDebugPrivileges(); 55 | std::vector& getProcessListSnapshotNative(); 56 | private: 57 | std::vector processList; 58 | 59 | DeviceNameResolver * deviceNameResolver; 60 | 61 | ProcessType checkIsProcess64(HANDLE hProcess); 62 | 63 | bool getAbsoluteFilePath(HANDLE hProcess, Process * process); 64 | 65 | 66 | void handleProcessInformationAndAddToList( PSYSTEM_PROCESS_INFORMATION pProcess ); 67 | void getProcessImageInformation( HANDLE hProcess, Process* process ); 68 | DWORD_PTR getPebAddressFromProcess( HANDLE hProcess ); 69 | }; -------------------------------------------------------------------------------- /Scylla/Scylla.cpp: -------------------------------------------------------------------------------- 1 | #include "Scylla.h" 2 | 3 | #include "NativeWinApi.h" 4 | #include "SystemInformation.h" 5 | #include "ProcessAccessHelp.h" 6 | 7 | ConfigurationHolder Scylla::config(L"Scylla.ini"); 8 | PluginLoader Scylla::plugins; 9 | 10 | ProcessLister Scylla::processLister; 11 | 12 | const WCHAR Scylla::DEBUG_LOG_FILENAME[] = L"Scylla_debug.log"; 13 | 14 | FileLog Scylla::debugLog(DEBUG_LOG_FILENAME); 15 | ListboxLog Scylla::windowLog; 16 | 17 | void Scylla::initAsGuiApp() 18 | { 19 | config.loadConfiguration(); 20 | plugins.findAllPlugins(); 21 | 22 | NativeWinApi::initialize(); 23 | SystemInformation::getSystemInformation(); 24 | 25 | if(config[DEBUG_PRIVILEGE].isTrue()) 26 | { 27 | processLister.setDebugPrivileges(); 28 | } 29 | 30 | ProcessAccessHelp::getProcessModules(GetCurrentProcess(), ProcessAccessHelp::ownModuleList); 31 | } 32 | 33 | void Scylla::initAsDll() 34 | { 35 | ProcessAccessHelp::ownModuleList.clear(); 36 | 37 | NativeWinApi::initialize(); 38 | SystemInformation::getSystemInformation(); 39 | ProcessAccessHelp::getProcessModules(GetCurrentProcess(), ProcessAccessHelp::ownModuleList); 40 | } -------------------------------------------------------------------------------- /Scylla/Scylla.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ConfigurationHolder.h" 4 | #include "PluginLoader.h" 5 | #include "ProcessLister.h" 6 | #include "Logger.h" 7 | 8 | #define APPNAME_S "Scylla" 9 | #define APPVERSION_S "v0.9.8" 10 | #define APPVERSIONDWORD 0x00009800 11 | 12 | #define DONATE_BTC_ADDRESS "1GmVrhWwUhwLohaCLP4SKV5kkz8rd16N8h" 13 | 14 | #define APPNAME TEXT(APPNAME_S) 15 | #define APPVERSION TEXT(APPVERSION_S) 16 | 17 | class Scylla 18 | { 19 | public: 20 | 21 | static void initAsGuiApp(); 22 | static void initAsDll(); 23 | 24 | static ConfigurationHolder config; 25 | static PluginLoader plugins; 26 | 27 | static ProcessLister processLister; 28 | 29 | static FileLog debugLog; 30 | static ListboxLog windowLog; 31 | 32 | private: 33 | 34 | static const WCHAR DEBUG_LOG_FILENAME[]; 35 | }; 36 | -------------------------------------------------------------------------------- /Scylla/StringConversion.cpp: -------------------------------------------------------------------------------- 1 | #include "StringConversion.h" 2 | //#include 3 | #include 4 | #include 5 | 6 | const char* StringConversion::ToASCII(const wchar_t* str, char* buf, size_t bufsize) 7 | { 8 | //wcstombs(buf, str, bufsize); 9 | ATL::CW2A str_a = str; 10 | strncpy_s(buf, bufsize, str_a, bufsize); 11 | buf[bufsize - 1] = '\0'; 12 | return buf; 13 | } 14 | 15 | const wchar_t* StringConversion::ToUTF16(const char* str, wchar_t* buf, size_t bufsize) 16 | { 17 | //mbstowcs_s(buf, str, bufsize); 18 | ATL::CA2W str_w = str; 19 | wcsncpy_s(buf, bufsize, str_w, bufsize); 20 | buf[bufsize - 1] = L'\0'; 21 | return buf; 22 | } 23 | -------------------------------------------------------------------------------- /Scylla/StringConversion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class StringConversion 4 | { 5 | public: 6 | 7 | static const char* ToASCII(const wchar_t* str, char* buf, size_t bufsize); 8 | static const wchar_t* ToUTF16(const char* str, wchar_t* buf, size_t bufsize); 9 | }; 10 | -------------------------------------------------------------------------------- /Scylla/SystemInformation.cpp: -------------------------------------------------------------------------------- 1 | #include "SystemInformation.h" 2 | 3 | OPERATING_SYSTEM SystemInformation::currenOS = UNKNOWN_OS; 4 | 5 | bool SystemInformation::getSystemInformation() 6 | { 7 | OSVERSIONINFOEX osvi = {0}; 8 | SYSTEM_INFO si = {0}; 9 | def_GetNativeSystemInfo _GetNativeSystemInfo = 0; 10 | 11 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 12 | if (!GetVersionEx((OSVERSIONINFO*) &osvi)) 13 | { 14 | return false; 15 | } 16 | 17 | if ((osvi.dwMajorVersion < 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0))) 18 | { 19 | return false; 20 | } 21 | 22 | _GetNativeSystemInfo = (def_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo"); 23 | if (_GetNativeSystemInfo) 24 | { 25 | _GetNativeSystemInfo(&si); 26 | } 27 | else 28 | { 29 | GetSystemInfo(&si); 30 | } 31 | 32 | bool isX64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; 33 | bool isX86 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL; 34 | 35 | DWORD major = osvi.dwMajorVersion; 36 | DWORD minor = osvi.dwMinorVersion; 37 | 38 | if(isX64 && major == 5 && minor == 2) 39 | { 40 | currenOS = WIN_XP_64; 41 | } 42 | else if(isX86 && major == 5 && minor == 1) 43 | { 44 | currenOS = WIN_XP_32; 45 | } 46 | else if(isX64 && major == 6 && minor == 0) 47 | { 48 | currenOS = WIN_VISTA_64; 49 | } 50 | else if(isX86 && major == 6 && minor == 0) 51 | { 52 | currenOS = WIN_VISTA_32; 53 | } 54 | else if(isX64 && major == 6 && minor == 1) 55 | { 56 | currenOS = WIN_7_64; 57 | } 58 | else if(isX86 && major == 6 && minor == 1) 59 | { 60 | currenOS = WIN_7_32; 61 | } 62 | else if(isX64 && major == 6 && minor == 2) 63 | { 64 | currenOS = WIN_8_64; 65 | } 66 | else if(isX86 && major == 6 && minor == 2) 67 | { 68 | currenOS = WIN_8_32; 69 | } 70 | else 71 | { 72 | currenOS = UNKNOWN_OS; 73 | } 74 | 75 | return (currenOS != UNKNOWN_OS); 76 | } 77 | -------------------------------------------------------------------------------- /Scylla/SystemInformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum OPERATING_SYSTEM { 6 | UNKNOWN_OS, 7 | WIN_XP_32, 8 | WIN_XP_64, 9 | WIN_VISTA_32, 10 | WIN_VISTA_64, 11 | WIN_7_32, 12 | WIN_7_64, 13 | WIN_8_32, 14 | WIN_8_64 15 | }; 16 | 17 | typedef void (WINAPI *def_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); 18 | 19 | class SystemInformation 20 | { 21 | public: 22 | 23 | static OPERATING_SYSTEM currenOS; 24 | static bool getSystemInformation(); 25 | }; 26 | -------------------------------------------------------------------------------- /Scylla/Thunks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // WTL 7 | #include 8 | #include 9 | #include // CTreeItem 10 | 11 | class ImportThunk 12 | { 13 | public: 14 | WCHAR moduleName[MAX_PATH]; 15 | char name[MAX_PATH]; 16 | DWORD_PTR va; 17 | DWORD_PTR rva; 18 | WORD ordinal; 19 | DWORD_PTR apiAddressVA; 20 | WORD hint; 21 | bool valid; 22 | bool suspect; 23 | 24 | CTreeItem hTreeItem; 25 | DWORD_PTR key; 26 | 27 | void invalidate(); 28 | }; 29 | 30 | class ImportModuleThunk 31 | { 32 | public: 33 | WCHAR moduleName[MAX_PATH]; 34 | std::map thunkList; 35 | 36 | DWORD_PTR firstThunk; 37 | 38 | CTreeItem hTreeItem; 39 | DWORD_PTR key; 40 | 41 | DWORD_PTR getFirstThunk() const; 42 | bool isValid() const; 43 | }; 44 | -------------------------------------------------------------------------------- /Scylla/TreeImportExport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ProcessLister.h" 5 | #include "Thunks.h" 6 | #include 7 | 8 | class TreeImportExport 9 | { 10 | public: 11 | 12 | TreeImportExport(const WCHAR * targetXmlFile); 13 | 14 | bool exportTreeList(const std::map & moduleList, const Process * process, DWORD_PTR addressOEP, DWORD_PTR addressIAT, DWORD sizeIAT) ; 15 | bool importTreeList(std::map & moduleList, DWORD_PTR * addressOEP, DWORD_PTR * addressIAT, DWORD * sizeIAT); 16 | 17 | private: 18 | 19 | WCHAR xmlPath[MAX_PATH]; 20 | 21 | char xmlStringBuffer[MAX_PATH]; 22 | 23 | void setTargetInformation(TiXmlElement * rootElement, const Process * process, DWORD_PTR addressOEP, DWORD_PTR addressIAT, DWORD sizeIAT); 24 | void addModuleListToRootElement(TiXmlElement * rootElement, const std::map & moduleList); 25 | 26 | void parseAllElementModules(TiXmlElement * targetElement, std::map & moduleList); 27 | void parseAllElementImports(TiXmlElement * moduleElement, ImportModuleThunk * importModuleThunk); 28 | 29 | TiXmlElement * getModuleXmlElement(const ImportModuleThunk * importModuleThunk); 30 | TiXmlElement * getImportXmlElement(const ImportThunk * importThunk); 31 | 32 | bool saveXmlToFile(const TiXmlDocument& doc, const WCHAR * xmlFilePath); 33 | bool readXmlFile(TiXmlDocument& doc, const WCHAR * xmlFilePath); 34 | 35 | void ConvertBoolToString(const bool boolValue); 36 | void ConvertWordToString(const WORD dwValue); 37 | void ConvertDwordPtrToString(const DWORD_PTR dwValue); 38 | 39 | DWORD_PTR ConvertStringToDwordPtr(const char * strValue); 40 | WORD ConvertStringToWord(const char * strValue); 41 | bool ConvertStringToBool(const char * strValue); 42 | }; 43 | -------------------------------------------------------------------------------- /Scylla/check.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/check.ico -------------------------------------------------------------------------------- /Scylla/error.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/error.ico -------------------------------------------------------------------------------- /Scylla/hexedit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __cplusplus 4 | #error WTL requires C++ compilation (use a .cpp suffix) 5 | #endif 6 | 7 | #ifndef __ATLMISC_H__ 8 | #error hexedit.h requires atlmisc.h to be included first 9 | #endif 10 | 11 | #ifndef __ATLCTRLS_H__ 12 | #error hexedit.h requires atlctrls.h to be included first 13 | #endif 14 | 15 | /* 16 | #ifdef _WIN64 17 | address = _wcstoui64(hexString, NULL, 16); 18 | #else 19 | address = wcstoul(hexString, NULL, 16); 20 | #endif 21 | */ 22 | 23 | template< class T, typename NUM_T, class TBase = CEdit, class TWinTraits = CControlWinTraits > 24 | class ATL_NO_VTABLE CHexEditImpl : public CWindowImpl< T, TBase, TWinTraits > 25 | { 26 | public: 27 | 28 | static const short int BASE = 16; 29 | static const size_t DIGITS = sizeof(NUM_T) * 2; // 2 digits / byte 30 | static const size_t STRSIZE = DIGITS + 1; 31 | 32 | static const TCHAR Digits[]; 33 | static const TCHAR OldProcProp[]; 34 | 35 | // Operations 36 | 37 | BOOL SubclassWindow(HWND hWnd) 38 | { 39 | ATLASSERT(m_hWnd == NULL); 40 | ATLASSERT(::IsWindow(hWnd)); 41 | BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd); 42 | if( bRet ) _Init(); 43 | return bRet; 44 | } 45 | 46 | NUM_T GetValue() const 47 | { 48 | ATLASSERT(::IsWindow(m_hWnd)); 49 | 50 | TCHAR String[STRSIZE] = { 0 }; 51 | GetWindowText(String, _countof(String)); 52 | return _StringToNum(String); 53 | } 54 | 55 | void SetValue(NUM_T Num, bool Fill = true) 56 | { 57 | ATLASSERT(::IsWindow(m_hWnd)); 58 | 59 | TCHAR String[STRSIZE] = { 0 }; 60 | _NumToString(Num, String, Fill); 61 | SetWindowText(String); 62 | } 63 | 64 | // Implementation 65 | 66 | void _Init() 67 | { 68 | ATLASSERT(::IsWindow(m_hWnd)); 69 | 70 | LimitText(DIGITS); 71 | } 72 | 73 | bool _IsValidChar(TCHAR Char) const 74 | { 75 | return ((NUM_T)-1 != _CharToNum(Char)); 76 | } 77 | 78 | bool _IsValidString(const TCHAR String[STRSIZE]) const 79 | { 80 | for(int i = 0; String[i]; i++) 81 | { 82 | if(!_IsValidChar(String[i])) 83 | return false; 84 | } 85 | return true; 86 | } 87 | 88 | NUM_T _CharToNum(TCHAR Char) const 89 | { 90 | Char = _totupper(Char); 91 | 92 | for(int i = 0; Digits[i]; i++) 93 | { 94 | if(Char == Digits[i]) 95 | return i; 96 | } 97 | 98 | return -1; 99 | } 100 | 101 | NUM_T _StringToNum(const TCHAR String[STRSIZE]) const 102 | { 103 | NUM_T CharNum; 104 | NUM_T Num = 0; 105 | 106 | for(int i = 0; String[i]; i++) 107 | { 108 | CharNum = _CharToNum(String[i]); 109 | if(CharNum == (NUM_T)-1) 110 | break; 111 | 112 | Num *= BASE; 113 | Num += CharNum; 114 | } 115 | 116 | return Num; 117 | } 118 | 119 | TCHAR _NumToChar(NUM_T Num) const 120 | { 121 | return Digits[Num % BASE]; 122 | } 123 | 124 | void _NumToString(NUM_T Num, TCHAR String[STRSIZE], bool Fill) const 125 | { 126 | NUM_T Nums[DIGITS]; 127 | int i, j; 128 | 129 | for(i = DIGITS-1; i >= 0; i--) 130 | { 131 | Nums[i] = Num % BASE; 132 | Num /= BASE; 133 | } 134 | for(i = j = 0; i < DIGITS; i++) 135 | { 136 | // Only copy num if : non-null OR Fill OR non-null encountered before OR last num 137 | if(Nums[i] || Fill || j || i == DIGITS-1) 138 | { 139 | String[j++] = _NumToChar(Nums[i]); 140 | } 141 | } 142 | String[j] = '\0'; 143 | } 144 | 145 | bool _GetClipboardText(TCHAR String[STRSIZE]) 146 | { 147 | #ifdef UNICODE 148 | const UINT Format = CF_UNICODETEXT; 149 | #else 150 | const UINT Format = CF_TEXT; 151 | #endif 152 | 153 | bool RetVal = false; 154 | 155 | if(IsClipboardFormatAvailable(Format) && OpenClipboard()) 156 | { 157 | HANDLE HMem = GetClipboardData(Format); 158 | if(HMem) 159 | { 160 | _tcsncpy_s(String, STRSIZE, (TCHAR *)GlobalLock(HMem), STRSIZE-1); 161 | String[STRSIZE-1] = '\0'; 162 | GlobalUnlock(HMem); 163 | RetVal = true; 164 | } 165 | CloseClipboard(); 166 | } 167 | 168 | return RetVal; 169 | } 170 | 171 | // Message map and handlers 172 | 173 | BEGIN_MSG_MAP_EX(CHexEditImpl) 174 | MESSAGE_HANDLER_EX(WM_CREATE, OnCreate) 175 | MSG_WM_SETTEXT(OnSetText) 176 | MSG_WM_PASTE(OnPaste) 177 | MSG_WM_CHAR(OnChar) 178 | END_MSG_MAP() 179 | 180 | LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam) 181 | { 182 | LRESULT lRes = DefWindowProc(); 183 | _Init(); 184 | return lRes; 185 | } 186 | 187 | int OnSetText(LPCTSTR lpstrText) 188 | { 189 | bool PassThrough = (_tcslen(lpstrText) <= DIGITS) && _IsValidString(lpstrText); 190 | if(!PassThrough) 191 | { 192 | MessageBeep(-1); 193 | return FALSE; 194 | } 195 | 196 | SetMsgHandled(FALSE); 197 | return TRUE; 198 | } 199 | 200 | void OnPaste() 201 | { 202 | TCHAR String[STRSIZE]; 203 | bool PassThrough = !_GetClipboardText(String) || _IsValidString(String); 204 | if(!PassThrough) 205 | { 206 | MessageBeep(-1); 207 | return; 208 | } 209 | 210 | SetMsgHandled(FALSE); 211 | return; 212 | } 213 | 214 | void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 215 | { 216 | // ignore all printable chars (incl. space) which are not valid digits 217 | bool PassThrough = !_istprint((TCHAR)nChar) || _IsValidChar((TCHAR)nChar); 218 | if(!PassThrough) 219 | { 220 | MessageBeep(-1); 221 | return; 222 | } 223 | 224 | SetMsgHandled(FALSE); 225 | return; 226 | } 227 | }; 228 | 229 | template< class T, typename NUM_T, class TBase, class TWinTraits > const TCHAR CHexEditImpl< T, NUM_T, TBase, TWinTraits >::Digits[] = _T("0123456789ABCDEF"); 230 | 231 | template class CHexEdit : public CHexEditImpl, NUM_T> 232 | { 233 | public: 234 | DECLARE_WND_CLASS(_T("WTL_HexEdit")) 235 | }; 236 | -------------------------------------------------------------------------------- /Scylla/main.cpp: -------------------------------------------------------------------------------- 1 | //#include // Visual Leak Detector 2 | 3 | #include // base ATL classes 4 | #include // base WTL classes 5 | #include "Architecture.h" 6 | 7 | CAppModule _Module; 8 | 9 | #include "MainGui.h" 10 | #include "Scylla.h" 11 | 12 | MainGui* pMainGui = NULL; // for Logger 13 | HINSTANCE hDllModule = 0; 14 | bool IsDllMode = false; 15 | 16 | LONG WINAPI HandleUnknownException(struct _EXCEPTION_POINTERS *ExceptionInfo); 17 | void AddExceptionHandler(); 18 | void RemoveExceptionHandler(); 19 | int InitializeGui(HINSTANCE hInstance, LPARAM param); 20 | 21 | int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) 22 | { 23 | AddExceptionHandler(); 24 | 25 | return InitializeGui(hInstance, (LPARAM)0); 26 | } 27 | 28 | int InitializeGui(HINSTANCE hInstance, LPARAM param) 29 | { 30 | CoInitialize(NULL); 31 | 32 | AtlInitCommonControls(ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES); 33 | 34 | Scylla::initAsGuiApp(); 35 | 36 | IsDllMode = false; 37 | 38 | HRESULT hRes = _Module.Init(NULL, hInstance); 39 | ATLASSERT(SUCCEEDED(hRes)); 40 | 41 | 42 | 43 | int nRet = 0; 44 | // BLOCK: Run application 45 | { 46 | MainGui dlgMain; 47 | pMainGui = &dlgMain; // o_O 48 | 49 | CMessageLoop loop; 50 | _Module.AddMessageLoop(&loop); 51 | 52 | dlgMain.Create(GetDesktopWindow(), param); 53 | 54 | dlgMain.ShowWindow(SW_SHOW); 55 | 56 | loop.Run(); 57 | } 58 | 59 | _Module.Term(); 60 | CoUninitialize(); 61 | 62 | return nRet; 63 | } 64 | 65 | void InitializeDll(HINSTANCE hinstDLL) 66 | { 67 | hDllModule = hinstDLL; 68 | IsDllMode = true; 69 | Scylla::initAsDll(); 70 | } 71 | 72 | 73 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 74 | { 75 | // Perform actions based on the reason for calling. 76 | switch(fdwReason) 77 | { 78 | case DLL_PROCESS_ATTACH: 79 | // Initialize once for each new process. 80 | // Return FALSE to fail DLL load. 81 | AddExceptionHandler(); 82 | InitializeDll(hinstDLL); 83 | break; 84 | 85 | case DLL_THREAD_ATTACH: 86 | // Do thread-specific initialization. 87 | break; 88 | 89 | case DLL_THREAD_DETACH: 90 | // Do thread-specific cleanup. 91 | break; 92 | 93 | case DLL_PROCESS_DETACH: 94 | // Perform any necessary cleanup. 95 | RemoveExceptionHandler(); 96 | break; 97 | } 98 | return TRUE; // Successful DLL_PROCESS_ATTACH. 99 | } 100 | 101 | LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; 102 | 103 | void AddExceptionHandler() 104 | { 105 | oldFilter = SetUnhandledExceptionFilter(HandleUnknownException); 106 | } 107 | void RemoveExceptionHandler() 108 | { 109 | SetUnhandledExceptionFilter(oldFilter); 110 | } 111 | 112 | LONG WINAPI HandleUnknownException(struct _EXCEPTION_POINTERS *ExceptionInfo) 113 | { 114 | WCHAR registerInfo[220]; 115 | WCHAR filepath[MAX_PATH] = {0}; 116 | WCHAR file[MAX_PATH] = {0}; 117 | WCHAR message[MAX_PATH + 200 + _countof(registerInfo)]; 118 | WCHAR osInfo[100]; 119 | DWORD_PTR baseAddress = 0; 120 | DWORD_PTR address = (DWORD_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress; 121 | 122 | wcscpy_s(filepath, L"unknown"); 123 | wcscpy_s(file, L"unknown"); 124 | 125 | if (GetMappedFileNameW(GetCurrentProcess(), (LPVOID)address, filepath, _countof(filepath)) > 0) 126 | { 127 | WCHAR *temp = wcsrchr(filepath, '\\'); 128 | if (temp) 129 | { 130 | temp++; 131 | wcscpy_s(file, temp); 132 | } 133 | } 134 | 135 | swprintf_s(osInfo, _countof(osInfo), TEXT("Exception! Please report it! OS: %X"), GetVersion()); 136 | 137 | DWORD_PTR moduleBase = (DWORD_PTR)GetModuleHandleW(file); 138 | 139 | swprintf_s(message, _countof(message), TEXT("ExceptionCode %08X\r\nExceptionFlags %08X\r\nNumberParameters %08X\r\nExceptionAddress VA ")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT(" - Base ")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("\r\nExceptionAddress module %s\r\n\r\n"), 140 | ExceptionInfo->ExceptionRecord->ExceptionCode, 141 | ExceptionInfo->ExceptionRecord->ExceptionFlags, 142 | ExceptionInfo->ExceptionRecord->NumberParameters, 143 | address, 144 | moduleBase, 145 | file); 146 | 147 | #ifdef _WIN64 148 | swprintf_s(registerInfo, _countof(registerInfo),TEXT("rax=0x%p, rbx=0x%p, rdx=0x%p, rcx=0x%p, rsi=0x%p, rdi=0x%p, rbp=0x%p, rsp=0x%p, rip=0x%p"), 149 | ExceptionInfo->ContextRecord->Rax, 150 | ExceptionInfo->ContextRecord->Rbx, 151 | ExceptionInfo->ContextRecord->Rdx, 152 | ExceptionInfo->ContextRecord->Rcx, 153 | ExceptionInfo->ContextRecord->Rsi, 154 | ExceptionInfo->ContextRecord->Rdi, 155 | ExceptionInfo->ContextRecord->Rbp, 156 | ExceptionInfo->ContextRecord->Rsp, 157 | ExceptionInfo->ContextRecord->Rip 158 | ); 159 | #else 160 | swprintf_s(registerInfo, _countof(registerInfo),TEXT("eax=0x%p, ebx=0x%p, edx=0x%p, ecx=0x%p, esi=0x%p, edi=0x%p, ebp=0x%p, esp=0x%p, eip=0x%p"), 161 | ExceptionInfo->ContextRecord->Eax, 162 | ExceptionInfo->ContextRecord->Ebx, 163 | ExceptionInfo->ContextRecord->Edx, 164 | ExceptionInfo->ContextRecord->Ecx, 165 | ExceptionInfo->ContextRecord->Esi, 166 | ExceptionInfo->ContextRecord->Edi, 167 | ExceptionInfo->ContextRecord->Ebp, 168 | ExceptionInfo->ContextRecord->Esp, 169 | ExceptionInfo->ContextRecord->Eip 170 | ); 171 | #endif 172 | 173 | wcscat_s(message, _countof(message), registerInfo); 174 | 175 | MessageBox(0, message, osInfo, MB_ICONERROR); 176 | 177 | return EXCEPTION_CONTINUE_SEARCH; 178 | } 179 | -------------------------------------------------------------------------------- /Scylla/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/resource.h -------------------------------------------------------------------------------- /Scylla/scylla.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/scylla.ico -------------------------------------------------------------------------------- /Scylla/scylla_export_functions.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | ScyllaDumpCurrentProcessW @1 3 | ScyllaDumpCurrentProcessA @2 4 | ScyllaDumpProcessW @3 5 | ScyllaDumpProcessA @4 6 | ScyllaRebuildFileW @5 7 | ScyllaRebuildFileA @6 8 | ScyllaVersionInformationW @7 9 | ScyllaVersionInformationA @8 10 | ScyllaVersionInformationDword @9 11 | ScyllaStartGui @10 12 | ScyllaIatSearch @11 13 | ScyllaIatFixAutoW @12 14 | -------------------------------------------------------------------------------- /Scylla/warning.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/Scylla/warning.ico -------------------------------------------------------------------------------- /ScyllaDllTest/ScyllaDllTest.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScyllaDllTest", "ScyllaDllTest\ScyllaDllTest.vcxproj", "{D7886EB7-3C3B-4AA7-B983-DD85E72798DD}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScyllaTestExe", "ScyllaTestExe\ScyllaTestExe.vcxproj", "{756E4AF7-342C-417F-86DC-3B2A78E782C9}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D7886EB7-3C3B-4AA7-B983-DD85E72798DD}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {D7886EB7-3C3B-4AA7-B983-DD85E72798DD}.Debug|Win32.Build.0 = Debug|Win32 18 | {D7886EB7-3C3B-4AA7-B983-DD85E72798DD}.Release|Win32.ActiveCfg = Release|Win32 19 | {D7886EB7-3C3B-4AA7-B983-DD85E72798DD}.Release|Win32.Build.0 = Release|Win32 20 | {756E4AF7-342C-417F-86DC-3B2A78E782C9}.Debug|Win32.ActiveCfg = Release|Win32 21 | {756E4AF7-342C-417F-86DC-3B2A78E782C9}.Debug|Win32.Build.0 = Release|Win32 22 | {756E4AF7-342C-417F-86DC-3B2A78E782C9}.Release|Win32.ActiveCfg = Release|Win32 23 | {756E4AF7-342C-417F-86DC-3B2A78E782C9}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /ScyllaDllTest/ScyllaDllTest/ScyllaDllTest.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {D7886EB7-3C3B-4AA7-B983-DD85E72798DD} 15 | Win32Proj 16 | ScyllaDllTest 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /ScyllaDllTest/ScyllaDllTest/Source.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | typedef const WCHAR * (WINAPI * def_ScyllaVersionInformationW)(); 10 | typedef const char * (WINAPI * def_ScyllaVersionInformationA)(); 11 | typedef DWORD (WINAPI * def_ScyllaVersionInformationDword)(); 12 | typedef int (WINAPI * def_ScyllaIatSearch)(DWORD dwProcessId, DWORD_PTR * iatStart, DWORD * iatSize, DWORD_PTR searchStart, BOOL advancedSearch); 13 | typedef int (WINAPI * def_ScyllaStartGui)(DWORD dwProcessId, HINSTANCE mod); 14 | 15 | def_ScyllaIatSearch ScyllaIatSearch = 0; 16 | def_ScyllaStartGui ScyllaStartGui = 0; 17 | def_ScyllaVersionInformationW ScyllaVersionInformationW = 0; 18 | def_ScyllaVersionInformationA ScyllaVersionInformationA = 0; 19 | def_ScyllaVersionInformationDword ScyllaVersionInformationDword = 0; 20 | 21 | 22 | void testGui(); 23 | void testIatSearch(); 24 | DWORD_PTR GetExeModuleBase(DWORD dwProcessId); 25 | 26 | 27 | STARTUPINFOW si = { 0 }; 28 | PROCESS_INFORMATION pi = { 0 }; 29 | WCHAR target[] = L"ScyllaTestExe.exe"; 30 | HMODULE hScylla = 0; 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | #ifdef _WIN64 35 | hScylla = LoadLibraryW(L"ScyllaDLLx64.dll"); 36 | #else 37 | hScylla = LoadLibraryW(L"ScyllaDLLx86.dll"); 38 | #endif 39 | 40 | if (hScylla) 41 | { 42 | ScyllaIatSearch = (def_ScyllaIatSearch)GetProcAddress(hScylla, "ScyllaIatSearch"); 43 | ScyllaStartGui = (def_ScyllaStartGui)GetProcAddress(hScylla, "ScyllaStartGui"); 44 | 45 | ScyllaVersionInformationW = (def_ScyllaVersionInformationW)GetProcAddress(hScylla, "ScyllaVersionInformationW"); 46 | ScyllaVersionInformationA = (def_ScyllaVersionInformationA)GetProcAddress(hScylla, "ScyllaVersionInformationA"); 47 | ScyllaVersionInformationDword = (def_ScyllaVersionInformationDword)GetProcAddress(hScylla, "ScyllaVersionInformationDword"); 48 | 49 | printf("Scylla DLL: %s - %08X\n", ScyllaVersionInformationA(), ScyllaVersionInformationDword()); 50 | 51 | testIatSearch(); 52 | //testGui(); 53 | } 54 | 55 | getchar(); 56 | return 0; 57 | } 58 | 59 | void testGui() 60 | { 61 | printf("----------------\nGUI TEST\n----------------\n"); 62 | 63 | si.cb = sizeof(STARTUPINFOW); 64 | 65 | if (CreateProcessW(0, target, 0, 0, TRUE, 0, 0, 0, &si, &pi)) 66 | { 67 | Sleep(1000); 68 | 69 | 70 | DWORD_PTR hMod = GetExeModuleBase(pi.dwProcessId); 71 | printf("GetExeModuleBase %X\n", hMod); 72 | 73 | ScyllaStartGui(pi.dwProcessId, 0); 74 | 75 | TerminateProcess(pi.hProcess, 0); 76 | CloseHandle(pi.hThread); 77 | CloseHandle(pi.hProcess); 78 | } 79 | } 80 | 81 | 82 | void testIatSearch() 83 | { 84 | printf("----------------\nIAT Search Test\n----------------\n"); 85 | 86 | si.cb = sizeof(STARTUPINFOW); 87 | 88 | if (CreateProcessW(0, target, 0, 0, TRUE, 0, 0, 0, &si, &pi)) 89 | { 90 | Sleep(1000); 91 | 92 | DWORD_PTR iatStart = 0; 93 | DWORD iatSize = 0; 94 | 95 | DWORD_PTR hMod = GetExeModuleBase(pi.dwProcessId); 96 | printf("GetExeModuleBase %X\n", hMod); 97 | 98 | int error = ScyllaIatSearch(pi.dwProcessId, &iatStart, &iatSize, hMod + 0x00001028, FALSE); 99 | 100 | printf("error %d iatStart %X iatSize %X\n", error, iatStart, iatSize); 101 | 102 | TerminateProcess(pi.hProcess, 0); 103 | CloseHandle(pi.hThread); 104 | CloseHandle(pi.hProcess); 105 | } 106 | } 107 | 108 | DWORD_PTR GetExeModuleBase(DWORD dwProcessId) 109 | { 110 | MODULEENTRY32 lpModuleEntry = { 0 }; 111 | HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId); 112 | lpModuleEntry.dwSize = sizeof(lpModuleEntry); 113 | Module32First(hSnapShot, &lpModuleEntry); 114 | 115 | CloseHandle(hSnapShot); 116 | 117 | return (DWORD_PTR)lpModuleEntry.modBaseAddr; 118 | } -------------------------------------------------------------------------------- /ScyllaDllTest/ScyllaTestExe/ScyllaTestExe.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {756E4AF7-342C-417F-86DC-3B2A78E782C9} 15 | Win32Proj 16 | ScyllaTestExe 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 56 | 57 | 58 | Windows 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 71 | MultiThreaded 72 | 73 | 74 | Windows 75 | false 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /ScyllaDllTest/ScyllaTestExe/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | 5 | int CALLBACK WinMain( 6 | _In_ HINSTANCE hInstance, 7 | _In_ HINSTANCE hPrevInstance, 8 | _In_ LPSTR lpCmdLine, 9 | _In_ int nCmdShow 10 | ) 11 | { 12 | MessageBoxW(0, L"Test", L"Test", MB_OK); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Scylla_Exports.txt: -------------------------------------------------------------------------------- 1 | Scylla DLL Export List: 2 | 3 | BOOL __stdcall ScyllaDumpCurrentProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 4 | BOOL __stdcall ScyllaDumpCurrentProcessA(const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 5 | 6 | BOOL __stdcall ScyllaDumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 7 | BOOL __stdcall ScyllaDumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 8 | 9 | BOOL __stdcall ScyllaRebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 10 | BOOL __stdcall ScyllaRebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 11 | 12 | const WCHAR * __stdcall ScyllaVersionInformationW(); 13 | const char * __stdcall ScyllaVersionInformationA(); 14 | DWORD __stdcall ScyllaVersionInformationDword(); 15 | 16 | int __stdcall ScyllaStartGui(DWORD dwProcessId, HINSTANCE mod, DWORD_PTR entrypoint); 17 | 18 | int __stdcall ScyllaIatSearch(DWORD dwProcessId, DWORD_PTR * iatStart, DWORD * iatSize, DWORD_PTR searchStart, BOOL advancedSearch); 19 | int __stdcall ScyllaIatFixAutoW(DWORD_PTR iatAddr, DWORD iatSize, DWORD dwProcessId, const WCHAR * dumpFile, const WCHAR * iatFixFile); 20 | 21 | 22 | Prototyps: 23 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 24 | C/C++: 25 | ------------ 26 | BOOL __stdcall ScyllaDumpCurrentProcessW(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 27 | BOOL __stdcall ScyllaDumpCurrentProcessA(const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 28 | 29 | BOOL __stdcall ScyllaDumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 30 | BOOL __stdcall ScyllaDumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); 31 | 32 | ------------ 33 | 32-Bit assembly e.g. MASM: 34 | ------------ 35 | ScyllaDumpCurrentProcessW PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 36 | ScyllaDumpCurrentProcessA PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 37 | ScyllaDumpProcessW PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 38 | ScyllaDumpProcessA PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 39 | 40 | ------------ 41 | 64-Bit assembly: 42 | ------------ 43 | ScyllaDumpCurrentProcessW PROTO :QWORD, :QWORD, :QWORD, :QWORD 44 | ScyllaDumpCurrentProcessA PROTO :QWORD, :QWORD, :QWORD, :QWORD 45 | ScyllaDumpProcessW PROTO :QWORD, :QWORD, :QWORD, :QWORD 46 | ScyllaDumpProcessA PROTO :QWORD, :QWORD, :QWORD, :QWORD 47 | 48 | 49 | fileToDump -> string pointer, this can be 0 50 | imagebase -> imagebase base of target 51 | entrypoint -> entrypoint 52 | fileResult -> string pointer, resulting file 53 | pid -> target process PID 54 | 55 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 56 | C/C++: 57 | ------------ 58 | BOOL __stdcall ScyllaRebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 59 | BOOL __stdcall ScyllaRebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 60 | 61 | ------------ 62 | 32-Bit assembly e.g. MASM: 63 | ------------ 64 | ScyllaRebuildFileW PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 65 | ScyllaRebuildFileA PROTO STDCALL :DWORD, :DWORD, :DWORD, :DWORD 66 | ------------ 67 | 64-Bit assembly: 68 | ------------ 69 | ScyllaRebuildFileW PROTO :QWORD, :DWORD, :DWORD, :DWORD 70 | ScyllaRebuildFileA PROTO :QWORD, :DWORD, :DWORD, :DWORD 71 | 72 | 73 | fileToRebuild - string pointer 74 | removeDosStub - to remove the dos stub -> 1 (TRUE) or 0 (FALSE) 75 | updatePeHeaderChecksum - to update the pe header checksum field -> 1 (TRUE) or 0 (FALSE) 76 | createBackup - create a backup file -> 1 (TRUE) or 0 (FALSE) 77 | 78 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 79 | C/C++: 80 | ------------ 81 | const WCHAR * __stdcall ScyllaVersionInformationW(); 82 | const char * __stdcall ScyllaVersionInformationA(); 83 | DWORD __stdcall ScyllaVersionInformationDword(); 84 | 85 | ------------ 86 | 64-Bit/32-Bit assembly e.g. MASM: 87 | ------------ 88 | ScyllaVersionInformationW PROTO 89 | ScyllaVersionInformationA PROTO 90 | ScyllaVersionInformationDword PROTO 91 | 92 | ScyllaVersionInformation - return value is a pointer to a string e.g. "Scylla x86 v0.7 Beta 6" 93 | 94 | ScyllaVersionInformationDword - return value is always a DWORD: 95 | 96 | e.g. 0x00007600 97 | 0000 -> major version 98 | 7600 -> minor version 99 | 100 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 101 | 102 | 103 | Example: 104 | 105 | 106 | typedef BOOL (__stdcall * def_ScyllaDumpCurrentProcessW)(const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); 107 | typedef BOOL (__stdcall * def_RebuildFileA)(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); 108 | 109 | HMODULE mod = LoadLibraryA("ScyllaDLL.dll"); 110 | 111 | def_ScyllaDumpCurrentProcessW ScyllaDumpCurrentProcessW = (def_ScyllaDumpCurrentProcessW)GetProcAddress(mod, "ScyllaDumpCurrentProcessW"); 112 | def_RebuildFileA RebuildFileA = (def_RebuildFileA)GetProcAddress(mod, "RebuildFileA"); 113 | 114 | ScyllaDumpCurrentProcessW(0, (DWORD_PTR)GetModuleHandleA((LPCSTR)0), 0x13370000, L"C:\\dump.exe"); 115 | RebuildFileA("some.exe", 1, 1, 1); 116 | 117 | 118 | MASM: 119 | 120 | szScyllaDll db "ScyllaDLL.dll",0h 121 | szRebuildFileA db "RebuildFileA",0h 122 | szTargetExe db "some.exe",0h 123 | 124 | push offset szScyllaDll 125 | call LoadLibraryA 126 | push offset szRebuildFileA 127 | push eax 128 | call GetProcAddress 129 | xor ecx, ecx 130 | inc ecx 131 | push ecx 132 | push ecx 133 | push ecx 134 | push offset szTargetExe 135 | call eax 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /WTL/README: -------------------------------------------------------------------------------- 1 | Download WTL from here: https://sourceforge.net/projects/wtl/ 2 | Extract the contents of the ZIP in this directory. -------------------------------------------------------------------------------- /diStorm/README: -------------------------------------------------------------------------------- 1 | Get diStorm source (distorm3-x.x.zip) from 2 | http://www.ragestorm.net/distorm/ 3 | and unzip the content of the distorm3-x.x folder 4 | it into this directory. 5 | -------------------------------------------------------------------------------- /diStorm/diStorm.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | -------------------------------------------------------------------------------- /diStorm/diStorm.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /diStorm/src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | config.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef CONFIG_H 25 | #define CONFIG_H 26 | 27 | /* diStorm version number. */ 28 | #define __DISTORMV__ 0x030300 29 | 30 | #include /* memset, memcpy - can be easily self implemented for libc independency. */ 31 | 32 | #include "../include/distorm.h" 33 | 34 | 35 | /* 36 | * 64 bit offsets support: 37 | * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET 38 | * Note: make sure that the caller (library user) defines it too! 39 | */ 40 | /* #define SUPPORT_64BIT_OFFSET */ 41 | 42 | /* 43 | * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. 44 | * So the interface functions will be exported, otherwise they are useable only for static library. 45 | * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. 46 | */ 47 | /* #define DISTORM_DYNAMIC */ 48 | 49 | /* 50 | * If DISTORM_LIGHT is defined, everything involved in formatting the instructions 51 | * as text will be excluded from compilation. 52 | * distorm_decode(..) and distorm_format(..) will not be available. 53 | * This will decrease the size of the executable and leave you with decomposition functionality only. 54 | * 55 | * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. 56 | * #define DISTORM_LIGHT 57 | */ 58 | 59 | /* 60 | * diStorm now supports little/big endian CPU's. 61 | * It should detect the endianness according to predefined macro's of the compiler. 62 | * If you don't use GCC/MSVC you will have to define it on your own. 63 | */ 64 | 65 | /* These macros are used in order to make the code portable. */ 66 | #ifdef __GNUC__ 67 | 68 | #include 69 | 70 | #define _DLLEXPORT_ 71 | #define _FASTCALL_ 72 | #define _INLINE_ static 73 | /* GCC ignores this directive... */ 74 | /*#define _FASTCALL_ __attribute__((__fastcall__))*/ 75 | 76 | /* Set endianity (supposed to be LE though): */ 77 | #ifdef __BIG_ENDIAN__ 78 | #define BE_SYSTEM 79 | #endif 80 | 81 | /* End of __GCC__ */ 82 | 83 | #elif __WATCOMC__ 84 | 85 | #include 86 | 87 | #define _DLLEXPORT_ 88 | #define _FASTCALL_ 89 | #define _INLINE_ __inline 90 | 91 | /* End of __WATCOMC__ */ 92 | 93 | #elif __DMC__ 94 | 95 | #include 96 | 97 | #define _DLLEXPORT_ 98 | #define _FASTCALL_ 99 | #define _INLINE_ __inline 100 | 101 | /* End of __DMC__ */ 102 | 103 | #elif __TINYC__ 104 | 105 | #include 106 | 107 | #define _DLLEXPORT_ 108 | #define _FASTCALL_ 109 | #define _INLINE_ 110 | 111 | /* End of __TINYC__ */ 112 | 113 | #elif _MSC_VER 114 | 115 | /* stdint alternative is defined in distorm.h */ 116 | 117 | #define _DLLEXPORT_ __declspec(dllexport) 118 | #define _FASTCALL_ __fastcall 119 | #define _INLINE_ __inline 120 | 121 | /* Set endianity (supposed to be LE though): */ 122 | #if !defined(_M_IX86) && !defined(_M_X64) 123 | #define BE_SYSTEM 124 | #endif 125 | 126 | #endif /* #elif _MSC_VER */ 127 | 128 | /* If the library isn't compiled as a dynamic library don't export any functions. */ 129 | #ifndef DISTORM_DYNAMIC 130 | #undef _DLLEXPORT_ 131 | #define _DLLEXPORT_ 132 | #endif 133 | 134 | #ifndef FALSE 135 | #define FALSE 0 136 | #endif 137 | #ifndef TRUE 138 | #define TRUE 1 139 | #endif 140 | 141 | /* Define stream read functions for big endian systems. */ 142 | #ifdef BE_SYSTEM 143 | /* 144 | * These functions can read from the stream safely! 145 | * Swap endianity of input to little endian. 146 | */ 147 | static _INLINE_ int16_t RSHORT(const uint8_t *s) 148 | { 149 | return s[0] | (s[1] << 8); 150 | } 151 | static _INLINE_ uint16_t RUSHORT(const uint8_t *s) 152 | { 153 | return s[0] | (s[1] << 8); 154 | } 155 | static _INLINE_ int32_t RLONG(const uint8_t *s) 156 | { 157 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 158 | } 159 | static _INLINE_ uint32_t RULONG(const uint8_t *s) 160 | { 161 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 162 | } 163 | static _INLINE_ int64_t RLLONG(const uint8_t *s) 164 | { 165 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); 166 | } 167 | static _INLINE_ uint64_t RULLONG(const uint8_t *s) 168 | { 169 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); 170 | } 171 | #else 172 | /* Little endian macro's will just make the cast. */ 173 | #define RSHORT(x) *(int16_t *)x 174 | #define RUSHORT(x) *(uint16_t *)x 175 | #define RLONG(x) *(int32_t *)x 176 | #define RULONG(x) *(uint32_t *)x 177 | #define RLLONG(x) *(int64_t *)x 178 | #define RULLONG(x) *(uint64_t *)x 179 | #endif 180 | 181 | #endif /* CONFIG_H */ 182 | -------------------------------------------------------------------------------- /diStorm/src/decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | decoder.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2011 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef DECODER_H 25 | #define DECODER_H 26 | 27 | #include "config.h" 28 | 29 | typedef unsigned int _iflags; 30 | 31 | _DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); 32 | 33 | #endif /* DECODER_H */ 34 | -------------------------------------------------------------------------------- /diStorm/src/insts.h: -------------------------------------------------------------------------------- 1 | /* 2 | insts.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef INSTS_H 25 | #define INSTS_H 26 | 27 | #include "instructions.h" 28 | 29 | 30 | /* Flags Table */ 31 | extern _iflags FlagsTable[]; 32 | 33 | /* Root Trie DB */ 34 | extern _InstSharedInfo InstSharedInfoTable[]; 35 | extern _InstInfo InstInfos[]; 36 | extern _InstInfoEx InstInfosEx[]; 37 | extern _InstNode InstructionsTree[]; 38 | 39 | /* 3DNow! Trie DB */ 40 | extern _InstNode Table_0F_0F; 41 | /* AVX related: */ 42 | extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; 43 | 44 | /* 45 | * The inst_lookup will return on of these two instructions according to the specified decoding mode. 46 | * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. 47 | */ 48 | extern _InstInfo II_MOVSXD; 49 | 50 | /* 51 | * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. 52 | * If 0x90 is prefixed by a usable REX it will become XCHG, otherwise it will become a NOP. 53 | * Also note that if it's prefixed by 0xf3, it becomes a Pause. 54 | */ 55 | extern _InstInfo II_NOP; 56 | extern _InstInfo II_PAUSE; 57 | 58 | /* 59 | * RDRAND and VMPTRLD share same 2.3 bytes opcode, and then alternates on the MOD bits, 60 | * RDRAND is OT_FULL_REG while VMPTRLD is OT_MEM, and there's no such mixed type. 61 | * So a hack into the inst_lookup was added for this decision, the DB isn't flexible enough. :( 62 | */ 63 | extern _InstInfo II_RDRAND; 64 | 65 | /* 66 | * Used for letting the extract operand know the type of operands without knowing the 67 | * instruction itself yet, because of the way those instructions work. 68 | * See function instructions.c!inst_lookup_3dnow. 69 | */ 70 | extern _InstInfo II_3DNOW; 71 | 72 | /* Helper tables for pseudo compare mnemonics. */ 73 | extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ 74 | extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ 75 | 76 | #endif /* INSTS_H */ 77 | -------------------------------------------------------------------------------- /diStorm/src/operands.h: -------------------------------------------------------------------------------- 1 | /* 2 | operands.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef OPERANDS_H 25 | #define OPERANDS_H 26 | 27 | #include "config.h" 28 | #include "decoder.h" 29 | #include "prefix.h" 30 | #include "instructions.h" 31 | 32 | 33 | extern uint32_t _REGISTERTORCLASS[]; 34 | 35 | int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, 36 | _iflags instFlags, _OpType type, _OperandNumberType opNum, 37 | unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, 38 | _DecodeType effAdrSz, int* lockableInstruction); 39 | 40 | #endif /* OPERANDS_H */ 41 | -------------------------------------------------------------------------------- /diStorm/src/prefix.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NtQuery/Scylla/e87fd578a3fa0e68b873dcc98951788f3a40e055/diStorm/src/prefix.c -------------------------------------------------------------------------------- /diStorm/src/prefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | prefix.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef PREFIX_H 25 | #define PREFIX_H 26 | 27 | #include "config.h" 28 | #include "decoder.h" 29 | 30 | 31 | /* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ 32 | typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; 33 | 34 | /* Specifies an index into a table of prefixes by their type. */ 35 | typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; 36 | 37 | /* 38 | * This holds the prefixes state for the current instruction we decode. 39 | * decodedPrefixes includes all specific prefixes that the instruction got. 40 | * start is a pointer to the first prefix to take into account. 41 | * last is a pointer to the last byte we scanned. 42 | * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. 43 | */ 44 | typedef struct { 45 | _iflags decodedPrefixes, usedPrefixes; 46 | const uint8_t *start, *last, *vexPos, *rexPos; 47 | _PrefixExtType prefixExtType; 48 | uint16_t unusedPrefixesMask; 49 | /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ 50 | int isOpSizeMandatory; 51 | /* If VEX prefix is used, store the VEX.vvvv field. */ 52 | unsigned int vexV; 53 | /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ 54 | unsigned int vrex; 55 | 56 | /* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */ 57 | 58 | /* Holds the offset to the prefix byte by its type. */ 59 | int pfxIndexer[PFXIDX_MAX]; 60 | } _PrefixState; 61 | 62 | /* 63 | * Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). 64 | * REX is the fifth prefix type, this time I'm based on AMD64. 65 | * VEX is the 6th, though it can't be repeated. 66 | */ 67 | #define MAX_PREFIXES (5) 68 | 69 | int prefixes_is_valid(unsigned int ch, _DecodeType dt); 70 | void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi); 71 | void prefixes_ignore_all(_PrefixState* ps); 72 | uint16_t prefixes_set_unused_mask(_PrefixState* ps); 73 | void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); 74 | void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); 75 | 76 | #endif /* PREFIX_H */ 77 | -------------------------------------------------------------------------------- /diStorm/src/textdefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "textdefs.h" 25 | 26 | #ifndef DISTORM_LIGHT 27 | 28 | static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 29 | #define NIBBLE_TO_CHR Nibble2ChrTable[t] 30 | 31 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x) 32 | { 33 | /* 34 | * def prebuilt(): 35 | * s = "" 36 | * for i in xrange(256): 37 | * if ((i % 0x10) == 0): 38 | * s += "\r\n" 39 | * s += "\"%02x\", " % (i) 40 | * return s 41 | */ 42 | static int8_t TextBTable[256][3] = { 43 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 44 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 45 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 46 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 47 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 48 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 49 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 50 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 51 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 52 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 53 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 54 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 55 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 56 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 57 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 58 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" 59 | }; 60 | 61 | /* 62 | * Fixed length of 3 including null terminate character. 63 | */ 64 | memcpy(&s->p[s->length], TextBTable[x & 255], 3); 65 | s->length += 2; 66 | } 67 | 68 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x) 69 | { 70 | static int8_t TextHBTable[256][5] = { 71 | /* 72 | * def prebuilt(): 73 | * s = "" 74 | * for i in xrange(256): 75 | * if ((i % 0x10) == 0): 76 | * s += "\r\n" 77 | * s += "\"0x%x\", " % (i) 78 | * return s 79 | */ 80 | "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf", 81 | "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f", 82 | "0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26", "0x27", "0x28", "0x29", "0x2a", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f", 83 | "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", 84 | "0x40", "0x41", "0x42", "0x43", "0x44", "0x45", "0x46", "0x47", "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f", 85 | "0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f", 86 | "0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", "0x68", "0x69", "0x6a", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", 87 | "0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f", 88 | "0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f", 89 | "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f", 90 | "0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", 91 | "0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", 92 | "0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", 93 | "0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", 94 | "0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef", 95 | "0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff" 96 | }; 97 | 98 | if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */ 99 | memcpy(&s->p[s->length], TextHBTable[x & 255], 4); 100 | s->length += 3; 101 | } else { /* >= 0x10 has a fixed length of 5 including null terminate. */ 102 | memcpy(&s->p[s->length], TextHBTable[x & 255], 5); 103 | s->length += 4; 104 | } 105 | } 106 | 107 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x) 108 | { 109 | int8_t* buf; 110 | int i = 0, shift = 0; 111 | unsigned int t = 0; 112 | 113 | buf = (int8_t*)&s->p[s->length]; 114 | 115 | buf[0] = '0'; 116 | buf[1] = 'x'; 117 | buf += 2; 118 | 119 | for (shift = 28; shift != 0; shift -= 4) { 120 | t = (x >> shift) & 0xf; 121 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 122 | } 123 | t = x & 0xf; 124 | buf[i++] = NIBBLE_TO_CHR; 125 | 126 | s->length += i + 2; 127 | buf[i] = '\0'; 128 | } 129 | 130 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]) 131 | { 132 | int8_t* buf; 133 | int i = 0, shift = 0; 134 | uint32_t x = RULONG(&src[sizeof(int32_t)]); 135 | int t; 136 | 137 | buf = (int8_t*)&s->p[s->length]; 138 | buf[0] = '0'; 139 | buf[1] = 'x'; 140 | buf += 2; 141 | 142 | for (shift = 28; shift != -4; shift -= 4) { 143 | t = (x >> shift) & 0xf; 144 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 145 | } 146 | 147 | x = RULONG(src); 148 | for (shift = 28; shift != 0; shift -= 4) { 149 | t = (x >> shift) & 0xf; 150 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 151 | } 152 | t = x & 0xf; 153 | buf[i++] = NIBBLE_TO_CHR; 154 | 155 | s->length += i + 2; 156 | buf[i] = '\0'; 157 | } 158 | 159 | #ifdef SUPPORT_64BIT_OFFSET 160 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x) 161 | { 162 | int8_t* buf; 163 | int i = 0, shift = 0; 164 | OFFSET_INTEGER t = 0; 165 | 166 | buf = (int8_t*)&s->p[s->length]; 167 | 168 | buf[0] = '0'; 169 | buf[1] = 'x'; 170 | buf += 2; 171 | 172 | for (shift = 60; shift != 0; shift -= 4) { 173 | t = (x >> shift) & 0xf; 174 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 175 | } 176 | t = x & 0xf; 177 | buf[i++] = NIBBLE_TO_CHR; 178 | 179 | s->length += i + 2; 180 | buf[i] = '\0'; 181 | } 182 | #endif /* SUPPORT_64BIT_OFFSET */ 183 | 184 | #endif /* DISTORM_LIGHT */ 185 | -------------------------------------------------------------------------------- /diStorm/src/textdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef TEXTDEFS_H 25 | #define TEXTDEFS_H 26 | 27 | #include "config.h" 28 | #include "wstring.h" 29 | 30 | #ifndef DISTORM_LIGHT 31 | 32 | #define PLUS_DISP_CHR '+' 33 | #define MINUS_DISP_CHR '-' 34 | #define OPEN_CHR '[' 35 | #define CLOSE_CHR ']' 36 | #define SP_CHR ' ' 37 | #define SEG_OFF_CHR ':' 38 | 39 | /* 40 | Naming Convention: 41 | 42 | * get - returns a pointer to a string. 43 | * str - concatenates to string. 44 | 45 | * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. 46 | * code - means the function is used for disassembled instruction - Big Endian output. 47 | * off - means the function is used for 64bit offset - Big Endian output. 48 | 49 | * h - '0x' in front of the string. 50 | 51 | * b - byte 52 | * dw - double word (can be used for word also) 53 | * qw - quad word 54 | 55 | * all numbers are in HEX. 56 | */ 57 | 58 | extern int8_t TextBTable[256][4]; 59 | 60 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); 61 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); 62 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); 63 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); 64 | 65 | #ifdef SUPPORT_64BIT_OFFSET 66 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); 67 | #endif 68 | 69 | #endif /* DISTORM_LIGHT */ 70 | 71 | #endif /* TEXTDEFS_H */ 72 | -------------------------------------------------------------------------------- /diStorm/src/wstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "wstring.h" 25 | 26 | #ifndef DISTORM_LIGHT 27 | 28 | void strclear_WS(_WString* s) 29 | { 30 | s->p[0] = '\0'; 31 | s->length = 0; 32 | } 33 | 34 | void chrcat_WS(_WString* s, uint8_t ch) 35 | { 36 | s->p[s->length] = ch; 37 | s->p[s->length + 1] = '\0'; 38 | s->length += 1; 39 | } 40 | 41 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) 42 | { 43 | s->length = len; 44 | memcpy((int8_t*)s->p, buf, len + 1); 45 | } 46 | 47 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) 48 | { 49 | memcpy((int8_t*)&s->p[s->length], buf, len + 1); 50 | s->length += len; 51 | } 52 | 53 | void strcat_WS(_WString* s, const _WString* s2) 54 | { 55 | memcpy((int8_t*)&s->p[s->length], s2->p, s2->length + 1); 56 | s->length += s2->length; 57 | } 58 | 59 | #endif /* DISTORM_LIGHT */ 60 | -------------------------------------------------------------------------------- /diStorm/src/wstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef WSTRING_H 25 | #define WSTRING_H 26 | 27 | #include "config.h" 28 | 29 | #ifndef DISTORM_LIGHT 30 | 31 | void strclear_WS(_WString* s); 32 | void chrcat_WS(_WString* s, uint8_t ch); 33 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); 34 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); 35 | void strcat_WS(_WString* s, const _WString* s2); 36 | 37 | /* 38 | * Warning, this macro should be used only when the compiler knows the size of string in advance! 39 | * This macro is used in order to spare the call to strlen when the strings are known already. 40 | * Note: sizeof includes NULL terminated character. 41 | */ 42 | #define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1) 43 | #define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1) 44 | 45 | #endif /* DISTORM_LIGHT */ 46 | 47 | #endif /* WSTRING_H */ 48 | -------------------------------------------------------------------------------- /diStorm/src/x86defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | x86defs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef X86DEFS_H 25 | #define X86DEFS_H 26 | 27 | 28 | #define SEG_REGS_MAX (6) 29 | #define CREGS_MAX (9) 30 | #define DREGS_MAX (8) 31 | 32 | /* Maximum instruction size, including prefixes */ 33 | #define INST_MAXIMUM_SIZE (15) 34 | 35 | /* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ 36 | #define INST_CMP_MAX_RANGE (8) 37 | 38 | /* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ 39 | #define INST_VCMP_MAX_RANGE (32) 40 | 41 | /* Wait instruction byte code. */ 42 | #define INST_WAIT_INDEX (0x9b) 43 | 44 | /* Lea instruction byte code. */ 45 | #define INST_LEA_INDEX (0x8d) 46 | 47 | /* NOP/XCHG instruction byte code. */ 48 | #define INST_NOP_INDEX (0x90) 49 | 50 | /* ARPL/MOVSXD instruction byte code. */ 51 | #define INST_ARPL_INDEX (0x63) 52 | 53 | /* 54 | * Minimal MODR/M value of divided instructions. 55 | * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. 56 | */ 57 | #define INST_DIVIDED_MODRM (0xc0) 58 | 59 | /* This is the escape byte value used for 3DNow! instructions. */ 60 | #define _3DNOW_ESCAPE_BYTE (0x0f) 61 | 62 | #define PREFIX_LOCK (0xf0) 63 | #define PREFIX_REPNZ (0xf2) 64 | #define PREFIX_REP (0xf3) 65 | #define PREFIX_CS (0x2e) 66 | #define PREFIX_SS (0x36) 67 | #define PREFIX_DS (0x3e) 68 | #define PREFIX_ES (0x26) 69 | #define PREFIX_FS (0x64) 70 | #define PREFIX_GS (0x65) 71 | #define PREFIX_OP_SIZE (0x66) 72 | #define PREFIX_ADDR_SIZE (0x67) 73 | #define PREFIX_VEX2b (0xc5) 74 | #define PREFIX_VEX3b (0xc4) 75 | 76 | /* REX prefix value range, 64 bits mode decoding only. */ 77 | #define PREFIX_REX_LOW (0x40) 78 | #define PREFIX_REX_HI (0x4f) 79 | /* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ 80 | #define EX_GPR_BASE (8) 81 | 82 | /* Mask for REX and VEX features: */ 83 | /* Base */ 84 | #define PREFIX_EX_B (1) 85 | /* Index */ 86 | #define PREFIX_EX_X (2) 87 | /* Register */ 88 | #define PREFIX_EX_R (4) 89 | /* Operand Width */ 90 | #define PREFIX_EX_W (8) 91 | /* Vector Lengh */ 92 | #define PREFIX_EX_L (0x10) 93 | 94 | #endif /* X86DEFS_H */ 95 | -------------------------------------------------------------------------------- /scylla_release.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | SET SCYVERSION=Scylla_v0.11 3 | if not exist .\%SCYVERSION% mkdir .\%SCYVERSION% 4 | copy ".\Win32\Release\Scylla.exe" ".\%SCYVERSION%\Scylla_x86.exe" 5 | copy ".\x64\Release\Scylla.exe" ".\%SCYVERSION%\Scylla_x64.exe" 6 | copy ".\Win32\Release\Scylla.map" ".\%SCYVERSION%\Scylla_x86.map" 7 | copy ".\x64\Release\Scylla.map" ".\%SCYVERSION%\Scylla_x64.map" 8 | copy ".\Win32\Release\ScyllaDLL.dll" ".\%SCYVERSION%\Scylla_x86.dll" 9 | copy ".\x64\Release\ScyllaDLL.dll" ".\%SCYVERSION%\Scylla_x64.dll" 10 | copy ".\Win32\Release\ScyllaDLL.lib" ".\%SCYVERSION%\Scylla_x86.lib" 11 | copy ".\x64\Release\ScyllaDLL.lib" ".\%SCYVERSION%\Scylla_x64.lib" 12 | pause -------------------------------------------------------------------------------- /tinyxml/README: -------------------------------------------------------------------------------- 1 | Download tinyxml from here: https://sourceforge.net/projects/tinyxml/ 2 | Copy the following files in this directory: 3 | tinystr.cpp 4 | tinyxml.cpp 5 | tinyxmlerror.cpp 6 | tinyxmlparser.cpp 7 | tinystr.h 8 | tinyxml.h -------------------------------------------------------------------------------- /tinyxml/tinyxml.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /tinyxml/tinyxml.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | --------------------------------------------------------------------------------