Unexported symbols resolve using MSDIA

This commit is contained in:
DarthTon
2017-12-13 22:53:59 +02:00
parent 42391268a3
commit 9e93246790
27 changed files with 897 additions and 456 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -8525,7 +8525,7 @@ namespace Catch {
Section::~Section() {
if( m_sectionIncluded ) {
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
if( std::uncaught_exception() )
if( std::uncaught_exceptions() )
getResultCapture().sectionEndedEarly( endInfo );
else
getResultCapture().sectionEnded( endInfo );
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../Config.h"
#pragma warning(disable : 4100)
#include "../../../contrib/AsmJit/AsmJit.h"
#include <AsmJit/AsmJit.h>
#pragma warning(default : 4100)
#include <vector>
+107 -18
View File
@@ -180,7 +180,6 @@
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
<EnableCppCoreCheck>true</EnableCppCoreCheck>
<CodeAnalysisRuleSet>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
@@ -189,19 +188,16 @@
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
<EnableCppCoreCheck>true</EnableCppCoreCheck>
<CodeAnalysisRuleSet>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
@@ -210,50 +206,42 @@
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(ProjectDir)..\..\contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -270,6 +258,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -278,6 +267,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug(XP)|Win32'">
<ClCompile>
@@ -293,6 +290,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -301,6 +299,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|Win32'">
<ClCompile>
@@ -316,17 +322,23 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(ProjectDir)..\..\contrib\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>diaguids.lib;Ole32.lib;$(ProjectDir)..\..\contrib\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -342,6 +354,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -350,6 +363,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug(XP)|x64'">
<ClCompile>
@@ -363,6 +384,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -371,6 +393,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|x64'">
<ClCompile>
@@ -384,15 +414,21 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(ProjectDir)..\..\contrib\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>diaguids.lib;Ole32.lib;$(ProjectDir)..\..\contrib\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -412,6 +448,7 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -422,6 +459,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|Win32'">
<ClCompile>
@@ -441,6 +486,7 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -451,6 +497,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|Win32'">
<ClCompile>
@@ -470,20 +524,26 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>$(ProjectDir)..\..\contrib\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>diaguids.lib;Ole32.lib;$(ProjectDir)..\..\contrib\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ShowProgress>NotSet</ShowProgress>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -499,6 +559,7 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -509,6 +570,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|x64'">
<ClCompile>
@@ -524,6 +593,7 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -534,6 +604,14 @@
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>diaguids.lib;Ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|x64'">
<ClCompile>
@@ -549,17 +627,23 @@
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(VsInstallDir)DIA SDK\include;$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>$(ProjectDir)..\..\contrib\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>diaguids.lib;Ole32.lib;$(ProjectDir)..\..\contrib\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(VsInstallDir)DIA SDK\lib\amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<PostBuildEvent>
<Command>xcopy "$(SolutionDir)DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y
xcopy "$(SolutionDir)DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\contrib\AsmJit\base\assembler.cpp" />
@@ -621,7 +705,6 @@
<ClCompile Include="ManualMap\Native\NtLoader.cpp" />
<ClCompile Include="Misc\InitOnce.cpp" />
<ClCompile Include="Misc\NameResolve.cpp" />
<ClCompile Include="Misc\PatternLoader.cpp" />
<ClCompile Include="Misc\Utils.cpp" />
<ClCompile Include="Patterns\PatternSearch.cpp" />
<ClCompile Include="PE\ImageNET.cpp" />
@@ -650,6 +733,9 @@
<ClCompile Include="Subsystem\NativeSubsystem.cpp" />
<ClCompile Include="Subsystem\Wow64Subsystem.cpp" />
<ClCompile Include="Subsystem\x86Subsystem.cpp" />
<ClCompile Include="Symbols\PatternLoader.cpp" />
<ClCompile Include="Symbols\PDBHelper.cpp" />
<ClCompile Include="Symbols\SymbolLoader.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\contrib\AsmJit\apibegin.h" />
@@ -730,7 +816,6 @@
<ClInclude Include="Misc\DynImport.h" />
<ClInclude Include="Misc\InitOnce.h" />
<ClInclude Include="Misc\NameResolve.h" />
<ClInclude Include="Misc\PatternLoader.h" />
<ClInclude Include="Misc\Thunk.hpp" />
<ClInclude Include="Misc\Trace.hpp" />
<ClInclude Include="Misc\Utils.h" />
@@ -754,6 +839,10 @@
<ClInclude Include="Subsystem\NativeSubsystem.h" />
<ClInclude Include="Subsystem\Wow64Subsystem.h" />
<ClInclude Include="Subsystem\x86Subsystem.h" />
<ClInclude Include="Symbols\PatternLoader.h" />
<ClInclude Include="Symbols\PDBHelper.h" />
<ClInclude Include="Symbols\SymbolLoader.h" />
<ClInclude Include="Symbols\SymbolData.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
+24 -6
View File
@@ -46,6 +46,9 @@
<Filter Include="Subsystem">
<UniqueIdentifier>{7eb59189-daeb-47d1-9fa8-c9e246b22039}</UniqueIdentifier>
</Filter>
<Filter Include="Symbols">
<UniqueIdentifier>{e666a795-e3de-4277-9223-b220c8d109ed}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Subsystem\NativeSubsystem.cpp">
@@ -192,10 +195,16 @@
<ClCompile Include="..\..\contrib\rewolf-wow64ext\src\wow64ext.cpp">
<Filter>Subsystem</Filter>
</ClCompile>
<ClCompile Include="Misc\PatternLoader.cpp">
<Filter>Misc</Filter>
</ClCompile>
<ClCompile Include="DllMain.cpp" />
<ClCompile Include="Symbols\SymbolLoader.cpp">
<Filter>Symbols</Filter>
</ClCompile>
<ClCompile Include="Symbols\PatternLoader.cpp">
<Filter>Symbols</Filter>
</ClCompile>
<ClCompile Include="Symbols\PDBHelper.cpp">
<Filter>Symbols</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Config.h" />
@@ -454,11 +463,20 @@
<ClInclude Include="Include\NativeEnums.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="Misc\PatternLoader.h">
<Filter>Misc</Filter>
</ClInclude>
<ClInclude Include="Include\HandleGuard.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="Symbols\SymbolData.h">
<Filter>Symbols</Filter>
</ClInclude>
<ClInclude Include="Symbols\SymbolLoader.h">
<Filter>Symbols</Filter>
</ClInclude>
<ClInclude Include="Symbols\PatternLoader.h">
<Filter>Symbols</Filter>
</ClInclude>
<ClInclude Include="Symbols\PDBHelper.h">
<Filter>Symbols</Filter>
</ClInclude>
</ItemGroup>
</Project>
+3 -5
View File
@@ -2,7 +2,7 @@
#include "../Process/Process.h"
#include "../Include/Macro.h"
#include "../Misc/Trace.hpp"
#include "../Misc/PatternLoader.h"
#include "../Symbols/SymbolData.h"
#include "../Asm/LDasm.h"
namespace blackbone
@@ -284,11 +284,9 @@ NTSTATUS MExcept::CreateVEH( Process& proc, ModuleData& mod, bool partial )
if (!pDecode)
return pDecode.status;
auto& data = g_PatternLoader->data();
replaceStub( newHandler, handlerSize, 0xDEADDA7A, static_cast<uint32_t>(data.LdrpInvertedFunctionTable32) );
replaceStub( newHandler, handlerSize, 0xDEADDA7A, static_cast<uint32_t>(g_symbols.LdrpInvertedFunctionTable32) );
replaceStub( newHandler, handlerSize, 0xDEADC0DE, static_cast<uint32_t>(pDecode->procAddress) );
replaceStub( newHandler, handlerSize, 0xDEADC0D2, static_cast<uint32_t>(data.LdrProtectMrdata) );
replaceStub( newHandler, handlerSize, 0xDEADC0D2, static_cast<uint32_t>(g_symbols.LdrProtectMrdata) );
}
// Write handler data into target process
+7 -7
View File
@@ -4,7 +4,7 @@
#include "../../Misc/Utils.h"
#include "../../Misc/DynImport.h"
#include "../../Misc/trace.hpp"
#include "../../Misc/PatternLoader.h"
#include "../../Symbols/SymbolData.h"
#include "../contrib/VersionHelpers.h"
@@ -163,12 +163,12 @@ NTSTATUS NtLdr::AddStaticTLSEntry( const NtLdrEntry& mod, ptr_t tlsPtr )
ptr_t LdrpHandleTlsData = 0;
if (mod.type == mt_mod64)
{
LdrpHandleTlsData = g_PatternLoader->data().LdrpHandleTlsData64;
LdrpHandleTlsData = g_symbols.LdrpHandleTlsData64;
pNode = SetNode<_LDR_DATA_TABLE_ENTRY_BASE64>( pNode, mod.baseAddress );
}
else
{
LdrpHandleTlsData = g_PatternLoader->data().LdrpHandleTlsData32;
LdrpHandleTlsData = g_symbols.LdrpHandleTlsData32;
pNode = SetNode<_LDR_DATA_TABLE_ENTRY_BASE32>( pNode, mod.baseAddress );
}
@@ -231,12 +231,12 @@ NTSTATUS NtLdr::AddStaticTLSEntry( const NtLdrEntry& mod, ptr_t tlsPtr )
/// <returns>true on success</returns>
bool NtLdr::InsertInvertedFunctionTable( NtLdrEntry& mod )
{
ptr_t RtlInsertInvertedFunctionTable = g_PatternLoader->data().RtlInsertInvertedFunctionTable64;
ptr_t LdrpInvertedFunctionTable = g_PatternLoader->data().LdrpInvertedFunctionTable64;
ptr_t RtlInsertInvertedFunctionTable = g_symbols.RtlInsertInvertedFunctionTable64;
ptr_t LdrpInvertedFunctionTable = g_symbols.LdrpInvertedFunctionTable64;
if (mod.type == mt_mod32)
{
RtlInsertInvertedFunctionTable = g_PatternLoader->data().RtlInsertInvertedFunctionTable32;
LdrpInvertedFunctionTable = g_PatternLoader->data().LdrpInvertedFunctionTable32;
RtlInsertInvertedFunctionTable = g_symbols.RtlInsertInvertedFunctionTable32;
LdrpInvertedFunctionTable = g_symbols.LdrpInvertedFunctionTable32;
}
// Invalid addresses. Probably pattern scan has failed
+3 -5
View File
@@ -5,7 +5,7 @@
#include "../../../contrib/VersionHelpers.h"
#include "DynImport.h"
#include "PatternLoader.h"
#include "../Symbols/SymbolLoader.h"
#include "NameResolve.h"
#include <string>
@@ -33,8 +33,8 @@ public:
GrantPriviledge( L"SeLoadDriverPrivilege" );
LoadFuncs();
g_PatternLoader = std::make_unique<PatternLoader>();
g_PatternLoader->DoSearch();
SymbolLoader sl;
sl.Load( g_symbols );
NameResolve::Instance().Initialize();
}
@@ -121,8 +121,6 @@ private:
static volatile long _done;
};
std::unique_ptr<PatternLoader> g_PatternLoader;
/// <summary>
/// Exported InitOnce wrapper
/// </summary>
-301
View File
@@ -1,301 +0,0 @@
#include "PatternLoader.h"
#include "../PE/PEImage.h"
#include "../Include/Winheaders.h"
#include "../Misc/Trace.hpp"
#include "../../../contrib/VersionHelpers.h"
namespace blackbone
{
/// <summary>
/// Scan ntdll for internal loader data
/// </summary>
/// <returns>Found data</returns>
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<int64_t>(ntdll32.imageBase()) - reinterpret_cast<int64_t>(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<int64_t>(ntdll32.imageBase()) - reinterpret_cast<int64_t>(ntdll32.base());
diff64 = static_cast<int64_t>(ntdll64.imageBase()) - reinterpret_cast<int64_t>(ntdll64.base());
}
auto fillRanges = []( const pe::PEImage& file, ptr_t& start, ptr_t& size )
{
for (auto& sec : file.sections())
if (_stricmp( reinterpret_cast<const char*>(sec.Name), ".text" ) == 0)
{
start = reinterpret_cast<ptr_t>(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<ptr_t> found;
if (rule.bit64)
{
scanStart = scanStart64;
scanSize = scanSize64;
diff = diff64;
}
else
{
scanStart = scanStart32;
scanSize = scanSize32;
diff = diff32;
}
rule.pattern.Search( reinterpret_cast<void*>(scanStart), static_cast<size_t>(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<int32_t*>(found.front() + (rule.dataStartOffset + rule.dataOperandOffset)) +
(found.front() + rule.dataStartOffset + rule.dataInstructionSize) + diff;
}
else
result = *reinterpret_cast<int32_t*>(found.front() + rule.dataStartOffset);
}
}
};
std::unordered_map<ptr_t*, OffsetData> 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 BLACKBONE_NO_TRACE
if (_data.LdrpHandleTlsData64 == 0)
BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData64 not found" );
if (_data.LdrpHandleTlsData32 == 0)
BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData32 not found" );
if (IsWindows8Point1OrGreater() && _data.LdrpInvertedFunctionTable64 == 0)
BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable64 not found" );
if (_data.LdrpInvertedFunctionTable32 == 0)
BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable32 not found" );
if (IsWindows8Point1OrGreater() && _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;
}
/// <summary>
/// Detect process and OS architecture
/// </summary>
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;
}
}
/// <summary>
/// Fill OS-dependent patterns
/// </summary>
/// <param name="patterns">Pattern collection</param>
void PatternLoader::OSFillPatterns( std::unordered_map<ptr_t*, OffsetData>& patterns )
{
if (IsWindows10FallCreatorsOrGreater())
{
// 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
// 53 56 57 8D 45 F8 8B FA
patterns.emplace( &_data.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8d\x45\xf8\x8b\xfa", false, 0x8 } );
// RtlpInsertInvertedFunctionTableEntry
// 33 F6 46 3B C6
patterns.emplace( &_data.LdrpInvertedFunctionTable32, OffsetData{ "\x33\xF6\x46\x3B\xC6", false, -1, -0x1B } );
// 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 (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{ PatternSearch( "\x83\x7d\x08\x00\x8b\x35", 6 ), 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 } );
}
}
}
-74
View File
@@ -1,74 +0,0 @@
#pragma once
#include "../Include/Types.h"
#include "../Patterns/PatternSearch.h"
#include <memory>
#include <unordered_map>
namespace blackbone
{
/// <summary>
/// Ntdll internal pointers
/// </summary>
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
};
/// <summary>
/// Ntdll scanner
/// </summary>
class PatternLoader
{
struct OffsetData
{
PatternSearch pattern;
bool bit64;
int32_t functionOffset;
int32_t dataStartOffset;
int32_t dataOperandOffset;
int32_t dataInstructionSize;
};
public:
/// <summary>
/// Scan ntdll for internal loader data
/// </summary>
/// <returns>Found data</returns>
const PatternData& DoSearch();
/// <summary>
/// Get internal loader data
/// </summary>
/// <returns>Internal loader data</returns>
inline const PatternData& data() const { return _data; }
private:
/// <summary>
/// Detect process and OS architecture
/// </summary>
void CheckSystem();
/// <summary>
/// Fill OS-dependent patterns
/// </summary>
/// <param name="patterns">Pattern collection</param>
void OSFillPatterns( std::unordered_map<ptr_t*, OffsetData>& 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<PatternLoader> g_PatternLoader;
}
+8 -2
View File
@@ -136,11 +136,14 @@ std::wstring Utils::GetExeDirectory()
/// </summary>
/// <param name="length">Desired length. 0 - random length from 5 to 15</param>
/// <returns>Generated string</returns>
// VS 15.5 update crashes on "alphabet[dist( rd )]" in x64 release build
#pragma optimize("", off)
std::wstring Utils::RandomANString( int length /*= 0*/ )
{
static const wchar_t alphabet[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz1234567890";
static constexpr wchar_t alphabet[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz1234567890";
static std::random_device rd;
static std::uniform_int_distribution<> dist( 0, ARRAYSIZE(alphabet) - 2 );
static std::uniform_int_distribution<> dist( 0, _countof( alphabet ) - 2 );
static std::uniform_int_distribution<> dist_len( 5, 15 );
std::wstring result;
@@ -149,10 +152,13 @@ std::wstring Utils::RandomANString( int length /*= 0*/ )
length = dist_len( rd );
for (int i = 0; i < length; i++)
{
result.push_back( alphabet[dist( rd )] );
}
return result;
}
#pragma optimize("", on)
/// <summary>
/// Cast string characters to lower case
+38 -12
View File
@@ -34,10 +34,6 @@ PatternSearch::PatternSearch( const uint8_t* pattern, size_t len /*= 0*/ )
{
}
PatternSearch::~PatternSearch()
{
}
/// <summary>
/// Default pattern matching with wildcards.
/// std::search is approximately 2x faster than naive approach.
@@ -48,16 +44,25 @@ PatternSearch::~PatternSearch()
/// <param name="out">Found results</param>
/// <param name="value_offset">Value that will be added to resulting addresses</param>
/// <returns>Number of found addresses</returns>
size_t PatternSearch::Search( uint8_t wildcard, void* scanStart, size_t scanSize, std::vector<ptr_t>& out, ptr_t value_offset /*= 0*/ )
size_t PatternSearch::Search(
uint8_t wildcard,
void* scanStart,
size_t scanSize,
std::vector<ptr_t>& out,
ptr_t value_offset /*= 0*/
) const
{
const uint8_t* cstart = (const uint8_t*)scanStart;
const uint8_t* cend = cstart + scanSize;
auto comparer = [&wildcard]( uint8_t val1, uint8_t val2 )
{
return (val1 == val2 || val2 == wildcard);
};
for (;;)
{
const uint8_t* res = std::search( cstart, cend, _pattern.begin(), _pattern.end(),
[&wildcard]( uint8_t val1, uint8_t val2 ){ return (val1 == val2 || val2 == wildcard); } );
const uint8_t* res = std::search( cstart, cend, _pattern.begin(), _pattern.end(), comparer );
if (res >= cend)
break;
@@ -81,7 +86,12 @@ size_t PatternSearch::Search( uint8_t wildcard, void* scanStart, size_t scanSize
/// <param name="out">Found results</param>
/// <param name="value_offset">Value that will be added to resulting addresses</param>
/// <returns>Number of found addresses</returns>
size_t PatternSearch::Search( void* scanStart, size_t scanSize, std::vector<ptr_t>& out, ptr_t value_offset /*= 0*/ )
size_t PatternSearch::Search(
void* scanStart,
size_t scanSize,
std::vector<ptr_t>& out,
ptr_t value_offset /*= 0*/
) const
{
size_t bad_char_skip[UCHAR_MAX + 1];
@@ -134,7 +144,13 @@ size_t PatternSearch::Search( void* scanStart, size_t scanSize, std::vector<ptr_
/// <param name="scanSize">Size of region to scan</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
size_t PatternSearch::SearchRemote( Process& remote, uint8_t wildcard, ptr_t scanStart, size_t scanSize, std::vector<ptr_t>& out )
size_t PatternSearch::SearchRemote(
Process& remote,
uint8_t wildcard,
ptr_t scanStart,
size_t scanSize,
std::vector<ptr_t>& out
) const
{
uint8_t *pBuffer = reinterpret_cast<uint8_t*>(VirtualAlloc( NULL, scanSize, MEM_COMMIT, PAGE_READWRITE ));
@@ -155,7 +171,12 @@ size_t PatternSearch::SearchRemote( Process& remote, uint8_t wildcard, ptr_t sca
/// <param name="scanSize">Size of region to scan</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
size_t PatternSearch::SearchRemote( Process& remote, ptr_t scanStart, size_t scanSize, std::vector<ptr_t>& out )
size_t PatternSearch::SearchRemote(
Process& remote,
ptr_t scanStart,
size_t scanSize,
std::vector<ptr_t>& out
) const
{
uint8_t *pBuffer = reinterpret_cast<uint8_t*>(VirtualAlloc( NULL, scanSize, MEM_COMMIT, PAGE_READWRITE ));
@@ -176,7 +197,12 @@ size_t PatternSearch::SearchRemote( Process& remote, ptr_t scanStart, size_t sca
/// <param name="wildcard">Pattern wildcard</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
size_t PatternSearch::SearchRemoteWhole( Process& remote, bool useWildcard, uint8_t wildcard, std::vector<ptr_t>& out )
size_t PatternSearch::SearchRemoteWhole(
Process& remote,
bool useWildcard,
uint8_t wildcard,
std::vector<ptr_t>& out
) const
{
MEMORY_BASIC_INFORMATION64 mbi = { 0 };
size_t bufsize = 1 * 1024 * 1024; // 1 MB
+33 -6
View File
@@ -18,7 +18,7 @@ public:
BLACKBONE_API PatternSearch( const char* pattern, size_t len = 0 );
BLACKBONE_API PatternSearch( const uint8_t* pattern, size_t len = 0 );
BLACKBONE_API ~PatternSearch();
BLACKBONE_API ~PatternSearch() = default;
/// <summary>
/// Default pattern matching with wildcards.
@@ -30,7 +30,13 @@ public:
/// <param name="out">Found results</param>
/// <param name="value_offset">Value that will be added to resulting addresses</param>
/// <returns>Number of found addresses</returns>
BLACKBONE_API size_t Search( uint8_t wildcard, void* scanStart, size_t scanSize, std::vector<ptr_t>& out, ptr_t value_offset = 0 );
BLACKBONE_API size_t Search(
uint8_t wildcard,
void* scanStart,
size_t scanSize,
std::vector<ptr_t>& out,
ptr_t value_offset = 0
) const;
/// <summary>
/// Full pattern match, no wildcards.
@@ -41,7 +47,12 @@ public:
/// <param name="out">Found results</param>
/// <param name="value_offset">Value that will be added to resulting addresses</param>
/// <returns>Number of found addresses</returns>
BLACKBONE_API size_t Search( void* scanStart, size_t scanSize, std::vector<ptr_t>& out, ptr_t value_offset = 0 );
BLACKBONE_API size_t Search(
void* scanStart,
size_t scanSize,
std::vector<ptr_t>& out,
ptr_t value_offset = 0
) const;
/// <summary>
/// Search pattern in remote process
@@ -52,7 +63,13 @@ public:
/// <param name="scanSize">Size of region to scan</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
BLACKBONE_API size_t SearchRemote( class Process& remote, uint8_t wildcard, ptr_t scanStart, size_t scanSize, std::vector<ptr_t>& out );
BLACKBONE_API size_t SearchRemote(
class Process& remote,
uint8_t wildcard,
ptr_t scanStart,
size_t scanSize,
std::vector<ptr_t>& out
) const;
/// <summary>
/// Search pattern in remote process
@@ -62,7 +79,12 @@ public:
/// <param name="scanSize">Size of region to scan</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
BLACKBONE_API size_t SearchRemote( class Process& remote, ptr_t scanStart, size_t scanSize, std::vector<ptr_t>& out );
BLACKBONE_API size_t SearchRemote(
class Process& remote,
ptr_t scanStart,
size_t scanSize,
std::vector<ptr_t>& out
) const;
/// <summary>
/// Search pattern in whole address space of remote process
@@ -72,7 +94,12 @@ public:
/// <param name="wildcard">Pattern wildcard</param>
/// <param name="out">Found results</param>
/// <returns>Number of found addresses</returns>
BLACKBONE_API size_t SearchRemoteWhole( class Process& remote, bool useWildcard, uint8_t wildcard, std::vector<ptr_t>& out );
BLACKBONE_API size_t SearchRemoteWhole(
class Process& remote,
bool useWildcard,
uint8_t wildcard,
std::vector<ptr_t>& out
) const;
private:
std::vector<uint8_t> _pattern; // Pattern to search
+2 -2
View File
@@ -4,7 +4,7 @@
#include "RPC/RemoteExec.h"
#include "../Misc/NameResolve.h"
#include "../Misc/Utils.h"
#include "../Misc/PatternLoader.h"
#include "../Symbols/SymbolData.h"
#include "../Asm/AsmFactory.h"
#include <memory>
@@ -445,7 +445,7 @@ call_result_t<ModuleDataPtr> ProcessModules::Inject( const std::wstring& path, T
if (switchMode == ForceSwitch && !_ldrPatched && IsWindows7OrGreater() && !IsWindows8OrGreater())
{
uint8_t patch[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
auto patchBase = g_PatternLoader->data().LdrKernel32PatchAddress;
auto patchBase = g_symbols.LdrKernel32PatchAddress;
if (patchBase != 0)
{
+1 -1
View File
@@ -1,7 +1,7 @@
#include "RemoteExec.h"
#include "../Process.h"
#include "../../Misc/DynImport.h"
#include "../../Misc/PatternLoader.h"
#include "../../Symbols/SymbolData.h"
#include <VersionHelpers.h>
#include <sddl.h>
+3 -3
View File
@@ -32,7 +32,7 @@ public:
// Manually set argument to custom value
void set( int pos, const AsmVariant& newVal )
{
if (arguments.size() > (size_t)pos)
if (arguments.size() > static_cast<size_t>(pos))
arguments[pos] = newVal;
}
@@ -46,8 +46,8 @@ public:
, _conv( conv )
{
static_assert(
!std::disjunction_v<std::is_reference<Args>...>,
"Please replace reference type to pointer type in function type specification"
(... && !std::is_reference_v<Args>),
"Please replace reference type with pointer type in function type specification"
);
}
+167
View File
@@ -0,0 +1,167 @@
#include "PDBHelper.h"
#include "../Misc/Trace.hpp"
#include <cstdint>
#include <sstream>
#define CHECK_SUCCESS(e)\
{ \
HRESULT hresult = (e); \
if(FAILED(hresult)) \
{ \
BLACKBONE_TRACE( "PDB: %s: (%s) failed with HRESULT 0x%08x", __FUNCTION__, #e , hresult ); \
return hresult; \
} \
}
namespace blackbone
{
PDBHelper::PDBHelper()
{
CoInitialize( nullptr );
// If _NT_SYMBOL_PATH exists, use it
wchar_t path[MAX_PATH] = { };
if (GetEnvironmentVariableW( L"_NT_SYMBOL_PATH", path, _countof( path ) ) == -1)
{
if (GetTempPathW( _countof( path ), path ) != -1)
{
std::wstringstream wss;
wss << L"srv*" << path << L"Symbols*https://msdl.microsoft.com/download/symbols";
_sympath = wss.str();
}
}
}
PDBHelper::~PDBHelper()
{
// Must be released before CoUninitialize
_global.Release();
_session.Release();
_source.Release();
CoUninitialize();
}
/// <summary>
/// Initialize symbols for target file
/// </summary>
/// <param name="file">Fully qualified path to target PE file</param>
/// <param name="base">Base ptr to add to RVAs</param>
/// <returns>Status code</returns>
HRESULT PDBHelper::Init( const std::wstring& file, ptr_t base /*= 0*/ )
{
CHECK_SUCCESS( CoCreateDiaDataSource() );
CHECK_SUCCESS( _source->loadDataForExe( file.c_str(), _sympath.empty() ? nullptr : _sympath.c_str(), nullptr ) );
CHECK_SUCCESS( _source->openSession( &_session ) );
CHECK_SUCCESS( _session->get_globalScope( &_global ) );
_base = base;
return PopulateSymbols();
}
/// <summary>
/// Get symbol RVA
/// </summary>
/// <param name="symName">Symbol name</param>
/// <param name="result">Resulting RVA</param>
/// <returns>Status code</returns>
HRESULT PDBHelper::GetSymAddress( const std::wstring& symName, ptr_t& result )
{
auto found = _cache.find( symName );
if (found != _cache.end())
{
result = _base + found->second;
return S_OK;
}
return E_PDB_DBG_NOT_FOUND;
}
/// <summary>
/// Initialize DIA
/// </summary>
/// <returns>Status code</returns>
HRESULT PDBHelper::CoCreateDiaDataSource()
{
const auto pSource = reinterpret_cast<void**>(&_source);
// Try to get from COM
HRESULT hr = CoCreateInstance( CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource), pSource );
// Retry with direct export call
if (hr == REGDB_E_CLASSNOTREG)
{
HMODULE hMod = LoadLibraryW( L"msdia140.dll" );
if (!hMod)
{
BLACKBONE_TRACE( "PDB: Failed to load msdia140.dll, error 0x08%x", GetLastError() );
return HRESULT_FROM_WIN32( GetLastError() );
}
auto DllGetClassObject = reinterpret_cast<BOOL( WINAPI* )(REFCLSID, REFIID, LPVOID)>(GetProcAddress( hMod, "DllGetClassObject" ));
if (!DllGetClassObject)
{
BLACKBONE_TRACE( "PDB: Failed to get DllGetClassObject from msdia140.dll" );
return HRESULT_FROM_WIN32( GetLastError() );
}
CComPtr<IClassFactory> classFactory;
CHECK_SUCCESS( DllGetClassObject( CLSID_DiaSource, IID_IClassFactory, &classFactory ) );
hr = classFactory->CreateInstance( nullptr, IID_IDiaDataSource, pSource );
}
if (FAILED( hr ))
{
BLACKBONE_TRACE( "PDB: %s failed with HRESULT 0x08%x", __FUNCTION__, hr );
}
return hr;
}
/// <summary>
/// Build module symbol map
/// </summary>
/// <returns>Status code</returns>
HRESULT PDBHelper::PopulateSymbols()
{
CComPtr<IDiaEnumSymbols> symbols;
CHECK_SUCCESS( _global->findChildren( SymTagNull, nullptr, nsNone, &symbols ) );
ULONG count = 0;
CComPtr<IDiaSymbol> symbol;
while (SUCCEEDED( symbols->Next( 1, &symbol, &count ) ) && count != 0)
{
DWORD rva = 0;
BSTR name = nullptr;
symbol->get_relativeVirtualAddress( &rva );
symbol->get_undecoratedName( &name );
if (name && rva)
{
std::wstring wname( name );
// Remove x86 __stdcall decoration
if (wname[0] == L'@' || wname[0] == L'_')
{
wname.erase( 0, 1 );
}
auto pos = wname.rfind( L'@' );
if (pos != wname.npos)
{
wname.erase( pos );
}
_cache.emplace( std::move( wname ), rva );
}
symbol.Release();
}
return S_OK;
}
}
+58
View File
@@ -0,0 +1,58 @@
#pragma once
#include "../include/Types.h"
#include <dia2.h>
#include <Objbase.h>
#include <atlcomcli.h>
#include <string>
#include <unordered_map>
namespace blackbone
{
class PDBHelper
{
public:
PDBHelper();
~PDBHelper();
/// <summary>
/// Initialize symbols for target file
/// </summary>
/// <param name="file">Fully qualified path to target PE file</param>
/// <param name="base">Base ptr to add to RVAs</param>
/// <returns>Status code</returns>
HRESULT Init( const std::wstring& file, ptr_t base = 0 );
/// <summary>
/// Get symbol RVA
/// </summary>
/// <param name="symName">Symbol name</param>
/// <param name="result">Resulting RVA</param>
/// <returns>Status code</returns>
HRESULT GetSymAddress( const std::wstring& symName, ptr_t& result );
private:
/// <summary>
/// Initialize DIA
/// </summary>
/// <returns>Status code</returns>
HRESULT CoCreateDiaDataSource();
/// <summary>
/// Build module symbol map
/// </summary>
/// <returns>Status code</returns>
HRESULT PopulateSymbols();
private:
// DIA interfaces
CComPtr<IDiaDataSource> _source;
CComPtr<IDiaSession> _session;
CComPtr<IDiaSymbol> _global;
uint64_t _base = 0; // Base ptr to add to RVAs
std::wstring _sympath; // Symbol cache directory
std::unordered_map<std::wstring, uint32_t> _cache; // Symbol name <--> RVA map
};
}
+283
View File
@@ -0,0 +1,283 @@
#include "PatternLoader.h"
#include "../Include/Winheaders.h"
#include "../Patterns/PatternSearch.h"
#include "../Misc/Trace.hpp"
#include "VersionHelpers.h"
#include <memory>
#include <unordered_map>
namespace blackbone
{
struct OffsetData
{
PatternSearch pattern;
bool bit64;
int32_t functionOffset;
int32_t dataStartOffset;
int32_t dataOperandOffset;
int32_t dataInstructionSize;
};
struct ScanParams
{
ptr_t start = 0;
ptr_t size = 0;
ptr_t diff = 0;
};
void FindPattern( const ScanParams& scan32, const ScanParams& scan64, const OffsetData& rule, ptr_t& result )
{
// Skip if already found
if (result != 0)
{
return;
}
const ScanParams& scan = rule.bit64 ? scan64 : scan32;
std::vector<ptr_t> found;
rule.pattern.Search( reinterpret_cast<void*>(scan.start), static_cast<size_t>(scan.size), found );
if (!found.empty())
{
// Plain pointer sum
if (rule.functionOffset != -1)
{
result = found.front() - rule.functionOffset + scan.diff;
}
// Pointer dereference inside instruction
else if (rule.dataStartOffset != 0)
{
if (rule.bit64)
{
result = *reinterpret_cast<int32_t*>(found.front() + (rule.dataStartOffset + rule.dataOperandOffset)) +
(found.front() + rule.dataStartOffset + rule.dataInstructionSize) + scan.diff;
}
else
{
result = *reinterpret_cast<int32_t*>(found.front() + rule.dataStartOffset);
}
}
}
};
/// <summary>
/// Fill OS-dependent patterns
/// </summary>
/// <param name="patterns">Pattern collection</param>
/// <param name="result">Result</param>
void OSFillPatterns( std::unordered_map<ptr_t*, OffsetData>& patterns, SymbolData& result )
{
if (IsWindows10FallCreatorsOrGreater())
{
// LdrpHandleTlsData
// 74 33 44 8D 43 09
patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x74\x33\x44\x8d\x43\x09", true, 0x43 } );
// RtlInsertInvertedFunctionTable
// 8B FA 49 8D 43 20
patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xfa\x49\x8d\x43\x20", true, 0x10 } );
// RtlpInsertInvertedFunctionTableEntry
// 49 8B E8 48 8B FA 0F 84
patterns.emplace( &result.LdrpInvertedFunctionTable64, OffsetData{ "\x49\x8b\xe8\x48\x8b\xfa\x0f\x84", true, -1, -0xF, 2, 6 } );
// RtlInsertInvertedFunctionTable
// 53 56 57 8D 45 F8 8B FA
patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8d\x45\xf8\x8b\xfa", false, 0x8 } );
// RtlpInsertInvertedFunctionTableEntry
// 33 F6 46 3B C6
patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x33\xF6\x46\x3B\xC6", false, -1, -0x1B } );
// LdrpHandleTlsData
// 8B C1 8D 4D BC 51
patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x8b\xc1\x8d\x4d\xbc\x51", false, 0x18 } );
// LdrProtectMrdata
// 75 24 85 F6 75 08
patterns.emplace( &result.LdrProtectMrdata, OffsetData{ "\x75\x24\x85\xf6\x75\x08", false, 0x1C } );
}
else if (IsWindows10CreatorsOrGreater())
{
// LdrpHandleTlsData
// 74 33 44 8D 43 09
patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x74\x33\x44\x8d\x43\x09", true, 0x43 } );
// RtlInsertInvertedFunctionTable
// 8B FA 49 8D 43 20
patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xfa\x49\x8d\x43\x20", true, 0x10 } );
// RtlpInsertInvertedFunctionTableEntry
// 49 8B E8 48 8B FA 0F 84
patterns.emplace( &result.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( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, 0xB } );
patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, -1, 0x4C } );
// LdrpHandleTlsData
// 8B C1 8D 4D BC 51
patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x8b\xc1\x8d\x4d\xbc\x51", false, 0x18 } );
// LdrProtectMrdata
// 75 24 85 F6 75 08
patterns.emplace( &result.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( &result.LdrpHandleTlsData64, OffsetData{ "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38", true, 0x43 } );
// RtlInsertInvertedFunctionTable
// 8B C3 2B D3 48 8D 48 01
patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xc3\x2b\xd3\x48\x8d\x48\x01", true, 0x84 } );
patterns.emplace( &result.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( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, 0xB } );
if (IsWindows10OrGreater())
patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, -1, 0x22 } );
else
patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, -1, 0x23 } );
// LdrpHandleTlsData
// 50 6A 09 6A 01 8B C1
patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x50\x6a\x09\x6a\x01\x8b\xc1", false, 0x1B } );
// LdrProtectMrdata
// 83 7D 08 00 8B 35
patterns.emplace( &result.LdrProtectMrdata, OffsetData{ PatternSearch( "\x83\x7d\x08\x00\x8b\x35", 6 ), false, 0x12 } );
}
else if (IsWindows8OrGreater())
{
// LdrpHandleTlsData
// 48 8B 79 30 45 8D 66 01
patterns.emplace( &result.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( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d", false, 0 } );
patterns.emplace( &result.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( &result.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( &result.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( &result.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( &result.APC64PatchAddress, OffsetData{ "\x48\x8b\x4c\x24\x18\x48\x8b\xc1\x4c", true, 0 } );
// RtlInsertInvertedFunctionTable
// 8B FF 55 8B EC 56 68
patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x56\x68", false, 0 } );
// RtlLookupFunctionTable + 0x11
// 89 5D E0 38
patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x89\x5D\xE0\x38", false, -1, 0x1B } );
// LdrpHandleTlsData
// 74 20 8D 45 D4 50 6A 09
patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x74\x20\x8d\x45\xd4\x50\x6a\x09", false, 0x14 } );
}
}
/// <summary>
/// Scan ntdll for internal loader data
/// </summary>
/// <param name="ntdll32">Mapped x86 ntdll</param>
/// <param name="ntdll64">Mapped x64 ntdll</param>
/// <param name="result">Result</param>
/// <returns>Status code</returns>
NTSTATUS ScanSymbolPatterns( const pe::PEImage& ntdll32, const pe::PEImage& ntdll64, SymbolData& result )
{
ScanParams scan32, scan64;
scan32.diff = static_cast<int64_t>(ntdll32.imageBase()) - reinterpret_cast<int64_t>(ntdll32.base());
scan64.diff = static_cast<int64_t>(ntdll64.imageBase()) - reinterpret_cast<int64_t>(ntdll64.base());
auto fillRanges = []( const pe::PEImage& file, ScanParams& params )
{
for (const auto& sec : file.sections())
{
if (_stricmp( reinterpret_cast<const char*>(sec.Name), ".text" ) == 0)
{
params.start = reinterpret_cast<ptr_t>(file.base()) + sec.VirtualAddress;
params.size = sec.Misc.VirtualSize;
break;
}
}
};
// Get code section bounds
fillRanges( ntdll32, scan32 );
if (ntdll64.base())
{
fillRanges( ntdll64, scan64 );
}
std::unordered_map<ptr_t*, OffsetData> patterns;
OSFillPatterns( patterns, result );
// Final search
for (const auto& e : patterns)
{
FindPattern( scan32, scan64, e.second, *e.first );
}
// Retry with old patterns
if (result.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 };
FindPattern( scan32, scan64, rule1, result.RtlInsertInvertedFunctionTable32 );
FindPattern( scan32, scan64, rule2, result.LdrpInvertedFunctionTable32 );
}
// Report errors
#ifndef BLACKBONE_NO_TRACE
if (result.LdrpHandleTlsData64 == 0)
BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData64 not found" );
if (result.LdrpHandleTlsData32 == 0)
BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData32 not found" );
if (IsWindows8Point1OrGreater() && result.LdrpInvertedFunctionTable64 == 0)
BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable64 not found" );
if (result.LdrpInvertedFunctionTable32 == 0)
BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable32 not found" );
if (IsWindows8Point1OrGreater() && result.RtlInsertInvertedFunctionTable64 == 0)
BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable64 not found" );
if (result.RtlInsertInvertedFunctionTable32 == 0)
BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable32 not found" );
if (IsWindows8Point1OrGreater() && result.LdrProtectMrdata == 0)
BLACKBONE_TRACE( "PatternData: LdrProtectMrdata not found" );
if (IsWindows7OrGreater() && !IsWindows8OrGreater())
{
if (result.LdrKernel32PatchAddress == 0)
BLACKBONE_TRACE( "PatternData: LdrKernel32PatchAddress not found" );
if (result.APC64PatchAddress == 0)
BLACKBONE_TRACE( "PatternData: APC64PatchAddress not found" );
}
#endif
return STATUS_SUCCESS;
}
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include "../Symbols/SymbolData.h"
#include "../PE/PEImage.h"
namespace blackbone
{
/// <summary>
/// Scan ntdll for internal loader data
/// </summary>
/// <param name="ntdll32">Mapped x86 ntdll</param>
/// <param name="ntdll64">Mapped x64 ntdll</param>
/// <param name="result">Result</param>
/// <returns>Status code</returns>
NTSTATUS ScanSymbolPatterns( const pe::PEImage& ntdll32, const pe::PEImage& ntdll64, SymbolData& result );
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "../include/Types.h"
namespace blackbone
{
/// <summary>
/// Ntdll internal pointers
/// </summary>
struct SymbolData
{
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
};
inline SymbolData g_symbols;
}
+80
View File
@@ -0,0 +1,80 @@
#include "SymbolLoader.h"
#include "PDBHelper.h"
#include "../Symbols/PatternLoader.h"
#include "../PE/PEImage.h"
namespace blackbone
{
SymbolLoader::SymbolLoader()
: _x86OS( false )
, _wow64Process( false )
{
SYSTEM_INFO info = { };
GetNativeSystemInfo( &info );
if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
_x86OS = true;
}
else
{
BOOL wowSrc = FALSE;
IsWow64Process( GetCurrentProcess(), &wowSrc );
_wow64Process = wowSrc != 0;
}
}
/// <summary>
/// Load symbol addresses from PDB or and pattern scans
/// </summary>
/// <param name="result">Found symbols</param>
/// <returns>Status code</returns>
NTSTATUS SymbolLoader::Load( SymbolData& result )
{
pe::PEImage ntdll32, ntdll64;
PDBHelper sym32, sym64;
wchar_t buf[MAX_PATH] = { 0 };
GetWindowsDirectoryW( buf, MAX_PATH );
std::wstring windir( buf );
if (_x86OS)
{
ntdll32.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true );
}
else
{
FsRedirector fsr( _wow64Process );
ntdll64.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true );
ntdll32.Load( std::wstring( windir + L"\\SysWOW64\\ntdll.dll" ), true );
}
HRESULT hr = sym32.Init( ntdll32.path(), ntdll32.imageBase() );
if (!_x86OS && SUCCEEDED( hr ))
{
hr = sym64.Init( ntdll64.path(), ntdll64.imageBase() );
}
// Get addresses from pdb
/*if (SUCCEEDED( hr ))
{
sym32.GetSymAddress( L"LdrpHandleTlsData", result.LdrpHandleTlsData32 );
sym64.GetSymAddress( L"LdrpHandleTlsData", result.LdrpHandleTlsData64 );
sym32.GetSymAddress( L"LdrpInvertedFunctionTable", result.LdrpInvertedFunctionTable32 );
sym64.GetSymAddress( L"LdrpInvertedFunctionTable", result.LdrpInvertedFunctionTable64 );
sym32.GetSymAddress( L"RtlInsertInvertedFunctionTable", result.RtlInsertInvertedFunctionTable32 );
sym64.GetSymAddress( L"RtlInsertInvertedFunctionTable", result.RtlInsertInvertedFunctionTable64 );
sym32.GetSymAddress( L"LdrProtectMrdata", result.LdrProtectMrdata );
}*/
// Fill missing symbols from patterns
return ScanSymbolPatterns( ntdll32, ntdll64, result );;
}
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "SymbolData.h"
namespace blackbone
{
class SymbolLoader
{
public:
SymbolLoader();
/// <summary>
/// Load symbol addresses from PDB or and pattern scans
/// </summary>
/// <param name="result">Found symbols</param>
/// <returns>Status code</returns>
NTSTATUS Load( SymbolData& result );
private:
bool _x86OS; // x86 OS
bool _wow64Process; // Current process is wow64 process
};
}
+12 -12
View File
@@ -179,26 +179,22 @@
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<EnableCppCoreCheck>true</EnableCppCoreCheck>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(XP)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
<EnableCppCoreCheck>true</EnableCppCoreCheck>
</PropertyGroup>
@@ -206,53 +202,45 @@
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(DLL)|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(XP)|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release(DLL)|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(SolutionDir)contrib;$(IncludePath)</IncludePath>
<TargetName>$(ProjectName)64</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -267,6 +255,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -294,6 +283,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -321,6 +311,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -348,6 +339,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -374,6 +366,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -400,6 +393,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -430,6 +424,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -459,6 +454,7 @@
<OmitFramePointers>false</OmitFramePointers>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -488,6 +484,7 @@
<OmitFramePointers>false</OmitFramePointers>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -514,6 +511,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -540,6 +538,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -566,6 +565,7 @@
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\contrib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>