mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
Rewrite IO handling (#6)
* csq stuff * oh yea * bugfix * epicc * some formating n dat * bug fix * class changes * e * fix up some of the io stuff * fix io PLEASEEE * fff
This commit is contained in:
parent
44d026bb88
commit
85c6fd6665
64 changed files with 2098 additions and 3275 deletions
133
.clang-format
133
.clang-format
|
@ -1,131 +1,4 @@
|
||||||
Language: Cpp
|
---
|
||||||
BasedOnStyle: webkit
|
BasedOnStyle: LLVM
|
||||||
AccessModifierOffset: -4
|
|
||||||
|
|
||||||
AlignAfterOpenBracket: Align
|
...
|
||||||
AlignConsecutiveAssignments: true
|
|
||||||
AlignConsecutiveDeclarations: true
|
|
||||||
|
|
||||||
AlignConsecutiveMacros: true
|
|
||||||
|
|
||||||
AlignEscapedNewlines: Left
|
|
||||||
AlignOperands: true
|
|
||||||
|
|
||||||
AlignTrailingComments: true
|
|
||||||
|
|
||||||
AllowAllArgumentsOnNextLine: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
|
|
||||||
AllowShortBlocksOnASingleLine: true
|
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
AllowShortFunctionsOnASingleLine: false
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterReturnType: TopLevel
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
|
|
||||||
AlwaysBreakTemplateDeclarations: true #false
|
|
||||||
|
|
||||||
BinPackArguments: false
|
|
||||||
BinPackParameters: false
|
|
||||||
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BraceWrapping:
|
|
||||||
AfterCaseLabel: true
|
|
||||||
AfterClass: true
|
|
||||||
AfterControlStatement: true
|
|
||||||
AfterEnum: true
|
|
||||||
AfterFunction: true
|
|
||||||
AfterNamespace: false
|
|
||||||
AfterStruct: true
|
|
||||||
AfterUnion: true
|
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: true
|
|
||||||
BeforeElse: true
|
|
||||||
|
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializers: AfterColon
|
|
||||||
BreakStringLiterals: false
|
|
||||||
|
|
||||||
ColumnLimit: 100
|
|
||||||
CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX '
|
|
||||||
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
||||||
ConstructorInitializerIndentWidth: 4
|
|
||||||
ContinuationIndentWidth: 4
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
|
|
||||||
IndentCaseLabels: false
|
|
||||||
IndentPPDirectives: AfterHash
|
|
||||||
IndentWidth: 8
|
|
||||||
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
Language: Cpp
|
|
||||||
|
|
||||||
MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$'
|
|
||||||
MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$'
|
|
||||||
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: None #All
|
|
||||||
PointerAlignment: Left
|
|
||||||
ReflowComments: true
|
|
||||||
SortIncludes: false
|
|
||||||
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
|
|
||||||
Standard: Cpp11
|
|
||||||
StatementMacros: [
|
|
||||||
'EXTERN_C',
|
|
||||||
'PAGED',
|
|
||||||
'PAGEDX',
|
|
||||||
'NONPAGED',
|
|
||||||
'PNPCODE',
|
|
||||||
'INITCODE',
|
|
||||||
'_At_',
|
|
||||||
'_When_',
|
|
||||||
'_Success_',
|
|
||||||
'_Check_return_',
|
|
||||||
'_Must_inspect_result_',
|
|
||||||
'_IRQL_requires_same_',
|
|
||||||
'_IRQL_requires_',
|
|
||||||
'_IRQL_requires_max_',
|
|
||||||
'_IRQL_requires_min_',
|
|
||||||
'_IRQL_saves_',
|
|
||||||
'_IRQL_restores_',
|
|
||||||
'_IRQL_saves_global_',
|
|
||||||
'_IRQL_restores_global_',
|
|
||||||
'_IRQL_raises_',
|
|
||||||
'_IRQL_lowers_',
|
|
||||||
'_Acquires_lock_',
|
|
||||||
'_Releases_lock_',
|
|
||||||
'_Acquires_exclusive_lock_',
|
|
||||||
'_Releases_exclusive_lock_',
|
|
||||||
'_Acquires_shared_lock_',
|
|
||||||
'_Releases_shared_lock_',
|
|
||||||
'_Requires_lock_held_',
|
|
||||||
'_Use_decl_annotations_',
|
|
||||||
'_Guarded_by_',
|
|
||||||
'__drv_preferredFunction',
|
|
||||||
'__drv_allocatesMem',
|
|
||||||
'__drv_freesMem',
|
|
||||||
]
|
|
||||||
|
|
||||||
TabWidth: '8'
|
|
||||||
UseTab: Never
|
|
||||||
|
|
131
.clang-format-c
Normal file
131
.clang-format-c
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: webkit
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: true
|
||||||
|
AlignConsecutiveDeclarations: true
|
||||||
|
|
||||||
|
AlignConsecutiveMacros: true
|
||||||
|
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
|
||||||
|
AlignTrailingComments: true
|
||||||
|
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: TopLevel
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
|
||||||
|
AlwaysBreakTemplateDeclarations: true #false
|
||||||
|
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: true
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: true
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: true
|
||||||
|
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
BreakStringLiterals: false
|
||||||
|
|
||||||
|
ColumnLimit: 100
|
||||||
|
CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX '
|
||||||
|
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentWidth: 8
|
||||||
|
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$'
|
||||||
|
MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$'
|
||||||
|
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None #All
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
|
||||||
|
Standard: Cpp11
|
||||||
|
StatementMacros: [
|
||||||
|
'EXTERN_C',
|
||||||
|
'PAGED',
|
||||||
|
'PAGEDX',
|
||||||
|
'NONPAGED',
|
||||||
|
'PNPCODE',
|
||||||
|
'INITCODE',
|
||||||
|
'_At_',
|
||||||
|
'_When_',
|
||||||
|
'_Success_',
|
||||||
|
'_Check_return_',
|
||||||
|
'_Must_inspect_result_',
|
||||||
|
'_IRQL_requires_same_',
|
||||||
|
'_IRQL_requires_',
|
||||||
|
'_IRQL_requires_max_',
|
||||||
|
'_IRQL_requires_min_',
|
||||||
|
'_IRQL_saves_',
|
||||||
|
'_IRQL_restores_',
|
||||||
|
'_IRQL_saves_global_',
|
||||||
|
'_IRQL_restores_global_',
|
||||||
|
'_IRQL_raises_',
|
||||||
|
'_IRQL_lowers_',
|
||||||
|
'_Acquires_lock_',
|
||||||
|
'_Releases_lock_',
|
||||||
|
'_Acquires_exclusive_lock_',
|
||||||
|
'_Releases_exclusive_lock_',
|
||||||
|
'_Acquires_shared_lock_',
|
||||||
|
'_Releases_shared_lock_',
|
||||||
|
'_Requires_lock_held_',
|
||||||
|
'_Use_decl_annotations_',
|
||||||
|
'_Guarded_by_',
|
||||||
|
'__drv_preferredFunction',
|
||||||
|
'__drv_allocatesMem',
|
||||||
|
'__drv_freesMem',
|
||||||
|
]
|
||||||
|
|
||||||
|
TabWidth: '8'
|
||||||
|
UseTab: Never
|
68
ac.sln
68
ac.sln
|
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.5.33502.453
|
VisualStudioVersion = 17.5.33502.453
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "user", "user\user.vcxproj", "{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "service", "service\service.csproj", "{6228E9DD-E1EA-45D8-8054-A00FC2D63414}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "service", "service\service.csproj", "{6228E9DD-E1EA-45D8-8054-A00FC2D63414}"
|
||||||
|
@ -13,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "server", "server\server.csp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdrv", "test\driver\testdrv.vcxproj", "{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdrv", "test\driver\testdrv.vcxproj", "{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "module", "module\module.vcxproj", "{3B18467A-4358-45EF-81B1-5C6F9B0B6728}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -33,38 +33,6 @@ Global
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|ARM64.ActiveCfg = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|ARM64.Build.0 = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|Any CPU.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|Any CPU.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|ARM64.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|ARM64.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|x64.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|x64.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|x86.ActiveCfg = Release - No Server|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win10|x86.Build.0 = Release - No Server|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|Any CPU.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|Any CPU.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|ARM64.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|ARM64.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|x64.ActiveCfg = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|x64.Build.0 = Release - No Server|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|x86.ActiveCfg = Release - No Server|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release - No Server - Win11|x86.Build.0 = Release - No Server|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|ARM64.ActiveCfg = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|ARM64.Build.0 = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.Build.0 = Release|x64
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.ActiveCfg = Debug|x64
|
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.Build.0 = Debug|x64
|
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.Deploy.0 = Debug|x64
|
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|Any CPU.Deploy.0 = Debug|x64
|
||||||
|
@ -225,6 +193,38 @@ Global
|
||||||
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.ActiveCfg = Release|x64
|
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.ActiveCfg = Release|x64
|
||||||
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.Build.0 = Release|x64
|
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.Build.0 = Release|x64
|
||||||
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.Deploy.0 = Release|x64
|
{3CE9C9B1-1FB1-4770-ABBB-EE4E6AA949B0}.Release|x86.Deploy.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|ARM64.ActiveCfg = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|ARM64.Build.0 = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|Any CPU.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|ARM64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|ARM64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|x64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|x64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|x86.ActiveCfg = Release|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win10|x86.Build.0 = Release|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|Any CPU.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|ARM64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|ARM64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|x64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|x64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|x86.ActiveCfg = Release|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release - No Server - Win11|x86.Build.0 = Release|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|ARM64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|ARM64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|x64.Build.0 = Release|x64
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{3B18467A-4358-45EF-81B1-5C6F9B0B6728}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -75,6 +75,7 @@ VOID
|
||||||
CleanupProcessListOnDriverUnload()
|
CleanupProcessListOnDriverUnload()
|
||||||
{
|
{
|
||||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||||
|
DEBUG_VERBOSE("Freeing process list");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!LookasideListFreeFirstEntry(
|
if (!LookasideListFreeFirstEntry(
|
||||||
|
@ -90,6 +91,7 @@ VOID
|
||||||
CleanupThreadListOnDriverUnload()
|
CleanupThreadListOnDriverUnload()
|
||||||
{
|
{
|
||||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||||
|
DEBUG_VERBOSE("Freeing thread list!");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!LookasideListFreeFirstEntry(
|
if (!LookasideListFreeFirstEntry(
|
||||||
|
@ -575,7 +577,9 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
||||||
*/
|
*/
|
||||||
if (!strcmp(process_creator_name, "lsass.exe") ||
|
if (!strcmp(process_creator_name, "lsass.exe") ||
|
||||||
!strcmp(process_creator_name, "csrss.exe") ||
|
!strcmp(process_creator_name, "csrss.exe") ||
|
||||||
!strcmp(process_creator_name, "WerFault.exe"))
|
!strcmp(process_creator_name, "WerFault.exe") ||
|
||||||
|
!strcmp(process_creator_name, "MsMpEng.exe") ||
|
||||||
|
!strcmp(process_creator_name, target_process_name))
|
||||||
{
|
{
|
||||||
/* We will downgrade these handles later */
|
/* We will downgrade these handles later */
|
||||||
// DEBUG_LOG("Handles created by CSRSS, LSASS and WerFault are allowed for
|
// DEBUG_LOG("Handles created by CSRSS, LSASS and WerFault are allowed for
|
||||||
|
@ -604,28 +608,31 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
||||||
!strcmp(process_creator_name, "explorer.exe"))
|
!strcmp(process_creator_name, "explorer.exe"))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
// DEBUG_LOG("handle stripped from: %s", process_creator_name);
|
//POPEN_HANDLE_FAILURE_REPORT report =
|
||||||
|
// ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||||
|
// sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
||||||
|
// REPORT_POOL_TAG);
|
||||||
|
|
||||||
POPEN_HANDLE_FAILURE_REPORT report =
|
//if (!report)
|
||||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
// goto end;
|
||||||
sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
|
||||||
REPORT_POOL_TAG);
|
|
||||||
|
|
||||||
if (!report)
|
//report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
||||||
goto end;
|
//report->is_kernel_handle = OperationInformation->KernelHandle;
|
||||||
|
//report->process_id = process_creator_id;
|
||||||
|
//report->thread_id = ImpPsGetCurrentThreadId();
|
||||||
|
//report->access =
|
||||||
|
// OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
||||||
|
|
||||||
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
//RtlCopyMemory(report->process_name,
|
||||||
report->is_kernel_handle = OperationInformation->KernelHandle;
|
// process_creator_name,
|
||||||
report->process_id = process_creator_id;
|
// HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||||
report->thread_id = ImpPsGetCurrentThreadId();
|
|
||||||
report->access =
|
|
||||||
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
|
||||||
|
|
||||||
RtlCopyMemory(report->process_name,
|
//if (!NT_SUCCESS(
|
||||||
process_creator_name,
|
// IrpQueueCompleteIrp(report, sizeof(OPEN_HANDLE_FAILURE_REPORT))))
|
||||||
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
//{
|
||||||
|
// DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
InsertReportToQueue(report);
|
// goto end;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,7 +806,11 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
|
||||||
RtlCopyMemory(
|
RtlCopyMemory(
|
||||||
&report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
&report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||||
|
|
||||||
InsertReportToQueue(report);
|
if (!NT_SUCCESS(IrpQueueCompleteIrp(report, sizeof(OPEN_HANDLE_FAILURE_REPORT))))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -842,6 +853,8 @@ EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry, _In_opt_ PVOI
|
||||||
|
|
||||||
#define REPEAT_TIME_10_SEC 10000
|
#define REPEAT_TIME_10_SEC 10000
|
||||||
|
|
||||||
|
ULONG value = 10;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
|
TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,19 +12,6 @@ typedef void (*THREADLIST_CALLBACK_ROUTINE)(_In_ PTHREAD_LIST_ENTRY ThreadListEn
|
||||||
typedef void (*PROCESSLIST_CALLBACK_ROUTINE)(_In_ PPROCESS_LIST_ENTRY ProcessListEntry,
|
typedef void (*PROCESSLIST_CALLBACK_ROUTINE)(_In_ PPROCESS_LIST_ENTRY ProcessListEntry,
|
||||||
_In_opt_ PVOID Context);
|
_In_opt_ PVOID Context);
|
||||||
|
|
||||||
#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64
|
|
||||||
|
|
||||||
typedef struct _OPEN_HANDLE_FAILURE_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT is_kernel_handle;
|
|
||||||
LONG process_id;
|
|
||||||
LONG thread_id;
|
|
||||||
LONG access;
|
|
||||||
CHAR process_name[HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH];
|
|
||||||
|
|
||||||
} OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT;
|
|
||||||
|
|
||||||
#define DRIVER_PATH_LENGTH 0x100
|
#define DRIVER_PATH_LENGTH 0x100
|
||||||
#define SHA_256_HASH_LENGTH 32
|
#define SHA_256_HASH_LENGTH 32
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include <wdftypes.h>
|
#include <wdftypes.h>
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#include "types/types.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For numbers < 32, these are equivalent to 0ul < x.
|
* For numbers < 32, these are equivalent to 0ul < x.
|
||||||
|
@ -39,6 +42,8 @@
|
||||||
|
|
||||||
#define STATIC static
|
#define STATIC static
|
||||||
|
|
||||||
|
#define MAX_MODULE_PATH 256
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interlocked intrinsics are only atomic with respect to other InterlockedXxx functions,
|
* Interlocked intrinsics are only atomic with respect to other InterlockedXxx functions,
|
||||||
* so all reads and writes to the THREAD_LIST->active flag must be with Interlocked instrinsics
|
* so all reads and writes to the THREAD_LIST->active flag must be with Interlocked instrinsics
|
||||||
|
@ -169,11 +174,29 @@ typedef struct _OB_CALLBACKS_CONFIG
|
||||||
|
|
||||||
} OB_CALLBACKS_CONFIG, *POB_CALLBACKS_CONFIG;
|
} OB_CALLBACKS_CONFIG, *POB_CALLBACKS_CONFIG;
|
||||||
|
|
||||||
|
typedef struct _DEFERRED_REPORT
|
||||||
|
{
|
||||||
|
LIST_ENTRY list_entry;
|
||||||
|
PVOID buffer;
|
||||||
|
UINT32 buffer_size;
|
||||||
|
|
||||||
|
} DEFERRED_REPORT, *PDEFERRED_REPORT;
|
||||||
|
|
||||||
|
typedef struct _DEFERRED_REPORTS_HEAD
|
||||||
|
{
|
||||||
|
LIST_ENTRY head;
|
||||||
|
UINT32 count;
|
||||||
|
KGUARDED_MUTEX lock;
|
||||||
|
|
||||||
|
} DEFERRED_REPORTS_HEAD, *PDEFERRED_REPORTS_HEAD;
|
||||||
|
|
||||||
typedef struct _IRP_QUEUE_HEAD
|
typedef struct _IRP_QUEUE_HEAD
|
||||||
{
|
{
|
||||||
SINGLE_LIST_ENTRY start;
|
LIST_ENTRY queue;
|
||||||
volatile INT count;
|
volatile UINT32 count;
|
||||||
KGUARDED_MUTEX lock;
|
IO_CSQ csq;
|
||||||
|
KGUARDED_MUTEX lock;
|
||||||
|
DEFERRED_REPORTS_HEAD reports;
|
||||||
|
|
||||||
} IRP_QUEUE_HEAD, *PIRP_QUEUE_HEAD;
|
} IRP_QUEUE_HEAD, *PIRP_QUEUE_HEAD;
|
||||||
|
|
||||||
|
@ -282,15 +305,6 @@ typedef struct _PROCESS_CONFIG
|
||||||
#define KPRCB_OFFSET_FROM_GS_BASE 0x180
|
#define KPRCB_OFFSET_FROM_GS_BASE 0x180
|
||||||
|
|
||||||
#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20
|
#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20
|
||||||
#define REPORT_NMI_CALLBACK_FAILURE 50
|
|
||||||
#define REPORT_MODULE_VALIDATION_FAILURE 60
|
|
||||||
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
|
|
||||||
#define REPORT_INVALID_PROCESS_ALLOCATION 80
|
|
||||||
#define REPORT_HIDDEN_SYSTEM_THREAD 90
|
|
||||||
#define REPORT_ILLEGAL_ATTACH_PROCESS 100
|
|
||||||
#define REPORT_APC_STACKWALK 110
|
|
||||||
#define REPORT_DPC_STACKWALK 120
|
|
||||||
#define REPORT_DATA_TABLE_ROUTINE 130
|
|
||||||
|
|
||||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||||
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
|
|
||||||
#include "hv.h"
|
#include "hv.h"
|
||||||
|
@ -41,10 +41,6 @@ STATIC
|
||||||
VOID
|
VOID
|
||||||
DrvUnloadFreeSymbolicLink();
|
DrvUnloadFreeSymbolicLink();
|
||||||
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
DrvUnloadFreeGlobalReportQueue();
|
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID
|
||||||
DrvUnloadFreeThreadList();
|
DrvUnloadFreeThreadList();
|
||||||
|
@ -84,7 +80,6 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_ST
|
||||||
# pragma alloc_text(PAGE, DrvUnloadUnregisterObCallbacks)
|
# pragma alloc_text(PAGE, DrvUnloadUnregisterObCallbacks)
|
||||||
# pragma alloc_text(PAGE, DrvUnloadFreeConfigStrings)
|
# pragma alloc_text(PAGE, DrvUnloadFreeConfigStrings)
|
||||||
# pragma alloc_text(PAGE, DrvUnloadFreeSymbolicLink)
|
# pragma alloc_text(PAGE, DrvUnloadFreeSymbolicLink)
|
||||||
# pragma alloc_text(PAGE, DrvUnloadFreeGlobalReportQueue)
|
|
||||||
# pragma alloc_text(PAGE, DrvUnloadFreeThreadList)
|
# pragma alloc_text(PAGE, DrvUnloadFreeThreadList)
|
||||||
# pragma alloc_text(PAGE, DrvLoadEnableNotifyRoutines)
|
# pragma alloc_text(PAGE, DrvLoadEnableNotifyRoutines)
|
||||||
# pragma alloc_text(PAGE, DrvLoadEnableNotifyRoutines)
|
# pragma alloc_text(PAGE, DrvLoadEnableNotifyRoutines)
|
||||||
|
@ -115,7 +110,6 @@ typedef struct _DRIVER_CONFIG
|
||||||
THREAD_LIST_HEAD thread_list;
|
THREAD_LIST_HEAD thread_list;
|
||||||
DRIVER_LIST_HEAD driver_list;
|
DRIVER_LIST_HEAD driver_list;
|
||||||
PROCESS_LIST_HEAD process_list;
|
PROCESS_LIST_HEAD process_list;
|
||||||
REPORT_QUEUE_HEAD report_queue;
|
|
||||||
|
|
||||||
} DRIVER_CONFIG, *PDRIVER_CONFIG;
|
} DRIVER_CONFIG, *PDRIVER_CONFIG;
|
||||||
|
|
||||||
|
@ -239,13 +233,6 @@ GetDriverConfigSystemInformation()
|
||||||
return &g_DriverConfig->system_information;
|
return &g_DriverConfig->system_information;
|
||||||
}
|
}
|
||||||
|
|
||||||
PREPORT_QUEUE_HEAD
|
|
||||||
GetDriverReportQueue()
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
return &g_DriverConfig->report_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PTHREAD_LIST_HEAD
|
PTHREAD_LIST_HEAD
|
||||||
GetThreadList()
|
GetThreadList()
|
||||||
{
|
{
|
||||||
|
@ -390,14 +377,6 @@ DrvUnloadFreeSymbolicLink()
|
||||||
ImpIoDeleteSymbolicLink(&g_DriverConfig->device_symbolic_link);
|
ImpIoDeleteSymbolicLink(&g_DriverConfig->device_symbolic_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
DrvUnloadFreeGlobalReportQueue()
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
FreeGlobalReportQueueObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID
|
||||||
DrvUnloadFreeThreadList()
|
DrvUnloadFreeThreadList()
|
||||||
|
@ -475,7 +454,6 @@ DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
|
||||||
DrvUnloadFreeDriverList();
|
DrvUnloadFreeDriverList();
|
||||||
|
|
||||||
DrvUnloadFreeConfigStrings();
|
DrvUnloadFreeConfigStrings();
|
||||||
DrvUnloadFreeGlobalReportQueue();
|
|
||||||
DrvUnloadFreeSymbolicLink();
|
DrvUnloadFreeSymbolicLink();
|
||||||
|
|
||||||
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||||
|
@ -566,14 +544,6 @@ DrvLoadSetupDriverLists()
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
DrvLoadInitialiseReportQueue()
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
InitialiseGlobalReportQueue(&g_DriverConfig->report_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID
|
||||||
DrvLoadInitialiseProcessConfig()
|
DrvLoadInitialiseProcessConfig()
|
||||||
|
@ -956,6 +926,15 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_ST
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = IrpQueueInitialise();
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueInitialise failed with status %x", status);
|
||||||
|
DrvUnloadFreeConfigStrings();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_VERBOSE("driver name: %s", g_DriverConfig->ansi_driver_name.Buffer);
|
DEBUG_VERBOSE("driver name: %s", g_DriverConfig->ansi_driver_name.Buffer);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +979,11 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
||||||
status = ResolveDynamicImports(DriverObject);
|
status = ResolveDynamicImports(DriverObject);
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("ResolveDynamicImports failed with status %x", status);
|
||||||
|
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath);
|
status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath);
|
||||||
|
|
||||||
|
@ -1008,10 +991,10 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("InitialiseDriverConfigOnDriverEntry failed with status %x", status);
|
DEBUG_ERROR("InitialiseDriverConfigOnDriverEntry failed with status %x", status);
|
||||||
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||||
|
DrvUnloadFreeImportsStructure();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrvLoadInitialiseReportQueue();
|
|
||||||
DrvLoadInitialiseProcessConfig();
|
DrvLoadInitialiseProcessConfig();
|
||||||
|
|
||||||
status = IoCreateSymbolicLink(&symbolic_link, &device_name);
|
status = IoCreateSymbolicLink(&symbolic_link, &device_name);
|
||||||
|
@ -1022,6 +1005,7 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
||||||
DrvUnloadFreeConfigStrings();
|
DrvUnloadFreeConfigStrings();
|
||||||
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||||
DrvUnloadFreeTimerObject();
|
DrvUnloadFreeTimerObject();
|
||||||
|
DrvUnloadFreeImportsStructure();
|
||||||
return STATUS_FAILED_DRIVER_ENTRY;
|
return STATUS_FAILED_DRIVER_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,6 @@ GetDriverSymbolicLink();
|
||||||
PSYSTEM_INFORMATION
|
PSYSTEM_INFORMATION
|
||||||
GetDriverConfigSystemInformation();
|
GetDriverConfigSystemInformation();
|
||||||
|
|
||||||
PREPORT_QUEUE_HEAD
|
|
||||||
GetDriverReportQueue();
|
|
||||||
|
|
||||||
PTHREAD_LIST_HEAD
|
PTHREAD_LIST_HEAD
|
||||||
GetThreadList();
|
GetThreadList();
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@
|
||||||
<ClCompile Include="hv.c" />
|
<ClCompile Include="hv.c" />
|
||||||
<ClCompile Include="imports.c" />
|
<ClCompile Include="imports.c" />
|
||||||
<ClCompile Include="integrity.c" />
|
<ClCompile Include="integrity.c" />
|
||||||
<ClCompile Include="ioctl.c" />
|
<ClCompile Include="io.c" />
|
||||||
<ClCompile Include="list.c" />
|
<ClCompile Include="list.c" />
|
||||||
<ClCompile Include="modules.c" />
|
<ClCompile Include="modules.c" />
|
||||||
<ClCompile Include="pool.c" />
|
<ClCompile Include="pool.c" />
|
||||||
|
@ -266,12 +266,13 @@
|
||||||
<ClInclude Include="ia32.h" />
|
<ClInclude Include="ia32.h" />
|
||||||
<ClInclude Include="imports.h" />
|
<ClInclude Include="imports.h" />
|
||||||
<ClInclude Include="integrity.h" />
|
<ClInclude Include="integrity.h" />
|
||||||
<ClInclude Include="ioctl.h" />
|
<ClInclude Include="io.h" />
|
||||||
<ClInclude Include="list.h" />
|
<ClInclude Include="list.h" />
|
||||||
<ClInclude Include="modules.h" />
|
<ClInclude Include="modules.h" />
|
||||||
<ClInclude Include="pool.h" />
|
<ClInclude Include="pool.h" />
|
||||||
<ClInclude Include="queue.h" />
|
<ClInclude Include="queue.h" />
|
||||||
<ClInclude Include="thread.h" />
|
<ClInclude Include="thread.h" />
|
||||||
|
<ClInclude Include="types\types.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MASM Include="arch.asm" />
|
<MASM Include="arch.asm" />
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
<ClCompile Include="driver.c">
|
<ClCompile Include="driver.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="ioctl.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="modules.c">
|
<ClCompile Include="modules.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -60,6 +57,9 @@
|
||||||
<ClCompile Include="list.c">
|
<ClCompile Include="list.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="io.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="driver.h">
|
<ClInclude Include="driver.h">
|
||||||
|
@ -68,9 +68,6 @@
|
||||||
<ClInclude Include="common.h">
|
<ClInclude Include="common.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="ioctl.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="modules.h">
|
<ClInclude Include="modules.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -104,6 +101,12 @@
|
||||||
<ClInclude Include="list.h">
|
<ClInclude Include="list.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="io.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="types\types.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MASM Include="arch.asm">
|
<MASM Include="arch.asm">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
# pragma alloc_text(PAGE, PerformVirtualizationDetection)
|
# pragma alloc_text(PAGE, PerformVirtualizationDetection)
|
||||||
|
|
|
@ -4,13 +4,6 @@
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
typedef struct _HYPERVISOR_DETECTION_REPORT
|
|
||||||
{
|
|
||||||
INT aperf_msr_timing_check;
|
|
||||||
INT invd_emulation_check;
|
|
||||||
|
|
||||||
} HYPERVISOR_DETECTION_REPORT, *PHYPERVISOR_DETECTION_REPORT;
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PerformVirtualizationDetection(_Inout_ PIRP Irp);
|
PerformVirtualizationDetection(_Inout_ PIRP Irp);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
|
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
|
@ -18,8 +18,6 @@ typedef struct _INTEGRITY_CHECK_HEADER
|
||||||
|
|
||||||
} INTEGRITY_CHECK_HEADER, *PINTEGRITY_CHECK_HEADER;
|
} INTEGRITY_CHECK_HEADER, *PINTEGRITY_CHECK_HEADER;
|
||||||
|
|
||||||
#define MAX_MODULE_PATH 256
|
|
||||||
|
|
||||||
typedef struct _PROCESS_MODULE_INFORMATION
|
typedef struct _PROCESS_MODULE_INFORMATION
|
||||||
{
|
{
|
||||||
PVOID module_base;
|
PVOID module_base;
|
||||||
|
@ -933,28 +931,29 @@ ValidateProcessLoadedModule(_Inout_ PIRP Irp)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!CompareHashes(disk_hash, memory_hash, memory_hash_size))
|
||||||
* Because each module is passed per IRP we don't need to send any reports
|
|
||||||
* to the queue we can simply pass it back to usermode via the same IRP.
|
|
||||||
* We also don't need to send any module information since usermode has everything
|
|
||||||
* needed to file the report.
|
|
||||||
*/
|
|
||||||
validation_result.is_module_valid = CompareHashes(disk_hash, memory_hash, memory_hash_size);
|
|
||||||
|
|
||||||
status = ValidateIrpOutputBuffer(Irp, sizeof(PROCESS_MODULE_VALIDATION_RESULT));
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to validate IRP output buffer");
|
PPROCESS_MODULE_VALIDATION_REPORT report = ImpExAllocatePool2(
|
||||||
goto end;
|
POOL_FLAG_NON_PAGED, sizeof(PROCESS_MODULE_VALIDATION_REPORT), REPORT_POOL_TAG);
|
||||||
|
|
||||||
|
if (!report)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
report->report_code = REPORT_INVALID_PROCESS_MODULE;
|
||||||
|
report->image_base = module_info->module_base;
|
||||||
|
report->image_size = module_info->module_size;
|
||||||
|
RtlCopyMemory(report->module_path, module_info->module_path,
|
||||||
|
sizeof(report->module_path));
|
||||||
|
|
||||||
|
status = IrpQueueCompleteIrp(report, sizeof(PROCESS_MODULE_VALIDATION_REPORT));
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x", status);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(PROCESS_MODULE_VALIDATION_RESULT);
|
|
||||||
|
|
||||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
|
||||||
&validation_result,
|
|
||||||
sizeof(PROCESS_MODULE_VALIDATION_RESULT));
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
||||||
if (section_handle)
|
if (section_handle)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
|
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
@ -60,49 +60,226 @@ DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation);
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define IOCTL_INSERT_IRP_INTO_QUEUE \
|
#define IOCTL_INSERT_IRP_INTO_QUEUE \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_QUERY_DEFERRED_REPORTS \
|
||||||
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
#define APC_OPERATION_STACKWALK 0x1
|
#define APC_OPERATION_STACKWALK 0x1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic cancel-safe IRP queue implementation. Stores pending IRPs in a list, allowing us to dequeue
|
||||||
|
* entries to send data back to user mode without being invoked by the user mode module via an io
|
||||||
|
* completion port.
|
||||||
|
*
|
||||||
|
* user mode program will automatically queue another irp when an irp completes, ensuring queue has
|
||||||
|
* a sufficient supply.
|
||||||
|
*/
|
||||||
VOID
|
VOID
|
||||||
IrpQueueMarkIrpCompleteCallback(_In_ PIRP_QUEUE_ENTRY Entry)
|
IrpQueueAcquireLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
|
||||||
{
|
{
|
||||||
ImpIofCompleteRequest(Entry->irp, IO_NO_INCREMENT);
|
KeAcquireGuardedMutex(&GetIrpQueueHead()->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
IrpQueueDequeue(PVOID Callback)
|
IrpQueueReleaseLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
|
||||||
{
|
{
|
||||||
|
KeReleaseGuardedMutex(&GetIrpQueueHead()->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIRP
|
||||||
|
IrpQueuePeekNextEntry(_In_ PIO_CSQ Csq, _In_ PIRP Irp, _In_ PVOID Context)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(Context);
|
||||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
ListFreeFirstEntry(&queue->start, &queue->lock, Callback);
|
|
||||||
|
if (queue->count == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return CONTAINING_RECORD(queue->queue.Flink, IRP, Tail.Overlay.ListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
IrpQueueInitialise()
|
IrpQueueRemove(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
UNREFERENCED_PARAMETER(Csq);
|
||||||
queue->count = 0;
|
GetIrpQueueHead()->count--;
|
||||||
ImpKeInitializeGuardedMutex(&queue->lock);
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
ListInit(&queue->start, &queue->lock);
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
IrpQueueIsThereDeferredReport(_In_ PIRP_QUEUE_HEAD Queue)
|
||||||
|
{
|
||||||
|
return Queue->reports.count > 0 ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEFERRED_REPORT
|
||||||
|
IrpQueueRemoveDeferredReport(_In_ PIRP_QUEUE_HEAD Queue)
|
||||||
|
{
|
||||||
|
return RemoveHeadList(&Queue->reports.head);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
IrpQueueCompleteDeferredReport(_In_ PDEFERRED_REPORT Report, _In_ PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS status = ValidateIrpOutputBuffer(Irp, Report->buffer_size);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Report->buffer, Report->buffer_size);
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = Report->buffer_size;
|
||||||
|
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
IrpQueueQueryPendingReports(_In_ PIRP Irp)
|
||||||
|
{
|
||||||
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
|
PDEFERRED_REPORT report = NULL;
|
||||||
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
if (IrpQueueIsThereDeferredReport(queue))
|
||||||
|
{
|
||||||
|
KeAcquireGuardedMutex(&queue->reports.lock);
|
||||||
|
report = IrpQueueRemoveDeferredReport(queue);
|
||||||
|
status = IrpQueueCompleteDeferredReport(report, Irp);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
KeReleaseGuardedMutex(&queue->reports.lock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue->reports.count--;
|
||||||
|
KeReleaseGuardedMutex(&queue->reports.lock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
IrpQueueInsert(PIRP Irp)
|
IrpQueueInsert(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
PIRP_QUEUE_ENTRY entry = NULL;
|
InsertTailList(&queue->queue, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
queue->count++;
|
||||||
|
}
|
||||||
|
|
||||||
entry = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(IRP_QUEUE_ENTRY), POOL_TAG_IRP_QUEUE);
|
VOID
|
||||||
|
IrpQueueCompleteCancelledIrp(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(Csq);
|
||||||
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
Irp->IoStatus.Status = 0;
|
||||||
|
ImpIofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
if (!entry)
|
PDEFERRED_REPORT
|
||||||
|
IrpQueueAllocateDeferredReport(_In_ PVOID Buffer, _In_ UINT32 BufferSize)
|
||||||
|
{
|
||||||
|
PDEFERRED_REPORT report =
|
||||||
|
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(DEFERRED_REPORT), REPORT_POOL_TAG);
|
||||||
|
|
||||||
|
if (!report)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
report->buffer = Buffer;
|
||||||
|
report->buffer_size = BufferSize;
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
IrpQueueDeferReport(_In_ PIRP_QUEUE_HEAD Queue, _In_ PVOID Buffer, _In_ UINT32 BufferSize)
|
||||||
|
{
|
||||||
|
if (Queue->reports.count > 100)
|
||||||
|
{
|
||||||
|
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEFERRED_REPORT report = IrpQueueAllocateDeferredReport(Buffer, BufferSize);
|
||||||
|
|
||||||
|
if (!report)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_PENDING;
|
KeAcquireGuardedMutex(&Queue->reports.lock);
|
||||||
IoMarkIrpPending(Irp);
|
InsertTailList(&Queue->reports.head, &report->list_entry);
|
||||||
entry->irp = Irp;
|
Queue->reports.count++;
|
||||||
queue->count++;
|
KeReleaseGuardedMutex(&Queue->reports.lock);
|
||||||
|
}
|
||||||
|
|
||||||
ListInsert(&queue->start, &entry->entry, &queue->lock);
|
/* takes ownership of the buffer, and regardless of the outcome will free it. */
|
||||||
IrpQueueDequeue(IrpQueueMarkIrpCompleteCallback);
|
NTSTATUS
|
||||||
|
IrpQueueCompleteIrp(_In_ PVOID Buffer, _In_ ULONG BufferSize)
|
||||||
|
{
|
||||||
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||||
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
|
|
||||||
|
PIRP irp = IoCsqRemoveNextIrp(&queue->csq, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no irps are available in our queue, lets store it in a deferred reports list which
|
||||||
|
* should be checked each time we insert a new irp into the queue.
|
||||||
|
*/
|
||||||
|
if (!irp)
|
||||||
|
{
|
||||||
|
IrpQueueDeferReport(queue, Buffer, BufferSize);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ValidateIrpOutputBuffer(irp, BufferSize);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
irp->IoStatus.Information = BufferSize;
|
||||||
|
RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, BufferSize);
|
||||||
|
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
|
||||||
|
ImpIofCompleteRequest(irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
IrpQueueFreeDeferredReports()
|
||||||
|
{
|
||||||
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
|
PDEFERRED_REPORT report = NULL;
|
||||||
|
|
||||||
|
while (IrpQueueIsThereDeferredReport(queue))
|
||||||
|
{
|
||||||
|
report = IrpQueueRemoveDeferredReport(queue);
|
||||||
|
ExFreePoolWithTag(report, REPORT_POOL_TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
IrpQueueInitialise()
|
||||||
|
{
|
||||||
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||||
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
|
|
||||||
|
KeInitializeGuardedMutex(&queue->lock);
|
||||||
|
KeInitializeGuardedMutex(&queue->reports.lock);
|
||||||
|
InitializeListHead(&queue->queue);
|
||||||
|
InitializeListHead(&queue->reports.head);
|
||||||
|
|
||||||
|
status = IoCsqInitialize(&queue->csq,
|
||||||
|
IrpQueueInsert,
|
||||||
|
IrpQueueRemove,
|
||||||
|
IrpQueuePeekNextEntry,
|
||||||
|
IrpQueueAcquireLock,
|
||||||
|
IrpQueueReleaseLock,
|
||||||
|
IrpQueueCompleteCancelledIrp);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
DEBUG_ERROR("IoCsqInitialize failed with status %x", status);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
|
@ -132,7 +309,7 @@ DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation)
|
||||||
default: DEBUG_WARNING("Invalid operation ID passed"); return STATUS_INVALID_PARAMETER;
|
default: DEBUG_WARNING("Invalid operation ID passed"); return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -241,8 +418,13 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
* it will issue a bug check under windows driver verifier.
|
* it will issue a bug check under windows driver verifier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = ImpPsCreateSystemThread(
|
status = ImpPsCreateSystemThread(&handle,
|
||||||
&handle, PROCESS_ALL_ACCESS, NULL, NULL, NULL, HandleValidateDriversIOCTL, Irp);
|
PROCESS_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
HandleValidateDriversIOCTL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
|
@ -250,27 +432,7 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Thread objects are a type of dispatcher object, meaning when they are freed
|
|
||||||
* its set to the signal state and any waiters will be signalled. This allows
|
|
||||||
* us to wait til our threads terminated and the IRP buffer has been either filled
|
|
||||||
* or left empty and then from there we can complete the IRP and return.
|
|
||||||
*/
|
|
||||||
status = ImpObReferenceObjectByHandle(
|
|
||||||
handle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &thread, NULL);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("ObReferenceObjectByHandle failed with status %lx", status);
|
|
||||||
ImpZwClose(handle);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImpKeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL);
|
|
||||||
|
|
||||||
ImpZwClose(handle);
|
ImpZwClose(handle);
|
||||||
ImpObDereferenceObject(thread);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
|
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
|
||||||
|
@ -302,11 +464,11 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
DEBUG_ERROR("QueryActiveApcContextsForCompletion failed with status %x",
|
DEBUG_ERROR("QueryActiveApcContextsForCompletion failed with status %x",
|
||||||
status);
|
status);
|
||||||
|
|
||||||
status = HandlePeriodicGlobalReportQueueQuery(Irp);
|
// status = HandlePeriodicGlobalReportQueueQuery(Irp);
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
// if (!NT_SUCCESS(status))
|
||||||
DEBUG_ERROR("HandlePeriodicGlobalReportQueueQuery failed with status %x",
|
// DEBUG_ERROR("HandlePeriodicGlobalReportQueueQuery failed with status %x",
|
||||||
status);
|
// status);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -478,7 +640,7 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
DEBUG_INFO("IOCTL_VALIDATE_SYSTEM_MODULES Received");
|
DEBUG_INFO("IOCTL_VALIDATE_SYSTEM_MODULES Received");
|
||||||
|
|
||||||
status = SystemModuleVerificationDispatcher();
|
status = SystemModuleVerificationDispatcher();
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
|
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
|
||||||
|
|
||||||
|
@ -496,13 +658,36 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_INSERT_IRP_INTO_QUEUE:
|
case IOCTL_INSERT_IRP_INTO_QUEUE:;
|
||||||
|
|
||||||
DEBUG_INFO("IOCTL_INSERT_IRP_INTO_QUEUE Received");
|
//DEBUG_INFO("IOCTL_INSERT_IRP_INTO_QUEUE Received");
|
||||||
|
|
||||||
IrpQueueInsert(Irp);
|
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the nature of the Windows IO subsystem and the cancel-safe queue
|
||||||
|
* implementation we use, we need to query for deferred reports before insert an irp
|
||||||
|
* into the queue. The reason for this is the cancel-safe queue will automically
|
||||||
|
* mark the irp as pending, so if we then use that irp to return a deferred report
|
||||||
|
* and return success here verifier has a lil cry.
|
||||||
|
*
|
||||||
|
* TODO: some issue with using an incoming irp meant for the queue and finishing a deferred report.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* before we queue our IRP, check if we can complete a deferred report */
|
||||||
|
status = IrpQueueQueryPendingReports(Irp);
|
||||||
|
|
||||||
|
/* if we return success, weve completed the irp, we can return success */
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
/* if there are no deferred reports, store the irp in
|
||||||
|
* the queue */
|
||||||
|
IoCsqInsertIrp(&queue->csq, Irp, NULL);
|
||||||
|
|
||||||
|
/* we dont want to complete the request */
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
/* we dont want to complete the request */
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -529,7 +714,6 @@ DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||||
DEBUG_INFO("Handle to driver closed.");
|
DEBUG_INFO("Handle to driver closed.");
|
||||||
|
|
||||||
/* we also lose reports here, so sohuld pass em into the irp before freeing */
|
/* we also lose reports here, so sohuld pass em into the irp before freeing */
|
||||||
FreeGlobalReportQueueObjects();
|
|
||||||
ProcCloseClearProcessConfiguration();
|
ProcCloseClearProcessConfiguration();
|
||||||
UnregisterProcessObCallbacks();
|
UnregisterProcessObCallbacks();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef IOCTL_H
|
#ifndef IO_H
|
||||||
#define IOCTL_H
|
#define IO_H
|
||||||
|
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include <wdftypes.h>
|
#include <wdftypes.h>
|
||||||
|
@ -27,7 +27,10 @@ ValidateIrpOutputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ValidateIrpInputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize);
|
ValidateIrpInputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize);
|
||||||
|
|
||||||
VOID
|
NTSTATUS
|
||||||
IrpQueueInitialise();
|
IrpQueueInitialise();
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
IrpQueueCompleteIrp(_In_ PVOID Buffer, _In_ ULONG BufferSize);
|
||||||
|
|
||||||
#endif
|
#endif
|
108
driver/modules.c
108
driver/modules.c
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
#include "ia32.h"
|
#include "ia32.h"
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
#include "apc.h"
|
#include "apc.h"
|
||||||
|
@ -621,12 +621,11 @@ end:
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
HandleValidateDriversIOCTL(_Inout_ PIRP Irp)
|
HandleValidateDriversIOCTL()
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||||
PVOID buffer = NULL;
|
|
||||||
ULONG buffer_size = 0;
|
ULONG buffer_size = 0;
|
||||||
SYSTEM_MODULES system_modules = {0};
|
SYSTEM_MODULES system_modules = {0};
|
||||||
MODULE_VALIDATION_FAILURE_HEADER header = {0};
|
MODULE_VALIDATION_FAILURE_HEADER header = {0};
|
||||||
|
@ -676,34 +675,6 @@ HandleValidateDriversIOCTL(_Inout_ PIRP Irp)
|
||||||
{
|
{
|
||||||
DEBUG_VERBOSE("System has an invalid driver count of: %i", head->count);
|
DEBUG_VERBOSE("System has an invalid driver count of: %i", head->count);
|
||||||
|
|
||||||
buffer_size =
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE_HEADER) +
|
|
||||||
MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT * sizeof(MODULE_VALIDATION_FAILURE);
|
|
||||||
|
|
||||||
status = ValidateIrpOutputBuffer(Irp, buffer_size);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to validate output buffer.");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer =
|
|
||||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, buffer_size, MODULES_REPORT_POOL_TAG);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
ImpExFreePoolWithTag(head, INVALID_DRIVER_LIST_HEAD_POOL);
|
|
||||||
ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL);
|
|
||||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Information =
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE_HEADER) +
|
|
||||||
MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT * sizeof(MODULE_VALIDATION_FAILURE);
|
|
||||||
|
|
||||||
RtlCopyMemory(buffer, &header, sizeof(MODULE_VALIDATION_FAILURE_HEADER));
|
|
||||||
|
|
||||||
for (INT index = 0; index < head->count; index++)
|
for (INT index = 0; index < head->count; index++)
|
||||||
{
|
{
|
||||||
/* make sure we free any non reported modules */
|
/* make sure we free any non reported modules */
|
||||||
|
@ -713,16 +684,21 @@ HandleValidateDriversIOCTL(_Inout_ PIRP Irp)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_VALIDATION_FAILURE report = {0};
|
PMODULE_VALIDATION_FAILURE report = ImpExAllocatePool2(
|
||||||
report.report_code = REPORT_MODULE_VALIDATION_FAILURE;
|
POOL_FLAG_PAGED, sizeof(MODULE_VALIDATION_FAILURE), POOL_TAG_INTEGRITY);
|
||||||
report.report_type = head->first_entry->reason;
|
|
||||||
report.driver_base_address = head->first_entry->driver->DriverStart;
|
if (!report)
|
||||||
report.driver_size = head->first_entry->driver->DriverSize;
|
continue;
|
||||||
|
|
||||||
|
report->report_code = REPORT_MODULE_VALIDATION_FAILURE;
|
||||||
|
report->report_type = head->first_entry->reason;
|
||||||
|
report->driver_base_address = head->first_entry->driver->DriverStart;
|
||||||
|
report->driver_size = head->first_entry->driver->DriverSize;
|
||||||
|
|
||||||
ANSI_STRING string = {0};
|
ANSI_STRING string = {0};
|
||||||
string.Length = 0;
|
string.Length = 0;
|
||||||
string.MaximumLength = MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
|
string.MaximumLength = MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
|
||||||
string.Buffer = &report.driver_name;
|
string.Buffer = &report->driver_name;
|
||||||
|
|
||||||
status = ImpRtlUnicodeStringToAnsiString(
|
status = ImpRtlUnicodeStringToAnsiString(
|
||||||
&string, &head->first_entry->driver->DriverName, FALSE);
|
&string, &head->first_entry->driver->DriverName, FALSE);
|
||||||
|
@ -732,21 +708,16 @@ HandleValidateDriversIOCTL(_Inout_ PIRP Irp)
|
||||||
DEBUG_ERROR("RtlUnicodeStringToAnsiString failed with status %x",
|
DEBUG_ERROR("RtlUnicodeStringToAnsiString failed with status %x",
|
||||||
status);
|
status);
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)buffer + sizeof(MODULE_VALIDATION_FAILURE_HEADER) +
|
status = IrpQueueCompleteIrp(report, sizeof(MODULE_VALIDATION_FAILURE));
|
||||||
index * sizeof(MODULE_VALIDATION_FAILURE),
|
|
||||||
&report,
|
if (!NT_SUCCESS(status))
|
||||||
sizeof(MODULE_VALIDATION_FAILURE));
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x", status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
RemoveInvalidDriverFromList(head);
|
RemoveInvalidDriverFromList(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
|
||||||
buffer,
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE_HEADER) +
|
|
||||||
MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT *
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE));
|
|
||||||
|
|
||||||
ImpExFreePoolWithTag(buffer, MODULES_REPORT_POOL_TAG);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -906,7 +877,12 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules,
|
||||||
RtlCopyMemory(
|
RtlCopyMemory(
|
||||||
report->thread, NmiContext[core].kthread, sizeof(report->thread));
|
report->thread, NmiContext[core].kthread, sizeof(report->thread));
|
||||||
|
|
||||||
InsertReportToQueue(report);
|
if (!NT_SUCCESS(
|
||||||
|
IrpQueueCompleteIrp(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT))))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1193,7 +1169,7 @@ ApcKernelRoutine(_In_ PRKAPC Apc,
|
||||||
if (flag == FALSE)
|
if (flag == FALSE)
|
||||||
{
|
{
|
||||||
PAPC_STACKWALK_REPORT report = ImpExAllocatePool2(
|
PAPC_STACKWALK_REPORT report = ImpExAllocatePool2(
|
||||||
POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), POOL_TAG_APC);
|
POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), REPORT_POOL_TAG);
|
||||||
|
|
||||||
if (!report)
|
if (!report)
|
||||||
goto free;
|
goto free;
|
||||||
|
@ -1202,11 +1178,11 @@ ApcKernelRoutine(_In_ PRKAPC Apc,
|
||||||
report->kthread_address = (UINT64)KeGetCurrentThread();
|
report->kthread_address = (UINT64)KeGetCurrentThread();
|
||||||
report->invalid_rip = stack_frame;
|
report->invalid_rip = stack_frame;
|
||||||
|
|
||||||
RtlCopyMemory(&report->driver,
|
if (!NT_SUCCESS(IrpQueueCompleteIrp(report, sizeof(APC_STACKWALK_REPORT))))
|
||||||
(UINT64)stack_frame - 0x500,
|
{
|
||||||
APC_STACKWALK_BUFFER_SIZE);
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
|
continue;
|
||||||
InsertReportToQueue(report);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1486,7 +1462,7 @@ ValidateDpcCapturedStack(_In_ PSYSTEM_MODULES Modules, _In_ PDPC_CONTEXT Context
|
||||||
{
|
{
|
||||||
report = ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
report = ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||||
sizeof(DPC_STACKWALK_REPORT),
|
sizeof(DPC_STACKWALK_REPORT),
|
||||||
POOL_TAG_DPC);
|
REPORT_POOL_TAG);
|
||||||
|
|
||||||
if (!report)
|
if (!report)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1495,11 +1471,16 @@ ValidateDpcCapturedStack(_In_ PSYSTEM_MODULES Modules, _In_ PDPC_CONTEXT Context
|
||||||
report->kthread_address = PsGetCurrentThread();
|
report->kthread_address = PsGetCurrentThread();
|
||||||
report->invalid_rip = Context[core].stack_frame[frame];
|
report->invalid_rip = Context[core].stack_frame[frame];
|
||||||
|
|
||||||
//RtlCopyMemory(report->driver,
|
// RtlCopyMemory(report->driver,
|
||||||
// (UINT64)Context[core].stack_frame[frame] - 0x50,
|
// (UINT64)Context[core].stack_frame[frame] - 0x50,
|
||||||
// APC_STACKWALK_BUFFER_SIZE);
|
// APC_STACKWALK_BUFFER_SIZE);
|
||||||
|
|
||||||
InsertReportToQueue(report);
|
if (!NT_SUCCESS(
|
||||||
|
IrpQueueCompleteIrp(report, sizeof(DPC_STACKWALK_REPORT))))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1806,7 +1787,7 @@ VOID
|
||||||
ReportDataTableInvalidRoutine(_In_ TABLE_ID TableId, _In_ UINT64 Address)
|
ReportDataTableInvalidRoutine(_In_ TABLE_ID TableId, _In_ UINT64 Address)
|
||||||
{
|
{
|
||||||
PDATA_TABLE_ROUTINE_REPORT report = ImpExAllocatePool2(
|
PDATA_TABLE_ROUTINE_REPORT report = ImpExAllocatePool2(
|
||||||
POOL_FLAG_NON_PAGED, sizeof(DATA_TABLE_ROUTINE_REPORT), POOL_TAG_INTEGRITY);
|
POOL_FLAG_NON_PAGED, sizeof(DATA_TABLE_ROUTINE_REPORT), REPORT_POOL_TAG);
|
||||||
|
|
||||||
if (!report)
|
if (!report)
|
||||||
return;
|
return;
|
||||||
|
@ -1819,7 +1800,8 @@ ReportDataTableInvalidRoutine(_In_ TABLE_ID TableId, _In_ UINT64 Address)
|
||||||
report->id = REPORT_DATA_TABLE_ROUTINE;
|
report->id = REPORT_DATA_TABLE_ROUTINE;
|
||||||
RtlCopyMemory(report->routine, Address, DATA_TABLE_ROUTINE_BUF_SIZE);
|
RtlCopyMemory(report->routine, Address, DATA_TABLE_ROUTINE_BUF_SIZE);
|
||||||
|
|
||||||
InsertReportToQueue(report);
|
if (!NT_SUCCESS(IrpQueueCompleteIrp(report, sizeof(DATA_TABLE_ROUTINE_REPORT))))
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -7,62 +7,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
typedef enum _TABLE_ID
|
|
||||||
{
|
|
||||||
HalDispatch = 0,
|
|
||||||
HalPrivateDispatch
|
|
||||||
} TABLE_ID;
|
|
||||||
|
|
||||||
#define DATA_TABLE_ROUTINE_BUF_SIZE 256
|
|
||||||
|
|
||||||
typedef struct _DATA_TABLE_ROUTINE_REPORT
|
|
||||||
{
|
|
||||||
UINT32 report_code;
|
|
||||||
TABLE_ID id;
|
|
||||||
UINT64 address;
|
|
||||||
CHAR routine[DATA_TABLE_ROUTINE_BUF_SIZE];
|
|
||||||
|
|
||||||
} DATA_TABLE_ROUTINE_REPORT, *PDATA_TABLE_ROUTINE_REPORT;
|
|
||||||
|
|
||||||
typedef struct _NMI_CALLBACK_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT were_nmis_disabled;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
|
|
||||||
} NMI_CALLBACK_FAILURE, *PNMI_CALLBACK_FAILURE;
|
|
||||||
|
|
||||||
#define APC_STACKWALK_BUFFER_SIZE 0x50
|
|
||||||
|
|
||||||
typedef struct _DPC_STACKWALK_REPORT
|
|
||||||
{
|
|
||||||
UINT32 report_code;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
|
|
||||||
|
|
||||||
} DPC_STACKWALK_REPORT, *PDPC_STACKWALK_REPORT;
|
|
||||||
|
|
||||||
typedef struct _MODULE_VALIDATION_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT report_type;
|
|
||||||
UINT64 driver_base_address;
|
|
||||||
UINT64 driver_size;
|
|
||||||
CHAR driver_name[128];
|
|
||||||
|
|
||||||
} MODULE_VALIDATION_FAILURE, *PMODULE_VALIDATION_FAILURE;
|
|
||||||
|
|
||||||
typedef struct _APC_STACKWALK_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
|
|
||||||
|
|
||||||
} APC_STACKWALK_REPORT, *PAPC_STACKWALK_REPORT;
|
|
||||||
|
|
||||||
typedef struct _APC_OPERATION_ID
|
typedef struct _APC_OPERATION_ID
|
||||||
{
|
{
|
||||||
int operation_id;
|
int operation_id;
|
||||||
|
@ -99,7 +43,7 @@ NTSTATUS
|
||||||
GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation);
|
GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
HandleValidateDriversIOCTL(_Inout_ PIRP Irp);
|
HandleValidateDriversIOCTL();
|
||||||
|
|
||||||
PRTL_MODULE_EXTENDED_INFO
|
PRTL_MODULE_EXTENDED_INFO
|
||||||
FindSystemModuleByName(_In_ LPCSTR ModuleName, _In_ PSYSTEM_MODULES SystemModules);
|
FindSystemModuleByName(_In_ LPCSTR ModuleName, _In_ PSYSTEM_MODULES SystemModules);
|
||||||
|
|
|
@ -701,14 +701,19 @@ FindUnlinkedProcesses()
|
||||||
POOL_FLAG_PAGED, sizeof(INVALID_PROCESS_ALLOCATION_REPORT), REPORT_POOL_TAG);
|
POOL_FLAG_PAGED, sizeof(INVALID_PROCESS_ALLOCATION_REPORT), REPORT_POOL_TAG);
|
||||||
|
|
||||||
if (!report_buffer)
|
if (!report_buffer)
|
||||||
goto end;
|
continue;
|
||||||
|
|
||||||
report_buffer->report_code = REPORT_INVALID_PROCESS_ALLOCATION;
|
report_buffer->report_code = REPORT_INVALID_PROCESS_ALLOCATION;
|
||||||
|
|
||||||
RtlCopyMemory(
|
RtlCopyMemory(
|
||||||
report_buffer->process, allocation, REPORT_INVALID_PROCESS_BUFFER_SIZE);
|
report_buffer->process, allocation, REPORT_INVALID_PROCESS_BUFFER_SIZE);
|
||||||
|
|
||||||
InsertReportToQueue(report_buffer);
|
if (!NT_SUCCESS(IrpQueueCompleteIrp(report_buffer,
|
||||||
|
sizeof(INVALID_PROCESS_ALLOCATION_REPORT))))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
|
@ -4,15 +4,6 @@
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 4096
|
|
||||||
|
|
||||||
typedef struct _INVALID_PROCESS_ALLOCATION_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
CHAR process[REPORT_INVALID_PROCESS_BUFFER_SIZE];
|
|
||||||
|
|
||||||
} INVALID_PROCESS_ALLOCATION_REPORT, *PINVALID_PROCESS_ALLOCATION_REPORT;
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FindUnlinkedProcesses();
|
FindUnlinkedProcesses();
|
||||||
|
|
||||||
|
|
207
driver/queue.c
207
driver/queue.c
|
@ -7,24 +7,10 @@
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "ioctl.h"
|
#include "io.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "imports.h"
|
#include "imports.h"
|
||||||
|
|
||||||
VOID
|
|
||||||
InitialiseGlobalReportQueue()
|
|
||||||
{
|
|
||||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
|
||||||
|
|
||||||
queue->head.start = NULL;
|
|
||||||
queue->head.end = NULL;
|
|
||||||
queue->head.entries = 0;
|
|
||||||
queue->is_driver_unloading = FALSE;
|
|
||||||
|
|
||||||
ImpKeInitializeGuardedMutex(&queue->head.lock);
|
|
||||||
ImpKeInitializeGuardedMutex(&queue->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
QueuePush(_Inout_ PQUEUE_HEAD Head, _In_ PVOID Data)
|
QueuePush(_Inout_ PQUEUE_HEAD Head, _In_ PVOID Data)
|
||||||
{
|
{
|
||||||
|
@ -75,195 +61,4 @@ QueuePop(_Inout_ PQUEUE_HEAD Head)
|
||||||
end:
|
end:
|
||||||
ImpKeReleaseGuardedMutex(&Head->lock);
|
ImpKeReleaseGuardedMutex(&Head->lock);
|
||||||
return data;
|
return data;
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
InsertReportToQueue(_In_ PVOID Report)
|
|
||||||
{
|
|
||||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
|
||||||
|
|
||||||
if (InterlockedExchange(&queue->is_driver_unloading, queue->is_driver_unloading))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
|
||||||
QueuePush(&queue->head, Report);
|
|
||||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FreeGlobalReportQueueObjects()
|
|
||||||
{
|
|
||||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
|
||||||
|
|
||||||
InterlockedExchange(&queue->is_driver_unloading, TRUE);
|
|
||||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
|
||||||
|
|
||||||
PVOID report = QueuePop(&queue->head);
|
|
||||||
|
|
||||||
while (report)
|
|
||||||
{
|
|
||||||
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
|
|
||||||
report = QueuePop(&queue->head);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function handles sending all the pending reports in the global report
|
|
||||||
* queue to the usermode application. This function is called periodically by the
|
|
||||||
* usermode application. The reason I have implemented this is because as this application
|
|
||||||
* expanded, it became apparent that some of the driver functions will generate multiple
|
|
||||||
* reports as a result of a single usermode request and hence it makes dealing with
|
|
||||||
* reports generated from ObRegisterCallbacks for example much easier.
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp)
|
|
||||||
{
|
|
||||||
INT count = 0;
|
|
||||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
||||||
PVOID report = NULL;
|
|
||||||
SIZE_T total_size = 0;
|
|
||||||
PVOID report_buffer = NULL;
|
|
||||||
ULONG report_buffer_size = 0;
|
|
||||||
PREPORT_HEADER report_header = NULL;
|
|
||||||
GLOBAL_REPORT_QUEUE_HEADER header = {0};
|
|
||||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
|
||||||
|
|
||||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
|
||||||
|
|
||||||
report_buffer_size = sizeof(INVALID_PROCESS_ALLOCATION_REPORT) * MAX_REPORTS_PER_IRP +
|
|
||||||
sizeof(GLOBAL_REPORT_QUEUE_HEADER);
|
|
||||||
|
|
||||||
status = ValidateIrpOutputBuffer(Irp, report_buffer_size);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x", status);
|
|
||||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
report_buffer = ImpExAllocatePool2(
|
|
||||||
POOL_FLAG_NON_PAGED, report_buffer_size, REPORT_QUEUE_TEMP_BUFFER_TAG);
|
|
||||||
|
|
||||||
if (!report_buffer)
|
|
||||||
{
|
|
||||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
|
||||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
|
||||||
}
|
|
||||||
|
|
||||||
report = QueuePop(&queue->head);
|
|
||||||
|
|
||||||
if (report == NULL)
|
|
||||||
{
|
|
||||||
DEBUG_VERBOSE("Callback report queue is empty. No reports to be sent to usermode.");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (report != NULL)
|
|
||||||
{
|
|
||||||
if (count >= MAX_REPORTS_PER_IRP)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
report_header = (PREPORT_HEADER)report;
|
|
||||||
|
|
||||||
switch (report_header->report_id)
|
|
||||||
{
|
|
||||||
case REPORT_ILLEGAL_HANDLE_OPERATION:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(OPEN_HANDLE_FAILURE_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(OPEN_HANDLE_FAILURE_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_ILLEGAL_ATTACH_PROCESS:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(ATTACH_PROCESS_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(ATTACH_PROCESS_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_INVALID_PROCESS_ALLOCATION:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(INVALID_PROCESS_ALLOCATION_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(INVALID_PROCESS_ALLOCATION_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_APC_STACKWALK:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(APC_STACKWALK_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(APC_STACKWALK_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_HIDDEN_SYSTEM_THREAD:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(HIDDEN_SYSTEM_THREAD_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_DPC_STACKWALK:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(DPC_STACKWALK_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(DPC_STACKWALK_REPORT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPORT_DATA_TABLE_ROUTINE:
|
|
||||||
|
|
||||||
RtlCopyMemory((UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) +
|
|
||||||
total_size,
|
|
||||||
report,
|
|
||||||
sizeof(DATA_TABLE_ROUTINE_REPORT));
|
|
||||||
|
|
||||||
total_size += sizeof(DATA_TABLE_ROUTINE_REPORT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* QueuePop frees the node, but we still need to free the returned data */
|
|
||||||
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
|
|
||||||
|
|
||||||
report = QueuePop(&queue->head);
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
|
|
||||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size;
|
|
||||||
header.count = count;
|
|
||||||
|
|
||||||
RtlCopyMemory(report_buffer, &header, sizeof(GLOBAL_REPORT_QUEUE_HEADER));
|
|
||||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
|
||||||
report_buffer,
|
|
||||||
sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size);
|
|
||||||
|
|
||||||
if (report_buffer)
|
|
||||||
ImpExFreePoolWithTag(report_buffer, REPORT_QUEUE_TEMP_BUFFER_TAG);
|
|
||||||
|
|
||||||
DEBUG_VERBOSE("All reports moved into the IRP, sending to usermode.");
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
|
@ -56,19 +56,4 @@ QueuePush(_Inout_ PQUEUE_HEAD Head, _In_ PVOID Data);
|
||||||
PVOID
|
PVOID
|
||||||
QueuePop(_Inout_ PQUEUE_HEAD Head);
|
QueuePop(_Inout_ PQUEUE_HEAD Head);
|
||||||
|
|
||||||
VOID
|
|
||||||
InitialiseGlobalReportQueue();
|
|
||||||
|
|
||||||
VOID
|
|
||||||
InsertReportToQueue(_In_ PVOID Report);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FreeGlobalReportQueueObjects();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -89,7 +89,7 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't care if a thread owned by our protected process is attached
|
* We don't care if a thread owned by our protected process is attached
|
||||||
*
|
*
|
||||||
* todo: this is filterless and will just report anything, need to have a look into what
|
* todo: this is filterless and will just report anything, need to have a look into what
|
||||||
* processes actually attach to real games
|
* processes actually attach to real games
|
||||||
*/
|
*/
|
||||||
|
@ -109,7 +109,8 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
|
||||||
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
||||||
report->thread_address = ThreadListEntry->thread;
|
report->thread_address = ThreadListEntry->thread;
|
||||||
|
|
||||||
InsertReportToQueue(report);
|
if (!NT_SUCCESS(IrpQueueCompleteIrp(report, sizeof(ATTACH_PROCESS_REPORT))))
|
||||||
|
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,34 +6,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
|
|
||||||
typedef struct _HIDDEN_SYSTEM_THREAD_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT found_in_kthreadlist;
|
|
||||||
INT found_in_pspcidtable;
|
|
||||||
UINT64 thread_address;
|
|
||||||
LONG thread_id;
|
|
||||||
CHAR thread[4096];
|
|
||||||
|
|
||||||
} HIDDEN_SYSTEM_THREAD_REPORT, *PHIDDEN_SYSTEM_THREAD_REPORT;
|
|
||||||
|
|
||||||
typedef struct _ATTACH_PROCESS_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT32 thread_id;
|
|
||||||
UINT64 thread_address;
|
|
||||||
|
|
||||||
} ATTACH_PROCESS_REPORT, *PATTACH_PROCESS_REPORT;
|
|
||||||
|
|
||||||
typedef struct _KPRCB_THREAD_VALIDATION_CTX
|
|
||||||
{
|
|
||||||
UINT64 thread;
|
|
||||||
BOOLEAN thread_found_in_pspcidtable;
|
|
||||||
// BOOLEAN thread_found_in_kthreadlist;
|
|
||||||
BOOLEAN finished;
|
|
||||||
|
|
||||||
} KPRCB_THREAD_VALIDATION_CTX, *PKPRCB_THREAD_VALIDATION_CTX;
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
ValidateThreadsPspCidTableEntry(_In_ PETHREAD Thread);
|
ValidateThreadsPspCidTableEntry(_In_ PETHREAD Thread);
|
||||||
|
|
||||||
|
|
141
driver/types/types.h
Normal file
141
driver/types/types.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
#ifndef TYPES_H
|
||||||
|
#define TYPES_H
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#define REPORT_NMI_CALLBACK_FAILURE 50
|
||||||
|
#define REPORT_MODULE_VALIDATION_FAILURE 60
|
||||||
|
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
|
||||||
|
#define REPORT_INVALID_PROCESS_ALLOCATION 80
|
||||||
|
#define REPORT_HIDDEN_SYSTEM_THREAD 90
|
||||||
|
#define REPORT_ILLEGAL_ATTACH_PROCESS 100
|
||||||
|
#define REPORT_APC_STACKWALK 110
|
||||||
|
#define REPORT_DPC_STACKWALK 120
|
||||||
|
#define REPORT_DATA_TABLE_ROUTINE 130
|
||||||
|
#define REPORT_INVALID_PROCESS_MODULE 140
|
||||||
|
|
||||||
|
typedef enum _TABLE_ID
|
||||||
|
{
|
||||||
|
HalDispatch = 0,
|
||||||
|
HalPrivateDispatch
|
||||||
|
} TABLE_ID;
|
||||||
|
|
||||||
|
typedef struct _HYPERVISOR_DETECTION_REPORT
|
||||||
|
{
|
||||||
|
INT aperf_msr_timing_check;
|
||||||
|
INT invd_emulation_check;
|
||||||
|
|
||||||
|
} HYPERVISOR_DETECTION_REPORT, *PHYPERVISOR_DETECTION_REPORT;
|
||||||
|
|
||||||
|
#define APC_STACKWALK_BUFFER_SIZE 500
|
||||||
|
|
||||||
|
typedef struct _APC_STACKWALK_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
UINT64 kthread_address;
|
||||||
|
UINT64 invalid_rip;
|
||||||
|
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
|
||||||
|
|
||||||
|
} APC_STACKWALK_REPORT, *PAPC_STACKWALK_REPORT;
|
||||||
|
|
||||||
|
typedef struct _DPC_STACKWALK_REPORT
|
||||||
|
{
|
||||||
|
UINT32 report_code;
|
||||||
|
UINT64 kthread_address;
|
||||||
|
UINT64 invalid_rip;
|
||||||
|
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
|
||||||
|
|
||||||
|
} DPC_STACKWALK_REPORT, *PDPC_STACKWALK_REPORT;
|
||||||
|
|
||||||
|
typedef struct _MODULE_VALIDATION_FAILURE
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
INT report_type;
|
||||||
|
UINT64 driver_base_address;
|
||||||
|
UINT64 driver_size;
|
||||||
|
CHAR driver_name[128];
|
||||||
|
|
||||||
|
} MODULE_VALIDATION_FAILURE, *PMODULE_VALIDATION_FAILURE;
|
||||||
|
|
||||||
|
#define DATA_TABLE_ROUTINE_BUF_SIZE 256
|
||||||
|
|
||||||
|
typedef struct _DATA_TABLE_ROUTINE_REPORT
|
||||||
|
{
|
||||||
|
UINT32 report_code;
|
||||||
|
TABLE_ID id;
|
||||||
|
UINT64 address;
|
||||||
|
CHAR routine[DATA_TABLE_ROUTINE_BUF_SIZE];
|
||||||
|
|
||||||
|
} DATA_TABLE_ROUTINE_REPORT, *PDATA_TABLE_ROUTINE_REPORT;
|
||||||
|
|
||||||
|
typedef struct _NMI_CALLBACK_FAILURE
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
INT were_nmis_disabled;
|
||||||
|
UINT64 kthread_address;
|
||||||
|
UINT64 invalid_rip;
|
||||||
|
|
||||||
|
} NMI_CALLBACK_FAILURE, *PNMI_CALLBACK_FAILURE;
|
||||||
|
|
||||||
|
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 500
|
||||||
|
|
||||||
|
typedef struct _INVALID_PROCESS_ALLOCATION_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
CHAR process[REPORT_INVALID_PROCESS_BUFFER_SIZE];
|
||||||
|
|
||||||
|
} INVALID_PROCESS_ALLOCATION_REPORT, *PINVALID_PROCESS_ALLOCATION_REPORT;
|
||||||
|
|
||||||
|
typedef struct _HIDDEN_SYSTEM_THREAD_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
INT found_in_kthreadlist;
|
||||||
|
INT found_in_pspcidtable;
|
||||||
|
UINT64 thread_address;
|
||||||
|
LONG thread_id;
|
||||||
|
CHAR thread[500];
|
||||||
|
|
||||||
|
} HIDDEN_SYSTEM_THREAD_REPORT, *PHIDDEN_SYSTEM_THREAD_REPORT;
|
||||||
|
|
||||||
|
typedef struct _ATTACH_PROCESS_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
UINT32 thread_id;
|
||||||
|
UINT64 thread_address;
|
||||||
|
|
||||||
|
} ATTACH_PROCESS_REPORT, *PATTACH_PROCESS_REPORT;
|
||||||
|
|
||||||
|
typedef struct _KPRCB_THREAD_VALIDATION_CTX
|
||||||
|
{
|
||||||
|
UINT64 thread;
|
||||||
|
BOOLEAN thread_found_in_pspcidtable;
|
||||||
|
// BOOLEAN thread_found_in_kthreadlist;
|
||||||
|
BOOLEAN finished;
|
||||||
|
|
||||||
|
} KPRCB_THREAD_VALIDATION_CTX, *PKPRCB_THREAD_VALIDATION_CTX;
|
||||||
|
|
||||||
|
#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64
|
||||||
|
|
||||||
|
typedef struct _OPEN_HANDLE_FAILURE_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
INT is_kernel_handle;
|
||||||
|
LONG process_id;
|
||||||
|
LONG thread_id;
|
||||||
|
LONG access;
|
||||||
|
CHAR process_name[HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH];
|
||||||
|
|
||||||
|
} OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT;
|
||||||
|
|
||||||
|
#define MODULE_PATH_LEN 256
|
||||||
|
|
||||||
|
typedef struct _PROCESS_MODULE_VALIDATION_REPORT
|
||||||
|
{
|
||||||
|
INT report_code;
|
||||||
|
UINT64 image_base;
|
||||||
|
UINT32 image_size;
|
||||||
|
WCHAR module_path[MODULE_PATH_LEN];
|
||||||
|
|
||||||
|
} PROCESS_MODULE_VALIDATION_REPORT, *PPROCESS_MODULE_VALIDATION_REPORT;
|
||||||
|
|
||||||
|
#endif
|
29
module/client/message_queue.cpp
Normal file
29
module/client/message_queue.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "message_queue.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#define TEST_STEAM_64_ID 123456789;
|
||||||
|
|
||||||
|
client::message_queue::message_queue(LPTSTR PipeName) {
|
||||||
|
#if NO_SERVER
|
||||||
|
LOG_INFO("No_Server build used. Not opening named pipe.");
|
||||||
|
#else
|
||||||
|
this->pipe_interface = std::make_unique<client::pipe>(PipeName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::message_queue::dequeue_message(void *Buffer, size_t Size) {
|
||||||
|
#if NO_SERVER
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
this->pipe_interface->read_pipe(Buffer, Size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::message_queue::enqueue_message(void *Buffer, size_t Size) {
|
||||||
|
#if NO_SERVER
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
43
module/client/message_queue.h
Normal file
43
module/client/message_queue.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef REPORT_H
|
||||||
|
#define REPORT_H
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "../dispatcher/threadpool.h"
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include "pipe.h"
|
||||||
|
|
||||||
|
#define REPORT_BUFFER_SIZE 8192
|
||||||
|
#define SEND_BUFFER_SIZE 8192
|
||||||
|
|
||||||
|
#define MAX_SIGNATURE_SIZE 256
|
||||||
|
|
||||||
|
#define MESSAGE_TYPE_CLIENT_REPORT 1
|
||||||
|
#define MESSAGE_TYPE_CLIENT_SEND 2
|
||||||
|
#define MESSAGE_TYPE_CLIENT_REQUEST 3
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
class message_queue {
|
||||||
|
struct MESSAGE_PACKET_HEADER {
|
||||||
|
int message_type;
|
||||||
|
int request_id;
|
||||||
|
unsigned __int64 steam64_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<client::pipe> pipe_interface;
|
||||||
|
std::mutex lock;
|
||||||
|
|
||||||
|
byte report_buffer[REPORT_BUFFER_SIZE];
|
||||||
|
|
||||||
|
public:
|
||||||
|
message_queue(LPTSTR PipeName);
|
||||||
|
void enqueue_message(void *Buffer, size_t Size);
|
||||||
|
void dequeue_message(void *Buffer, size_t Size);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
|
||||||
|
#endif
|
40
module/client/pipe.cpp
Normal file
40
module/client/pipe.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "pipe.h"
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
client::pipe::pipe(LPTSTR PipeName) {
|
||||||
|
this->pipe_name = PipeName;
|
||||||
|
this->pipe_handle =
|
||||||
|
CreateFile(this->pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
|
||||||
|
if (this->pipe_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
LOG_ERROR("CreateFile failed with status 0x%x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::pipe::write_pipe(PVOID Buffer, SIZE_T Size) {
|
||||||
|
DWORD bytes_written = 0;
|
||||||
|
|
||||||
|
WriteFile(this->pipe_handle, Buffer, Size, &bytes_written, NULL);
|
||||||
|
|
||||||
|
if (bytes_written == 0) {
|
||||||
|
LOG_ERROR("WriteFile failed with status code 0x%x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::pipe::read_pipe(PVOID Buffer, SIZE_T Size) {
|
||||||
|
BOOL status = FALSE;
|
||||||
|
DWORD bytes_read = 0;
|
||||||
|
|
||||||
|
status = ReadFile(this->pipe_handle, Buffer, Size, &bytes_read, NULL);
|
||||||
|
|
||||||
|
if (status == NULL) {
|
||||||
|
LOG_ERROR("ReadFile failed with status code 0x%x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
51
module/client/pipe.h
Normal file
51
module/client/pipe.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#define MESSAGE_TYPE_CLIENT_REPORT 1
|
||||||
|
#define MESSAGE_TYPE_CLIENT_SEND 2
|
||||||
|
#define MESSAGE_TYPE_CLIENT_REQUEST 3
|
||||||
|
|
||||||
|
#define MOTHERBOARD_SERIAL_CODE_LENGTH 64
|
||||||
|
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
class pipe {
|
||||||
|
HANDLE pipe_handle;
|
||||||
|
LPTSTR pipe_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
pipe(LPTSTR PipeName);
|
||||||
|
|
||||||
|
void write_pipe(PVOID Buffer, SIZE_T Size);
|
||||||
|
void read_pipe(PVOID Buffer, SIZE_T Size);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace headers {
|
||||||
|
typedef enum _ENVIRONMENT_TYPE {
|
||||||
|
NativeWindows = 0,
|
||||||
|
Vmware,
|
||||||
|
VirtualBox
|
||||||
|
|
||||||
|
} ENVIRONMENT_TYPE;
|
||||||
|
|
||||||
|
typedef enum _PROCESSOR_TYPE {
|
||||||
|
Unknown = 0,
|
||||||
|
GenuineIntel,
|
||||||
|
AuthenticAmd
|
||||||
|
|
||||||
|
} PROCESSOR_TYPE;
|
||||||
|
|
||||||
|
#define VENDOR_STRING_MAX_LENGTH 256
|
||||||
|
struct SYSTEM_INFORMATION {
|
||||||
|
CHAR motherboard_serial[MOTHERBOARD_SERIAL_CODE_LENGTH];
|
||||||
|
CHAR drive_0_serial[DEVICE_DRIVE_0_SERIAL_CODE_LENGTH];
|
||||||
|
CHAR vendor[VENDOR_STRING_MAX_LENGTH];
|
||||||
|
BOOLEAN virtualised_environment;
|
||||||
|
ENVIRONMENT_TYPE environment;
|
||||||
|
PROCESSOR_TYPE processor;
|
||||||
|
RTL_OSVERSIONINFOW os_information;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace headers
|
||||||
|
} // namespace client
|
|
@ -1,11 +1,11 @@
|
||||||
#ifndef COMMON_H
|
#pragma once
|
||||||
#define COMMON_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define LOG_INFO(fmt, ...) printf("[+] " fmt "\n", ##__VA_ARGS__)
|
#define LOG_INFO(fmt, ...) printf("[+] " fmt "\n", ##__VA_ARGS__)
|
||||||
#define LOG_ERROR(fmt, ...) printf("[-] " fmt "\n", ##__VA_ARGS__)
|
#define LOG_ERROR(fmt, ...) printf("[-] " fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
62
module/dispatcher/dispatcher.cpp
Normal file
62
module/dispatcher/dispatcher.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "dispatcher.h"
|
||||||
|
|
||||||
|
#include "../client/message_queue.h"
|
||||||
|
#include "../helper.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
dispatcher::dispatcher::dispatcher(LPCWSTR driver_name,
|
||||||
|
client::message_queue &message_queue)
|
||||||
|
: thread_pool(DISPATCHER_THREAD_COUNT),
|
||||||
|
k_interface(driver_name, message_queue) {}
|
||||||
|
|
||||||
|
void dispatcher::dispatcher::run() {
|
||||||
|
helper::generate_rand_seed();
|
||||||
|
thread_pool.queue_job([this]() { k_interface.run_completion_port(); });
|
||||||
|
while (true) {
|
||||||
|
this->issue_kernel_job();
|
||||||
|
helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatcher::dispatcher::issue_kernel_job() {
|
||||||
|
switch (helper::generate_rand_int(KERNEL_DISPATCH_FUNCTION_COUNT)) {
|
||||||
|
case 0:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.enumerate_handle_tables(); });
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.perform_integrity_check(); });
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
thread_pool.queue_job(
|
||||||
|
[this]() { k_interface.scan_for_unlinked_processes(); });
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
thread_pool.queue_job(
|
||||||
|
[this]() { k_interface.verify_process_module_executable_regions(); });
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
thread_pool.queue_job(
|
||||||
|
[this]() { k_interface.validate_system_driver_objects(); });
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.run_nmi_callbacks(); });
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
thread_pool.queue_job(
|
||||||
|
[this]() { k_interface.scan_for_attached_threads(); });
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.initiate_apc_stackwalk(); });
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.scan_for_ept_hooks(); });
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.perform_dpc_stackwalk(); });
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
thread_pool.queue_job([this]() { k_interface.validate_system_modules(); });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
23
module/dispatcher/dispatcher.h
Normal file
23
module/dispatcher/dispatcher.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "threadpool.h"
|
||||||
|
|
||||||
|
#include "../kernel_interface/kernel_interface.h"
|
||||||
|
|
||||||
|
namespace dispatcher {
|
||||||
|
|
||||||
|
static const int DISPATCH_LOOP_SLEEP_TIME = 10;
|
||||||
|
static const int KERNEL_DISPATCH_FUNCTION_COUNT = 11;
|
||||||
|
static const int DISPATCHER_THREAD_COUNT = 4;
|
||||||
|
|
||||||
|
class dispatcher {
|
||||||
|
thread_pool thread_pool;
|
||||||
|
kernel_interface::kernel_interface k_interface;
|
||||||
|
|
||||||
|
void issue_kernel_job();
|
||||||
|
|
||||||
|
public:
|
||||||
|
dispatcher(LPCWSTR driver_name, client::message_queue &queue);
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
} // namespace dispatcher
|
92
module/dispatcher/threadpool.cpp
Normal file
92
module/dispatcher/threadpool.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include "threadpool.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the idle loop each thread will be running until a job is ready
|
||||||
|
* for execution
|
||||||
|
*/
|
||||||
|
void dispatcher::thread_pool::wait_for_task() {
|
||||||
|
while (true) {
|
||||||
|
std::function<void()> job;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is equivalent to :
|
||||||
|
*
|
||||||
|
* while (!this->jobs.empty() || should_terminate)
|
||||||
|
* mutex_condition.wait(lock);
|
||||||
|
*
|
||||||
|
* we are essentially waiting for a job to be queued up or the terminate
|
||||||
|
*flag to be set. Another piece of useful information is that the
|
||||||
|
*predicate is checked under the lock as the precondition for .wait() is
|
||||||
|
*that the calling thread owns the lock.
|
||||||
|
*
|
||||||
|
* Now, when .wait() is run, the lock is unlocked the the executing thread
|
||||||
|
*is blocked and is added to a list of threads current waiting on the
|
||||||
|
*predicate. In our case whether there are new jobs available for the
|
||||||
|
*terminate flag is set. Once the condition variables are true i.e there
|
||||||
|
*are new jobs or we are terminating, the lock is reacquired by the thread
|
||||||
|
*and the thread is unblocked.
|
||||||
|
*/
|
||||||
|
mutex_condition.wait(lock, [this] {
|
||||||
|
return !this->jobs.empty() || this->should_terminate;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this->should_terminate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* get the first job in the queue*/
|
||||||
|
job = jobs.front();
|
||||||
|
jobs.pop();
|
||||||
|
}
|
||||||
|
/* run the job */
|
||||||
|
job();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatcher::thread_pool::thread_pool(int thread_count) {
|
||||||
|
this->thread_count = thread_count;
|
||||||
|
this->should_terminate = false;
|
||||||
|
|
||||||
|
/* Initiate our threads and store them in our threads vector */
|
||||||
|
for (int i = 0; i < this->thread_count; i++) {
|
||||||
|
this->threads.emplace_back(std::thread(&thread_pool::wait_for_task, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatcher::thread_pool::queue_job(const std::function<void()> &job) {
|
||||||
|
/* push a job into our job queue safely by holding our queue lock */
|
||||||
|
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
||||||
|
|
||||||
|
this->jobs.push(job);
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
mutex_condition.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatcher::thread_pool::terminate() {
|
||||||
|
/* safely set our termination flag to true */
|
||||||
|
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
||||||
|
should_terminate = true;
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
/* unlock all threads waiting on our condition */
|
||||||
|
mutex_condition.notify_all();
|
||||||
|
|
||||||
|
/* join the threads and clear our threads vector */
|
||||||
|
for (std::thread &thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
threads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dispatcher::thread_pool::busy_wait() {
|
||||||
|
/* allows us to wait for when the job queue is empty allowing us to safely
|
||||||
|
* call the destructor */
|
||||||
|
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
||||||
|
|
||||||
|
bool pool_busy = !jobs.empty();
|
||||||
|
this->queue_mutex.unlock();
|
||||||
|
|
||||||
|
return pool_busy;
|
||||||
|
}
|
30
module/dispatcher/threadpool.h
Normal file
30
module/dispatcher/threadpool.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dispatcher {
|
||||||
|
/*
|
||||||
|
* This ThreadPool class is a simple threadpool implementation that will allow
|
||||||
|
* us to delegate jobs to a set number of threads without the constant need to
|
||||||
|
* close and open new threads.
|
||||||
|
*/
|
||||||
|
class thread_pool {
|
||||||
|
int thread_count;
|
||||||
|
bool should_terminate;
|
||||||
|
std::mutex queue_mutex;
|
||||||
|
std::condition_variable mutex_condition;
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
std::queue<std::function<void()>> jobs;
|
||||||
|
|
||||||
|
void wait_for_task();
|
||||||
|
|
||||||
|
public:
|
||||||
|
thread_pool(int thread_count);
|
||||||
|
void queue_job(const std::function<void()> &job);
|
||||||
|
void terminate();
|
||||||
|
bool busy_wait();
|
||||||
|
};
|
||||||
|
} // namespace dispatcher
|
169
module/helper.cpp
Normal file
169
module/helper.cpp
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
void helper::generate_rand_seed() { srand(time(nullptr)); }
|
||||||
|
|
||||||
|
int helper::generate_rand_int(int max) { return rand() % max; }
|
||||||
|
|
||||||
|
void helper::sleep_thread(int seconds) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
int helper::get_report_id_from_buffer(void *buffer) {
|
||||||
|
kernel_interface::report_header *header =
|
||||||
|
reinterpret_cast<kernel_interface::report_header *>(buffer);
|
||||||
|
return header->report_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_interface::report_id helper::get_kernel_report_type(void *buffer) {
|
||||||
|
switch (helper::get_report_id_from_buffer(buffer)) {
|
||||||
|
case kernel_interface::report_id::report_nmi_callback_failure:
|
||||||
|
return kernel_interface::report_id::report_nmi_callback_failure;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_module_validation_failure:
|
||||||
|
return kernel_interface::report_id::report_module_validation_failure;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_illegal_handle_operation:
|
||||||
|
return kernel_interface::report_id::report_illegal_handle_operation;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_invalid_process_allocation:
|
||||||
|
return kernel_interface::report_id::report_invalid_process_allocation;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_hidden_system_thread:
|
||||||
|
return kernel_interface::report_id::report_hidden_system_thread;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_illegal_attach_process:
|
||||||
|
return kernel_interface::report_id::report_illegal_attach_process;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_apc_stackwalk:
|
||||||
|
return kernel_interface::report_id::report_apc_stackwalk;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_dpc_stackwalk:
|
||||||
|
return kernel_interface::report_id::report_dpc_stackwalk;
|
||||||
|
|
||||||
|
case kernel_interface::report_id::report_data_table_routine:
|
||||||
|
return kernel_interface::report_id::report_data_table_routine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper::print_kernel_report(void *buffer) {
|
||||||
|
switch (get_kernel_report_type(buffer)) {
|
||||||
|
case kernel_interface::report_id::report_nmi_callback_failure: {
|
||||||
|
kernel_interface::nmi_callback_failure *r1 =
|
||||||
|
reinterpret_cast<kernel_interface::nmi_callback_failure *>(buffer);
|
||||||
|
LOG_INFO("report type: nmi_callback_failure");
|
||||||
|
LOG_INFO("report code: %lx", r1->report_code);
|
||||||
|
LOG_INFO("were_nmis_disabled: %lx", r1->were_nmis_disabled);
|
||||||
|
LOG_INFO("kthread_address: %llx", r1->kthread_address);
|
||||||
|
LOG_INFO("invalid_rip: %llx", r1->invalid_rip);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_invalid_process_allocation: {
|
||||||
|
kernel_interface::invalid_process_allocation_report *r2 =
|
||||||
|
reinterpret_cast<kernel_interface::invalid_process_allocation_report *>(
|
||||||
|
buffer);
|
||||||
|
LOG_INFO("report type: invalid_process_allocation_report");
|
||||||
|
LOG_INFO("report code: %d", r2->report_code);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_hidden_system_thread: {
|
||||||
|
kernel_interface::hidden_system_thread_report *r3 =
|
||||||
|
reinterpret_cast<kernel_interface::hidden_system_thread_report *>(
|
||||||
|
buffer);
|
||||||
|
LOG_INFO("report type: hidden_system_thread_report");
|
||||||
|
LOG_INFO("report code: %lx", r3->report_code);
|
||||||
|
LOG_INFO("found_in_kthreadlist: %lx", r3->found_in_kthreadlist);
|
||||||
|
LOG_INFO("found_in_pspcidtable: %lx", r3->found_in_pspcidtable);
|
||||||
|
LOG_INFO("thread_address: %llx", r3->thread_address);
|
||||||
|
LOG_INFO("thread_id: %lx", r3->thread_id);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_illegal_attach_process: {
|
||||||
|
kernel_interface::attach_process_report *r4 =
|
||||||
|
reinterpret_cast<kernel_interface::attach_process_report *>(buffer);
|
||||||
|
LOG_INFO("report type: attach_process_report");
|
||||||
|
LOG_INFO("report code: %lx", r4->report_code);
|
||||||
|
LOG_INFO("thread_id: %lx", r4->thread_id);
|
||||||
|
LOG_INFO("thread_address: %llx", r4->thread_address);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_illegal_handle_operation: {
|
||||||
|
kernel_interface::open_handle_failure_report *r5 =
|
||||||
|
reinterpret_cast<kernel_interface::open_handle_failure_report *>(
|
||||||
|
buffer);
|
||||||
|
LOG_INFO("report type: open_handle_failure_report");
|
||||||
|
LOG_INFO("report code: %lx", r5->report_code);
|
||||||
|
LOG_INFO("is_kernel_handle: %lx", r5->is_kernel_handle);
|
||||||
|
LOG_INFO("process_id: %lx", r5->process_id);
|
||||||
|
LOG_INFO("thread_id: %lx", r5->thread_id);
|
||||||
|
LOG_INFO("access: %lx", r5->access);
|
||||||
|
LOG_INFO("process_name: %s", r5->process_name);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_invalid_process_module: {
|
||||||
|
kernel_interface::process_module_validation_report *r6 =
|
||||||
|
reinterpret_cast<kernel_interface::process_module_validation_report *>(
|
||||||
|
buffer);
|
||||||
|
LOG_INFO("report type: process_module_validation_report");
|
||||||
|
LOG_INFO("report code: %d", r6->report_code);
|
||||||
|
LOG_INFO("image_base: %llx", r6->image_base);
|
||||||
|
LOG_INFO("image_size: %u", r6->image_size);
|
||||||
|
LOG_INFO("module_path: %ls", r6->module_path);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_apc_stackwalk: {
|
||||||
|
kernel_interface::apc_stackwalk_report *r7 =
|
||||||
|
reinterpret_cast<kernel_interface::apc_stackwalk_report *>(buffer);
|
||||||
|
LOG_INFO("report type: apc_stackwalk_report");
|
||||||
|
LOG_INFO("report code: %d", r7->report_code);
|
||||||
|
LOG_INFO("kthread_address: %llx", r7->kthread_address);
|
||||||
|
LOG_INFO("invalid_rip: %llx", r7->invalid_rip);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_dpc_stackwalk: {
|
||||||
|
kernel_interface::dpc_stackwalk_report *r8 =
|
||||||
|
reinterpret_cast<kernel_interface::dpc_stackwalk_report *>(buffer);
|
||||||
|
LOG_INFO("report type: dpc_stackwalk_report");
|
||||||
|
LOG_INFO("report code: %d", r8->report_code);
|
||||||
|
LOG_INFO("kthread_address: %llx", r8->kthread_address);
|
||||||
|
LOG_INFO("invalid_rip: %llx", r8->invalid_rip);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_data_table_routine: {
|
||||||
|
kernel_interface::data_table_routine_report *r9 =
|
||||||
|
reinterpret_cast<kernel_interface::data_table_routine_report *>(buffer);
|
||||||
|
LOG_INFO("report type: data_table_routine_report");
|
||||||
|
LOG_INFO("report code: %d", r9->report_code);
|
||||||
|
LOG_INFO("id: %d", r9->id);
|
||||||
|
LOG_INFO("address: %llx", r9->address);
|
||||||
|
LOG_INFO("routine: %s", r9->routine);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kernel_interface::report_id::report_module_validation_failure: {
|
||||||
|
kernel_interface::module_validation_failure *r10 =
|
||||||
|
reinterpret_cast<kernel_interface::module_validation_failure *>(buffer);
|
||||||
|
LOG_INFO("report type: module_validation_failure");
|
||||||
|
LOG_INFO("report code: %lx", r10->report_code);
|
||||||
|
LOG_INFO("report type: %lx", r10->report_type);
|
||||||
|
LOG_INFO("driver_base_address: %llx", r10->driver_base_address);
|
||||||
|
LOG_INFO("driver_size: %llx", r10->driver_size);
|
||||||
|
LOG_INFO("driver_name: %s", r10->driver_name);
|
||||||
|
LOG_INFO("********************************");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_INFO("Invalid report type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
12
module/helper.h
Normal file
12
module/helper.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kernel_interface/kernel_interface.h"
|
||||||
|
|
||||||
|
namespace helper {
|
||||||
|
void generate_rand_seed();
|
||||||
|
int generate_rand_int(int max);
|
||||||
|
void sleep_thread(int seconds);
|
||||||
|
kernel_interface::report_id get_kernel_report_type(void *buffer);
|
||||||
|
int get_report_id_from_buffer(void *buffer);
|
||||||
|
void print_kernel_report(void *buffer);
|
||||||
|
} // namespace helper
|
3
module/imports.cpp
Normal file
3
module/imports.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include "imports.h"
|
||||||
|
|
||||||
|
bool imports::initialise_imports() { return false; }
|
8
module/imports.h
Normal file
8
module/imports.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace imports
|
||||||
|
{
|
||||||
|
bool initialise_imports();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
290
module/kernel_interface/kernel_interface.cpp
Normal file
290
module/kernel_interface/kernel_interface.cpp
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
#include "kernel_interface.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../helper.h"
|
||||||
|
|
||||||
|
#include <TlHelp32.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
|
||||||
|
typedef BOOLEAN(NTAPI *RtlDosPathNameToNtPathName_U)(PCWSTR DosPathName,
|
||||||
|
PUNICODE_STRING NtPathName,
|
||||||
|
PCWSTR *NtFileNamePart,
|
||||||
|
PVOID DirectoryInfo);
|
||||||
|
|
||||||
|
kernel_interface::event_dispatcher *
|
||||||
|
kernel_interface::kernel_interface::get_free_event_entry() {
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
for (std::vector<event_dispatcher>::iterator it = events.begin();
|
||||||
|
it != events.end(); it++) {
|
||||||
|
if (it->in_use == false) {
|
||||||
|
it->in_use = true;
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::terminate_completion_port() {
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
for (std::vector<event_dispatcher>::iterator it = events.begin();
|
||||||
|
it != events.end(); it++) {
|
||||||
|
free(it->buffer);
|
||||||
|
CloseHandle(it->overlapped.hEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::run_completion_port() {
|
||||||
|
DWORD bytes = 0;
|
||||||
|
OVERLAPPED *io = nullptr;
|
||||||
|
ULONG_PTR key = 0;
|
||||||
|
while (true) {
|
||||||
|
GetQueuedCompletionStatus(this->port, &bytes, &key, &io, INFINITE);
|
||||||
|
if (io == nullptr)
|
||||||
|
continue;
|
||||||
|
void *buffer = get_buffer_from_event_object(io);
|
||||||
|
helper::print_kernel_report(buffer);
|
||||||
|
release_event_object(io);
|
||||||
|
send_pending_irp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::initiate_completion_port() {
|
||||||
|
for (int index = 0; index < EVENT_COUNT; index++) {
|
||||||
|
void *buffer = malloc(MAXIMUM_REPORT_BUFFER_SIZE);
|
||||||
|
this->events.push_back(
|
||||||
|
event_dispatcher(buffer, MAXIMUM_REPORT_BUFFER_SIZE));
|
||||||
|
}
|
||||||
|
this->port = CreateIoCompletionPort(this->driver_handle, nullptr, 0, 0);
|
||||||
|
if (!this->port) {
|
||||||
|
LOG_ERROR("CreateIoCompletePort failed with status %x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < EVENT_COUNT; index++) {
|
||||||
|
send_pending_irp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::release_event_object(
|
||||||
|
OVERLAPPED *event) {
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
for (std::vector<event_dispatcher>::iterator it = events.begin();
|
||||||
|
it != events.end(); it++) {
|
||||||
|
if (&it->overlapped == event) {
|
||||||
|
/* simply zero our the buffer, no need to free and realloc */
|
||||||
|
memset(it->buffer, 0, it->buffer_size);
|
||||||
|
it->in_use = false;
|
||||||
|
ResetEvent(it->overlapped.hEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *kernel_interface::kernel_interface::get_buffer_from_event_object(
|
||||||
|
OVERLAPPED *event) {
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
for (std::vector<event_dispatcher>::iterator it = events.begin();
|
||||||
|
it != events.end(); it++) {
|
||||||
|
if (&it->overlapped == event) {
|
||||||
|
return it->buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_interface::kernel_interface::kernel_interface(
|
||||||
|
LPCWSTR driver_name, client::message_queue &queue)
|
||||||
|
: message_queue(queue) {
|
||||||
|
this->driver_name = driver_name;
|
||||||
|
this->port = INVALID_HANDLE_VALUE;
|
||||||
|
this->driver_handle = CreateFileW(
|
||||||
|
driver_name, GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE, 0, 0,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
||||||
|
if (this->driver_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
LOG_ERROR("Failed to open handle to driver with status 0x%x",
|
||||||
|
GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->notify_driver_on_process_launch();
|
||||||
|
this->initiate_completion_port();
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_interface::kernel_interface::~kernel_interface() {
|
||||||
|
this->terminate_completion_port();
|
||||||
|
this->notify_driver_on_process_termination();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int kernel_interface::kernel_interface::generic_driver_call_output(
|
||||||
|
ioctl_code ioctl, void *output_buffer, size_t buffer_size,
|
||||||
|
unsigned long *bytes_returned) {
|
||||||
|
return DeviceIoControl(this->driver_handle, ioctl, nullptr, 0, output_buffer,
|
||||||
|
buffer_size, bytes_returned, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::generic_driver_call_input(
|
||||||
|
ioctl_code ioctl, void *input_buffer, size_t buffer_size,
|
||||||
|
unsigned long *bytes_returned) {
|
||||||
|
if (!DeviceIoControl(this->driver_handle, ioctl, input_buffer, buffer_size,
|
||||||
|
nullptr, 0, bytes_returned, nullptr))
|
||||||
|
LOG_ERROR("DeviceIoControl failed with status %x", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::generic_driver_call_apc(
|
||||||
|
apc_operation operation) {
|
||||||
|
apc_operation_init init = {0};
|
||||||
|
init.operation_id = operation;
|
||||||
|
this->generic_driver_call_input(ioctl_code::InitiateApcStackwalkOperation,
|
||||||
|
&init, sizeof(init), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::notify_driver_on_process_launch() {
|
||||||
|
unsigned long bytes_returned = 0;
|
||||||
|
process_load_packet packet = {0};
|
||||||
|
packet.protected_process_id = GetCurrentProcessId();
|
||||||
|
generic_driver_call_input(ioctl_code::NotifyDriverOnProcessLaunch, &packet,
|
||||||
|
sizeof(packet), &bytes_returned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::detect_system_virtualization() {
|
||||||
|
unsigned int status = 0;
|
||||||
|
unsigned long bytes_returned = 0;
|
||||||
|
hv_detection_packet packet = {0};
|
||||||
|
status = generic_driver_call_output(ioctl_code::PerformVirtualisationCheck,
|
||||||
|
&packet, sizeof(packet), &bytes_returned);
|
||||||
|
if (!status) {
|
||||||
|
LOG_ERROR("Failed virtualization detection with status %x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (packet.aperf_msr_timing_check == true ||
|
||||||
|
packet.invd_emulation_check == true)
|
||||||
|
LOG_INFO("HYPERVISOR DETECTED!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::generic_driver_call(ioctl_code ioctl) {
|
||||||
|
if (!DeviceIoControl(this->driver_handle, ioctl, nullptr, 0, nullptr, 0,
|
||||||
|
nullptr, nullptr))
|
||||||
|
LOG_ERROR("DeviceIoControl failed with status %x", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::run_nmi_callbacks() {
|
||||||
|
this->generic_driver_call(ioctl_code::RunNmiCallbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::validate_system_driver_objects() {
|
||||||
|
this->generic_driver_call(ioctl_code::ValidateDriverObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::enumerate_handle_tables() {
|
||||||
|
this->generic_driver_call(ioctl_code::EnumerateHandleTables);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::scan_for_unlinked_processes() {
|
||||||
|
this->generic_driver_call(ioctl_code::ScanForUnlinkedProcesses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::perform_integrity_check() {
|
||||||
|
this->generic_driver_call(ioctl_code::PerformModuleIntegrityCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::
|
||||||
|
notify_driver_on_process_termination() {
|
||||||
|
this->generic_driver_call(ioctl_code::NotifyDriverOnProcessTermination);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::scan_for_attached_threads() {
|
||||||
|
this->generic_driver_call(ioctl_code::ScanFroAttachedThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::scan_for_ept_hooks() {
|
||||||
|
this->generic_driver_call(ioctl_code::ScanForEptHooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::perform_dpc_stackwalk() {
|
||||||
|
this->generic_driver_call(ioctl_code::InitiateDpcStackwalk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::validate_system_modules() {
|
||||||
|
this->generic_driver_call(ioctl_code::ValidateSystemModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::
|
||||||
|
verify_process_module_executable_regions() {
|
||||||
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||||
|
MODULEENTRY32 module_entry = {0};
|
||||||
|
BOOLEAN status = FALSE;
|
||||||
|
process_module module = {0};
|
||||||
|
unsigned long bytes_returned = 0;
|
||||||
|
RtlDosPathNameToNtPathName_U pRtlDosPathNameToNtPathName_U = NULL;
|
||||||
|
UNICODE_STRING nt_path_name = {0};
|
||||||
|
pRtlDosPathNameToNtPathName_U = (RtlDosPathNameToNtPathName_U)GetProcAddress(
|
||||||
|
GetModuleHandle(L"ntdll.dll"), "RtlDosPathNameToNtPathName_U");
|
||||||
|
handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32,
|
||||||
|
GetCurrentProcessId());
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
LOG_ERROR("CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with "
|
||||||
|
"status 0x%x",
|
||||||
|
GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
module_entry.dwSize = sizeof(MODULEENTRY32);
|
||||||
|
if (!Module32First(handle, &module_entry)) {
|
||||||
|
LOG_ERROR("Module32First failed with status 0x%x", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
module.module_base = module_entry.modBaseAddr;
|
||||||
|
module.module_size = module_entry.modBaseSize;
|
||||||
|
status = (*pRtlDosPathNameToNtPathName_U)(module_entry.szExePath,
|
||||||
|
&nt_path_name, NULL, NULL);
|
||||||
|
if (!status) {
|
||||||
|
LOG_ERROR("RtlDosPathNameToNtPathName_U failed with no status.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memcpy(module.module_path, nt_path_name.Buffer, MAX_MODULE_PATH);
|
||||||
|
this->generic_driver_call_input(ioctl_code::ValidateProcessLoadedModule,
|
||||||
|
&module, sizeof(module), &bytes_returned);
|
||||||
|
} while (Module32Next(handle, &module_entry));
|
||||||
|
end:
|
||||||
|
CloseHandle(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::initiate_apc_stackwalk() {
|
||||||
|
this->generic_driver_call_apc(apc_operation::operation_stackwalk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_interface::kernel_interface::send_pending_irp() {
|
||||||
|
DWORD status = 0;
|
||||||
|
event_dispatcher *event = get_free_event_entry();
|
||||||
|
if (!event) {
|
||||||
|
LOG_ERROR("All event objects in use.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status = DeviceIoControl(
|
||||||
|
this->driver_handle, ioctl_code::InsertIrpIntoIrpQueue, NULL, NULL,
|
||||||
|
event->buffer, event->buffer_size, NULL, &event->overlapped);
|
||||||
|
/*
|
||||||
|
* im not sure why this returns a status of ERROR_INVALID_FUNCTION when we use
|
||||||
|
* the inserted irp to complete a deferred irp - even though that procedure
|
||||||
|
* should return STATUS_SUCCESS? Weird.. Anyhow it works.
|
||||||
|
*/
|
||||||
|
if (status == ERROR_IO_PENDING || status == ERROR_SUCCESS ||
|
||||||
|
status == ERROR_INVALID_FUNCTION)
|
||||||
|
return;
|
||||||
|
LOG_ERROR("failed to insert irp into irp queue %x", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void kernel_interface::kernel_interface::query_deferred_reports() {
|
||||||
|
// unsigned long bytes_returned = 0;
|
||||||
|
// void *buffer = malloc(MAXIMUM_REPORT_BUFFER_SIZE);
|
||||||
|
// if (!buffer)
|
||||||
|
// return;
|
||||||
|
// for (int i = 0; i < QUERY_DEFERRED_REPORT_COUNT; i++) {
|
||||||
|
// unsigned int status =
|
||||||
|
// generic_driver_call_output(ioctl_code::QueryDeferredReports, buffer,
|
||||||
|
// MAXIMUM_REPORT_BUFFER_SIZE, &bytes_returned);
|
||||||
|
// if (status && bytes_returned > 0)
|
||||||
|
// helper::print_kernel_report(buffer);
|
||||||
|
// memset(buffer, 0, MAXIMUM_REPORT_BUFFER_SIZE);
|
||||||
|
// }
|
||||||
|
// free(buffer);
|
||||||
|
//}
|
221
module/kernel_interface/kernel_interface.h
Normal file
221
module/kernel_interface/kernel_interface.h
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "../client/message_queue.h"
|
||||||
|
|
||||||
|
namespace kernel_interface {
|
||||||
|
|
||||||
|
static constexpr int EVENT_COUNT = 5;
|
||||||
|
static constexpr int MAX_MODULE_PATH = 256;
|
||||||
|
static constexpr int MAXIMUM_REPORT_BUFFER_SIZE = 1000;
|
||||||
|
static constexpr int QUERY_DEFERRED_REPORT_COUNT = 10;
|
||||||
|
|
||||||
|
enum report_id {
|
||||||
|
report_nmi_callback_failure = 50,
|
||||||
|
report_module_validation_failure = 60,
|
||||||
|
report_illegal_handle_operation = 70,
|
||||||
|
report_invalid_process_allocation = 80,
|
||||||
|
report_hidden_system_thread = 90,
|
||||||
|
report_illegal_attach_process = 100,
|
||||||
|
report_apc_stackwalk = 110,
|
||||||
|
report_dpc_stackwalk = 120,
|
||||||
|
report_data_table_routine = 130,
|
||||||
|
report_invalid_process_module = 140
|
||||||
|
};
|
||||||
|
|
||||||
|
struct report_header {
|
||||||
|
int report_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int APC_STACKWALK_BUFFER_SIZE = 500;
|
||||||
|
constexpr int DATA_TABLE_ROUTINE_BUF_SIZE = 256;
|
||||||
|
constexpr int REPORT_INVALID_PROCESS_BUFFER_SIZE = 500;
|
||||||
|
constexpr int HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH = 64;
|
||||||
|
constexpr int MODULE_PATH_LEN = 256;
|
||||||
|
|
||||||
|
struct apc_stackwalk_report {
|
||||||
|
int report_code;
|
||||||
|
uint64_t kthread_address;
|
||||||
|
uint64_t invalid_rip;
|
||||||
|
char driver[APC_STACKWALK_BUFFER_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dpc_stackwalk_report {
|
||||||
|
uint32_t report_code;
|
||||||
|
uint64_t kthread_address;
|
||||||
|
uint64_t invalid_rip;
|
||||||
|
char driver[APC_STACKWALK_BUFFER_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct module_validation_failure {
|
||||||
|
int report_code;
|
||||||
|
int report_type;
|
||||||
|
uint64_t driver_base_address;
|
||||||
|
uint64_t driver_size;
|
||||||
|
char driver_name[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum table_id { hal_dispatch = 0, hal_private_dispatch };
|
||||||
|
|
||||||
|
struct data_table_routine_report {
|
||||||
|
uint32_t report_code;
|
||||||
|
table_id id;
|
||||||
|
uint64_t address;
|
||||||
|
char routine[DATA_TABLE_ROUTINE_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nmi_callback_failure {
|
||||||
|
int report_code;
|
||||||
|
int were_nmis_disabled;
|
||||||
|
uint64_t kthread_address;
|
||||||
|
uint64_t invalid_rip;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct invalid_process_allocation_report {
|
||||||
|
int report_code;
|
||||||
|
char process[REPORT_INVALID_PROCESS_BUFFER_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hidden_system_thread_report {
|
||||||
|
int report_code;
|
||||||
|
int found_in_kthreadlist;
|
||||||
|
int found_in_pspcidtable;
|
||||||
|
uint64_t thread_address;
|
||||||
|
long thread_id;
|
||||||
|
char thread[500];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct attach_process_report {
|
||||||
|
int report_code;
|
||||||
|
uint32_t thread_id;
|
||||||
|
uint64_t thread_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kprcb_thread_validation_ctx {
|
||||||
|
uint64_t thread;
|
||||||
|
bool thread_found_in_pspcidtable;
|
||||||
|
bool finished;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct open_handle_failure_report {
|
||||||
|
int report_code;
|
||||||
|
int is_kernel_handle;
|
||||||
|
long process_id;
|
||||||
|
long thread_id;
|
||||||
|
long access;
|
||||||
|
char process_name[HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct process_module_validation_report {
|
||||||
|
int report_code;
|
||||||
|
uint64_t image_base;
|
||||||
|
uint32_t image_size;
|
||||||
|
wchar_t module_path[MODULE_PATH_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apc_operation { operation_stackwalk = 0x1 };
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
enum ioctl_code
|
||||||
|
{
|
||||||
|
RunNmiCallbacks = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20001, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ValidateDriverObjects = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20002, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
NotifyDriverOnProcessLaunch = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20004, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
QueryForApcCompletion = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20005, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
PerformVirtualisationCheck = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20006, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
EnumerateHandleTables = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20007, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
NotifyDriverOnProcessTermination = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20010, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ScanForUnlinkedProcesses = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20011, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
PerformModuleIntegrityCheck = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20013, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ScanFroAttachedThreads = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20014, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ValidateProcessLoadedModule = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20015, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
RequestHardwareInformation = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20016, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
InitiateApcStackwalkOperation = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20017, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ScanForEptHooks = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20018, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
InitiateDpcStackwalk = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20019, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
ValidateSystemModules = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
InsertIrpIntoIrpQueue = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||||
|
QueryDeferredReports = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
struct event_dispatcher {
|
||||||
|
bool in_use;
|
||||||
|
OVERLAPPED overlapped;
|
||||||
|
void *buffer;
|
||||||
|
unsigned long buffer_size;
|
||||||
|
|
||||||
|
event_dispatcher(void *buffer, unsigned long buffer_size) {
|
||||||
|
this->in_use = false;
|
||||||
|
this->overlapped.hEvent = CreateEvent(nullptr, false, false, nullptr);
|
||||||
|
this->buffer = buffer;
|
||||||
|
this->buffer_size = buffer_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class kernel_interface {
|
||||||
|
struct process_load_packet {
|
||||||
|
unsigned long protected_process_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hv_detection_packet {
|
||||||
|
unsigned long aperf_msr_timing_check;
|
||||||
|
unsigned long invd_emulation_check;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct process_module {
|
||||||
|
void *module_base;
|
||||||
|
size_t module_size;
|
||||||
|
wchar_t module_path[MAX_MODULE_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apc_operation_init {
|
||||||
|
int operation_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
HANDLE driver_handle;
|
||||||
|
LPCWSTR driver_name;
|
||||||
|
client::message_queue &message_queue;
|
||||||
|
HANDLE port;
|
||||||
|
std::mutex lock;
|
||||||
|
std::vector<event_dispatcher> events;
|
||||||
|
|
||||||
|
void initiate_completion_port();
|
||||||
|
void terminate_completion_port();
|
||||||
|
event_dispatcher *get_free_event_entry();
|
||||||
|
void release_event_object(OVERLAPPED *event);
|
||||||
|
void *get_buffer_from_event_object(OVERLAPPED *event);
|
||||||
|
|
||||||
|
void notify_driver_on_process_launch();
|
||||||
|
void notify_driver_on_process_termination();
|
||||||
|
void generic_driver_call(ioctl_code ioctl);
|
||||||
|
unsigned int generic_driver_call_output(ioctl_code ioctl, void *output_buffer,
|
||||||
|
size_t buffer_size,
|
||||||
|
unsigned long *bytes_returned);
|
||||||
|
void generic_driver_call_input(ioctl_code ioctl, void *input_buffer,
|
||||||
|
size_t buffer_size,
|
||||||
|
unsigned long *bytes_returned);
|
||||||
|
void generic_driver_call_apc(apc_operation operation);
|
||||||
|
|
||||||
|
public:
|
||||||
|
kernel_interface(LPCWSTR driver_name, client::message_queue &queue);
|
||||||
|
~kernel_interface();
|
||||||
|
|
||||||
|
void run_completion_port();
|
||||||
|
void run_nmi_callbacks();
|
||||||
|
void validate_system_driver_objects();
|
||||||
|
void detect_system_virtualization();
|
||||||
|
void enumerate_handle_tables();
|
||||||
|
void scan_for_unlinked_processes();
|
||||||
|
void perform_integrity_check();
|
||||||
|
void scan_for_attached_threads();
|
||||||
|
void scan_for_ept_hooks();
|
||||||
|
void perform_dpc_stackwalk();
|
||||||
|
void validate_system_modules();
|
||||||
|
void verify_process_module_executable_regions();
|
||||||
|
void initiate_apc_stackwalk();
|
||||||
|
void send_pending_irp();
|
||||||
|
void query_deferred_reports();
|
||||||
|
};
|
||||||
|
} // namespace kernel_interface
|
33
module/main.cpp
Normal file
33
module/main.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
DWORD WINAPI Init(HINSTANCE hinstDLL) { module::run(hinstDLL); }
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||||
|
LPVOID lpReserved) {
|
||||||
|
switch (ul_reason_for_call) {
|
||||||
|
case DLL_PROCESS_ATTACH: {
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
|
||||||
|
const auto thread =
|
||||||
|
CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(Init),
|
||||||
|
hModule, 0, nullptr);
|
||||||
|
|
||||||
|
if (thread)
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_INFO("process closing!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
31
module/module.cpp
Normal file
31
module/module.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "client/message_queue.h"
|
||||||
|
#include "dispatcher/dispatcher.h"
|
||||||
|
|
||||||
|
void module::run(HINSTANCE hinstDLL) {
|
||||||
|
AllocConsole();
|
||||||
|
FILE *file;
|
||||||
|
freopen_s(&file, "CONOUT$", "w", stdout);
|
||||||
|
freopen_s(&file, "CONIN$", "r", stdin);
|
||||||
|
|
||||||
|
LPTSTR pipe_name = (LPTSTR)L"\\\\.\\pipe\\DonnaACPipe";
|
||||||
|
LPCWSTR driver_name = L"\\\\.\\DonnaAC";
|
||||||
|
|
||||||
|
client::message_queue queue(pipe_name);
|
||||||
|
dispatcher::dispatcher dispatch(driver_name, queue);
|
||||||
|
dispatch.run();
|
||||||
|
|
||||||
|
fclose(stdout);
|
||||||
|
fclose(stdin);
|
||||||
|
FreeConsole();
|
||||||
|
|
||||||
|
FreeLibraryAndExitThread(hinstDLL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void module::terminate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
10
module/module.h
Normal file
10
module/module.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace module {
|
||||||
|
void run(HINSTANCE hinstDLL);
|
||||||
|
void terminate();
|
||||||
|
} // namespace module
|
167
module/module.vcxproj
Normal file
167
module/module.vcxproj
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>17.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{3b18467a-4358-45ef-81b1-5c6f9b0b6728}</ProjectGuid>
|
||||||
|
<RootNamespace>module</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="helper.cpp" />
|
||||||
|
<ClCompile Include="imports.cpp" />
|
||||||
|
<ClCompile Include="module.cpp" />
|
||||||
|
<ClCompile Include="client\message_queue.cpp" />
|
||||||
|
<ClCompile Include="client\pipe.cpp" />
|
||||||
|
<ClCompile Include="dispatcher\dispatcher.cpp" />
|
||||||
|
<ClCompile Include="dispatcher\threadpool.cpp" />
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="kernel_interface\kernel_interface.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="client\message_queue.h" />
|
||||||
|
<ClInclude Include="client\pipe.h" />
|
||||||
|
<ClInclude Include="dispatcher\dispatcher.h" />
|
||||||
|
<ClInclude Include="dispatcher\threadpool.h" />
|
||||||
|
<ClInclude Include="common.h" />
|
||||||
|
<ClInclude Include="helper.h" />
|
||||||
|
<ClInclude Include="imports.h" />
|
||||||
|
<ClInclude Include="kernel_interface\kernel_interface.h" />
|
||||||
|
<ClInclude Include="module.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -18,28 +18,28 @@
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="um\umanager.cpp">
|
<ClCompile Include="kernel_interface\kernel_interface.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="km\kmanager.cpp">
|
<ClCompile Include="dispatcher\dispatcher.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="um\process.cpp">
|
<ClCompile Include="dispatcher\threadpool.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="threadpool.cpp">
|
<ClCompile Include="client\message_queue.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="um\imports.cpp">
|
<ClCompile Include="client\pipe.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="km\driver.cpp">
|
<ClCompile Include="module.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="client.cpp">
|
<ClCompile Include="helper.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="pipe.cpp">
|
<ClCompile Include="imports.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -47,28 +47,28 @@
|
||||||
<ClInclude Include="common.h">
|
<ClInclude Include="common.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="um\umanager.h">
|
<ClInclude Include="kernel_interface\kernel_interface.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="km\kmanager.h">
|
<ClInclude Include="dispatcher\dispatcher.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="um\process.h">
|
<ClInclude Include="dispatcher\threadpool.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="threadpool.h">
|
<ClInclude Include="client\message_queue.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="um\imports.h">
|
<ClInclude Include="client\pipe.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="km\driver.h">
|
<ClInclude Include="module.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="client.h">
|
<ClInclude Include="helper.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="pipe.h">
|
<ClInclude Include="imports.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
|
@ -3,81 +3,65 @@
|
||||||
UNICODE_STRING DRIVER_NAME = RTL_CONSTANT_STRING(L"donna-ac-test");
|
UNICODE_STRING DRIVER_NAME = RTL_CONSTANT_STRING(L"donna-ac-test");
|
||||||
UNICODE_STRING DRIVER_LINK = RTL_CONSTANT_STRING(L"donna-ac-test-link");
|
UNICODE_STRING DRIVER_LINK = RTL_CONSTANT_STRING(L"donna-ac-test-link");
|
||||||
|
|
||||||
#define IOCTL_RUN_NMI_CALLBACKS \
|
#define IOCTL_RUN_NMI_CALLBACKS \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
|
||||||
{
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||||||
UNREFERENCED_PARAMETER(DeviceObject);
|
|
||||||
|
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation(Irp);
|
PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
switch (stack_location->Parameters.DeviceIoControl.IoControlCode)
|
switch (stack_location->Parameters.DeviceIoControl.IoControlCode) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
end:
|
end:
|
||||||
Irp->IoStatus.Status = status;
|
Irp->IoStatus.Status = status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
|
||||||
{
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||||||
UNREFERENCED_PARAMETER(DeviceObject);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
return Irp->IoStatus.Status;
|
||||||
return Irp->IoStatus.Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
DeviceCreate(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
DeviceCreate(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
|
||||||
{
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||||||
UNREFERENCED_PARAMETER(DeviceObject);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
return Irp->IoStatus.Status;
|
||||||
return Irp->IoStatus.Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID DriverUnload(_In_ PDRIVER_OBJECT DriverObject) {
|
||||||
DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
|
IoDeleteDevice(DriverObject->DeviceObject);
|
||||||
{
|
|
||||||
IoDeleteDevice(DriverObject->DeviceObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,
|
||||||
|
_In_ PUNICODE_STRING RegistryPath) {
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
extern "C"
|
status = IoCreateDevice(DriverObject, NULL, &DRIVER_NAME, FILE_DEVICE_UNKNOWN,
|
||||||
NTSTATUS
|
FILE_DEVICE_SECURE_OPEN, FALSE,
|
||||||
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
&DriverObject->DeviceObject);
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
|
|
||||||
status = IoCreateDevice(DriverObject,
|
if (!NT_SUCCESS(status)) {
|
||||||
NULL,
|
return STATUS_FAILED_DRIVER_ENTRY;
|
||||||
&DRIVER_NAME,
|
}
|
||||||
FILE_DEVICE_UNKNOWN,
|
|
||||||
FILE_DEVICE_SECURE_OPEN,
|
|
||||||
FALSE,
|
|
||||||
&DriverObject->DeviceObject);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
status = IoCreateSymbolicLink(&DRIVER_LINK, &DRIVER_NAME);
|
||||||
{
|
|
||||||
return STATUS_FAILED_DRIVER_ENTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = IoCreateSymbolicLink(&DRIVER_LINK, &DRIVER_NAME);
|
if (!NT_SUCCESS(status)) {
|
||||||
|
IoDeleteDevice(DriverObject->DeviceObject);
|
||||||
|
return STATUS_FAILED_DRIVER_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;
|
||||||
{
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;
|
||||||
IoDeleteDevice(DriverObject->DeviceObject);
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
|
||||||
return STATUS_FAILED_DRIVER_ENTRY;
|
DriverObject->DriverUnload = DriverUnload;
|
||||||
}
|
|
||||||
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;
|
return STATUS_SUCCESS;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
|
|
||||||
DriverObject->DriverUnload = DriverUnload;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
|
@ -1,11 +1,7 @@
|
||||||
#include "patch.hpp"
|
#include "patch.hpp"
|
||||||
|
|
||||||
namespace framework {
|
namespace framework {
|
||||||
patch::patch(char* image_name)
|
patch::patch(char *image_name) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
patch::~patch()
|
patch::~patch() {}
|
||||||
{
|
} // namespace framework
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#define TEST_STEAM_64_ID 123456789;
|
|
||||||
|
|
||||||
global::Client::Client(std::shared_ptr<global::ThreadPool> ThreadPool, LPTSTR PipeName)
|
|
||||||
{
|
|
||||||
this->thread_pool = ThreadPool;
|
|
||||||
#if NO_SERVER
|
|
||||||
LOG_INFO("No_Server build used. Not opening named pipe.");
|
|
||||||
#else
|
|
||||||
this->pipe = std::make_shared<global::Pipe>(PipeName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Request an item from the server
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
global::Client::ServerReceive(PVOID Buffer, SIZE_T Size)
|
|
||||||
{
|
|
||||||
this->pipe->ReadPipe(Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send an item to the server
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
global::Client::ServerSend(PVOID Buffer, SIZE_T Size, INT RequestId)
|
|
||||||
{
|
|
||||||
#if NO_SERVER
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
mutex.lock();
|
|
||||||
|
|
||||||
SIZE_T total_header_size = sizeof(global::headers::CLIENT_SEND_PACKET_HEADER) +
|
|
||||||
sizeof(global::headers::PIPE_PACKET_HEADER);
|
|
||||||
|
|
||||||
if (Size + total_header_size > MAX_CLIENT_SEND_PACKET_SIZE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Packet is too large to send");
|
|
||||||
mutex.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVOID send_buffer = malloc(total_header_size + Size);
|
|
||||||
|
|
||||||
if (send_buffer == nullptr)
|
|
||||||
{
|
|
||||||
mutex.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlZeroMemory(send_buffer, total_header_size + Size);
|
|
||||||
|
|
||||||
global::headers::PIPE_PACKET_HEADER header = {0};
|
|
||||||
header.message_type = MESSAGE_TYPE_CLIENT_SEND;
|
|
||||||
header.steam64_id = TEST_STEAM_64_ID;
|
|
||||||
|
|
||||||
memcpy(send_buffer, &header, sizeof(global::headers::PIPE_PACKET_HEADER));
|
|
||||||
|
|
||||||
global::headers::CLIENT_SEND_PACKET_HEADER header_extension = {0};
|
|
||||||
header_extension.request_id = RequestId;
|
|
||||||
header_extension.packet_size = Size + total_header_size;
|
|
||||||
|
|
||||||
memcpy(PVOID((UINT64)send_buffer + sizeof(global::headers::PIPE_PACKET_HEADER)),
|
|
||||||
&header_extension,
|
|
||||||
sizeof(global::headers::CLIENT_SEND_PACKET_HEADER));
|
|
||||||
|
|
||||||
memcpy(PVOID((UINT64)send_buffer + total_header_size), Buffer, Size);
|
|
||||||
|
|
||||||
LOG_INFO("Writing to pipe");
|
|
||||||
|
|
||||||
this->pipe->WriteToPipe(send_buffer, header_extension.packet_size);
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
free(send_buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
237
user/client.h
237
user/client.h
|
@ -1,237 +0,0 @@
|
||||||
#ifndef REPORT_H
|
|
||||||
#define REPORT_H
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include "threadpool.h"
|
|
||||||
#include "pipe.h"
|
|
||||||
#include <TlHelp32.h>
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define REPORT_BUFFER_SIZE 8192
|
|
||||||
#define SEND_BUFFER_SIZE 8192
|
|
||||||
|
|
||||||
#define MAX_SIGNATURE_SIZE 256
|
|
||||||
|
|
||||||
#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20
|
|
||||||
|
|
||||||
#define REPORT_CODE_PROCESS_MODULE_VERIFICATION 10
|
|
||||||
#define REPORT_CODE_START_ADDRESS_VERIFICATION 20
|
|
||||||
#define REPORT_PAGE_PROTECTION_VERIFICATION 30
|
|
||||||
#define REPORT_PATTERN_SCAN_FAILURE 40
|
|
||||||
#define REPORT_NMI_CALLBACK_FAILURE 50
|
|
||||||
#define REPORT_MODULE_VALIDATION_FAILURE 60
|
|
||||||
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
|
|
||||||
#define REPORT_INVALID_PROCESS_ALLOCATION 80
|
|
||||||
#define REPORT_HIDDEN_SYSTEM_THREAD 90
|
|
||||||
#define REPORT_ILLEGAL_ATTACH_PROCESS 100
|
|
||||||
#define REPORT_APC_STACKWALK 110
|
|
||||||
#define REPORT_DPC_STACKWALK 120
|
|
||||||
#define REPORT_DATA_TABLE_ROUTINE 130
|
|
||||||
|
|
||||||
#define TEST_STEAM_64_ID 123456789;
|
|
||||||
|
|
||||||
enum REPORT_CODES
|
|
||||||
{
|
|
||||||
USERMODE_MODULE = 10,
|
|
||||||
START_ADDRESS = 20,
|
|
||||||
PAGE_PROTECTION = 30,
|
|
||||||
PATTERN_SCAN = 40,
|
|
||||||
NMI_CALLBACK = 50,
|
|
||||||
SYSTEM_MODULE = 60,
|
|
||||||
HANDLE_OPERATION = 70
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CLIENT_REQUEST_MODULE_INTEGRITY_CHECK 10
|
|
||||||
|
|
||||||
#define CLIENT_SEND_SYSTEM_INFORMATION 10
|
|
||||||
|
|
||||||
#define MAX_CLIENT_SEND_PACKET_SIZE 60000
|
|
||||||
|
|
||||||
enum SERVER_SEND_CODES
|
|
||||||
{
|
|
||||||
MODULE_INTEGRITY_CHECK = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace global {
|
|
||||||
class Client
|
|
||||||
{
|
|
||||||
std::shared_ptr<global::ThreadPool> thread_pool;
|
|
||||||
std::shared_ptr<global::Pipe> pipe;
|
|
||||||
std::mutex mutex;
|
|
||||||
|
|
||||||
byte report_buffer[REPORT_BUFFER_SIZE];
|
|
||||||
|
|
||||||
public:
|
|
||||||
Client(std::shared_ptr<global::ThreadPool> ThreadPool, LPTSTR PipeName);
|
|
||||||
|
|
||||||
void UpdateSystemInformation(global::headers::SYSTEM_INFORMATION* SystemInformation);
|
|
||||||
|
|
||||||
/* lock buffer, attach header, copy report, send to service then clear buffer */
|
|
||||||
template <typename T>
|
|
||||||
void ReportViolation(T* Report)
|
|
||||||
{
|
|
||||||
#if NO_SERVER
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
mutex.lock();
|
|
||||||
|
|
||||||
global::headers::PIPE_PACKET_HEADER header = {0};
|
|
||||||
header.message_type = MESSAGE_TYPE_CLIENT_REPORT;
|
|
||||||
header.steam64_id = TEST_STEAM_64_ID;
|
|
||||||
memcpy(&this->report_buffer, &header, sizeof(global::headers::PIPE_PACKET_HEADER));
|
|
||||||
|
|
||||||
memcpy(PVOID((UINT64)this->report_buffer +
|
|
||||||
sizeof(global::headers::PIPE_PACKET_HEADER)),
|
|
||||||
Report,
|
|
||||||
sizeof(T));
|
|
||||||
this->pipe->WriteToPipe(this->report_buffer,
|
|
||||||
sizeof(T) + sizeof(global::headers::PIPE_PACKET_HEADER));
|
|
||||||
RtlZeroMemory(this->report_buffer, REPORT_BUFFER_SIZE);
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerReceive(PVOID Buffer, SIZE_T Size);
|
|
||||||
void ServerSend(PVOID Buffer, SIZE_T Size, INT RequestId);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace report_structures {
|
|
||||||
struct PROCESS_MODULES_INTEGRITY_CHECK_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT64 module_base_address;
|
|
||||||
UINT64 module_size;
|
|
||||||
CHAR module_name[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PROCESS_THREAD_START_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
LONG thread_id;
|
|
||||||
UINT64 start_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PAGE_PROTECTION_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT64 page_base_address;
|
|
||||||
LONG allocation_protection;
|
|
||||||
LONG allocation_state;
|
|
||||||
LONG allocation_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PATTERN_SCAN_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT signature_id;
|
|
||||||
UINT64 address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NMI_CALLBACK_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT were_nmis_disabled;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MODULE_VALIDATION_FAILURE_HEADER
|
|
||||||
{
|
|
||||||
INT module_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MODULE_VALIDATION_FAILURE
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT report_type;
|
|
||||||
UINT64 driver_base_address;
|
|
||||||
UINT64 driver_size;
|
|
||||||
CHAR driver_name[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct REPORT_QUEUE_HEADER
|
|
||||||
{
|
|
||||||
INT count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OPEN_HANDLE_FAILURE_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT is_kernel_handle;
|
|
||||||
LONG process_id;
|
|
||||||
LONG thread_id;
|
|
||||||
LONG desired_access;
|
|
||||||
CHAR process_name[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct INVALID_PROCESS_ALLOCATION_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
CHAR process[4096];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No point copying data from the start address here
|
|
||||||
* since people can easily change it.
|
|
||||||
*/
|
|
||||||
struct HIDDEN_SYSTEM_THREAD_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
INT found_in_kthreadlist;
|
|
||||||
INT found_in_pspcidtable;
|
|
||||||
UINT64 thread_address;
|
|
||||||
LONG thread_id;
|
|
||||||
CHAR thread[4096];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ATTACH_PROCESS_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT32 thread_id;
|
|
||||||
UINT64 thread_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SYSTEM_INFORMATION_REQUEST_RESPONSE
|
|
||||||
{
|
|
||||||
INT RequestId;
|
|
||||||
INT CanUserProceed;
|
|
||||||
INT reason;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct APC_STACKWALK_REPORT
|
|
||||||
{
|
|
||||||
INT report_code;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
CHAR driver[4096];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DPC_STACKWALK_REPORT
|
|
||||||
{
|
|
||||||
UINT32 report_code;
|
|
||||||
UINT64 kthread_address;
|
|
||||||
UINT64 invalid_rip;
|
|
||||||
CHAR driver[4096];
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TABLE_ID
|
|
||||||
{
|
|
||||||
HalDispatch = 0,
|
|
||||||
HalPrivateDispatch
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DATA_TABLE_ROUTINE_BUF_SIZE 256
|
|
||||||
|
|
||||||
struct DATA_TABLE_ROUTINE_REPORT
|
|
||||||
{
|
|
||||||
UINT32 report_code;
|
|
||||||
TABLE_ID id;
|
|
||||||
UINT64 address;
|
|
||||||
CHAR routine[DATA_TABLE_ROUTINE_BUF_SIZE];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,671 +0,0 @@
|
||||||
#include "driver.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
#include <winternl.h>
|
|
||||||
|
|
||||||
typedef BOOLEAN(NTAPI* RtlDosPathNameToNtPathName_U)(PCWSTR DosPathName,
|
|
||||||
PUNICODE_STRING NtPathName,
|
|
||||||
PCWSTR* NtFileNamePart,
|
|
||||||
PVOID DirectoryInfo);
|
|
||||||
|
|
||||||
using namespace global::report_structures;
|
|
||||||
|
|
||||||
kernelmode::Driver::Driver(LPCWSTR DriverName, std::shared_ptr<global::Client> ReportInterface)
|
|
||||||
{
|
|
||||||
this->driver_name = DriverName;
|
|
||||||
this->report_interface = ReportInterface;
|
|
||||||
this->driver_handle = CreateFileW(DriverName,
|
|
||||||
GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (this->driver_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to open handle to driver with status 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->NotifyDriverOnProcessLaunch();
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelmode::Driver::~Driver()
|
|
||||||
{
|
|
||||||
this->NotifyDriverOnProcessTermination();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::RunNmiCallbacks()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
NMI_CALLBACK_FAILURE report = {0};
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_RUN_NMI_CALLBACKS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&report,
|
|
||||||
sizeof(NMI_CALLBACK_FAILURE),
|
|
||||||
&bytes_returned,
|
|
||||||
(LPOVERLAPPED)NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed with status code 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_returned == NULL)
|
|
||||||
{
|
|
||||||
LOG_INFO("All threads valid, nmis fine.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else, report */
|
|
||||||
this->report_interface->ReportViolation(&report);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 1. Checks that every device object has a system module to back it
|
|
||||||
* 2. Checks the IOCTL dispatch routines to ensure they lie within the module
|
|
||||||
*/
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::VerifySystemModuleDriverObjects()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
PVOID buffer = NULL;
|
|
||||||
SIZE_T buffer_size = 0;
|
|
||||||
SIZE_T header_size = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* allocate enough to report 5 invalid driver objects + header. The reason we use a raw
|
|
||||||
* pointer here is so we can pass the address to DeviceIoControl. You are not able (atleast
|
|
||||||
* as far as im concerned) to pass a shared ptr to DeviceIoControl.
|
|
||||||
*/
|
|
||||||
header_size = sizeof(MODULE_VALIDATION_FAILURE_HEADER);
|
|
||||||
|
|
||||||
buffer_size =
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE) * MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT +
|
|
||||||
header_size;
|
|
||||||
|
|
||||||
buffer = malloc(buffer_size);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_VALIDATE_DRIVER_OBJECTS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
buffer,
|
|
||||||
buffer_size,
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed with status code 0x%x", GetLastError());
|
|
||||||
free(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_returned == NULL)
|
|
||||||
{
|
|
||||||
LOG_INFO("All modules valid :)");
|
|
||||||
free(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We are splitting up each packet here and passing them on one by one since
|
|
||||||
* if I am being honest it is just easier in c++ and that way the process
|
|
||||||
* is streamlined just like all other report packets.
|
|
||||||
*/
|
|
||||||
MODULE_VALIDATION_FAILURE_HEADER* header = (MODULE_VALIDATION_FAILURE_HEADER*)buffer;
|
|
||||||
|
|
||||||
LOG_INFO("Module count: %lx", header->module_count);
|
|
||||||
|
|
||||||
for (int i = 0; i < header->module_count; i++)
|
|
||||||
{
|
|
||||||
MODULE_VALIDATION_FAILURE* report =
|
|
||||||
(MODULE_VALIDATION_FAILURE*)((UINT64)buffer +
|
|
||||||
sizeof(MODULE_VALIDATION_FAILURE_HEADER) +
|
|
||||||
i * sizeof(MODULE_VALIDATION_FAILURE));
|
|
||||||
|
|
||||||
this->report_interface->ReportViolation(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HOW THIS WILL WORK:
|
|
||||||
*
|
|
||||||
* 1. On driver initiation, ObRegisterCallbacks will be registered
|
|
||||||
* 2. Each time a process that is not whitelisted tries to open a handle
|
|
||||||
* to our game we will store the report in an a report queue
|
|
||||||
* 3. the user mode app will then periodically query the driver asking
|
|
||||||
* how many pending reports there are
|
|
||||||
* 4. once the number is received, the app will allocate a buffer large enough
|
|
||||||
* for all the reports and once again call CompleteQueuedCallbackReports
|
|
||||||
* 5. This will then retrieve the reports into the buffer and from there
|
|
||||||
* we can iteratively report them the same way as we do with the system
|
|
||||||
* modules.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct REPORT_ID
|
|
||||||
{
|
|
||||||
INT report_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::QueryReportQueue()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
PVOID buffer = NULL;
|
|
||||||
LONG buffer_size = 0;
|
|
||||||
REPORT_ID* report_header = NULL;
|
|
||||||
SIZE_T total_size = NULL;
|
|
||||||
OPEN_HANDLE_FAILURE_REPORT handle_report = {0};
|
|
||||||
ATTACH_PROCESS_REPORT attach_report = {0};
|
|
||||||
INVALID_PROCESS_ALLOCATION_REPORT allocation_report = {0};
|
|
||||||
APC_STACKWALK_REPORT apc_report = {0};
|
|
||||||
HIDDEN_SYSTEM_THREAD_REPORT hidden_report = {0};
|
|
||||||
|
|
||||||
/* allocate enough for the largest report buffer * max reports */
|
|
||||||
buffer_size =
|
|
||||||
sizeof(APC_STACKWALK_REPORT) * MAX_REPORTS_PER_IRP + sizeof(REPORT_QUEUE_HEADER);
|
|
||||||
|
|
||||||
/* this isnt very c++ of us... */
|
|
||||||
buffer = malloc(buffer_size);
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
buffer,
|
|
||||||
buffer_size,
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed with status code 0x%x", GetLastError());
|
|
||||||
free(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
REPORT_QUEUE_HEADER* header = (REPORT_QUEUE_HEADER*)buffer;
|
|
||||||
|
|
||||||
if (!header || !header->count)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
for (INT index = 0; index < header->count; index++)
|
|
||||||
{
|
|
||||||
report_header =
|
|
||||||
(REPORT_ID*)((UINT64)buffer + sizeof(REPORT_QUEUE_HEADER) + total_size);
|
|
||||||
|
|
||||||
LOG_INFO("Report id: %d", report_header->report_id);
|
|
||||||
|
|
||||||
switch (report_header->report_id)
|
|
||||||
{
|
|
||||||
case REPORT_ILLEGAL_ATTACH_PROCESS:
|
|
||||||
ReportTypeFromReportQueue<ATTACH_PROCESS_REPORT>(
|
|
||||||
buffer, &total_size, &attach_report);
|
|
||||||
break;
|
|
||||||
case REPORT_ILLEGAL_HANDLE_OPERATION:
|
|
||||||
ReportTypeFromReportQueue<OPEN_HANDLE_FAILURE_REPORT>(
|
|
||||||
buffer, &total_size, &handle_report);
|
|
||||||
break;
|
|
||||||
case REPORT_INVALID_PROCESS_ALLOCATION:
|
|
||||||
ReportTypeFromReportQueue<INVALID_PROCESS_ALLOCATION_REPORT>(
|
|
||||||
buffer, &total_size, &allocation_report);
|
|
||||||
break;
|
|
||||||
case REPORT_APC_STACKWALK:
|
|
||||||
ReportTypeFromReportQueue<APC_STACKWALK_REPORT>(
|
|
||||||
buffer, &total_size, &apc_report);
|
|
||||||
break;
|
|
||||||
case REPORT_HIDDEN_SYSTEM_THREAD:
|
|
||||||
ReportTypeFromReportQueue<HIDDEN_SYSTEM_THREAD_REPORT>(
|
|
||||||
buffer, &total_size, &hidden_report);
|
|
||||||
break;
|
|
||||||
case REPORT_DPC_STACKWALK:
|
|
||||||
ReportTypeFromReportQueue<DPC_STACKWALK_REPORT>(
|
|
||||||
buffer, &total_size, &hidden_report);
|
|
||||||
break;
|
|
||||||
case REPORT_DATA_TABLE_ROUTINE:
|
|
||||||
ReportTypeFromReportQueue<DATA_TABLE_ROUTINE_REPORT>(
|
|
||||||
buffer, &total_size, &hidden_report);
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::RunCallbackReportQueue()
|
|
||||||
{
|
|
||||||
/*TODO have some volatile flag instead */
|
|
||||||
this->QueryReportQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::NotifyDriverOnProcessLaunch()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
kernelmode::DRIVER_INITIATION_INFORMATION information = {0};
|
|
||||||
information.protected_process_id = GetCurrentProcessId();
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH,
|
|
||||||
&information,
|
|
||||||
sizeof(kernelmode::DRIVER_INITIATION_INFORMATION),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("Failed to notify driver on process launch 0x%x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::DetectSystemVirtualization()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
HYPERVISOR_DETECTION_REPORT report = {0};
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_PERFORM_VIRTUALIZATION_CHECK,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&report,
|
|
||||||
sizeof(HYPERVISOR_DETECTION_REPORT),
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed virtualization detect with status %x",
|
|
||||||
GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (report.aperf_msr_timing_check == TRUE || report.invd_emulation_check == TRUE)
|
|
||||||
LOG_INFO("HYPERVISOR DETECTED!!!");
|
|
||||||
|
|
||||||
/* shutdown the application or smth lmao */
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::CheckHandleTableEntries()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = {0};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only pass the IOCTL code and nothing else since the reports are bundled
|
|
||||||
* with the handle ObRegisterCallbacks report queue hence the QueryReportQueue
|
|
||||||
* function will handle these reports.
|
|
||||||
*/
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_ENUMERATE_HANDLE_TABLES,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("CheckHandleTableEntries failed with status %x", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::RequestModuleExecutableRegions()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
ULONG module_size = 0;
|
|
||||||
PVOID buffer = NULL;
|
|
||||||
|
|
||||||
module_size = this->RequestTotalModuleSize();
|
|
||||||
|
|
||||||
if (module_size == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("RequestTotalModuleSize failed lolz");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("module size: %lx", module_size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* allocate a buffer big enough for the entire module not including section headers or
|
|
||||||
* packet headers, however it should be big enough since executable sections do not
|
|
||||||
* make up 100% of the image size. Bit hacky but it works.
|
|
||||||
*/
|
|
||||||
buffer = malloc(module_size);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
buffer,
|
|
||||||
module_size,
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("failed to retrieve module executable regions lozl %x", GetLastError());
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("bytes returned: %lx", bytes_returned);
|
|
||||||
|
|
||||||
this->report_interface->ServerSend(
|
|
||||||
buffer, bytes_returned, CLIENT_REQUEST_MODULE_INTEGRITY_CHECK);
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::ScanForUnlinkedProcess()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
INVALID_PROCESS_ALLOCATION_REPORT report = {0};
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_SCAN_FOR_UNLINKED_PROCESS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&report,
|
|
||||||
sizeof(report),
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("failed to scan for unlinked processes %x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::PerformIntegrityCheck()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_PERFORM_INTEGRITY_CHECK, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("Failed to perform integrity check with status %x", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
kernelmode::Driver::RequestTotalModuleSize()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
ULONG module_size = 0;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_REQUEST_TOTAL_MODULE_SIZE,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&module_size,
|
|
||||||
sizeof(ULONG),
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("CheckHandleTableEntries failed with status %x", status);
|
|
||||||
|
|
||||||
return module_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::NotifyDriverOnProcessTermination()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("NotifyDriverOnProcessTermination failed with status %x", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::CheckForAttachedThreads()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_DETECT_ATTACHED_THREADS, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("failed to check for attached threads %x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::CheckForEptHooks()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_CHECK_FOR_EPT_HOOK, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("failed to check for ept hooks %x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::StackwalkThreadsViaDpc()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_LAUNCH_DPC_STACKWALK, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("failed to stackwalk threads via dpc %x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::ValidateSystemModules()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_VALIDATE_SYSTEM_MODULES, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("failed to validate system modules %x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::CheckDriverHeartbeat()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::VerifyProcessLoadedModuleExecutableRegions()
|
|
||||||
{
|
|
||||||
HANDLE process_modules_handle = INVALID_HANDLE_VALUE;
|
|
||||||
MODULEENTRY32 module_entry = {0};
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
PROCESS_MODULE_INFORMATION module_information = {0};
|
|
||||||
PROCESS_MODULE_VALIDATION_RESULT validation_result = {0};
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
RtlDosPathNameToNtPathName_U pRtlDosPathNameToNtPathName_U = NULL;
|
|
||||||
UNICODE_STRING nt_path_name = {0};
|
|
||||||
|
|
||||||
pRtlDosPathNameToNtPathName_U = (RtlDosPathNameToNtPathName_U)GetProcAddress(
|
|
||||||
GetModuleHandle(L"ntdll.dll"), "RtlDosPathNameToNtPathName_U");
|
|
||||||
|
|
||||||
process_modules_handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32,
|
|
||||||
GetCurrentProcessId());
|
|
||||||
|
|
||||||
if (process_modules_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x",
|
|
||||||
GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_entry.dwSize = sizeof(MODULEENTRY32);
|
|
||||||
|
|
||||||
if (!Module32First(process_modules_handle, &module_entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Module32First failed with status 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
module_information.module_base = module_entry.modBaseAddr;
|
|
||||||
module_information.module_size = module_entry.modBaseSize;
|
|
||||||
|
|
||||||
status = (*pRtlDosPathNameToNtPathName_U)(
|
|
||||||
module_entry.szExePath, &nt_path_name, NULL, NULL);
|
|
||||||
|
|
||||||
if (!status)
|
|
||||||
{
|
|
||||||
LOG_ERROR("RtlDosPathNameToNtPathName_U failed with no status.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(module_information.module_path, nt_path_name.Buffer, MAX_MODULE_PATH);
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_VALIDATE_PROCESS_LOADED_MODULE,
|
|
||||||
&module_information,
|
|
||||||
sizeof(module_information),
|
|
||||||
&validation_result,
|
|
||||||
sizeof(validation_result),
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL || bytes_returned == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("failed to validate process module with status %x",
|
|
||||||
GetLastError());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validation_result.is_module_valid == FALSE)
|
|
||||||
{
|
|
||||||
/*TODO: copy module aswell from an anomaly offset */
|
|
||||||
PROCESS_MODULES_INTEGRITY_CHECK_FAILURE report;
|
|
||||||
report.report_code = REPORT_CODE_PROCESS_MODULE_VERIFICATION;
|
|
||||||
report.module_base_address = (UINT64)module_entry.modBaseAddr;
|
|
||||||
report.module_size = module_entry.modBaseSize;
|
|
||||||
std::wstring wstr(module_entry.szModule);
|
|
||||||
std::string module_name_string = std::string(wstr.begin(), wstr.end());
|
|
||||||
memcpy(
|
|
||||||
&report.module_name, &module_name_string, module_name_string.length());
|
|
||||||
this->report_interface->ReportViolation(&report);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_INFO("Module %S is valid", module_entry.szModule);
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (Module32Next(process_modules_handle, &module_entry));
|
|
||||||
|
|
||||||
end:
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::SendClientHardwareInformation()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
global::headers::SYSTEM_INFORMATION system_information = {0};
|
|
||||||
DWORD bytes_returned = 0;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_REQUEST_HARDWARE_INFORMATION,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&system_information,
|
|
||||||
sizeof(global::headers::SYSTEM_INFORMATION),
|
|
||||||
&bytes_returned,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL || bytes_returned == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed with status %x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->report_interface->ServerSend(&system_information,
|
|
||||||
sizeof(global::headers::SYSTEM_INFORMATION),
|
|
||||||
CLIENT_SEND_SYSTEM_INFORMATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
kernelmode::Driver::InitiateApcOperation(INT OperationId)
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
APC_OPERATION_INFORMATION operation = {0};
|
|
||||||
|
|
||||||
operation.operation_id = OperationId;
|
|
||||||
|
|
||||||
status = DeviceIoControl(this->driver_handle,
|
|
||||||
IOCTL_INITIATE_APC_OPERATION,
|
|
||||||
&operation,
|
|
||||||
sizeof(APC_OPERATION_INFORMATION),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("DeviceIoControl failed with status %x", GetLastError());
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::Driver::SendIrpForDriverToStore()
|
|
||||||
{
|
|
||||||
BOOLEAN status = FALSE;
|
|
||||||
|
|
||||||
status = DeviceIoControl(
|
|
||||||
this->driver_handle, IOCTL_INSERT_IRP_INTO_QUEUE, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
LOG_ERROR("failed to insert irp into irp queue %x", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
GetKernelStructureOffsets()
|
|
||||||
{
|
|
||||||
}
|
|
133
user/km/driver.h
133
user/km/driver.h
|
@ -1,133 +0,0 @@
|
||||||
#ifndef DRIVER_H
|
|
||||||
#define DRIVER_H
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include "../threadpool.h"
|
|
||||||
#include "../client.h"
|
|
||||||
|
|
||||||
#define IOCTL_RUN_NMI_CALLBACKS \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_VALIDATE_DRIVER_OBJECTS \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20002, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20004, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20005, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_PERFORM_VIRTUALIZATION_CHECK \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20006, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_ENUMERATE_HANDLE_TABLES \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20007, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20008, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_REQUEST_TOTAL_MODULE_SIZE \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20009, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20010, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_SCAN_FOR_UNLINKED_PROCESS \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20011, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_PERFORM_INTEGRITY_CHECK \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20013, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_DETECT_ATTACHED_THREADS \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20014, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20015, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_REQUEST_HARDWARE_INFORMATION \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20016, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_INITIATE_APC_OPERATION \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20017, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_CHECK_FOR_EPT_HOOK \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20018, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_LAUNCH_DPC_STACKWALK \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20019, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_VALIDATE_SYSTEM_MODULES \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
#define IOCTL_INSERT_IRP_INTO_QUEUE \
|
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
||||||
|
|
||||||
#define MAX_REPORTS_PER_IRP 20
|
|
||||||
|
|
||||||
#define MAX_MODULE_PATH 256
|
|
||||||
|
|
||||||
namespace kernelmode {
|
|
||||||
enum APC_OPERATION_IDS
|
|
||||||
{
|
|
||||||
operation_stackwalk = 0x1
|
|
||||||
};
|
|
||||||
|
|
||||||
class Driver
|
|
||||||
{
|
|
||||||
HANDLE driver_handle;
|
|
||||||
LPCWSTR driver_name;
|
|
||||||
std::shared_ptr<global::Client> report_interface;
|
|
||||||
|
|
||||||
ULONG RequestTotalModuleSize();
|
|
||||||
VOID NotifyDriverOnProcessLaunch();
|
|
||||||
VOID CheckDriverHeartbeat();
|
|
||||||
VOID NotifyDriverOnProcessTermination();
|
|
||||||
// VOID GetKernelStructureOffsets();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
VOID ReportTypeFromReportQueue(CONST PVOID Buffer, PSIZE_T Offset, PVOID Report)
|
|
||||||
{
|
|
||||||
Report = (T*)((UINT64)Buffer +
|
|
||||||
sizeof(global::report_structures::REPORT_QUEUE_HEADER) + *Offset);
|
|
||||||
|
|
||||||
this->report_interface->ReportViolation((T*)Report);
|
|
||||||
|
|
||||||
*Offset += sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Driver(LPCWSTR DriverName, std::shared_ptr<global::Client> ReportInterface);
|
|
||||||
~Driver();
|
|
||||||
|
|
||||||
VOID RunNmiCallbacks();
|
|
||||||
VOID VerifySystemModuleDriverObjects();
|
|
||||||
VOID RunCallbackReportQueue();
|
|
||||||
VOID DetectSystemVirtualization();
|
|
||||||
VOID QueryReportQueue();
|
|
||||||
VOID CheckHandleTableEntries();
|
|
||||||
VOID RequestModuleExecutableRegions();
|
|
||||||
VOID ScanForUnlinkedProcess();
|
|
||||||
VOID PerformIntegrityCheck();
|
|
||||||
VOID CheckForAttachedThreads();
|
|
||||||
VOID VerifyProcessLoadedModuleExecutableRegions();
|
|
||||||
VOID SendClientHardwareInformation();
|
|
||||||
VOID CheckForEptHooks();
|
|
||||||
VOID StackwalkThreadsViaDpc();
|
|
||||||
VOID ValidateSystemModules();
|
|
||||||
BOOLEAN InitiateApcOperation(INT OperationId);
|
|
||||||
VOID SendIrpForDriverToStore();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DRIVER_INITIATION_INFORMATION
|
|
||||||
{
|
|
||||||
ULONG protected_process_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HYPERVISOR_DETECTION_REPORT
|
|
||||||
{
|
|
||||||
INT aperf_msr_timing_check;
|
|
||||||
INT invd_emulation_check;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PROCESS_MODULE_INFORMATION
|
|
||||||
{
|
|
||||||
PVOID module_base;
|
|
||||||
SIZE_T module_size;
|
|
||||||
WCHAR module_path[MAX_MODULE_PATH];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PROCESS_MODULE_VALIDATION_RESULT
|
|
||||||
{
|
|
||||||
INT is_module_valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct APC_OPERATION_INFORMATION
|
|
||||||
{
|
|
||||||
int operation_id;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,118 +0,0 @@
|
||||||
#include "kmanager.h"
|
|
||||||
|
|
||||||
kernelmode::KManager::KManager(LPCWSTR DriverName,
|
|
||||||
std::shared_ptr<global::ThreadPool> ThreadPool,
|
|
||||||
std::shared_ptr<global::Client> ReportInterface)
|
|
||||||
{
|
|
||||||
this->driver_interface = std::make_unique<Driver>(DriverName, ReportInterface);
|
|
||||||
this->thread_pool = ThreadPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::RunNmiCallbacks()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->RunNmiCallbacks(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::VerifySystemModuleDriverObjects()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->VerifySystemModuleDriverObjects(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::MonitorCallbackReports()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->QueryReportQueue(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::DetectSystemVirtualization()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->DetectSystemVirtualization(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::EnumerateHandleTables()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->CheckHandleTableEntries(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kernelmode::KManager::RequestModuleExecutableRegionsForIntegrityCheck()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->RequestModuleExecutableRegions(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::ScanPoolsForUnlinkedProcesses()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->ScanForUnlinkedProcess(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::PerformIntegrityCheck()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->PerformIntegrityCheck(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::CheckForAttachedThreads()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->CheckForAttachedThreads(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::ValidateProcessModules()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob(
|
|
||||||
[this]() { this->driver_interface->VerifyProcessLoadedModuleExecutableRegions(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::SendClientHardwareInformation()
|
|
||||||
{
|
|
||||||
this->driver_interface->SendClientHardwareInformation();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::InitiateApcStackwalkOperation()
|
|
||||||
{
|
|
||||||
this->driver_interface->InitiateApcOperation(
|
|
||||||
kernelmode::APC_OPERATION_IDS::operation_stackwalk);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::CheckForEptHooks()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->CheckForEptHooks(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::StackwalkThreadsViaDpc()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->StackwalkThreadsViaDpc(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::ValidateSystemModules()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->ValidateSystemModules(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::InsertIrpIntoIrpQueue()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->driver_interface->SendIrpForDriverToStore(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
kernelmode::KManager::StartIoCompletionPortThread()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#ifndef KMANAGER_H
|
|
||||||
#define KMANAGER_H
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "..\client.h"
|
|
||||||
#include "..\threadpool.h"
|
|
||||||
|
|
||||||
#include "driver.h"
|
|
||||||
|
|
||||||
namespace kernelmode {
|
|
||||||
class KManager
|
|
||||||
{
|
|
||||||
std::unique_ptr<Driver> driver_interface;
|
|
||||||
std::shared_ptr<global::ThreadPool> thread_pool;
|
|
||||||
|
|
||||||
VOID StartIoCompletionPortThread();
|
|
||||||
|
|
||||||
public:
|
|
||||||
KManager(LPCWSTR DriverName,
|
|
||||||
std::shared_ptr<global::ThreadPool> ThreadPool,
|
|
||||||
std::shared_ptr<global::Client> ReportInterface);
|
|
||||||
|
|
||||||
VOID RunNmiCallbacks();
|
|
||||||
VOID VerifySystemModuleDriverObjects();
|
|
||||||
VOID MonitorCallbackReports();
|
|
||||||
VOID DetectSystemVirtualization();
|
|
||||||
VOID EnumerateHandleTables();
|
|
||||||
VOID RequestModuleExecutableRegionsForIntegrityCheck();
|
|
||||||
VOID ScanPoolsForUnlinkedProcesses();
|
|
||||||
VOID PerformIntegrityCheck();
|
|
||||||
VOID CheckForAttachedThreads();
|
|
||||||
VOID ValidateProcessModules();
|
|
||||||
VOID SendClientHardwareInformation();
|
|
||||||
VOID InitiateApcStackwalkOperation();
|
|
||||||
VOID CheckForEptHooks();
|
|
||||||
VOID StackwalkThreadsViaDpc();
|
|
||||||
VOID ValidateSystemModules();
|
|
||||||
VOID InsertIrpIntoIrpQueue();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
137
user/main.cpp
137
user/main.cpp
|
@ -1,137 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <string>
|
|
||||||
#include <WDBGEXTS.H>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "threadpool.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include "../user/um/umanager.h"
|
|
||||||
#include "../user/km/kmanager.h"
|
|
||||||
|
|
||||||
// BOOLEAN IsTestSigningModeEnabled()
|
|
||||||
//{
|
|
||||||
// ULONG return_length = 0;
|
|
||||||
//
|
|
||||||
// SYSTEM_CODEINTEGRITY_INFORMATION info = { 0 };
|
|
||||||
// info.Length = sizeof(SYSTEM_CODEINTEGRITY_INFORMATION);
|
|
||||||
// info.CodeIntegrityOptions = 0;
|
|
||||||
//
|
|
||||||
// NTSTATUS status = NtQuerySystemInformation(
|
|
||||||
// SystemCodeIntegrityInformation,
|
|
||||||
// &info,
|
|
||||||
// sizeof(info),
|
|
||||||
// &return_length
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// if (!NT_SUCCESS(status))
|
|
||||||
// {
|
|
||||||
// LOG_ERROR("NtQuerySystemInformation failed with status: %lx", status);
|
|
||||||
// return FALSE;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return info.CodeIntegrityOptions & CODEINTEGRITY_OPTION_TESTSIGN;
|
|
||||||
// }
|
|
||||||
|
|
||||||
DWORD WINAPI
|
|
||||||
Init(HINSTANCE hinstDLL)
|
|
||||||
{
|
|
||||||
AllocConsole();
|
|
||||||
FILE* file;
|
|
||||||
freopen_s(&file, "CONOUT$", "w", stdout);
|
|
||||||
freopen_s(&file, "CONIN$", "r", stdin);
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
||||||
|
|
||||||
LPTSTR pipe_name = (LPTSTR)L"\\\\.\\pipe\\DonnaACPipe";
|
|
||||||
LPCWSTR driver_name = L"\\\\.\\DonnaAC";
|
|
||||||
|
|
||||||
std::shared_ptr<global::ThreadPool> thread_pool = std::make_shared<global::ThreadPool>(4);
|
|
||||||
std::shared_ptr<global::Client> client_interface =
|
|
||||||
std::make_shared<global::Client>(thread_pool, pipe_name);
|
|
||||||
|
|
||||||
usermode::UManager umanager(thread_pool, client_interface);
|
|
||||||
kernelmode::KManager kmanager(driver_name, thread_pool, client_interface);
|
|
||||||
|
|
||||||
global::headers::SYSTEM_INFORMATION system_information = {0};
|
|
||||||
kmanager.SendClientHardwareInformation();
|
|
||||||
|
|
||||||
global::report_structures::SYSTEM_INFORMATION_REQUEST_RESPONSE response = {0};
|
|
||||||
|
|
||||||
// client_interface->ServerReceive( &response, sizeof( response ) );
|
|
||||||
|
|
||||||
// std::cout << "RequestID: " << response.RequestId << " CanUserProceed: " <<
|
|
||||||
// response.CanUserProceed << " Reason: " << response.reason << std::endl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that this is really just for testing the methods for extended periods of time.
|
|
||||||
* The "real business logic" would execute the methods with varying degrees of uncertaintity
|
|
||||||
* but still allow for bias, i.e we don't want NMI callbacks to be running every 10 seconds.
|
|
||||||
* We also need to take into account the performance penalty that some of these routines
|
|
||||||
* have, such as the process module validation. At the end of the day an anti cheat that
|
|
||||||
* imposes a significant performance pentalty on the game its protecting is useless.
|
|
||||||
*/
|
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
while (!GetAsyncKeyState(VK_DELETE))
|
|
||||||
{
|
|
||||||
int seed = (rand() % 11);
|
|
||||||
|
|
||||||
std::cout << "Seed: " << seed << std::endl;
|
|
||||||
|
|
||||||
switch (seed)
|
|
||||||
{
|
|
||||||
case 0: kmanager.EnumerateHandleTables(); break;
|
|
||||||
case 1: kmanager.PerformIntegrityCheck(); break;
|
|
||||||
case 2: kmanager.ScanPoolsForUnlinkedProcesses(); break;
|
|
||||||
case 3: kmanager.VerifySystemModuleDriverObjects(); break;
|
|
||||||
case 4: kmanager.ValidateProcessModules(); break;
|
|
||||||
case 5: kmanager.RunNmiCallbacks(); break;
|
|
||||||
case 6: kmanager.CheckForAttachedThreads(); break;
|
|
||||||
case 7: kmanager.InitiateApcStackwalkOperation(); break;
|
|
||||||
case 8: kmanager.CheckForEptHooks(); break;
|
|
||||||
case 9: kmanager.StackwalkThreadsViaDpc(); break;
|
|
||||||
case 10: kmanager.ValidateSystemModules(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
kmanager.MonitorCallbackReports();
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(stdout);
|
|
||||||
fclose(stdin);
|
|
||||||
FreeConsole();
|
|
||||||
|
|
||||||
FreeLibraryAndExitThread(hinstDLL, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL WINAPI
|
|
||||||
DllMain(HINSTANCE hinstDLL, // handle to DLL module
|
|
||||||
DWORD fdwReason, // reason for calling function
|
|
||||||
LPVOID lpvReserved) // reserved
|
|
||||||
{
|
|
||||||
// Perform actions based on the reason for calling.
|
|
||||||
switch (fdwReason)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
|
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
|
||||||
|
|
||||||
const auto thread = CreateThread(nullptr,
|
|
||||||
0,
|
|
||||||
reinterpret_cast<LPTHREAD_START_ROUTINE>(Init),
|
|
||||||
hinstDLL,
|
|
||||||
0,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
if (thread)
|
|
||||||
CloseHandle(thread);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE; // Successful DLL_PROCESS_ATTACH.
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
#include "pipe.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include <intrin.h>
|
|
||||||
|
|
||||||
global::Pipe::Pipe(LPTSTR PipeName)
|
|
||||||
{
|
|
||||||
this->pipe_name = PipeName;
|
|
||||||
this->pipe_handle = CreateFile(this->pipe_name,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_OVERLAPPED,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (this->pipe_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("CreateFile failed with status 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
global::Pipe::WriteToPipe(PVOID Buffer, SIZE_T Size)
|
|
||||||
{
|
|
||||||
DWORD bytes_written = 0;
|
|
||||||
|
|
||||||
WriteFile(this->pipe_handle, Buffer, Size, &bytes_written, NULL);
|
|
||||||
|
|
||||||
if (bytes_written == 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("WriteFile failed with status code 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
global::Pipe::ReadPipe(PVOID Buffer, SIZE_T Size)
|
|
||||||
{
|
|
||||||
BOOL status = FALSE;
|
|
||||||
DWORD bytes_read = 0;
|
|
||||||
|
|
||||||
status = ReadFile(this->pipe_handle, Buffer, Size, &bytes_read, NULL);
|
|
||||||
|
|
||||||
if (status == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ReadFile failed with status code 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
75
user/pipe.h
75
user/pipe.h
|
@ -1,75 +0,0 @@
|
||||||
#ifndef PIPE_H
|
|
||||||
#define PIPE_H
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#define MESSAGE_TYPE_CLIENT_REPORT 1
|
|
||||||
#define MESSAGE_TYPE_CLIENT_SEND 2
|
|
||||||
#define MESSAGE_TYPE_CLIENT_REQUEST 3
|
|
||||||
|
|
||||||
#define MOTHERBOARD_SERIAL_CODE_LENGTH 64
|
|
||||||
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64
|
|
||||||
|
|
||||||
namespace global {
|
|
||||||
class Pipe
|
|
||||||
{
|
|
||||||
HANDLE pipe_handle;
|
|
||||||
LPTSTR pipe_name;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Pipe(LPTSTR PipeName);
|
|
||||||
|
|
||||||
void WriteToPipe(PVOID Buffer, SIZE_T Size);
|
|
||||||
void ReadPipe(PVOID Buffer, SIZE_T Size);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace headers {
|
|
||||||
typedef enum _ENVIRONMENT_TYPE
|
|
||||||
{
|
|
||||||
NativeWindows = 0,
|
|
||||||
Vmware,
|
|
||||||
VirtualBox
|
|
||||||
|
|
||||||
} ENVIRONMENT_TYPE;
|
|
||||||
|
|
||||||
typedef enum _PROCESSOR_TYPE
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
GenuineIntel,
|
|
||||||
AuthenticAmd
|
|
||||||
|
|
||||||
} PROCESSOR_TYPE;
|
|
||||||
|
|
||||||
#define VENDOR_STRING_MAX_LENGTH 256
|
|
||||||
struct SYSTEM_INFORMATION
|
|
||||||
{
|
|
||||||
CHAR motherboard_serial[MOTHERBOARD_SERIAL_CODE_LENGTH];
|
|
||||||
CHAR drive_0_serial[DEVICE_DRIVE_0_SERIAL_CODE_LENGTH];
|
|
||||||
CHAR vendor[VENDOR_STRING_MAX_LENGTH];
|
|
||||||
BOOLEAN virtualised_environment;
|
|
||||||
ENVIRONMENT_TYPE environment;
|
|
||||||
PROCESSOR_TYPE processor;
|
|
||||||
RTL_OSVERSIONINFOW os_information;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PIPE_PACKET_HEADER
|
|
||||||
{
|
|
||||||
INT message_type;
|
|
||||||
UINT64 steam64_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PIPE_PACKET_REQUEST_EXTENSION_HEADER
|
|
||||||
{
|
|
||||||
INT request_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CLIENT_SEND_PACKET_HEADER
|
|
||||||
{
|
|
||||||
INT request_id;
|
|
||||||
LONG packet_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,103 +0,0 @@
|
||||||
#include "threadpool.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the idle loop each thread will be running until a job is ready
|
|
||||||
* for execution
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
global::ThreadPool::ThreadLoop()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
std::function<void()> job;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is equivalent to :
|
|
||||||
*
|
|
||||||
* while (!this->jobs.empty() || should_terminate)
|
|
||||||
* mutex_condition.wait(lock);
|
|
||||||
*
|
|
||||||
* we are essentially waiting for a job to be queued up or the terminate
|
|
||||||
*flag to be set. Another piece of useful information is that the predicate
|
|
||||||
*is checked under the lock as the precondition for .wait() is that the
|
|
||||||
*calling thread owns the lock.
|
|
||||||
*
|
|
||||||
* Now, when .wait() is run, the lock is unlocked the the executing thread
|
|
||||||
*is blocked and is added to a list of threads current waiting on the
|
|
||||||
*predicate. In our case whether there are new jobs available for the
|
|
||||||
*terminate flag is set. Once the condition variables are true i.e there are
|
|
||||||
*new jobs or we are terminating, the lock is reacquired by the thread and
|
|
||||||
*the thread is unblocked.
|
|
||||||
*/
|
|
||||||
mutex_condition.wait(
|
|
||||||
lock, [this] { return !this->jobs.empty() || this->should_terminate; });
|
|
||||||
|
|
||||||
if (this->should_terminate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* get the first job in the queue*/
|
|
||||||
job = jobs.front();
|
|
||||||
jobs.pop();
|
|
||||||
}
|
|
||||||
/* run the job */
|
|
||||||
job();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global::ThreadPool::ThreadPool(int ThreadCount)
|
|
||||||
{
|
|
||||||
this->thread_count = ThreadCount;
|
|
||||||
this->should_terminate = false;
|
|
||||||
|
|
||||||
/* Initiate our threads and store them in our threads vector */
|
|
||||||
for (int i = 0; i < this->thread_count; i++)
|
|
||||||
{
|
|
||||||
this->threads.emplace_back(std::thread(&ThreadPool::ThreadLoop, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
global::ThreadPool::QueueJob(const std::function<void()>& job)
|
|
||||||
{
|
|
||||||
/* push a job into our job queue safely by holding our queue lock */
|
|
||||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
|
||||||
|
|
||||||
this->jobs.push(job);
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
mutex_condition.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
global::ThreadPool::Stop()
|
|
||||||
{
|
|
||||||
/* safely set our termination flag to true */
|
|
||||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
|
||||||
should_terminate = true;
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
/* unlock all threads waiting on our condition */
|
|
||||||
mutex_condition.notify_all();
|
|
||||||
|
|
||||||
/* join the threads and clear our threads vector */
|
|
||||||
for (std::thread& thread : threads)
|
|
||||||
{
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
threads.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
global::ThreadPool::Busy()
|
|
||||||
{
|
|
||||||
/* allows us to wait for when the job queue is empty allowing us to safely call the
|
|
||||||
* destructor */
|
|
||||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
|
||||||
|
|
||||||
bool pool_busy = !jobs.empty();
|
|
||||||
this->queue_mutex.unlock();
|
|
||||||
|
|
||||||
return pool_busy;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef THREADPOOL_H
|
|
||||||
#define THREADPOOL_H
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <vector>
|
|
||||||
#include <queue>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace global {
|
|
||||||
/*
|
|
||||||
* This ThreadPool class is a simple threadpool implementation that will allow us
|
|
||||||
* to delegate jobs to a set number of threads without the constant need to close
|
|
||||||
* and open new threads.
|
|
||||||
*/
|
|
||||||
class ThreadPool
|
|
||||||
{
|
|
||||||
int thread_count;
|
|
||||||
bool should_terminate;
|
|
||||||
std::mutex queue_mutex;
|
|
||||||
std::condition_variable mutex_condition;
|
|
||||||
std::vector<std::thread> threads;
|
|
||||||
std::queue<std::function<void()>> jobs;
|
|
||||||
|
|
||||||
void ThreadLoop();
|
|
||||||
|
|
||||||
public:
|
|
||||||
ThreadPool(int ThreadCount);
|
|
||||||
void QueueJob(const std::function<void()>& job);
|
|
||||||
void Stop();
|
|
||||||
bool Busy();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,32 +0,0 @@
|
||||||
#include "imports.h"
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
usermode::Imports::Imports()
|
|
||||||
{
|
|
||||||
NtQueryInformationThread = nullptr;
|
|
||||||
RtlDosPathNameToNtPathName_U = nullptr;
|
|
||||||
|
|
||||||
this->ImportMap["NtQueryInformationThread"] = NtQueryInformationThread;
|
|
||||||
this->ImportMap["RtlDosPathNameToNtPathName_U"] = RtlDosPathNameToNtPathName_U;
|
|
||||||
|
|
||||||
std::map<std::string, void*>::iterator it;
|
|
||||||
|
|
||||||
for (it = this->ImportMap.begin(); it != this->ImportMap.end(); it++)
|
|
||||||
{
|
|
||||||
HMODULE module_handle = GetModuleHandle(L"ntdll.dll");
|
|
||||||
|
|
||||||
if (!module_handle)
|
|
||||||
{
|
|
||||||
LOG_ERROR("GetModuleHandle failed with status code 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
it->second = GetProcAddress(module_handle, it->first.c_str());
|
|
||||||
|
|
||||||
if (!it->second)
|
|
||||||
{
|
|
||||||
LOG_ERROR("GetProcAddress failed with status code 0x%x", GetLastError());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef IMPORTS_H
|
|
||||||
#define IMPORTS_H
|
|
||||||
|
|
||||||
#include <winternl.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
typedef NTSTATUS(WINAPI* pNtQueryInformationThread)(HANDLE, LONG, PVOID, ULONG, PULONG);
|
|
||||||
typedef BOOLEAN(NTAPI pRtlDosPathNameToNtPathName_U(PCWSTR, PVOID, PCWSTR*, PVOID));
|
|
||||||
|
|
||||||
namespace usermode {
|
|
||||||
class Imports
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::map<std::string, void*> ImportMap;
|
|
||||||
|
|
||||||
void* NtQueryInformationThread;
|
|
||||||
void* NtQueryVirtualMemory;
|
|
||||||
void* RtlDosPathNameToNtPathName_U;
|
|
||||||
|
|
||||||
Imports();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,321 +0,0 @@
|
||||||
#include "process.h"
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
#include "../um/imports.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#include "../client.h"
|
|
||||||
|
|
||||||
#include <ImageHlp.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
const static char MASK_BYTE = '\x00';
|
|
||||||
|
|
||||||
usermode::Process::Process(std::shared_ptr<global::Client> ClientInterface)
|
|
||||||
{
|
|
||||||
this->process_handle = GetCurrentProcess();
|
|
||||||
this->process_id = GetCurrentProcessId();
|
|
||||||
this->function_imports = std::make_unique<Imports>();
|
|
||||||
this->client_interface = ClientInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::Process::ValidateProcessThreads()
|
|
||||||
{
|
|
||||||
HANDLE thread_snapshot_handle = INVALID_HANDLE_VALUE;
|
|
||||||
THREADENTRY32 thread_entry = {0};
|
|
||||||
NTSTATUS status = 0;
|
|
||||||
HANDLE thread_handle = INVALID_HANDLE_VALUE;
|
|
||||||
UINT64 start_address = 0;
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
pNtQueryInformationThread NtQueryInfo = (pNtQueryInformationThread)this->function_imports
|
|
||||||
->ImportMap["NtQueryInformationThread"];
|
|
||||||
|
|
||||||
/* th32ProcessId ignored for TH32CS_SNAPTHREAD value */
|
|
||||||
thread_snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
|
||||||
|
|
||||||
if (thread_snapshot_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("thread snapshot handle invalid with error 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_entry.dwSize = sizeof(THREADENTRY32);
|
|
||||||
|
|
||||||
if (!Thread32First(thread_snapshot_handle, &thread_entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Thread32First failed with status 0x%x", GetLastError());
|
|
||||||
CloseHandle(thread_snapshot_handle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (thread_entry.th32OwnerProcessID != process_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_entry.th32ThreadID);
|
|
||||||
|
|
||||||
if (thread_handle == INVALID_HANDLE_VALUE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
status = NtQueryInfo(thread_handle,
|
|
||||||
(THREADINFOCLASS)ThreadQuerySetWin32StartAddress,
|
|
||||||
&start_address,
|
|
||||||
sizeof(UINT64),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
LOG_ERROR("NtQueryInfo failed with status code 0x%lx", status);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckIfAddressLiesWithinValidProcessModule(start_address, &result))
|
|
||||||
{
|
|
||||||
if (result == false)
|
|
||||||
{
|
|
||||||
global::report_structures::PROCESS_THREAD_START_FAILURE report;
|
|
||||||
report.report_code = REPORT_CODE_START_ADDRESS_VERIFICATION;
|
|
||||||
report.start_address = start_address;
|
|
||||||
report.thread_id = thread_entry.th32ThreadID;
|
|
||||||
this->client_interface->ReportViolation(&report);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (Thread32Next(thread_snapshot_handle, &thread_entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterates through a processes modules and confirms whether the address lies within the memory
|
|
||||||
* region of the module. A simple way to check if a thread is a valid thread, however there are ways
|
|
||||||
* around this check so it is not a perfect solution.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
usermode::Process::CheckIfAddressLiesWithinValidProcessModule(UINT64 Address, bool* Result)
|
|
||||||
{
|
|
||||||
HANDLE process_modules_handle = INVALID_HANDLE_VALUE;
|
|
||||||
MODULEENTRY32 module_entry = {0};
|
|
||||||
|
|
||||||
process_modules_handle =
|
|
||||||
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, this->process_id);
|
|
||||||
|
|
||||||
LOG_INFO("Address: %llx", Address);
|
|
||||||
|
|
||||||
if (process_modules_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x",
|
|
||||||
GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_entry.dwSize = sizeof(MODULEENTRY32);
|
|
||||||
|
|
||||||
if (!Module32First(process_modules_handle, &module_entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Module32First failed with status 0x%x", GetLastError());
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UINT64 base = (UINT64)module_entry.modBaseAddr;
|
|
||||||
UINT64 end = base + module_entry.modBaseSize;
|
|
||||||
|
|
||||||
if (Address >= base && Address <= end)
|
|
||||||
{
|
|
||||||
LOG_INFO("found valid module LOL");
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
*Result = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (Module32Next(process_modules_handle, &module_entry));
|
|
||||||
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
*Result = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
usermode::Process::GetHandleToProcessGivenName(std::string ProcessName)
|
|
||||||
{
|
|
||||||
std::wstring wide_process_name = {0};
|
|
||||||
std::wstring target_process_name = {0};
|
|
||||||
HANDLE process_snapshot_handle = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE process_handle = INVALID_HANDLE_VALUE;
|
|
||||||
PROCESSENTRY32 process_entry = {0};
|
|
||||||
|
|
||||||
wide_process_name = std::wstring(ProcessName.begin(), ProcessName.end());
|
|
||||||
process_snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
||||||
|
|
||||||
if (process_snapshot_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to create snapshot of current running processes error: 0x%x",
|
|
||||||
GetLastError());
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
process_entry.dwSize = sizeof(PROCESSENTRY32);
|
|
||||||
|
|
||||||
if (!Process32First(process_snapshot_handle, &process_entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to get the first process using Process32First error: 0x%x",
|
|
||||||
GetLastError());
|
|
||||||
CloseHandle(process_snapshot_handle);
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
process_handle =
|
|
||||||
OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_entry.th32ProcessID);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* this will generally fail due to a process being an elevated process and denying
|
|
||||||
* us access so we dont really care if OpenProcess fails in most cases
|
|
||||||
*/
|
|
||||||
if (process_handle == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
target_process_name = std::wstring(process_entry.szExeFile);
|
|
||||||
|
|
||||||
if (wide_process_name == target_process_name)
|
|
||||||
{
|
|
||||||
LOG_INFO("Found target process");
|
|
||||||
CloseHandle(process_snapshot_handle);
|
|
||||||
return process_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (Process32Next(process_snapshot_handle, &process_entry));
|
|
||||||
|
|
||||||
CloseHandle(process_snapshot_handle);
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
usermode::Process::GetProcessBaseAddress(UINT64* Result)
|
|
||||||
{
|
|
||||||
HANDLE process_modules_handle = INVALID_HANDLE_VALUE;
|
|
||||||
MODULEENTRY32 module_entry = {0};
|
|
||||||
|
|
||||||
process_modules_handle =
|
|
||||||
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, this->process_id);
|
|
||||||
|
|
||||||
if (process_modules_handle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x",
|
|
||||||
GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_entry.dwSize = sizeof(MODULEENTRY32);
|
|
||||||
|
|
||||||
if (!Module32First(process_modules_handle, &module_entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Module32First failed with status 0x%x", GetLastError());
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*Result = (UINT64)module_entry.modBaseAddr;
|
|
||||||
CloseHandle(process_modules_handle);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::Process::ScanProcessMemory()
|
|
||||||
{
|
|
||||||
MEMORY_BASIC_INFORMATION memory_info = {0};
|
|
||||||
UINT64 address = 0;
|
|
||||||
|
|
||||||
if (!GetProcessBaseAddress(&address))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to get process base address with status 0x%x", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (VirtualQueryEx(
|
|
||||||
this->process_handle, (PVOID)address, &memory_info, sizeof(MEMORY_BASIC_INFORMATION)))
|
|
||||||
{
|
|
||||||
this->CheckPageProtection(&memory_info);
|
|
||||||
this->PatternScanRegion(address, &memory_info);
|
|
||||||
|
|
||||||
address += memory_info.RegionSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::Process::PatternScanRegion(UINT64 Address, MEMORY_BASIC_INFORMATION* Page)
|
|
||||||
{
|
|
||||||
/* todo: stream signatures from server */
|
|
||||||
// char buf[] = "\x85\xc0\x74\x00\xb9\x00\x00\x00\x00\xcd";
|
|
||||||
char buf[] =
|
|
||||||
"\x55\x8B\xEC\xFF\x75\x00\xD9\x45\x00\x51\xD9\x1C\x00\xE8\x00\x00\x00\x00\x5D\xC2\x00\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC";
|
|
||||||
std::vector<char> signature = {0};
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
signature.push_back(buf[i]);
|
|
||||||
|
|
||||||
/* skip free or reserved pages */
|
|
||||||
if (Page->State == MEM_RESERVE || Page->State == MEM_FREE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char* base = (char*)Address;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < Page->RegionSize; i++)
|
|
||||||
{
|
|
||||||
for (unsigned j = 0; j < signature.size(); j++)
|
|
||||||
{
|
|
||||||
char current_byte = *(base + i);
|
|
||||||
char current_sig_byte = signature[j];
|
|
||||||
|
|
||||||
/* if we've found the signature, report */
|
|
||||||
if (j + 1 == signature.size())
|
|
||||||
{
|
|
||||||
global::report_structures::PATTERN_SCAN_FAILURE report;
|
|
||||||
report.report_code = REPORT_PATTERN_SCAN_FAILURE;
|
|
||||||
report.address = (UINT64)base + i;
|
|
||||||
report.signature_id =
|
|
||||||
1; /* this will be taken from the vector in future */
|
|
||||||
this->client_interface->ReportViolation(&report);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* for now return, however when we stream the signatures we iterate
|
|
||||||
* over each signature for every page
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else, continue searching */
|
|
||||||
if (current_byte != current_sig_byte && current_sig_byte != MASK_BYTE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::Process::CheckPageProtection(MEMORY_BASIC_INFORMATION* Page)
|
|
||||||
{
|
|
||||||
/* MEM_IMAGE indicates the pages are mapped into view of an image section */
|
|
||||||
if (Page->Type == MEM_IMAGE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Page->AllocationProtect & PAGE_EXECUTE || Page->AllocationProtect & PAGE_EXECUTE_READ ||
|
|
||||||
Page->AllocationProtect & PAGE_EXECUTE_READWRITE ||
|
|
||||||
Page->AllocationProtect & PAGE_EXECUTE_WRITECOPY)
|
|
||||||
{
|
|
||||||
// Not etirely sure about this check, needs to be looked into further.
|
|
||||||
global::report_structures::PAGE_PROTECTION_FAILURE report;
|
|
||||||
report.report_code = REPORT_PAGE_PROTECTION_VERIFICATION;
|
|
||||||
report.page_base_address = (UINT64)Page->AllocationBase;
|
|
||||||
report.allocation_protection = Page->AllocationProtect;
|
|
||||||
report.allocation_state = Page->State;
|
|
||||||
report.allocation_type = Page->Type;
|
|
||||||
this->client_interface->ReportViolation(&report);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef PROCESS_H
|
|
||||||
#define PROCESS_H
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winternl.h>
|
|
||||||
#include <TlHelp32.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "../client.h"
|
|
||||||
#include "../threadpool.h"
|
|
||||||
#include "../um/imports.h"
|
|
||||||
#include "../km/kmanager.h"
|
|
||||||
|
|
||||||
#define ThreadQuerySetWin32StartAddress 9
|
|
||||||
|
|
||||||
namespace usermode {
|
|
||||||
/*
|
|
||||||
* This class represents a process and the usermode functions responsible for
|
|
||||||
* the protection of it. This class represents the protected process and allows
|
|
||||||
* us to split protection class into methods which can then be easily managed
|
|
||||||
* by the usermode manager class.
|
|
||||||
*/
|
|
||||||
class Process
|
|
||||||
{
|
|
||||||
HANDLE process_handle;
|
|
||||||
DWORD process_id;
|
|
||||||
std::mutex mutex;
|
|
||||||
std::unique_ptr<Imports> function_imports;
|
|
||||||
std::vector<DWORD> in_memory_module_checksums;
|
|
||||||
std::shared_ptr<global::Client> client_interface;
|
|
||||||
|
|
||||||
HANDLE GetHandleToProcessGivenName(std::string ProcessName);
|
|
||||||
bool CheckIfAddressLiesWithinValidProcessModule(UINT64 Address, bool* Result);
|
|
||||||
bool GetProcessBaseAddress(UINT64* Result);
|
|
||||||
void CheckPageProtection(MEMORY_BASIC_INFORMATION* Page);
|
|
||||||
void PatternScanRegion(UINT64 Address, MEMORY_BASIC_INFORMATION* Page);
|
|
||||||
|
|
||||||
public:
|
|
||||||
Process(std::shared_ptr<global::Client> ClientInterface);
|
|
||||||
|
|
||||||
void ValidateProcessThreads();
|
|
||||||
void ScanProcessMemory();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include "umanager.h"
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "../um/imports.h"
|
|
||||||
|
|
||||||
#include <TlHelp32.h>
|
|
||||||
|
|
||||||
usermode::UManager::UManager(std::shared_ptr<global::ThreadPool> ThreadPool,
|
|
||||||
std::shared_ptr<global::Client> ReportInterface)
|
|
||||||
{
|
|
||||||
this->thread_pool = ThreadPool;
|
|
||||||
this->process = std::make_unique<Process>(ReportInterface);
|
|
||||||
}
|
|
||||||
|
|
||||||
usermode::UManager::~UManager()
|
|
||||||
{
|
|
||||||
/* Wait for our jobs to be finished, then safely stop our pool */
|
|
||||||
// while ( true )
|
|
||||||
//{
|
|
||||||
// if ( this->thread_pool->Busy() == FALSE )
|
|
||||||
// {
|
|
||||||
// this->thread_pool->Stop();
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::UManager::ValidateProcessThreads()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->process->ValidateProcessThreads(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
usermode::UManager::ValidateProcessMemory()
|
|
||||||
{
|
|
||||||
this->thread_pool->QueueJob([this]() { this->process->ScanProcessMemory(); });
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#ifndef UMANAGER_H
|
|
||||||
#define UMANAGER_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <winternl.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "..\client.h"
|
|
||||||
|
|
||||||
#include "process.h"
|
|
||||||
|
|
||||||
namespace usermode {
|
|
||||||
/*
|
|
||||||
* The manager class is meant to abstract away the interaction between the Process
|
|
||||||
* class and the threadpool class to allow a single thread (or multiple) to easily run
|
|
||||||
* the core business logic of running tasks in a certain order.
|
|
||||||
*/
|
|
||||||
class UManager
|
|
||||||
{
|
|
||||||
std::unique_ptr<Process> process;
|
|
||||||
std::shared_ptr<global::ThreadPool> thread_pool;
|
|
||||||
|
|
||||||
public:
|
|
||||||
UManager(std::shared_ptr<global::ThreadPool> ThreadPool,
|
|
||||||
std::shared_ptr<global::Client> ReportInterface);
|
|
||||||
~UManager();
|
|
||||||
|
|
||||||
void ValidateProcessThreads();
|
|
||||||
void ValidateProcessMemory();
|
|
||||||
void ValidateProcessModules();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,283 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release - No Server - Win11|Win32">
|
|
||||||
<Configuration>Release - No Server - Win11</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release - No Server - Win11|x64">
|
|
||||||
<Configuration>Release - No Server - Win11</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release - No Server|Win32">
|
|
||||||
<Configuration>Release - No Server</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release - No Server|x64">
|
|
||||||
<Configuration>Release - No Server</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<ProjectGuid>{3c8194c7-9f20-4ff8-8c4c-b26c3d053611}</ProjectGuid>
|
|
||||||
<RootNamespace>user</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Users\lachuie\source\repos\ac\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Users\lachuie\source\repos\ac\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;NO_SERVER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Users\lachuie\source\repos\ac\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - No Server - Win11|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;NO_SERVER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Users\lachuie\source\repos\ac\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="pipe.cpp" />
|
|
||||||
<ClCompile Include="km\driver.cpp" />
|
|
||||||
<ClCompile Include="km\kmanager.cpp" />
|
|
||||||
<ClCompile Include="main.cpp" />
|
|
||||||
<ClCompile Include="um\imports.cpp" />
|
|
||||||
<ClCompile Include="um\process.cpp" />
|
|
||||||
<ClCompile Include="threadpool.cpp" />
|
|
||||||
<ClCompile Include="um\umanager.cpp" />
|
|
||||||
<ClCompile Include="client.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="pipe.h" />
|
|
||||||
<ClInclude Include="common.h" />
|
|
||||||
<ClInclude Include="km\driver.h" />
|
|
||||||
<ClInclude Include="km\kmanager.h" />
|
|
||||||
<ClInclude Include="client.h" />
|
|
||||||
<ClInclude Include="um\imports.h" />
|
|
||||||
<ClInclude Include="um\process.h" />
|
|
||||||
<ClInclude Include="threadpool.h" />
|
|
||||||
<ClInclude Include="um\umanager.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
Loading…
Reference in a new issue