diff --git a/src/BlackBone/BlackBone.vcxproj b/src/BlackBone/BlackBone.vcxproj
index abf04ba..a98db9e 100644
--- a/src/BlackBone/BlackBone.vcxproj
+++ b/src/BlackBone/BlackBone.vcxproj
@@ -618,9 +618,9 @@
-
+
@@ -717,6 +717,7 @@
+
diff --git a/src/BlackBone/BlackBone.vcxproj.filters b/src/BlackBone/BlackBone.vcxproj.filters
index 4b9c5d8..0675d19 100644
--- a/src/BlackBone/BlackBone.vcxproj.filters
+++ b/src/BlackBone/BlackBone.vcxproj.filters
@@ -90,9 +90,6 @@
Patterns
-
- Misc
-
Misc
@@ -195,6 +192,9 @@
Subsystem
+
+ Misc
+
@@ -450,5 +450,8 @@
AsmJit\Helpers
+
+ Misc
+
\ No newline at end of file
diff --git a/src/BlackBone/ManualMap/Native/NtLoader.cpp b/src/BlackBone/ManualMap/Native/NtLoader.cpp
index 615c3de..2df700a 100644
--- a/src/BlackBone/ManualMap/Native/NtLoader.cpp
+++ b/src/BlackBone/ManualMap/Native/NtLoader.cpp
@@ -1,10 +1,10 @@
#include "NtLoader.h"
#include "../../Process/Process.h"
-#include "../../Patterns/PatternSearch.h"
-#include "../../Misc/Utils.h"
#include "../../Include/Macro.h"
+#include "../../Misc/Utils.h"
#include "../../Misc/DynImport.h"
#include "../../Misc/trace.hpp"
+#include "../../Misc/PattrernLoader.h"
#include "../contrib/VersionHelpers.h"
@@ -35,9 +35,7 @@ bool NtLdr::Init()
ScanPatterns();
_nodeMap.clear();
- //
// Report errors
- //
#ifndef BLACBONE_NO_TRACE
auto barrier = _process.barrier().type;
if (_LdrpHashTable == 0)
@@ -46,24 +44,6 @@ bool NtLdr::Init()
BLACKBONE_TRACE( "NativeLdr: LdrpModuleIndexBase not found" );
if (_LdrHeapBase == 0 && (barrier == wow_32_32 || barrier == wow_64_64))
BLACKBONE_TRACE( "NativeLdr: LdrHeapBase not found" );
- if (_LdrpHandleTlsData == 0)
- BLACKBONE_TRACE( "NativeLdr: LdrpHandleTlsData not found" );
-#ifdef USE64
- if (IsWindows7OrGreater() && !IsWindows8OrGreater())
- {
- if (_LdrKernel32PatchAddress == 0)
- BLACKBONE_TRACE( "NativeLdr: LdrKernel32PatchAddress not found" );
- if (_APC64PatchAddress == 0)
- BLACKBONE_TRACE( "NativeLdr: APC64PatchAddress not found" );
- }
-#else
- if (_LdrpInvertedFunctionTable == 0)
- BLACKBONE_TRACE( "NativeLdr: LdrpInvertedFunctionTable not found" );
- if (_RtlInsertInvertedFunctionTable == 0)
- BLACKBONE_TRACE( "NativeLdr: RtlInsertInvertedFunctionTable not found" );
- if (IsWindows8Point1OrGreater() && _LdrProtectMrdata == 0)
- BLACKBONE_TRACE( "NativeLdr: LdrProtectMrdata not found" );
-#endif
#endif
return true;
@@ -752,15 +732,14 @@ ULONG NtLdr::HashString( const std::wstring& str )
/// Find LdrpHashTable[] variable
///
/// true on success
-bool NtLdr::FindLdrpHashTable( )
+bool NtLdr::FindLdrpHashTable()
{
PEB_LDR_DATA_T *Ldr =
reinterpret_cast(
reinterpret_cast(
reinterpret_cast(NtCurrentTeb())->ProcessEnvironmentBlock)->Ldr);
- LDR_DATA_TABLE_ENTRY_BASE_T *Ntdll = CONTAINING_RECORD( Ldr->InInitializationOrderModuleList.Flink,
- LDR_DATA_TABLE_ENTRY_BASE_T, InInitializationOrderLinks );
+ auto Ntdll = CONTAINING_RECORD( Ldr->InInitializationOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY_BASE_T, InInitializationOrderLinks );
ULONG NtdllHashIndex = HashString( reinterpret_cast(Ntdll->BaseDllName.Buffer) ) & 0x1F;
@@ -768,26 +747,21 @@ bool NtLdr::FindLdrpHashTable( )
ULONG_PTR NtdllEndAddress = NtdllBase + Ntdll->SizeOfImage - 1;
// scan hash list to the head (head is located within ntdll)
- bool bHeadFound = false;
- PLIST_ENTRY pNtdllHashHead = NULL;
+ PLIST_ENTRY pNtdllHashHead = nullptr;
- for (PLIST_ENTRY e = reinterpret_cast(Ntdll->HashLinks.Flink);
- e != reinterpret_cast(&Ntdll->HashLinks);
- e = e->Flink)
+ for (auto e = reinterpret_cast(Ntdll->HashLinks.Flink); e != reinterpret_cast(&Ntdll->HashLinks); e = e->Flink)
{
- if (reinterpret_cast(e) >= NtdllBase &&
- reinterpret_cast(e) < NtdllEndAddress)
+ if (reinterpret_cast(e) >= NtdllBase && reinterpret_cast(e) < NtdllEndAddress)
{
- bHeadFound = true;
pNtdllHashHead = e;
break;
}
}
- if (bHeadFound)
+ if (pNtdllHashHead != nullptr)
_LdrpHashTable = reinterpret_cast(pNtdllHashHead - NtdllHashIndex);
- return bHeadFound;
+ return _LdrpHashTable != 0;
}
@@ -795,16 +769,15 @@ bool NtLdr::FindLdrpHashTable( )
/// Find LdrpModuleIndex variable under win8
///
/// true on success
-bool NtLdr::FindLdrpModuleIndexBase( )
+bool NtLdr::FindLdrpModuleIndexBase()
{
PEB_T* pPeb = reinterpret_cast(reinterpret_cast(NtCurrentTeb())->ProcessEnvironmentBlock);
if(pPeb)
{
PRTL_BALANCED_NODE lastNode = 0;
- PEB_LDR_DATA_T* Ldr = reinterpret_cast(pPeb->Ldr);
- _LDR_DATA_TABLE_ENTRY_W8 *Ntdll = CONTAINING_RECORD( Ldr->InInitializationOrderModuleList.Flink,
- _LDR_DATA_TABLE_ENTRY_W8, InInitializationOrderLinks );
+ auto Ldr = reinterpret_cast(pPeb->Ldr);
+ auto Ntdll = CONTAINING_RECORD( Ldr->InInitializationOrderModuleList.Flink, _LDR_DATA_TABLE_ENTRY_W8, InInitializationOrderLinks );
PRTL_BALANCED_NODE pNode = &Ntdll->BaseAddressIndexNode;
@@ -851,275 +824,23 @@ bool NtLdr::FindLdrpModuleIndexBase( )
/// true on success
bool NtLdr::ScanPatterns( )
{
- std::vector foundData;
- pe::PEImage ntdll;
- void* pStart = nullptr;
- size_t scanSize = 0;
+ auto& data = g_PatternLoader->data();
- HMODULE hNtdll = GetModuleHandleW( L"ntdll.dll" );
- ntdll.Parse( hNtdll );
+ _LdrKernel32PatchAddress = static_cast(data.LdrKernel32PatchAddress);
+ _APC64PatchAddress = static_cast(data.APC64PatchAddress);
+ _LdrProtectMrdata = static_cast(data.LdrProtectMrdata);
- // Find ntdll code section
- for (auto& section : ntdll.sections())
+ if (_process.core().isWow64())
{
- if (_stricmp( reinterpret_cast(section.Name), ".text" ) == 0)
- {
- pStart = reinterpret_cast(reinterpret_cast(hNtdll) + section.VirtualAddress);
- scanSize = section.Misc.VirtualSize;
-
- break;
- }
+ _LdrpHandleTlsData = static_cast(data.LdrpHandleTlsData32);
+ _LdrpInvertedFunctionTable = static_cast(data.LdrpInvertedFunctionTable32);
+ _RtlInsertInvertedFunctionTable = static_cast(data.RtlInsertInvertedFunctionTable32);
}
-
- // Code section not found
- if(pStart == nullptr)
- return false;
-
- // Win10 update 2
- if (IsWindows10CreatorsOrGreater())
+ else
{
-#ifdef USE64
- // LdrpHandleTlsData
- // 74 33 44 8D 43 09
- PatternSearch ps( "\x74\x33\x44\x8d\x43\x09" );
- ps.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x43);
- foundData.clear();
- }
-
- // RtlInsertInvertedFunctionTable
- // 8B FA 49 8D 43 20
- PatternSearch ps2( "\x8b\xfa\x49\x8d\x43\x20" );
- ps2.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front() - 0x10);
- foundData.clear();
- }
-
- // RtlpInsertInvertedFunctionTableEntry
- // 49 8B E8 48 8B FA 0F 84
- PatternSearch ps3( "\x49\x8b\xe8\x48\x8b\xfa\x0f\x84" );
- ps3.Search( pStart, scanSize, foundData );
- if (!foundData.empty())
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() - 0xF + 2) + (foundData.front() - 0xF + 6);
-#else
- // RtlInsertInvertedFunctionTable
- // 8D 45 F0 89 55 F8 50 8D 55 F4
- PatternSearch ps1( "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4" );
- ps1.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front() - 0xB);
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() + 0x4C);
- foundData.clear();
- }
-
- // LdrpHandleTlsData
- // 8B C1 8D 4D BC 51
- PatternSearch ps2( "\x8b\xc1\x8d\x4d\xbc\x51" );
- ps2.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x18);
- foundData.clear();
- }
-
- // LdrProtectMrdata
- // 75 24 85 F6 75 08
- PatternSearch ps3( "\x75\x24\x85\xf6\x75\x08" );
- ps3.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- _LdrProtectMrdata = static_cast(foundData.front() - 0x1C);
-#endif
- }
- // Win 8.1 and later
- else if (IsWindows8Point1OrGreater())
- {
- #ifdef USE64
- // LdrpHandleTlsData
- // 44 8D 43 09 4C 8D 4C 24 38
- PatternSearch ps( "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38" );
- ps.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x43);
- foundData.clear();
- }
-
- // RtlInsertInvertedFunctionTable
- // 8B C3 2B D3 48 8D 48 01
- PatternSearch ps2( "\x8B\xC3\x2B\xD3\x48\x8D\x48\x01" );
- ps2.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front() - 0x84);
- if (IsWindows10OrGreater())
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() - 0x27 + 3) + (foundData.front() - 0x27 + 7);
- }
- #else
- // RtlInsertInvertedFunctionTable
- // 53 56 57 8B DA 8B F9 50
- PatternSearch ps1( "\x53\x56\x57\x8b\xda\x8b\xf9\x50" );
- ps1.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front() - 0xB);
-
- if (IsWindows10OrGreater())
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() + 0x22);
- else
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() + 0x23);
-
- foundData.clear();
- }
- // Rescan using old pattern
- else
- {
- // RtlInsertInvertedFunctionTable
- // 8D 45 F4 89 55 F8 50 8D 55 FC
- PatternSearch ps12( "\x8d\x45\xf4\x89\x55\xf8\x50\x8d\x55\xfc" );
- ps12.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front() - 0xB);
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() + 0x1D);
- foundData.clear();
- }
- }
-
- // LdrpHandleTlsData
- // 8D 45 ?? 50 6A 09 6A 01 8B C1
- PatternSearch ps2( "\x8d\x45\xcc\x50\x6a\x09\x6a\x01\x8b\xc1" );
- ps2.Search( 0xCC, pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x18);
- foundData.clear();
- }
-
- // LdrProtectMrdata
- // 83 7D 08 00 8B 35
- PatternSearch ps3( "\x83\x7d\x08\x00\x8b\x35", 6 );
- ps3.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- _LdrProtectMrdata = static_cast(foundData.front() - 0x12);
- #endif
- }
- // Win 8
- else if (IsWindows8OrGreater())
- {
- #ifdef USE64
- // LdrpHandleTlsData
- // 48 8B 79 30 45 8D 66 01
- PatternSearch ps( "\x48\x8b\x79\x30\x45\x8d\x66\x01" );
- ps.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x49);
- #else
- // RtlInsertInvertedFunctionTable
- // 8B FF 55 8B EC 51 51 53 57 8B 7D 08 8D
- PatternSearch ps1( "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d" );
- ps1.Search( pStart, scanSize, foundData );
-
- if(!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front());
- _LdrpInvertedFunctionTable = *reinterpret_cast(_RtlInsertInvertedFunctionTable + 0x26);
- foundData.clear();
- }
-
- // LdrpHandleTlsData
- // 8B 45 08 89 45 A0
- PatternSearch ps2( "\x8b\x45\x08\x89\x45\xa0" );
- ps2.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- _LdrpHandleTlsData = static_cast(foundData.front() - 0xC);
- #endif
- }
- // Win 7
- else if(IsWindows7OrGreater())
- {
- #ifdef USE64
- // LdrpHandleTlsData
- // 41 B8 09 00 00 00 48 8D 44 24 38
- PatternSearch ps1( "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38", 11 );
- ps1.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x27);
- foundData.clear();
- }
-
- // LdrpFindOrMapDll patch address
- // 48 8D 8C 24 98 00 00 00 41 b0 01
- PatternSearch ps2( "\x48\x8D\x8C\x24\x98\x00\x00\x00\x41\xb0\x01", 11 );
- ps2.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _LdrKernel32PatchAddress = static_cast(foundData.front() + 0x12);
- foundData.clear();
- }
-
- // KiUserApcDispatcher patch address
- // 48 8B 4C 24 18 48 8B C1 4C
- PatternSearch ps3( "\x48\x8b\x4c\x24\x18\x48\x8b\xc1\x4c");
- ps3.Search( pStart, scanSize, foundData );
-
- if (!foundData.empty())
- {
- _APC64PatchAddress = static_cast(foundData.front());
- foundData.clear();
- }
- #else
- // RtlInsertInvertedFunctionTable
- // 8B FF 55 8B EC 56 68
- PatternSearch ps1( "\x8b\xff\x55\x8b\xec\x56\x68" );
- ps1.Search( pStart, scanSize, foundData);
-
- if(!foundData.empty())
- {
- _RtlInsertInvertedFunctionTable = static_cast(foundData.front( ));
- foundData.clear();
- }
-
- // RtlLookupFunctionTable + 0x11
- // 89 5D E0 38
- PatternSearch ps2( "\x89\x5D\xE0\x38" );
- ps2.Search( pStart, scanSize, foundData );
-
- if(!foundData.empty())
- {
- _LdrpInvertedFunctionTable = *reinterpret_cast(foundData.front() + 0x1B);
- foundData.clear();
- }
-
- // LdrpHandleTlsData
- // 74 20 8D 45 D4 50 6A 09
- PatternSearch ps3( "\x74\x20\x8d\x45\xd4\x50\x6a\x09" );
- ps3.Search( pStart, scanSize, foundData );
-
- if(!foundData.empty())
- _LdrpHandleTlsData = static_cast(foundData.front() - 0x14);
-
- #endif
+ _LdrpHandleTlsData = static_cast(data.LdrpHandleTlsData64);
+ _LdrpInvertedFunctionTable = static_cast(data.LdrpInvertedFunctionTable64);
+ _RtlInsertInvertedFunctionTable = static_cast(data.RtlInsertInvertedFunctionTable64);
}
return true;
diff --git a/src/BlackBone/Misc/DynImport.cpp b/src/BlackBone/Misc/DynImport.cpp
deleted file mode 100644
index c50a843..0000000
--- a/src/BlackBone/Misc/DynImport.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "DynImport.h"
-
-namespace blackbone
-{
-
-///
-/// Load function into database
-///
-/// Function name
-/// Module name
-/// true on success
-FARPROC DynImport::load( const std::string& name, const std::wstring& module )
-{
- auto mod = GetModuleHandleW( module.c_str() );
- return load( name, mod );
-}
-
-///
-/// Load function into database
-///
-/// Function name
-/// Module base
-/// true on success
-FARPROC blackbone::DynImport::load( const std::string& name, HMODULE hMod )
-{
- CSLock lck( _mapGuard );
-
- auto proc = GetProcAddress( hMod, name.c_str() );
- if (proc)
- {
- _funcs.insert( std::make_pair( name, proc ) );
- return proc;
- }
-
- return nullptr;
-}
-
-}
\ No newline at end of file
diff --git a/src/BlackBone/Misc/DynImport.h b/src/BlackBone/Misc/DynImport.h
index 5e91b36..835e68f 100644
--- a/src/BlackBone/Misc/DynImport.h
+++ b/src/BlackBone/Misc/DynImport.h
@@ -72,7 +72,11 @@ public:
/// Function name
/// Module name
/// true on success
- BLACKBONE_API FARPROC load( const std::string& name, const std::wstring& module );
+ BLACKBONE_API FARPROC load( const std::string& name, const std::wstring& module )
+ {
+ auto mod = GetModuleHandleW( module.c_str() );
+ return load( name, mod );
+ }
///
/// Load function into database
@@ -80,7 +84,19 @@ public:
/// Function name
/// Module base
/// true on success
- BLACKBONE_API FARPROC load( const std::string& name, HMODULE hMod );
+ BLACKBONE_API FARPROC load( const std::string& name, HMODULE hMod )
+ {
+ CSLock lck( _mapGuard );
+
+ auto proc = GetProcAddress( hMod, name.c_str() );
+ if (proc)
+ {
+ _funcs.insert( std::make_pair( name, proc ) );
+ return proc;
+ }
+
+ return nullptr;
+ }
private:
DynImport() = default;
diff --git a/src/BlackBone/Misc/InitOnce.cpp b/src/BlackBone/Misc/InitOnce.cpp
index c99ad82..f34e8a3 100644
--- a/src/BlackBone/Misc/InitOnce.cpp
+++ b/src/BlackBone/Misc/InitOnce.cpp
@@ -2,6 +2,7 @@
#include "../Include/Winheaders.h"
#include "../Include/Macro.h"
#include "DynImport.h"
+#include "PattrernLoader.h"
#include
#include
@@ -19,6 +20,10 @@ public:
GrantPriviledge( L"SeDebugPrivilege" );
GrantPriviledge( L"SeLoadDriverPrivilege" );
LoadFuncs();
+
+ g_PatternLoader.reset( new PatternLoader );
+ g_PatternLoader->DoSearch();
+
_done = true;
}
@@ -115,7 +120,8 @@ private:
static bool _done;
};
+std::unique_ptr g_PatternLoader;
+
bool InitOnce::_done = false;
const bool g_Initialized = InitOnce::Exec();
-
}
\ No newline at end of file
diff --git a/src/BlackBone/Misc/PattrernLoader.cpp b/src/BlackBone/Misc/PattrernLoader.cpp
new file mode 100644
index 0000000..adbc840
--- /dev/null
+++ b/src/BlackBone/Misc/PattrernLoader.cpp
@@ -0,0 +1,296 @@
+#include "PattrernLoader.h"
+#include "../PE/PEImage.h"
+#include "../Include/Winheaders.h"
+#include "../Misc/Trace.hpp"
+#include "../../../contrib/VersionHelpers.h"
+
+namespace blackbone
+{
+
+///
+/// System32 helper
+///
+class FsRedirector
+{
+public:
+ FsRedirector( bool wow64 )
+ : _wow64( wow64 )
+ {
+ if (wow64)
+ Wow64DisableWow64FsRedirection( &_fsRedirection );
+ }
+
+ ~FsRedirector()
+ {
+ if (_wow64)
+ Wow64RevertWow64FsRedirection( _fsRedirection );
+ }
+
+private:
+ PVOID _fsRedirection = nullptr;
+ bool _wow64;
+};
+
+///
+/// Scan ntdll for internal loader data
+///
+/// Found data
+const PatternData& PatternLoader::DoSearch()
+{
+ CheckSystem();
+
+ pe::PEImage ntdll32;
+ pe::PEImage ntdll64;
+ ptr_t scanStart32 = 0, scanSize32 = 0;
+ ptr_t scanStart64 = 0, scanSize64 = 0;
+ int64_t diff32 = 0, diff64 = 0;
+
+ wchar_t buf[MAX_PATH] = { 0 };
+ GetWindowsDirectoryW( buf, MAX_PATH );
+
+ std::wstring windir( buf );
+
+ // Load ntdlls
+ if (_x86OS)
+ {
+ ntdll32.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true );
+ diff32 = static_cast(ntdll32.imageBase()) - reinterpret_cast(ntdll32.base());
+ }
+ else
+ {
+ FsRedirector fsr( _wow64Process );
+ ntdll64.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true );
+ ntdll32.Load( std::wstring( windir + L"\\SysWOW64\\ntdll.dll" ), true );
+
+ diff32 = static_cast(ntdll32.imageBase()) - reinterpret_cast(ntdll32.base());
+ diff64 = static_cast(ntdll64.imageBase()) - reinterpret_cast(ntdll64.base());
+ }
+
+ auto fillRanges = []( const pe::PEImage& file, ptr_t& start, ptr_t& size )
+ {
+ for (auto& sec : file.sections())
+ if (_stricmp( reinterpret_cast(sec.Name), ".text" ) == 0)
+ {
+ start = reinterpret_cast(file.base()) + sec.VirtualAddress;
+ size = sec.Misc.VirtualSize;
+ break;
+ }
+ };
+
+ // Get code section bounds
+ fillRanges( ntdll32, scanStart32, scanSize32 );
+ if (!_x86OS)
+ fillRanges( ntdll64, scanStart64, scanSize64 );
+
+ auto scan = [&]( OffsetData& rule, auto& result )
+ {
+ ptr_t scanStart = 0, scanSize = 0;
+ int64_t diff = 0;
+ std::vector found;
+
+ if (rule.bit64)
+ {
+ scanStart = scanStart64;
+ scanSize = scanSize64;
+ diff = diff64;
+ }
+ else
+ {
+ scanStart = scanStart32;
+ scanSize = scanSize32;
+ diff = diff32;
+ }
+
+ rule.pattern.Search( reinterpret_cast(scanStart), static_cast(scanSize), found );
+ if (!found.empty())
+ {
+ // Plain pointer sum
+ if (rule.functionOffset != -1)
+ {
+ result = found.front() - rule.functionOffset + diff;
+ }
+ // Pointer dereference inside instruction
+ else if (rule.dataStartOffset != 0)
+ {
+ if (rule.bit64)
+ {
+ result = *reinterpret_cast(found.front() + (rule.dataStartOffset + rule.dataOperandOffset)) +
+ (found.front() + rule.dataStartOffset + rule.dataInstructionSize) + diff;
+ }
+ else
+ result = *reinterpret_cast(found.front() + rule.dataStartOffset);
+ }
+ }
+ };
+
+ std::unordered_map patterns;
+ OSFillPatterns( patterns );
+
+ // Final search
+ for (auto& e : patterns)
+ scan( e.second, *e.first );
+
+ // Retry with old patterns
+ if (_data.RtlInsertInvertedFunctionTable32 == 0 && IsWindows8Point1OrGreater() && !IsWindows10CreatorsOrGreater())
+ {
+ // RtlInsertInvertedFunctionTable
+ // 8D 45 F4 89 55 F8 50 8D 55 FC
+ OffsetData rule1{ "\x8d\x45\xf4\x89\x55\xf8\x50\x8d\x55\xfc", false, 0xB };
+ OffsetData rule2{ "\x8d\x45\xf4\x89\x55\xf8\x50\x8d\x55\xfc", false, -1, 0x1D };
+
+ scan( rule1, _data.RtlInsertInvertedFunctionTable32 );
+ scan( rule2, _data.LdrpInvertedFunctionTable32 );
+ }
+
+ // Report errors
+#ifndef BLACBONE_NO_TRACE
+ if (_data.LdrpHandleTlsData64 == 0)
+ BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData64 not found" );
+ if (_data.LdrpHandleTlsData32 == 0)
+ BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData32 not found" );
+ if (_data.LdrpInvertedFunctionTable64 == 0)
+ BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable64 not found" );
+ if (_data.LdrpInvertedFunctionTable32 == 0)
+ BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable32 not found" );
+ if (_data.RtlInsertInvertedFunctionTable64 == 0)
+ BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable64 not found" );
+ if (_data.RtlInsertInvertedFunctionTable32 == 0)
+ BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable32 not found" );
+ if (IsWindows8Point1OrGreater() && _data.LdrProtectMrdata == 0)
+ BLACKBONE_TRACE( "PatternData: LdrProtectMrdata not found" );
+ if (IsWindows7OrGreater() && !IsWindows8OrGreater())
+ {
+ if (_data.LdrKernel32PatchAddress == 0)
+ BLACKBONE_TRACE( "PatternData: LdrKernel32PatchAddress not found" );
+ if (_data.APC64PatchAddress == 0)
+ BLACKBONE_TRACE( "PatternData: APC64PatchAddress not found" );
+ }
+#endif
+ return _data;
+}
+
+///
+/// Detect process and OS architecture
+///
+void PatternLoader::CheckSystem()
+{
+ SYSTEM_INFO info = { { 0 } };
+ GetNativeSystemInfo( &info );
+
+ if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ {
+ _x86OS = true;
+ }
+ else
+ {
+ BOOL wowSrc = FALSE;
+ IsWow64Process( GetCurrentProcess(), &wowSrc );
+ _wow64Process = wowSrc != 0;
+ }
+}
+
+///
+/// Fill OS-dependent patterns
+///
+/// Pattern collection
+void PatternLoader::OSFillPatterns( std::unordered_map& patterns )
+{
+ if (IsWindows10CreatorsOrGreater())
+ {
+ // LdrpHandleTlsData
+ // 74 33 44 8D 43 09
+ patterns.emplace( &_data.LdrpHandleTlsData64, OffsetData{ "\x74\x33\x44\x8d\x43\x09", true, 0x43 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 8B FA 49 8D 43 20
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xfa\x49\x8d\x43\x20", true, 0x10 } );
+
+ // RtlpInsertInvertedFunctionTableEntry
+ // 49 8B E8 48 8B FA 0F 84
+ patterns.emplace( &_data.LdrpInvertedFunctionTable64, OffsetData{ "\x49\x8b\xe8\x48\x8b\xfa\x0f\x84", true, -1, -0xF, 2, 6 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 8D 45 F0 89 55 F8 50 8D 55 F4
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, 0xB } );
+ patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, -1, 0x4C } );
+
+ // LdrpHandleTlsData
+ // 8B C1 8D 4D BC 51
+ patterns.emplace( &_data.LdrpHandleTlsData32, OffsetData{ "\x8b\xc1\x8d\x4d\xbc\x51", false, 0x18 } );
+
+ // LdrProtectMrdata
+ // 75 24 85 F6 75 08
+ patterns.emplace( &_data.LdrProtectMrdata, OffsetData{ "\x75\x24\x85\xf6\x75\x08", false, 0x1C } );
+ }
+ else if (IsWindows8Point1OrGreater())
+ {
+ // LdrpHandleTlsData
+ // 44 8D 43 09 4C 8D 4C 24 38
+ patterns.emplace( &_data.LdrpHandleTlsData64, OffsetData{ "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38", true, 0x43 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 8B C3 2B D3 48 8D 48 01
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xc3\x2b\xd3\x48\x8d\x48\x01", true, 0x84 } );
+ patterns.emplace( &_data.LdrpInvertedFunctionTable64, OffsetData{ "\x8b\xc3\x2b\xd3\x48\x8d\x48\x01", true, -1, -0x27, 3, 7 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 53 56 57 8B DA 8B F9 50
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, 0xB } );
+
+ if (IsWindows10OrGreater())
+ patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, -1, 0x22 } );
+ else
+ patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, -1, 0x23 } );
+
+ // LdrpHandleTlsData
+ // 50 6A 09 6A 01 8B C1
+ patterns.emplace( &_data.LdrpHandleTlsData32, OffsetData{ "\x50\x6a\x09\x6a\x01\x8b\xc1", false, 0x1B } );
+
+ // LdrProtectMrdata
+ // 83 7D 08 00 8B 35
+ patterns.emplace( &_data.LdrProtectMrdata, OffsetData{ "\x83\x7d\x08\x00\x8b\x35", false, 0x12 } );
+ }
+ else if (IsWindows8OrGreater())
+ {
+ // LdrpHandleTlsData
+ // 48 8B 79 30 45 8D 66 01
+ patterns.emplace( &_data.LdrpHandleTlsData64, OffsetData{ "\x48\x8b\x79\x30\x45\x8d\x66\x01", true, 0x49 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 8B FF 55 8B EC 51 51 53 57 8B 7D 08 8D
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d", false, 0 } );
+ patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d", false, -1, 0x26 } );
+
+ // LdrpHandleTlsData
+ // 8B 45 08 89 45 A0
+ patterns.emplace( &_data.LdrpHandleTlsData32, OffsetData{ "\x8b\x45\x08\x89\x45\xa0", false, 0xC } );
+ }
+ else if (IsWindows7OrGreater())
+ {
+ // LdrpHandleTlsData
+ // 41 B8 09 00 00 00 48 8D 44 24 38
+ patterns.emplace( &_data.LdrpHandleTlsData64, OffsetData{ PatternSearch( "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38", 11 ), true, 0x27 } );
+
+ // LdrpFindOrMapDll patch address
+ // 48 8D 8C 24 98 00 00 00 41 b0 01
+ patterns.emplace( &_data.LdrKernel32PatchAddress, OffsetData{ PatternSearch( "\x48\x8D\x8C\x24\x98\x00\x00\x00\x41\xb0\x01", 11 ), true, -0x12 } );
+
+ // KiUserApcDispatcher patch address
+ // 48 8B 4C 24 18 48 8B C1 4C
+ patterns.emplace( &_data.APC64PatchAddress, OffsetData{ "\x48\x8b\x4c\x24\x18\x48\x8b\xc1\x4c", true, 0 } );
+
+ // RtlInsertInvertedFunctionTable
+ // 8B FF 55 8B EC 56 68
+ patterns.emplace( &_data.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x56\x68", false, 0 } );
+
+ // RtlLookupFunctionTable + 0x11
+ // 89 5D E0 38
+ patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x89\x5D\xE0\x38", false, -1, 0x1B } );
+
+ // LdrpHandleTlsData
+ // 74 20 8D 45 D4 50 6A 09
+ patterns.emplace( &_data.LdrpHandleTlsData32, OffsetData{ "\x74\x20\x8d\x45\xd4\x50\x6a\x09", false, 0x14 } );
+ }
+}
+
+}
\ No newline at end of file
diff --git a/src/BlackBone/Misc/PattrernLoader.h b/src/BlackBone/Misc/PattrernLoader.h
new file mode 100644
index 0000000..31fee53
--- /dev/null
+++ b/src/BlackBone/Misc/PattrernLoader.h
@@ -0,0 +1,74 @@
+#pragma once
+#include "../Include/Types.h"
+#include "../Patterns/PatternSearch.h"
+
+#include
+#include
+
+namespace blackbone
+{
+
+///
+/// Ntdll internal pointers
+///
+struct PatternData
+{
+ ptr_t LdrKernel32PatchAddress = 0; // Address to patch to enable kernel32 loading under win7
+ ptr_t APC64PatchAddress = 0; // Address to patch for x64->WOW64 APC dispatching under win7
+ ptr_t LdrpHandleTlsData32 = 0; // LdrpHandleTlsData address
+ ptr_t LdrpHandleTlsData64 = 0; // LdrpHandleTlsData address
+ ptr_t LdrpInvertedFunctionTable32 = 0; // LdrpInvertedFunctionTable address
+ ptr_t LdrpInvertedFunctionTable64 = 0; // LdrpInvertedFunctionTable address
+ ptr_t RtlInsertInvertedFunctionTable32 = 0; // RtlInsertInvertedFunctionTable address
+ ptr_t RtlInsertInvertedFunctionTable64 = 0; // RtlInsertInvertedFunctionTable address
+ ptr_t LdrProtectMrdata = 0; // LdrProtectMrdata address
+};
+
+///
+/// Ntdll scanner
+///
+class PatternLoader
+{
+ struct OffsetData
+ {
+ PatternSearch pattern;
+ bool bit64;
+ int32_t functionOffset;
+ int32_t dataStartOffset;
+ int32_t dataOperandOffset;
+ int32_t dataInstructionSize;
+ };
+
+public:
+ ///
+ /// Scan ntdll for internal loader data
+ ///
+ /// Found data
+ const PatternData& DoSearch();
+
+ ///
+ /// Get internal loader data
+ ///
+ /// Internal loader data
+ inline const PatternData& data() const { return _data; }
+private:
+ ///
+ /// Detect process and OS architecture
+ ///
+ void CheckSystem();
+
+ ///
+ /// Fill OS-dependent patterns
+ ///
+ /// Pattern collection
+ void OSFillPatterns( std::unordered_map& patterns );
+
+private:
+ bool _x86OS = false; // x86 OS
+ bool _wow64Process = false; // Current process is wow64 process
+ PatternData _data; // Ntdll internal loader data
+};
+
+extern std::unique_ptr g_PatternLoader;
+
+}
\ No newline at end of file
diff --git a/src/BlackBone/Process/Threads/Thread.h b/src/BlackBone/Process/Threads/Thread.h
index b4a4c88..2d259eb 100644
--- a/src/BlackBone/Process/Threads/Thread.h
+++ b/src/BlackBone/Process/Threads/Thread.h
@@ -5,6 +5,7 @@
#include "../../Include/NativeStructures.h"
#include "../../Include/CallResult.h"
#include "../../Include/Types.h"
+#include "../../Misc/Utils.h"
#include
diff --git a/src/BlackBone/Process/Threads/Threads.cpp b/src/BlackBone/Process/Threads/Threads.cpp
index b4912a5..ca05887 100644
--- a/src/BlackBone/Process/Threads/Threads.cpp
+++ b/src/BlackBone/Process/Threads/Threads.cpp
@@ -43,7 +43,7 @@ call_result_t ProcessThreads::CreateNew( ptr_t threadProc, ptr_t arg,
if (!NT_SUCCESS( status ))
return status;
- std::lock_guard lg( _lock );
+ CSLock lg( _lock );
_threads.emplace_back( new Thread( hThd, &_core ) );
return _threads.back();
}
@@ -75,7 +75,7 @@ std::vector& ProcessThreads::getAll( bool dontUpdate /*= false*/ )
if (tEntry.th32OwnerProcessID != _core.pid())
continue;
- std::lock_guard lg( _lock );
+ CSLock lg( _lock );
_threads.emplace_back( new Thread( tEntry.th32ThreadID, &_core ) );
}
diff --git a/src/BlackBone/Process/Threads/Threads.h b/src/BlackBone/Process/Threads/Threads.h
index 775d6df..985474c 100644
--- a/src/BlackBone/Process/Threads/Threads.h
+++ b/src/BlackBone/Process/Threads/Threads.h
@@ -74,7 +74,7 @@ private:
private:
class ProcessCore& _core; // Core process functions
std::vector _threads; // Process thread snapshot
- std::mutex _lock; // Update lock
+ CriticalSection _lock; // Update lock
};
}
\ No newline at end of file
diff --git a/src/TestApp/LocalHookTest.cpp b/src/TestApp/LocalHookTest.cpp
index c79e903..ab89956 100644
--- a/src/TestApp/LocalHookTest.cpp
+++ b/src/TestApp/LocalHookTest.cpp
@@ -131,7 +131,7 @@ TEST_CASE( "05. Local hooks" )
REQUIRE( det.Hook( &CloseHandle, &MyMook::hkCloseHandle, &mh, HookType::HWBP ) );
REQUIRE( det2.Hook( &TestFastcall, &hkTestFastcall, HookType::Inline ) );
- REQUIRE( det3.Hook( ptr, &::hkTest, HookType::Inline ) );
+ REQUIRE( det3.Hook( ptr, &::hkTest, HookType::Int3 ) );
REQUIRE( det4.Hook( (void**)&testClass, 0, &MyMook::hkVFunc, &mh ) );
int a = args[0];