Page Menu
Home
desp's stash
Search
Configure Global Search
Log In
Files
F191379
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
28 KB
Subscribers
None
View Options
diff --git a/Plugins/ImpRec_Plugins/Imprec_Wrapper_DLL.dll b/Plugins/ImpRec_Plugins/Imprec_Wrapper_DLL.dll
new file mode 100644
index 0000000..6cd85b2
Binary files /dev/null and b/Plugins/ImpRec_Plugins/Imprec_Wrapper_DLL.dll differ
diff --git a/Plugins/ImpRec_Plugins/PECompact 2.7.x.dll b/Plugins/ImpRec_Plugins/PECompact 2.7.x.dll
new file mode 100644
index 0000000..13f044a
Binary files /dev/null and b/Plugins/ImpRec_Plugins/PECompact 2.7.x.dll differ
diff --git a/Plugins/Include_Headers/ScyllaPlugin.h b/Plugins/Include_Headers/ScyllaPlugin.h
new file mode 100644
index 0000000..3aad3f4
--- /dev/null
+++ b/Plugins/Include_Headers/ScyllaPlugin.h
@@ -0,0 +1,46 @@
+
+#include <windows.h>
+
+const char FILE_MAPPING_NAME[] = "ScyllaPluginExchange";
+
+#define SCYLLA_STATUS_SUCCESS 0
+#define SCYLLA_STATUS_UNKNOWN_ERROR 1
+#define SCYLLA_STATUS_UNSUPPORTED_PROTECTION 2
+#define SCYLLA_STATUS_IMPORT_RESOLVING_FAILED 3
+#define SCYLLA_STATUS_MAPPING_FAILED 0xFF
+
+/* Important note:
+ *
+ * If you write a plugin for the x86 (32-Bit) edition: DWORD_PTR address has 32 bit (4 byte)
+ * If you write a plugin for the x64 (64-Bit) edition: DWORD_PTR address has 64 bit (8 byte)
+ */
+typedef struct _UNRESOLVED_IMPORT { // Scylla Plugin exchange format
+ DWORD_PTR ImportTableAddressPointer; //in VA, address in IAT which points to an invalid api address
+ DWORD_PTR InvalidApiAddress; //in VA, invalid api address that needs to be resolved
+} UNRESOLVED_IMPORT, *PUNRESOLVED_IMPORT;
+
+typedef struct _SCYLLA_EXCHANGE {
+ BYTE status; //return a status, default 0xFF == SCYLLA_STATUS_MAPPING_FAILED
+ DWORD_PTR imageBase; //image base
+ DWORD_PTR imageSize; //size of the image
+ DWORD_PTR numberOfUnresolvedImports; //number of unresolved imports in this structure
+ BYTE offsetUnresolvedImportsArray;
+} SCYLLA_EXCHANGE, *PSCYLLA_EXCHANGE;
+
+
+
+#define DllExport __declspec(dllexport)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef UNICODE
+ DllExport wchar_t * __cdecl ScyllaPluginNameW();
+#else
+ DllExport char * __cdecl ScyllaPluginNameA();
+#endif
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/Plugins/PECompact.dll b/Plugins/PECompact.dll
new file mode 100644
index 0000000..667e26d
Binary files /dev/null and b/Plugins/PECompact.dll differ
diff --git a/Plugins/PESpin_x64_v1.dll b/Plugins/PESpin_x64_v1.dll
new file mode 100644
index 0000000..092e2c3
Binary files /dev/null and b/Plugins/PESpin_x64_v1.dll differ
diff --git a/Plugins/Sources/Imprec_Wrapper_DLL.cpp b/Plugins/Sources/Imprec_Wrapper_DLL.cpp
new file mode 100644
index 0000000..cf8a5fb
--- /dev/null
+++ b/Plugins/Sources/Imprec_Wrapper_DLL.cpp
@@ -0,0 +1,373 @@
+#include "ScyllaPlugin.h"
+
+//remove c runtime library
+//#pragma comment(linker, "/ENTRY:DllMain")
+
+//typedef DWORD (__stdcall * def_ImpREC_TraceSTD)(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall);
+//typedef DWORD (__cdecl * def_ImpREC_TraceCDE)(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall);
+typedef DWORD (* def_voidFunction)();
+
+#define PLUGIN_IMPREC_EXCHANGE_DLL_PATH "ScyllaImprecPluginExchangePath"
+#define PLUGIN_MAPPING_NAME "Imprec_plugin_exchanging"
+
+const char logFileName[] = "logfile_scylla_plugin.txt";
+BOOL writeToLogFile(const char * text);
+BOOL getLogFilePath();
+
+HMODULE hImprecPlugin = 0;
+HANDLE hMapFile = 0;
+LPVOID lpViewOfFile = 0;
+WCHAR imprecPluginPath[260];
+char textBuffer[200];
+char logFilePath[260];
+
+def_voidFunction voidFunction = 0;
+
+BOOL stdcallPlugin = 0;
+
+BOOL getMappedView();
+void cleanUp();
+
+void resolveImports();
+BOOL getImprecPlugin();
+
+DWORD callImprecTraceFunction(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall);
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved)
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Initialize once for each new process.
+ // Return FALSE to fail DLL load.
+
+ getLogFilePath();
+
+ writeToLogFile("DLL attached - Injection successful\r\n");
+
+ if (getImprecPlugin())
+ {
+ writeToLogFile("Loading ImpREC Plugin successful\r\n");
+
+ if (getMappedView()) //open file mapping
+ {
+ writeToLogFile("Open mapping successful\r\n");
+ resolveImports(); //resolve imports
+ writeToLogFile("Resolving Imports successful\r\n");
+ cleanUp(); //clean up handles
+ writeToLogFile("Cleanup successful\r\n");
+ }
+ }
+ else
+ {
+ writeToLogFile("Failed to get ImpREC Plugin\r\n");
+ }
+
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // Do thread-specific initialization.
+ break;
+
+ case DLL_THREAD_DETACH:
+ // Do thread-specific cleanup.
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ writeToLogFile("DLL successfully detached\r\n");
+ break;
+ }
+ return TRUE; // Successful DLL_PROCESS_ATTACH.
+}
+
+/*void checkCallingConvention()
+{
+ __asm {
+ push eax
+ push 0
+ push 0
+ push 0
+ push 0
+ push 0x1337
+ }
+
+ voidFunction();
+
+ __asm {
+ cmp dword ptr ss:[esp],0x1337
+ je cdecl_call
+ mov stdcallPlugin, 1
+ jmp finished
+cdecl_call:
+ add esp, 0x14
+ mov stdcallPlugin, 0
+finished:
+ pop eax
+ }
+}*/
+
+BOOL getImprecPlugin()
+{
+ HANDLE hImprecExchange = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, PLUGIN_IMPREC_EXCHANGE_DLL_PATH); //open named file mapping object
+ if (hImprecExchange == 0)
+ {
+ writeToLogFile("getImprecPlugin() -> OpenFileMappingA failed\r\n");
+ return FALSE;
+ }
+
+ LPVOID lpImprecViewOfFile = MapViewOfFile(hImprecExchange, FILE_MAP_READ, 0, 0, 0); //map the view with full access
+
+ if (lpImprecViewOfFile == 0)
+ {
+ CloseHandle(hImprecExchange); //close mapping handle
+ writeToLogFile("getImprecPlugin() -> MapViewOfFile failed\r\n");
+ return FALSE;
+ }
+
+ lstrcpyW(imprecPluginPath, (LPWSTR)lpImprecViewOfFile);
+
+ UnmapViewOfFile(lpImprecViewOfFile);
+ CloseHandle(hImprecExchange);
+
+ wsprintfA(textBuffer, "- ImpREC Plugin -> %S\r\n", imprecPluginPath);
+ writeToLogFile(textBuffer);
+
+ hImprecPlugin = LoadLibraryW(imprecPluginPath);
+
+ if (hImprecPlugin)
+ {
+ voidFunction = (def_voidFunction)GetProcAddress(hImprecPlugin, "Trace");
+ if (voidFunction)
+ {
+ return TRUE;
+ }
+ else
+ {
+ writeToLogFile("getImprecPlugin() -> Cannot find Trace method\r\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ wsprintfA(textBuffer, "getImprecPlugin() -> LoadLibraryW failed 0x%X\r\n", GetLastError());
+ writeToLogFile(textBuffer);
+ return FALSE;
+ }
+}
+
+BOOL getMappedView()
+{
+ hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, FILE_MAPPING_NAME); //open named file mapping object
+
+ if (hMapFile == 0)
+ {
+ writeToLogFile("OpenFileMappingA failed\r\n");
+ return FALSE;
+ }
+
+ lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); //map the view with full access
+
+ if (lpViewOfFile == 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ hMapFile = 0;
+ writeToLogFile("MapViewOfFile failed\r\n");
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void cleanUp()
+{
+ if (lpViewOfFile != 0)
+ {
+ UnmapViewOfFile(lpViewOfFile); //close map view
+ lpViewOfFile = 0;
+ }
+ if (hMapFile != 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ hMapFile = 0;
+ }
+ if (hImprecPlugin != 0)
+ {
+ FreeLibrary(hImprecPlugin);
+ hImprecPlugin = 0;
+ }
+}
+
+DWORD callImprecTraceFunction(DWORD hFileMap, DWORD dwSizeMap, DWORD dwTimeOut, DWORD dwToTrace, DWORD dwExactCall)
+{
+ DWORD retValue = 0;
+
+ //some ImpREC Plugins use __cdecl and some other use __stdcall
+
+ __asm {
+ push eax
+ xor eax, eax
+ push eax
+ push dwExactCall
+ push dwToTrace
+ push dwTimeOut
+ push dwSizeMap
+ push hFileMap
+ }
+
+ retValue = voidFunction();
+
+ __asm {
+ cmp dword ptr ss:[esp],0
+ jne cdecl_call
+ jmp finished
+cdecl_call:
+ add esp, 0x14
+finished:
+ pop eax
+ pop eax
+ }
+
+ return retValue;
+}
+
+void resolveImports()
+{
+ PSCYLLA_EXCHANGE scyllaExchange = 0;
+ PUNRESOLVED_IMPORT unresolvedImport = 0;
+ DWORD pluginRet = 0;
+ DWORD * pluginOutput = 0;
+ LPVOID lpMapped = 0;
+ HANDLE hPluginMap = 0, hPluginMapDup = 0;
+
+ scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
+ unresolvedImport = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray);
+
+ scyllaExchange->status = SCYLLA_STATUS_SUCCESS;
+
+ hPluginMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, sizeof(DWORD), PLUGIN_MAPPING_NAME);
+
+ if (hPluginMap == 0)
+ {
+ scyllaExchange->status = SCYLLA_STATUS_MAPPING_FAILED;
+ writeToLogFile("resolveImports :: CreateFileMappingA hPluginMap failed\r\n");
+ return;
+ }
+
+ while (unresolvedImport->ImportTableAddressPointer != 0) //last element is a nulled struct
+ {
+
+ if (!DuplicateHandle(GetCurrentProcess(), hPluginMap, GetCurrentProcess(), &hPluginMapDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ wsprintfA(textBuffer,"resolveImports :: DuplicateHandle failed error code %d\r\n", GetLastError());
+ writeToLogFile(textBuffer);
+ }
+
+ /*
+ - hFileMap : HANDLE of the file mapped by ImportREC
+ - dwSizeMap : Size of the mapped file
+ - dwTimeOut : TimeOut in ImportREC Options
+ - dwToTrace : The pointer to trace (in VA)
+ - dwExactCall : The EIP of the 'Exact Call' (in VA)
+ (this value is 0 when it is not an 'Exact Call')
+ */
+
+ pluginRet = callImprecTraceFunction((DWORD)hPluginMapDup, sizeof(DWORD), 200, unresolvedImport->InvalidApiAddress, 0);
+
+ lpMapped = MapViewOfFile(hPluginMap, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, 0);
+
+ if (lpMapped != 0)
+ {
+ pluginOutput = (DWORD *)lpMapped;
+
+ wsprintfA(textBuffer, "- Plugin return value %d resolved import %X\r\n", pluginRet, *pluginOutput);
+ writeToLogFile(textBuffer);
+
+ if (*pluginOutput != 0)
+ {
+ unresolvedImport->InvalidApiAddress = *pluginOutput;
+ *pluginOutput = 0;
+ }
+ else
+ {
+ scyllaExchange->status = SCYLLA_STATUS_IMPORT_RESOLVING_FAILED;
+ }
+
+ if (!UnmapViewOfFile(lpMapped))
+ {
+ wsprintfA(textBuffer,"resolveImports :: UnmapViewOfFile failed error code %d\r\n", GetLastError());
+ writeToLogFile(textBuffer);
+ }
+
+
+ lpMapped = 0;
+ }
+ else
+ {
+ scyllaExchange->status = SCYLLA_STATUS_MAPPING_FAILED;
+ wsprintfA(textBuffer,"resolveImports :: MapViewOfFile failed error code %d\r\n", GetLastError());
+ writeToLogFile(textBuffer);
+ }
+
+ unresolvedImport++; //next pointer to struct
+ }
+
+ CloseHandle(hPluginMap);
+}
+
+BOOL getLogFilePath()
+{
+ size_t i = 0;
+
+ if (!GetModuleFileNameA(0, logFilePath, sizeof(logFilePath))) //get full path of exe
+ {
+ return FALSE;
+ }
+
+ for (i = (lstrlenA(logFilePath) - 1); i >= 0; i--) //remove the exe file name from full path
+ {
+ if (logFilePath[i] == '\\')
+ {
+ logFilePath[i+1] = 0x00;
+ break;
+ }
+ }
+
+ if (lstrcatA(logFilePath,logFileName) == 0) //append log file name to path
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL writeToLogFile(const char * text)
+{
+ DWORD lpNumberOfBytesWritten = 0;
+ BOOL wfRet = 0;
+ HANDLE hFile = 0;
+
+ hFile = CreateFileA(logFilePath, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); //open log file for writing
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
+
+ SetFilePointer(hFile, 0, 0, FILE_END); //set file pointer to the end of file
+
+ if (WriteFile(hFile, text, (DWORD)lstrlenA(text), &lpNumberOfBytesWritten, 0)) //write message to logfile
+ {
+ wfRet = TRUE;
+ }
+ else
+ {
+ wfRet = FALSE;
+ }
+
+ CloseHandle(hFile);
+ return wfRet;
+}
\ No newline at end of file
diff --git a/Plugins/Sources/PECompact.cpp b/Plugins/Sources/PECompact.cpp
new file mode 100644
index 0000000..03cc7b2
--- /dev/null
+++ b/Plugins/Sources/PECompact.cpp
@@ -0,0 +1,194 @@
+
+#include "ScyllaPlugin.h"
+
+//remove c runtime library
+//#pragma comment(linker, "/ENTRY:DllMain")
+
+
+const char logFileName[] = "logfile_scylla_plugin.txt";
+BOOL writeToLogFile(const char * text);
+
+
+HANDLE hMapFile = 0;
+LPVOID lpViewOfFile = 0;
+
+BOOL getMappedView();
+void cleanUp();
+
+void resolveImports();
+
+
+#define PLUGIN_NAME "PECompact v2.x"
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved)
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Initialize once for each new process.
+ // Return FALSE to fail DLL load.
+
+ writeToLogFile("DLL attached - Injection successful\r\n");
+ if (getMappedView()) //open file mapping
+ {
+ writeToLogFile("Open mapping successful\r\n");
+ resolveImports(); //resolve imports
+ cleanUp(); //clean up handles
+ }
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // Do thread-specific initialization.
+ break;
+
+ case DLL_THREAD_DETACH:
+ // Do thread-specific cleanup.
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ writeToLogFile("DLL successfully detached\r\n");
+ break;
+ }
+ return TRUE; // Successful DLL_PROCESS_ATTACH.
+}
+
+BOOL getMappedView()
+{
+ hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, FILE_MAPPING_NAME); //open named file mapping object
+
+ if (hMapFile == 0)
+ {
+ writeToLogFile("OpenFileMappingA failed\r\n");
+ return FALSE;
+ }
+
+ lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); //map the view with full access
+
+ if (lpViewOfFile == 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ hMapFile = 0;
+ writeToLogFile("MapViewOfFile failed\r\n");
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void cleanUp()
+{
+ if (lpViewOfFile != 0)
+ {
+ UnmapViewOfFile(lpViewOfFile); //close map view
+ }
+ if (hMapFile != 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ }
+}
+
+
+void resolveImports()
+{
+ DWORD_PTR invalidApiAddress = 0;
+ PSCYLLA_EXCHANGE scyllaExchange = 0;
+ PUNRESOLVED_IMPORT unresolvedImport = 0;
+
+ scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
+ unresolvedImport = (PUNRESOLVED_IMPORT)((DWORD_PTR)scyllaExchange + scyllaExchange->offsetUnresolvedImportsArray);
+
+ scyllaExchange->status = SCYLLA_STATUS_SUCCESS;
+
+ while (unresolvedImport->ImportTableAddressPointer != 0) //last element is a nulled struct
+ {
+ //get real WINAPI address
+
+ //overwrite the existing wrong value with the good api address
+ invalidApiAddress = unresolvedImport->InvalidApiAddress;
+
+ //PECompact example
+ //01BF01FF B8 45128275 MOV EAX,kernel32.GetModuleHandleA
+ //01BF0204 - FFE0 JMP EAX
+
+ if (*((BYTE *)invalidApiAddress) == 0xB8) //is it pe compact?
+ {
+ invalidApiAddress++; //increase 1 opcode
+
+ //write right value to struct
+ unresolvedImport->InvalidApiAddress = *((DWORD_PTR *)invalidApiAddress);
+ }
+ else
+ {
+ writeToLogFile("Unsupported opcode found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+
+ unresolvedImport++; //next pointer to struct
+ }
+}
+
+BOOL writeToLogFile(const char * text)
+{
+ DWORD lpNumberOfBytesWritten = 0;
+ size_t i = 0;
+ BOOL wfRet = 0;
+ HANDLE hFile = 0;
+ char buffer[260];
+
+ if (!GetModuleFileNameA(0, buffer, sizeof(buffer))) //get full path of exe
+ {
+ return FALSE;
+ }
+
+ for (i = (lstrlenA(buffer) - 1); i >= 0; i--) //remove the exe file name from full path
+ {
+ if (buffer[i] == '\\')
+ {
+ buffer[i+1] = 0x00;
+ break;
+ }
+ }
+
+ if (lstrcatA(buffer,logFileName) == 0) //append log file name to path
+ {
+ return FALSE;
+ }
+
+ hFile = CreateFileA(buffer, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); //open log file for writing
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
+
+ SetFilePointer(hFile, 0, 0, FILE_END); //set file pointer to the end of file
+
+ if (WriteFile(hFile, text, (DWORD)lstrlenA(text), &lpNumberOfBytesWritten, 0)) //write message to logfile
+ {
+ wfRet = TRUE;
+ }
+ else
+ {
+ wfRet = FALSE;
+ }
+
+ CloseHandle(hFile);
+ return wfRet;
+}
+
+
+#ifdef UNICODE
+DllExport wchar_t * __cdecl ScyllaPluginNameW()
+{
+ return TEXT(PLUGIN_NAME);
+}
+#else
+DllExport char * __cdecl ScyllaPluginNameA()
+{
+ return PLUGIN_NAME;
+}
+#endif
\ No newline at end of file
diff --git a/Plugins/Sources/PESpin_x64_v1.cpp b/Plugins/Sources/PESpin_x64_v1.cpp
new file mode 100644
index 0000000..bdfde65
--- /dev/null
+++ b/Plugins/Sources/PESpin_x64_v1.cpp
@@ -0,0 +1,496 @@
+#include "ScyllaPlugin.h"
+
+const char logFileName[] = "logfile_scylla_plugin.txt";
+BOOL writeToLogFile(const char * text);
+
+
+HANDLE hMapFile = 0;
+LPVOID lpViewOfFile = 0;
+
+BOOL getMappedView();
+void cleanUp();
+
+void resolveImports();
+DWORD getApiHash(const char * apiName);
+DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, const BYTE * pattern, const char * mask);
+DWORD_PTR getApiAddress(DWORD_PTR dllBaseArray, DWORD_PTR apiHash);
+BOOL searchMagicConstant(DWORD_PTR startAddress);
+DWORD_PTR findJumpDestination(DWORD_PTR startAddress);
+DWORD_PTR findApiDefinition(DWORD_PTR startAddress);
+DWORD_PTR findDllBaseArrayAddress(DWORD_PTR startAddress);
+
+#define PLUGIN_NAME "PESpin x64 v1.x"
+
+char textBuffer[200];
+DWORD magicConstant = 0;
+BOOL executeOnce = 0;
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved)
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Initialize once for each new process.
+ // Return FALSE to fail DLL load.
+
+ DisableThreadLibraryCalls(hinstDLL);
+
+ writeToLogFile("DLL attached - Injection successful\r\n");
+ if (getMappedView()) //open file mapping
+ {
+ writeToLogFile("Open mapping successful\r\n");
+
+ resolveImports(); //resolve imports
+ writeToLogFile("resolveImports done\r\n");
+
+ cleanUp(); //clean up handles
+ writeToLogFile("All Plugin stuff done\r\n");
+ }
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // Do thread-specific initialization.
+ break;
+
+ case DLL_THREAD_DETACH:
+ // Do thread-specific cleanup.
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ writeToLogFile("DLL successfully detached\r\n");
+ break;
+ }
+ return TRUE; // Successful DLL_PROCESS_ATTACH.
+}
+
+BOOL getMappedView()
+{
+ hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, FILE_MAPPING_NAME); //open named file mapping object
+
+ if (hMapFile == 0)
+ {
+ writeToLogFile("OpenFileMappingA failed\r\n");
+ return FALSE;
+ }
+
+ lpViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); //map the view with full access
+
+ if (lpViewOfFile == 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ hMapFile = 0;
+ writeToLogFile("MapViewOfFile failed\r\n");
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void cleanUp()
+{
+ if (lpViewOfFile != 0)
+ {
+ UnmapViewOfFile(lpViewOfFile); //close map view
+ }
+ if (hMapFile != 0)
+ {
+ CloseHandle(hMapFile); //close mapping handle
+ }
+}
+
+
+void resolveImports()
+{
+ DWORD_PTR invalidApiAddress = 0;
+ DWORD_PTR apiHash = 0;
+ DWORD_PTR destination = 0;
+ DWORD_PTR dllBaseArray = 0;
+ PSCYLLA_EXCHANGE scyllaExchange = 0;
+ PUNRESOLVED_IMPORT unresolvedImport = 0;
+
+ scyllaExchange = (PSCYLLA_EXCHANGE)lpViewOfFile;
+ unresolvedImport = (PUNRESOLVED_IMPORT)((DWORD_PTR)lpViewOfFile + scyllaExchange->offsetUnresolvedImportsArray);
+
+ scyllaExchange->status = SCYLLA_STATUS_SUCCESS;
+
+ while (unresolvedImport->ImportTableAddressPointer != 0) //last element is a nulled struct
+ {
+ //get real WINAPI address
+
+ //overwrite the existing wrong value with the good api address
+ invalidApiAddress = unresolvedImport->InvalidApiAddress;
+
+
+ //000000014000F676 50 push rax
+ //000000014000F677 48B800657410C2584800 mov rax,004858C210746500
+ //000000014000F681 E928030000 jmp 000000014000F9AE
+
+ if (*((BYTE *)invalidApiAddress) == 0x50) //is it pespin, push rax
+ {
+ apiHash = findApiDefinition(invalidApiAddress); //read 00657410C2584800
+
+ if (!apiHash)
+ {
+ writeToLogFile("API Definition not found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+
+ destination = findJumpDestination(invalidApiAddress); //jmp 000000014000F9AE
+
+ if (!destination)
+ {
+ writeToLogFile("JMP Destination not found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+
+ if (!executeOnce)
+ {
+ if (!searchMagicConstant(destination))
+ {
+ writeToLogFile("Magic Constant not found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+ }
+
+ dllBaseArray = findDllBaseArrayAddress(destination);
+
+ if (!dllBaseArray)
+ {
+ writeToLogFile("DLL Base Array not found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+
+ unresolvedImport->InvalidApiAddress = getApiAddress(dllBaseArray, apiHash);
+
+ if (!unresolvedImport->InvalidApiAddress)
+ {
+ writeToLogFile("API not found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_IMPORT_RESOLVING_FAILED;
+ break;
+ }
+
+ }
+ else
+ {
+ writeToLogFile("Unsupported opcode found\r\n");
+ scyllaExchange->status = SCYLLA_STATUS_UNSUPPORTED_PROTECTION;
+ break;
+ }
+
+ unresolvedImport++; //next pointer to struct
+ }
+}
+
+
+ /*
+ 000000014000F9E1 4C 8D 1D AE FF FF FF lea r11, off_14000F996 ;dll base
+ 000000014000F9E8 4C 8B D0 mov r10, rax
+ 000000014000F9EB 49 81 E2 FF 00 00 00 and r10, 0FFh
+ 000000014000F9F2 49 C1 E2 03 shl r10, 3
+ 000000014000F9F6 4F 8B 14 1A mov r10, [r10+r11]
+ */
+DWORD_PTR findDllBaseArrayAddress(DWORD_PTR startAddress)
+{
+ __int32 relAddress = 0;
+
+ startAddress = findPattern(startAddress, 300, (BYTE *)"\x4C\x8D\xFF\xFF\xFF\xFF\xFF\x4C\x8B\xD0\x49\x81\xE2\xFF\x00\x00","xx?????xxxxxxxxx");
+
+ if (startAddress)
+ {
+ startAddress += 3;
+ relAddress = *((__int32 *)startAddress);
+
+ wsprintfA(textBuffer, "- Found DLL Base array -> %016I64X\r\n", (relAddress + startAddress + sizeof(DWORD)));
+ writeToLogFile(textBuffer);
+
+ return (relAddress + startAddress + sizeof(DWORD));
+ }
+ else
+ {
+ writeToLogFile("findDllBaseArrayAddress failed\r\n");
+ return 0;
+ }
+}
+
+DWORD_PTR findApiDefinition(DWORD_PTR startAddress)
+{
+ startAddress += 3; //increase 3 bytes
+
+ wsprintfA(textBuffer, "- Found API Definition -> %016I64X\r\n", *((DWORD_PTR *)startAddress));
+ writeToLogFile(textBuffer);
+
+ return *((DWORD_PTR *)startAddress); //read 00657410C2584800
+}
+
+DWORD_PTR findJumpDestination(DWORD_PTR startAddress)
+{
+ __int32 destination = 0;
+
+ startAddress += sizeof(DWORD_PTR) + 4; //increase 8 + 4 bytes
+
+ destination = *((__int32 *)startAddress); //get jmp relative 4 bytes
+
+ wsprintfA(textBuffer, "- Found JMP Destination -> %016I64X\r\n", destination + startAddress + sizeof(DWORD));
+ writeToLogFile(textBuffer);
+
+ return destination + startAddress + sizeof(DWORD); //increase 4 + 1 bytes
+}
+
+BOOL searchMagicConstant(DWORD_PTR startAddress)
+{
+
+ executeOnce = 1;
+ /*
+
+ 000000014000FBF9 32 D0 xor dl, al
+ 000000014000FBFB B0 08 mov al, 8
+ 000000014000FBFD
+ 000000014000FBFD loc_14000FBFD:
+ 000000014000FBFD D1 EA shr edx, 1
+ 000000014000FBFF 73 06 jnb short loc_14000FC07
+ 000000014000FC01 81 F2 1F AF 81 73 xor edx, 7381AF1F ; constant
+ 000000014000FC07
+ 000000014000FC07 loc_14000FC07:
+ 000000014000FC07 FE C8 dec al
+ 000000014000FC09 75 F2 jnz short loc_14000FBFD
+ 000000014000FC0B EB E3 jmp short loc_14000FBF0
+ 000000014000FC0D
+ 000000014000FC0D loc_14000FC0D:
+ 000000014000FC0D 48 92 xchg rax, rdx
+
+ */
+
+ DWORD_PTR address = findPattern(startAddress, 1000, (BYTE *)"\x32\xD0\xB0\x08\xD1\xEA\x73\x06\x81\xF2\xFF\xFF\xFF\xFF\xFE\xC8\x75","xxxxxxxxxx????xxx");
+ if (address)
+ {
+ address += 10;
+ magicConstant = *((DWORD *)address);
+
+ wsprintfA(textBuffer, "- Found magic constant -> %08X\r\n", magicConstant);
+ writeToLogFile(textBuffer);
+
+ return 1;
+ }
+ else
+ {
+ magicConstant = 0;
+ writeToLogFile("Magic Constant not found\r\n");
+ return 0;
+ }
+}
+
+/*
+ * Resolve PESpin Api String to VA
+ */
+DWORD_PTR getApiAddress(DWORD_PTR dllBaseArray, DWORD_PTR apiHash)
+{
+ PIMAGE_DOS_HEADER pDosHeader = 0;
+ PIMAGE_NT_HEADERS pNtHeader = 0;
+ PIMAGE_EXPORT_DIRECTORY pExportHeader = 0;
+ DWORD_PTR dllBase = 0;
+ int dllBaseIndex = 0;
+ DWORD *addressOfFunctionsArray = 0,*addressOfNamesArray = 0;
+ WORD *addressOfNameOrdinalsArray = 0;
+ char *functionName = 0;
+ DWORD_PTR RVA = 0, VA = 0, deltaAddress = 0;
+ DWORD apiNameHash = 0;
+ char apiNameCmp[3] = {0};
+
+ dllBaseIndex = apiHash & 0xFF;
+ dllBase = *((DWORD_PTR *)dllBaseArray + dllBaseIndex);
+
+ //e.g. 0x0021AF0957746500
+ apiNameHash = (DWORD)(apiHash >> 24); //21AF0957
+ apiNameCmp[0] = (char)(apiHash >> 8); //65
+ apiNameCmp[1] = (char)(apiHash >> 16); //74
+
+ pDosHeader = (PIMAGE_DOS_HEADER)dllBase;
+
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ writeToLogFile("Wrong dll base, IMAGE_DOS_SIGNATURE doesn't match\r\n");
+ return 0;
+ }
+
+ pNtHeader = (PIMAGE_NT_HEADERS)(dllBase + pDosHeader->e_lfanew);
+
+ if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ {
+ writeToLogFile("Wrong dll base, IMAGE_NT_SIGNATURE doesn't match\r\n");
+ return 0;
+ }
+
+ if (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
+ {
+ writeToLogFile("No export table found\r\n");
+ return 0;
+ }
+
+ pExportHeader = (PIMAGE_EXPORT_DIRECTORY)(dllBase + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+
+ deltaAddress = (DWORD_PTR)pExportHeader - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ addressOfFunctionsArray = (DWORD *)((DWORD_PTR)pExportHeader->AddressOfFunctions + deltaAddress);
+ addressOfNamesArray = (DWORD *)((DWORD_PTR)pExportHeader->AddressOfNames + deltaAddress);
+ addressOfNameOrdinalsArray = (WORD *)((DWORD_PTR)pExportHeader->AddressOfNameOrdinals + deltaAddress);
+
+ for (DWORD i = 0; i < pExportHeader->NumberOfNames; i++)
+ {
+ functionName = (char*)(addressOfNamesArray[i] + deltaAddress);
+
+ if (functionName[1] == apiNameCmp[0] && functionName[2] == apiNameCmp[1])
+ {
+
+ if (getApiHash(functionName) == apiNameHash)
+ {
+ //VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + dllBase;
+
+ //avoid forward api handling:
+ VA = (DWORD_PTR)GetProcAddress((HMODULE)dllBase, functionName);
+
+ wsprintfA(textBuffer, "- Found %s %016I64X\r\n",functionName, VA);
+ writeToLogFile(textBuffer);
+
+ return VA;
+ }
+ }
+ }
+
+ wsprintfA(textBuffer, "- Cannot find apiHash %016I64X dllBaseArray address %016I64X\r\n",apiHash, dllBaseArray);
+ writeToLogFile(textBuffer);
+
+ return 0;
+}
+
+
+/*
+ * Api name hash function at VA 14000FBEC
+ *
+ * Start: 000000014000FBEC 52 push rdx
+ * End: 000000014000FC10 C3 retn
+ */
+DWORD getApiHash(const char * apiName)
+{
+ DWORD dwCheck = 0xFFFFFFFF;
+ char key = 0;
+
+ for (int i = 0; i < lstrlenA(apiName); i++)
+ {
+ key = apiName[i];
+
+ dwCheck = (dwCheck & 0xFFFFFF00) + ((dwCheck & 0xFF) ^ key);
+ key = 0x8;
+
+ do
+ {
+ if (dwCheck % 2)
+ {
+ dwCheck >>= 1;
+ dwCheck ^= magicConstant;
+ }
+ else
+ {
+ dwCheck >>= 1;
+ }
+
+ key--;
+ } while (key);
+ }
+
+ return dwCheck;
+}
+
+/*
+ * Search a memory region for a byte pattern and return the address
+ */
+DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, const BYTE * pattern, const char * mask)
+{
+ DWORD pos = 0;
+ int searchLen = lstrlenA(mask) - 1;
+
+ for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++)
+ {
+ if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' )
+ {
+ if(mask[pos+1] == 0x00)
+ {
+ return (retAddress - searchLen);
+ }
+ pos++;
+ } else {
+ pos = 0;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Write text to a logfile, the logfile is in the same folder as the target exe
+ */
+BOOL writeToLogFile(const char * text)
+{
+ DWORD lpNumberOfBytesWritten = 0;
+ size_t i = 0;
+ BOOL wfRet = 0;
+ HANDLE hFile = 0;
+ char buffer[260];
+
+ if (!GetModuleFileNameA(0, buffer, sizeof(buffer))) //get full path of exe
+ {
+ return FALSE;
+ }
+
+ for (i = (lstrlenA(buffer) - 1); i >= 0; i--) //remove the exe file name from full path
+ {
+ if (buffer[i] == '\\')
+ {
+ buffer[i+1] = 0x00;
+ break;
+ }
+ }
+
+ if (lstrcatA(buffer,logFileName) == 0) //append log file name to path
+ {
+ return FALSE;
+ }
+
+ hFile = CreateFileA(buffer, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); //open log file for writing
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
+
+ SetFilePointer(hFile, 0, 0, FILE_END); //set file pointer to the end of file
+
+ if (WriteFile(hFile, text, (DWORD)lstrlenA(text), &lpNumberOfBytesWritten, 0)) //write message to logfile
+ {
+ wfRet = TRUE;
+ }
+ else
+ {
+ wfRet = FALSE;
+ }
+
+ CloseHandle(hFile);
+ return wfRet;
+}
+
+
+#ifdef UNICODE
+DllExport wchar_t * __cdecl ScyllaPluginNameW()
+{
+ return TEXT(PLUGIN_NAME);
+}
+#else
+DllExport char * __cdecl ScyllaPluginNameA()
+{
+ return PLUGIN_NAME;
+}
+#endif
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Sep 21, 9:52 PM (1 d, 17 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
11/91/2a133f58bc590aac9826c26a6972
Attached To
rSCY Scylla
Event Timeline
Log In to Comment