├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Tools
├── ATAIdentifyDump
│ ├── ATAIdentifyDump.cpp
│ ├── ATAIdentifyDump.vcxproj
│ ├── ATAIdentifyDump.vcxproj.filters
│ ├── IdentifyDeviceData.h
│ ├── README.md
│ ├── pch.cpp
│ └── pch.h
└── StructDumpCodegen
│ ├── README.md
│ └── struct_dump_codegen.linq
├── al-khaser.sln
└── al-khaser
├── Al-khaser.cpp
├── AntiAnalysis
├── pch.h
├── process.cpp
└── process.h
├── AntiDebug
├── BeingDebugged.cpp
├── BeingDebugged.h
├── CheckRemoteDebuggerPresent.cpp
├── CheckRemoteDebuggerPresent.h
├── CloseHandle_InvalidHandle.cpp
├── CloseHandle_InvalidHandle.h
├── HardwareBreakpoints.cpp
├── HardwareBreakpoints.h
├── Interrupt_0x2d.cpp
├── Interrupt_0x2d.h
├── Interrupt_3.cpp
├── Interrupt_3.h
├── IsDebuggerPresent.cpp
├── IsDebuggerPresent.h
├── LowFragmentationHeap.cpp
├── LowFragmentationHeap.h
├── MemoryBreakpoints_PageGuard.cpp
├── MemoryBreakpoints_PageGuard.h
├── ModuleBoundsHookCheck.cpp
├── ModuleBoundsHookCheck.h
├── NtGlobalFlag.cpp
├── NtGlobalFlag.h
├── NtQueryInformationProcess_ProcessDebugFlags.cpp
├── NtQueryInformationProcess_ProcessDebugFlags.h
├── NtQueryInformationProcess_ProcessDebugObject.cpp
├── NtQueryInformationProcess_ProcessDebugObject.h
├── NtQueryInformationProcess_ProcessDebugPort.cpp
├── NtQueryInformationProcess_ProcessDebugPort.h
├── NtQueryObject_AllTypesInformation.cpp
├── NtQueryObject_ObjectInformation.h
├── NtQueryObject_ObjectTypeInformation.cpp
├── NtQuerySystemInformation_SystemKernelDebuggerInformation.cpp
├── NtQuerySystemInformation_SystemKernelDebuggerInformation.h
├── NtSetInformationThread_ThreadHideFromDebugger.cpp
├── NtSetInformationThread_ThreadHideFromDebugger.h
├── NtSystemDebugControl.cpp
├── NtSystemDebugControl.h
├── NtYieldExecution.cpp
├── NtYieldExecution.h
├── OutputDebugStringAPI.cpp
├── OutputDebugStringAPI.h
├── PageExceptionBreakpointCheck.cpp
├── PageExceptionBreakpointCheck.h
├── ParentProcess.cpp
├── ParentProcess.h
├── ProcessHeap_Flags.cpp
├── ProcessHeap_Flags.h
├── ProcessHeap_ForceFlags.cpp
├── ProcessHeap_ForceFlags.h
├── ProcessJob.cpp
├── ProcessJob.h
├── ScanForModules.cpp
├── ScanForModules.h
├── SeDebugPrivilege.cpp
├── SeDebugPrivilege.h
├── SetHandleInformation_API.cpp
├── SetHandleInformation_API.h
├── SharedUserData_KernelDebugger.cpp
├── SharedUserData_KernelDebugger.h
├── SoftwareBreakpoints.cpp
├── SoftwareBreakpoints.h
├── TLS_callbacks.cpp
├── TLS_callbacks.h
├── TrapFlag.cpp
├── TrapFlag.h
├── UnhandledExceptionFilter_Handler.cpp
├── UnhandledExceptionFilter_Handler.h
├── WUDF_IsDebuggerPresent.cpp
├── WUDF_IsDebuggerPresent.h
├── WriteWatch.cpp
├── WriteWatch.h
├── int2d_x64.asm
├── int2d_x86.asm
└── pch.h
├── AntiDisassm
├── AntiDisassm.cpp
├── AntiDisassm.h
├── AntiDisassm_x64.asm
├── AntiDisassm_x86.asm
└── pch.h
├── AntiDump
├── ErasePEHeaderFromMemory.cpp
├── ErasePEHeaderFromMemory.h
├── SizeOfImage.cpp
├── SizeOfImage.h
└── pch.h
├── AntiVM
├── Generic.cpp
├── Generic.h
├── HyperV.cpp
├── HyperV.h
├── KVM.cpp
├── KVM.h
├── Parallels.cpp
├── Parallels.h
├── Qemu.cpp
├── Qemu.h
├── Services.cpp
├── Services.h
├── VMWare.cpp
├── VMWare.h
├── VirtualBox.cpp
├── VirtualBox.h
├── VirtualPC.cpp
├── VirtualPC.h
├── Wine.cpp
├── Wine.h
├── Xen.cpp
├── Xen.h
└── pch.h
├── CodeInjection
├── CreateRemoteThread.cpp
├── CreateRemoteThread.h
├── GetSetThreadContext.cpp
├── GetSetThreadContext.h
├── InjectedDLL
│ ├── InjectedDLL.cpp
│ ├── InjectedDLL.h
│ ├── InjectedDLL.vcxproj
│ ├── InjectedDLL.vcxproj.filters
│ └── definitions.def
├── NtCreateThreadEx.cpp
├── NtCreateThreadEx.h
├── QueueUserAPC.cpp
├── QueueUserAPC.h
├── RtlCreateUserThread.cpp
├── RtlCreateUserThread.h
├── SetWindowsHooksEx.cpp
├── SetWindowsHooksEx.h
└── pch.h
├── OfficeMacro
├── al-khaser.docm
└── macros.vba
├── Shared
├── APIs.cpp
├── APIs.h
├── ApiTypeDefs.cpp
├── ApiTypeDefs.h
├── Common.cpp
├── Common.h
├── Utils.cpp
├── Utils.h
├── VersionHelpers.h
├── WinStructs.h
├── log.cpp
├── log.h
├── pch.h
└── winapifamily.h
├── TimingAttacks
├── pch.h
├── timing.cpp
└── timing.h
├── al-khaser.manifest
├── al-khaser.vcxproj
├── al-khaser.vcxproj.filters
├── packages.config
├── pch.cpp
└── pch.h
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; Top-most EditorConfig file
2 | root = true
3 |
4 | ; Windows-style newlines
5 | [*]
6 | end_of_line = CRLF
7 |
8 | ; Tab indentation
9 | [*.{cpp,h}]
10 | indent_style = tab
11 | tab_width = 4
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set the merge driver for project and solution files
8 | #
9 | # Merging from the command prompt will add diff markers to the files if there
10 | # are conflicts (Merging from VS is not affected by the settings below, in VS
11 | # the diff markers are never inserted). Diff markers may cause the following
12 | # file extensions to fail to load in VS. An alternative would be to treat
13 | # these files as binary and thus will always conflict and require user
14 | # intervention with every merge. To do so, just comment the entries below and
15 | # uncomment the group further below
16 | ###############################################################################
17 |
18 | *.sln text eol=crlf
19 | *.csproj text eol=crlf
20 | *.vbproj text eol=crlf
21 | *.vcxproj text eol=crlf
22 | *.vcproj text eol=crlf
23 | *.dbproj text eol=crlf
24 | *.fsproj text eol=crlf
25 | *.lsproj text eol=crlf
26 | *.wixproj text eol=crlf
27 | *.modelproj text eol=crlf
28 | *.sqlproj text eol=crlf
29 | *.wmaproj text eol=crlf
30 |
31 | *.xproj text eol=crlf
32 | *.props text eol=crlf
33 | *.filters text eol=crlf
34 | *.vcxitems text eol=crlf
35 |
36 |
37 | #*.sln merge=binary
38 | #*.csproj merge=binary
39 | #*.vbproj merge=binary
40 | #*.vcxproj merge=binary
41 | #*.vcproj merge=binary
42 | #*.dbproj merge=binary
43 | #*.fsproj merge=binary
44 | #*.lsproj merge=binary
45 | #*.wixproj merge=binary
46 | #*.modelproj merge=binary
47 | #*.sqlproj merge=binary
48 | #*.wwaproj merge=binary
49 |
50 | #*.xproj merge=binary
51 | #*.props merge=binary
52 | #*.filters merge=binary
53 | #*.vcxitems merge=binary
54 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build Pull Request Artifacts
2 | on: [pull_request]
3 | jobs:
4 | build:
5 | runs-on: windows-2022
6 |
7 | steps:
8 | - uses: actions/checkout@v2
9 |
10 | - name: Add MSBuild to PATH
11 | uses: microsoft/setup-msbuild@v1.1.3
12 |
13 | - name: Restore NuGet packages
14 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
15 |
16 | - name: Build x86
17 | run: msbuild /m /p:Platform=x86 /p:Configuration=Release al-khaser.sln
18 |
19 | - name: Build x64
20 | run: msbuild /m /p:Platform=x64 /p:Configuration=Release al-khaser.sln
21 |
22 | - name: Zip x86 Binaries
23 | run: 7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -mhe=on -p"yug69gG89T98HGUY8y" al-khaser_x86.7z al-khaser_x86.exe
24 |
25 | - name: Zip x64 Binaries
26 | run: 7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -mhe=on -p"yug69gG89T98HGUY8y" al-khaser_x64.7z al-khaser_x64.exe
27 |
28 | - name: Upload x86 Binaries
29 | uses: actions/upload-artifact@v4
30 | with:
31 | name: x86
32 | path: "al-khaser_x86.7z"
33 |
34 | - name: Upload x64 Binaries
35 | uses: actions/upload-artifact@v4
36 | with:
37 | name: x64
38 | path: "al-khaser_x64.7z"
39 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Build Release Artifacts
2 | on:
3 | release:
4 | types: [published]
5 | jobs:
6 | build:
7 | runs-on: windows-2022
8 |
9 | steps:
10 | - uses: actions/checkout@v2
11 |
12 | - name: Add MSBuild to PATH
13 | uses: microsoft/setup-msbuild@v1.1.3
14 |
15 | - name: Restore NuGet packages
16 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
17 |
18 | - name: Build x86
19 | run: msbuild /m /p:Platform=x86 /p:Configuration=Release al-khaser.sln
20 |
21 | - name: Build x64
22 | run: msbuild /m /p:Platform=x64 /p:Configuration=Release al-khaser.sln
23 |
24 | - name: Zip x86 Binaries
25 | run: 7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -mhe=on -p"yug69gG89T98HGUY8y" al-khaser_x86.7z al-khaser_x86.exe
26 |
27 | - name: Zip x64 Binaries
28 | run: 7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -mhe=on -p"yug69gG89T98HGUY8y" al-khaser_x64.7z al-khaser_x64.exe
29 |
30 | - name: Attach Binaries to release
31 | uses: AButler/upload-release-assets@v3.0
32 | with:
33 | files: "al-khaser_x*.7z"
34 | repo-token: ${{ secrets.GITHUB_TOKEN }}
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # Precompiled Headers
14 | *.gch
15 | *.pch
16 |
17 | # Compiled Dynamic libraries
18 | *.so
19 | *.dylib
20 | *.dll
21 |
22 | # Fortran module files
23 | *.mod
24 |
25 | # Compiled Static libraries
26 | *.lai
27 | *.la
28 | *.a
29 | *.lib
30 |
31 | # Executables
32 | *.out
33 | *.app
34 |
35 | # User-specific files
36 | *.suo
37 | *.user
38 | *.userosscache
39 | *.sln.docstates
40 |
41 | # Visual C++ cache files
42 | ipch/
43 | *.aps
44 | *.ncb
45 | *.opensdf
46 | *.sdf
47 | *.cachefile
48 |
49 | # Build results
50 | [Dd]ebug/
51 | [Dd]ebugPublic/
52 | [Rr]elease/
53 | [Rr]eleases/
54 | x64/
55 | x86/
56 | build/
57 | bld/
58 | [Bb]in/
59 | [Oo]bj/
60 | *.VC.opendb
61 |
62 | # Visual C++ Solution
63 | *.VC.db
64 |
65 | # NuGet packages
66 | packages/
67 |
68 | # Alkhaser log file
69 | log.txt
70 |
71 | # Packages
72 | packages/
73 |
--------------------------------------------------------------------------------
/Tools/ATAIdentifyDump/ATAIdentifyDump.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 |
26 |
27 | Source Files
28 |
29 |
30 | Source Files
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Tools/ATAIdentifyDump/IdentifyDeviceData.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef struct _IDENTIFY_DEVICE_DATA {
4 | struct {
5 | USHORT Reserved1 : 1;
6 | USHORT Retired3 : 1;
7 | USHORT ResponseIncomplete : 1;
8 | USHORT Retired2 : 3;
9 | USHORT FixedDevice : 1;
10 | USHORT RemovableMedia : 1;
11 | USHORT Retired1 : 7;
12 | USHORT DeviceType : 1;
13 | } GeneralConfiguration;
14 | USHORT NumCylinders;
15 | USHORT ReservedWord2;
16 | USHORT NumHeads;
17 | USHORT Retired1[2];
18 | USHORT NumSectorsPerTrack;
19 | USHORT VendorUnique1[3];
20 | UCHAR SerialNumber[20];
21 | USHORT Retired2[2];
22 | USHORT Obsolete1;
23 | UCHAR FirmwareRevision[8];
24 | UCHAR ModelNumber[40];
25 | UCHAR MaximumBlockTransfer;
26 | UCHAR VendorUnique2;
27 | USHORT ReservedWord48;
28 | struct {
29 | UCHAR ReservedByte49;
30 | UCHAR DmaSupported : 1;
31 | UCHAR LbaSupported : 1;
32 | UCHAR IordyDisable : 1;
33 | UCHAR IordySupported : 1;
34 | UCHAR Reserved1 : 1;
35 | UCHAR StandybyTimerSupport : 1;
36 | UCHAR Reserved2 : 2;
37 | USHORT ReservedWord50;
38 | } Capabilities;
39 | USHORT ObsoleteWords51[2];
40 | USHORT TranslationFieldsValid : 3;
41 | USHORT Reserved3 : 13;
42 | USHORT NumberOfCurrentCylinders;
43 | USHORT NumberOfCurrentHeads;
44 | USHORT CurrentSectorsPerTrack;
45 | ULONG CurrentSectorCapacity;
46 | UCHAR CurrentMultiSectorSetting;
47 | UCHAR MultiSectorSettingValid : 1;
48 | UCHAR ReservedByte59 : 7;
49 | ULONG UserAddressableSectors;
50 | USHORT ObsoleteWord62;
51 | USHORT MultiWordDMASupport : 8;
52 | USHORT MultiWordDMAActive : 8;
53 | USHORT AdvancedPIOModes : 8;
54 | USHORT ReservedByte64 : 8;
55 | USHORT MinimumMWXferCycleTime;
56 | USHORT RecommendedMWXferCycleTime;
57 | USHORT MinimumPIOCycleTime;
58 | USHORT MinimumPIOCycleTimeIORDY;
59 | USHORT ReservedWords69[6];
60 | USHORT QueueDepth : 5;
61 | USHORT ReservedWord75 : 11;
62 | USHORT ReservedWords76[4];
63 | USHORT MajorRevision;
64 | USHORT MinorRevision;
65 | struct {
66 | USHORT SmartCommands : 1;
67 | USHORT SecurityMode : 1;
68 | USHORT RemovableMediaFeature : 1;
69 | USHORT PowerManagement : 1;
70 | USHORT Reserved1 : 1;
71 | USHORT WriteCache : 1;
72 | USHORT LookAhead : 1;
73 | USHORT ReleaseInterrupt : 1;
74 | USHORT ServiceInterrupt : 1;
75 | USHORT DeviceReset : 1;
76 | USHORT HostProtectedArea : 1;
77 | USHORT Obsolete1 : 1;
78 | USHORT WriteBuffer : 1;
79 | USHORT ReadBuffer : 1;
80 | USHORT Nop : 1;
81 | USHORT Obsolete2 : 1;
82 | USHORT DownloadMicrocode : 1;
83 | USHORT DmaQueued : 1;
84 | USHORT Cfa : 1;
85 | USHORT AdvancedPm : 1;
86 | USHORT Msn : 1;
87 | USHORT PowerUpInStandby : 1;
88 | USHORT ManualPowerUp : 1;
89 | USHORT Reserved2 : 1;
90 | USHORT SetMax : 1;
91 | USHORT Acoustics : 1;
92 | USHORT BigLba : 1;
93 | USHORT DeviceConfigOverlay : 1;
94 | USHORT FlushCache : 1;
95 | USHORT FlushCacheExt : 1;
96 | USHORT Resrved3 : 2;
97 | USHORT SmartErrorLog : 1;
98 | USHORT SmartSelfTest : 1;
99 | USHORT MediaSerialNumber : 1;
100 | USHORT MediaCardPassThrough : 1;
101 | USHORT StreamingFeature : 1;
102 | USHORT GpLogging : 1;
103 | USHORT WriteFua : 1;
104 | USHORT WriteQueuedFua : 1;
105 | USHORT WWN64Bit : 1;
106 | USHORT URGReadStream : 1;
107 | USHORT URGWriteStream : 1;
108 | USHORT ReservedForTechReport : 2;
109 | USHORT IdleWithUnloadFeature : 1;
110 | USHORT Reserved4 : 2;
111 | } CommandSetSupport;
112 | struct {
113 | USHORT SmartCommands : 1;
114 | USHORT SecurityMode : 1;
115 | USHORT RemovableMediaFeature : 1;
116 | USHORT PowerManagement : 1;
117 | USHORT Reserved1 : 1;
118 | USHORT WriteCache : 1;
119 | USHORT LookAhead : 1;
120 | USHORT ReleaseInterrupt : 1;
121 | USHORT ServiceInterrupt : 1;
122 | USHORT DeviceReset : 1;
123 | USHORT HostProtectedArea : 1;
124 | USHORT Obsolete1 : 1;
125 | USHORT WriteBuffer : 1;
126 | USHORT ReadBuffer : 1;
127 | USHORT Nop : 1;
128 | USHORT Obsolete2 : 1;
129 | USHORT DownloadMicrocode : 1;
130 | USHORT DmaQueued : 1;
131 | USHORT Cfa : 1;
132 | USHORT AdvancedPm : 1;
133 | USHORT Msn : 1;
134 | USHORT PowerUpInStandby : 1;
135 | USHORT ManualPowerUp : 1;
136 | USHORT Reserved2 : 1;
137 | USHORT SetMax : 1;
138 | USHORT Acoustics : 1;
139 | USHORT BigLba : 1;
140 | USHORT DeviceConfigOverlay : 1;
141 | USHORT FlushCache : 1;
142 | USHORT FlushCacheExt : 1;
143 | USHORT Resrved3 : 2;
144 | USHORT SmartErrorLog : 1;
145 | USHORT SmartSelfTest : 1;
146 | USHORT MediaSerialNumber : 1;
147 | USHORT MediaCardPassThrough : 1;
148 | USHORT StreamingFeature : 1;
149 | USHORT GpLogging : 1;
150 | USHORT WriteFua : 1;
151 | USHORT WriteQueuedFua : 1;
152 | USHORT WWN64Bit : 1;
153 | USHORT URGReadStream : 1;
154 | USHORT URGWriteStream : 1;
155 | USHORT ReservedForTechReport : 2;
156 | USHORT IdleWithUnloadFeature : 1;
157 | USHORT Reserved4 : 2;
158 | } CommandSetActive;
159 | USHORT UltraDMASupport : 8;
160 | USHORT UltraDMAActive : 8;
161 | USHORT ReservedWord89[4];
162 | USHORT HardwareResetResult;
163 | USHORT CurrentAcousticValue : 8;
164 | USHORT RecommendedAcousticValue : 8;
165 | USHORT ReservedWord95[5];
166 | ULONG Max48BitLBA[2];
167 | USHORT StreamingTransferTime;
168 | USHORT ReservedWord105;
169 | struct {
170 | USHORT LogicalSectorsPerPhysicalSector : 4;
171 | USHORT Reserved0 : 8;
172 | USHORT LogicalSectorLongerThan256Words : 1;
173 | USHORT MultipleLogicalSectorsPerPhysicalSector : 1;
174 | USHORT Reserved1 : 2;
175 | } PhysicalLogicalSectorSize;
176 | USHORT InterSeekDelay;
177 | USHORT WorldWideName[4];
178 | USHORT ReservedForWorldWideName128[4];
179 | USHORT ReservedForTlcTechnicalReport;
180 | USHORT WordsPerLogicalSector[2];
181 | struct {
182 | USHORT ReservedForDrqTechnicalReport : 1;
183 | USHORT WriteReadVerifySupported : 1;
184 | USHORT Reserved01 : 11;
185 | USHORT Reserved1 : 2;
186 | } CommandSetSupportExt;
187 | struct {
188 | USHORT ReservedForDrqTechnicalReport : 1;
189 | USHORT WriteReadVerifyEnabled : 1;
190 | USHORT Reserved01 : 11;
191 | USHORT Reserved1 : 2;
192 | } CommandSetActiveExt;
193 | USHORT ReservedForExpandedSupportandActive[6];
194 | USHORT MsnSupport : 2;
195 | USHORT ReservedWord1274 : 14;
196 | struct {
197 | USHORT SecuritySupported : 1;
198 | USHORT SecurityEnabled : 1;
199 | USHORT SecurityLocked : 1;
200 | USHORT SecurityFrozen : 1;
201 | USHORT SecurityCountExpired : 1;
202 | USHORT EnhancedSecurityEraseSupported : 1;
203 | USHORT Reserved0 : 2;
204 | USHORT SecurityLevel : 1;
205 | USHORT Reserved1 : 7;
206 | } SecurityStatus;
207 | USHORT ReservedWord129[31];
208 | struct {
209 | USHORT MaximumCurrentInMA2 : 12;
210 | USHORT CfaPowerMode1Disabled : 1;
211 | USHORT CfaPowerMode1Required : 1;
212 | USHORT Reserved0 : 1;
213 | USHORT Word160Supported : 1;
214 | } CfaPowerModel;
215 | USHORT ReservedForCfaWord161[8];
216 | struct {
217 | USHORT SupportsTrim : 1;
218 | USHORT Reserved0 : 15;
219 | } DataSetManagementFeature;
220 | USHORT ReservedForCfaWord170[6];
221 | USHORT CurrentMediaSerialNumber[30];
222 | USHORT ReservedWord206;
223 | USHORT ReservedWord207[2];
224 | struct {
225 | USHORT AlignmentOfLogicalWithinPhysical : 14;
226 | USHORT Word209Supported : 1;
227 | USHORT Reserved0 : 1;
228 | } BlockAlignment;
229 | USHORT WriteReadVerifySectorCountMode3Only[2];
230 | USHORT WriteReadVerifySectorCountMode2Only[2];
231 | struct {
232 | USHORT NVCachePowerModeEnabled : 1;
233 | USHORT Reserved0 : 3;
234 | USHORT NVCacheFeatureSetEnabled : 1;
235 | USHORT Reserved1 : 3;
236 | USHORT NVCachePowerModeVersion : 4;
237 | USHORT NVCacheFeatureSetVersion : 4;
238 | } NVCacheCapabilities;
239 | USHORT NVCacheSizeLSW;
240 | USHORT NVCacheSizeMSW;
241 | USHORT NominalMediaRotationRate;
242 | USHORT ReservedWord218;
243 | struct {
244 | UCHAR NVCacheEstimatedTimeToSpinUpInSeconds;
245 | UCHAR Reserved;
246 | } NVCacheOptions;
247 | USHORT ReservedWord220[35];
248 | USHORT Signature : 8;
249 | USHORT CheckSum : 8;
250 | } IDENTIFY_DEVICE_DATA, *PIDENTIFY_DEVICE_DATA;
--------------------------------------------------------------------------------
/Tools/ATAIdentifyDump/README.md:
--------------------------------------------------------------------------------
1 | # ATAIdentifyDump
2 |
3 | ATAIdentifyDump dumps ATA IDENTIFY data from physical disks. This data is useful for identifying VMs.
4 |
5 | You must run this tool as an administrator.
--------------------------------------------------------------------------------
/Tools/ATAIdentifyDump/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/Tools/ATAIdentifyDump/pch.h:
--------------------------------------------------------------------------------
1 | #ifndef PCH_H
2 | #define PCH_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include "IdentifyDeviceData.h"
8 |
9 | #endif // PCH_H
--------------------------------------------------------------------------------
/Tools/StructDumpCodegen/README.md:
--------------------------------------------------------------------------------
1 | # Struct Dump Codegen
2 |
3 | This is a LINQpad script to turn a struct definition into C++ code that prints out its contents. So far it supports USHORT, ULONG, and UCHAR.
4 |
5 | This was written specifically for IDENTIFY_DEVICE_DATA in order to speed up writing ATAIdentifyDump.
6 |
7 | This can probably be used for similar structs too, so it might be useful elsewhere.
--------------------------------------------------------------------------------
/Tools/StructDumpCodegen/struct_dump_codegen.linq:
--------------------------------------------------------------------------------
1 |
2 | <RuntimeDirectory>\System.Drawing.dll
3 | <RuntimeDirectory>\System.IO.dll
4 | <RuntimeDirectory>\System.Net.dll
5 | <RuntimeDirectory>\System.Numerics.dll
6 | <RuntimeDirectory>\System.Numerics.Vectors.dll
7 | <RuntimeDirectory>\System.Security.dll
8 | System.Collections
9 | System.Collections.Concurrent
10 | System.Collections.Generic
11 | System.Collections.Specialized
12 | System.Drawing
13 | System.Drawing.Imaging
14 | System.IO
15 | System.IO.MemoryMappedFiles
16 | System.IO.Pipes
17 | System.IO.Ports
18 | System.Net
19 | System.Net.Sockets
20 | System.Numerics
21 | System.Runtime.InteropServices
22 | System.Runtime.InteropServices
23 | System.Runtime.Serialization
24 | System.Runtime.Serialization.Formatters.Binary
25 | System.Security
26 | System.Security.AccessControl
27 | System.Security.Cryptography
28 | System.Security.Principal
29 | System.Text
30 | System.Threading
31 | System.Threading.Tasks
32 |
33 |
34 | /*
35 | Script to turn a struct definition into C++ code that prints out its contents. So far it supports USHORT, ULONG, and UCHAR.
36 |
37 | This was written specifically for IDENTIFY_DEVICE_DATA in order to speed up writing ATAIdentifyDump.
38 |
39 | This can probably be used for similar structs too, so it might be useful elsewhere.
40 | */
41 |
42 | const string SourceFile = @"C:\Users\Graham\Source\Repos\al-khaser\Tools\ATAIdentifyDump\IdentifyDeviceData.h";
43 | const string StructVar = "idd";
44 | const bool SwapStringEndian = true; // for IDENTIFY_DEVICE_DATA
45 |
46 | void Main()
47 | {
48 |
49 | string[] lines = File.ReadAllLines(SourceFile);
50 |
51 | bool foundStart = false;
52 | bool inStruct = false;
53 | var structLines = new List();
54 |
55 | var output = new StringBuilder();
56 |
57 | foreach (string rawLine in lines)
58 | {
59 | var line = rawLine.Trim().TrimEnd(';');
60 | if (!foundStart)
61 | {
62 | if (line.StartsWith("typedef struct"))
63 | {
64 | foundStart = true;
65 | }
66 | continue;
67 | }
68 |
69 | if (line.StartsWith("struct {"))
70 | {
71 | if (inStruct)
72 | {
73 | throw new InvalidDataException();
74 | }
75 |
76 | // we're starting a nested structure
77 | inStruct = true;
78 | structLines.Clear();
79 | continue;
80 | }
81 |
82 | if (line.StartsWith("}"))
83 | {
84 | if (!inStruct)
85 | {
86 | Console.WriteLine("// end");
87 | break;
88 | }
89 |
90 | // we're ending a nested structure
91 | var structNameMatch = Regex.Match(line, "^}\\s+([a-zA-Z0-9]+)$");
92 | if (!structNameMatch.Success)
93 | {
94 | throw new InvalidDataException();
95 | }
96 |
97 | string structName = structNameMatch.Groups[1].Value;
98 |
99 | inStruct = false;
100 | foreach (string structLine in structLines)
101 | {
102 | ProcessLine(StructVar, structLine, structName);
103 | }
104 | continue;
105 | }
106 |
107 | if (inStruct)
108 | {
109 | structLines.Add(line);
110 | continue;
111 | }
112 |
113 | ProcessLine(StructVar, line);
114 | }
115 | }
116 |
117 | void ProcessLine(string structvar, string line, string structname = null)
118 | {
119 | string[] parts = line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
120 |
121 | string fieldType = null;
122 | string fieldName = null;
123 | int arraySize = 0;
124 |
125 | if (parts.Length == 2)
126 | {
127 | fieldType = parts[0];
128 | if (parts[1].Contains("["))
129 | {
130 | var arrayMatch = Regex.Match(parts[1], "^([a-zA-Z0-9]+)\\[(\\d+)\\]$");
131 | if (!arrayMatch.Success)
132 | {
133 | throw new InvalidDataException();
134 | }
135 | fieldName = arrayMatch.Groups[1].Value;
136 | arraySize = int.Parse(arrayMatch.Groups[2].Value);
137 | }
138 | else
139 | {
140 | fieldName = parts[1];
141 | }
142 | }
143 | else
144 | {
145 | if (!parts.Contains(":"))
146 | {
147 | throw new InvalidDataException();
148 | }
149 |
150 | fieldType = parts[0];
151 | fieldName = parts[1];
152 | }
153 |
154 | if (structname != null)
155 | {
156 | structname += ".";
157 | }
158 |
159 | if (fieldType == "USHORT")
160 | {
161 | if (arraySize == 0)
162 | {
163 | Console.WriteLine($"printf(\"{structname ?? ""}{fieldName} = %hu\\r\\n\", {structvar}->{structname ?? ""}{fieldName});");
164 | }
165 | else
166 | {
167 | for (int i = 0; i < arraySize; i++)
168 | {
169 | Console.WriteLine($"printf(\"{structname ?? ""}{fieldName}[{i}] = %hu\\r\\n\", {structvar}->{structname ?? ""}{fieldName}[{i}]);");
170 | }
171 | }
172 | }
173 | else if (fieldType == "ULONG")
174 | {
175 | if (arraySize == 0)
176 | {
177 | Console.WriteLine($"printf(\"{structname ?? ""}{fieldName} = %lu\\r\\n\", {structvar}->{structname ?? ""}{fieldName});");
178 | }
179 | else
180 | {
181 | for (int i = 0; i < arraySize; i++)
182 | {
183 | Console.WriteLine($"printf(\"{structname ?? ""}{fieldName}[{i}] = %lu\\r\\n\", {structvar}->{structname ?? ""}{fieldName}[{i}]);");
184 | }
185 | }
186 | }
187 | else if (fieldType == "UCHAR")
188 | {
189 | if (arraySize == 0)
190 | {
191 | Console.WriteLine($"printf(\"{structname ?? ""}{fieldName} = %d\\r\\n\", {structvar}->{structname ?? ""}{fieldName});");
192 | }
193 | else
194 | {
195 | string format = string.Concat(Enumerable.Repeat("%c", arraySize));
196 | Console.Write($"printf(\"{structname ?? ""}{fieldName} = \\\"{format}\\\"\\r\\n\"");
197 | for (int i = 0; i < arraySize; i++)
198 | {
199 | int ni = i;
200 | if (SwapStringEndian)
201 | {
202 | ni = (i - (i % 2)) + (1 - (i % 2));
203 | }
204 | Console.Write($", {structvar}->{structname ?? ""}{fieldName}[{ni}]");
205 | }
206 | Console.WriteLine(");");
207 | }
208 | }
209 | else
210 | {
211 | throw new InvalidDataException();
212 | }
213 | }
--------------------------------------------------------------------------------
/al-khaser.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 15
3 | VisualStudioVersion = 15.0.28010.2026
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "al-khaser", "al-khaser\al-khaser.vcxproj", "{77AEFBC3-0ECE-46AD-A113-966AAAA838E1}"
6 | EndProject
7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{71BFEE2B-52EC-4526-90F5-D91D98B9C786}"
8 | EndProject
9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ATAIdentifyDump", "Tools\ATAIdentifyDump\ATAIdentifyDump.vcxproj", "{245D8670-A888-4ECC-9B51-80584E55B701}"
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|x64 = Release|x64
16 | Release|x86 = Release|x86
17 | EndGlobalSection
18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
19 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Debug|x64.ActiveCfg = Debug|x64
20 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Debug|x64.Build.0 = Debug|x64
21 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Debug|x86.ActiveCfg = Debug|Win32
22 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Debug|x86.Build.0 = Debug|Win32
23 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Release|x64.ActiveCfg = Release|x64
24 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Release|x64.Build.0 = Release|x64
25 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Release|x86.ActiveCfg = Release|Win32
26 | {77AEFBC3-0ECE-46AD-A113-966AAAA838E1}.Release|x86.Build.0 = Release|Win32
27 | {245D8670-A888-4ECC-9B51-80584E55B701}.Debug|x64.ActiveCfg = Debug|x64
28 | {245D8670-A888-4ECC-9B51-80584E55B701}.Debug|x64.Build.0 = Debug|x64
29 | {245D8670-A888-4ECC-9B51-80584E55B701}.Debug|x86.ActiveCfg = Debug|Win32
30 | {245D8670-A888-4ECC-9B51-80584E55B701}.Debug|x86.Build.0 = Debug|Win32
31 | {245D8670-A888-4ECC-9B51-80584E55B701}.Release|x64.ActiveCfg = Release|x64
32 | {245D8670-A888-4ECC-9B51-80584E55B701}.Release|x64.Build.0 = Release|x64
33 | {245D8670-A888-4ECC-9B51-80584E55B701}.Release|x86.ActiveCfg = Release|Win32
34 | {245D8670-A888-4ECC-9B51-80584E55B701}.Release|x86.Build.0 = Release|Win32
35 | EndGlobalSection
36 | GlobalSection(SolutionProperties) = preSolution
37 | HideSolutionNode = FALSE
38 | EndGlobalSection
39 | GlobalSection(NestedProjects) = preSolution
40 | {245D8670-A888-4ECC-9B51-80584E55B701} = {71BFEE2B-52EC-4526-90F5-D91D98B9C786}
41 | EndGlobalSection
42 | GlobalSection(ExtensibilityGlobals) = postSolution
43 | SolutionGuid = {0772817E-132F-4922-8377-5DA07255372F}
44 | EndGlobalSection
45 | EndGlobal
46 |
--------------------------------------------------------------------------------
/al-khaser/AntiAnalysis/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/AntiAnalysis/process.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #pragma once
3 | #include "process.h"
4 |
5 | /*
6 | Check for process list
7 | */
8 |
9 | VOID analysis_tools_process()
10 | {
11 | const TCHAR *szProcesses[] = {
12 | _T("ollydbg.exe"), // OllyDebug debugger
13 | _T("ollyice.exe"), // OllyICE debugger
14 | _T("ProcessHacker.exe"), // Process Hacker
15 | _T("tcpview.exe"), // Part of Sysinternals Suite
16 | _T("autoruns.exe"), // Part of Sysinternals Suite
17 | _T("autorunsc.exe"), // Part of Sysinternals Suite
18 | _T("filemon.exe"), // Part of Sysinternals Suite
19 | _T("procmon.exe"), // Part of Sysinternals Suite
20 | _T("regmon.exe"), // Part of Sysinternals Suite
21 | _T("procexp.exe"), // Part of Sysinternals Suite
22 | _T("idaq.exe"), // IDA Pro Interactive Disassembler
23 | _T("idaq64.exe"), // IDA Pro Interactive Disassembler
24 | _T("ImmunityDebugger.exe"), // ImmunityDebugger
25 | _T("Wireshark.exe"), // Wireshark packet sniffer
26 | _T("dumpcap.exe"), // Network traffic dump tool
27 | _T("HookExplorer.exe"), // Find various types of runtime hooks
28 | _T("ImportREC.exe"), // Import Reconstructor
29 | _T("PETools.exe"), // PE Tool
30 | _T("LordPE.exe"), // LordPE
31 | _T("SysInspector.exe"), // ESET SysInspector
32 | _T("proc_analyzer.exe"), // Part of SysAnalyzer iDefense
33 | _T("sysAnalyzer.exe"), // Part of SysAnalyzer iDefense
34 | _T("sniff_hit.exe"), // Part of SysAnalyzer iDefense
35 | _T("windbg.exe"), // Microsoft WinDbg
36 | _T("joeboxcontrol.exe"), // Part of Joe Sandbox
37 | _T("joeboxserver.exe"), // Part of Joe Sandbox
38 | _T("ResourceHacker.exe"), // Resource Hacker
39 | _T("x32dbg.exe"), // x32dbg
40 | _T("x64dbg.exe"), // x64dbg
41 | _T("Fiddler.exe"), // Fiddler
42 | _T("httpdebugger.exe"), // Http Debugger
43 | _T("cheatengine-i386.exe"), // Cheat Engine
44 | _T("cheatengine-x86_64.exe"), // Cheat Engine
45 | _T("cheatengine-x86_64-SSE4-AVX2.exe"), // Cheat Engine
46 | _T("frida-helper-32.exe"), // Frida
47 | _T("frida-helper-64.exe"), // Frida
48 | _T("ghidra.exe"), // Ghidra
49 | _T("radare2.exe"), // radare2
50 | _T("r2.exe"), //
51 | _T("cutter.exe"), // Cutter
52 | _T("dnSpy.exe"), // DnSpy
53 | _T("dnSpyEx.exe"), //
54 | _T("ILSpy.exe"), // ILSpy
55 | _T("HxD.exe"), // HxD
56 | _T("SystemInformer.exe"), // System Informer
57 | _T("DetectItEasy.exe"), // DIE
58 | _T("FakeNet.exe"), // FakeNet-NG
59 | _T("ResourceHacker.exe"), // Resource editor
60 | };
61 |
62 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
63 | for (int i = 0; i < iLength; i++)
64 | {
65 | TCHAR msg[256] = _T("");
66 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking process of malware analysis tool: %s "), szProcesses[i]);
67 | if (GetProcessIdFromName(szProcesses[i]))
68 | print_results(TRUE, msg);
69 | else
70 | print_results(FALSE, msg);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/al-khaser/AntiAnalysis/process.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID analysis_tools_process();
4 |
5 | /*
6 |
7 | avpui.exe
8 | avgui.exe
9 | bdagent.exe
10 |
11 | */
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/BeingDebugged.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "BeingDebugged.h"
3 |
4 |
5 | BOOL
6 | IsDebuggerPresentPEB(
7 | VOID
8 | )
9 | /*++
10 |
11 | Routine Description:
12 |
13 | Checks if the BeingDebugged flag is set in the Process Environment Block (PEB).
14 | This is effectively the same code that IsDebuggerPresent() executes internally.
15 | The PEB pointer is fetched from DWORD FS:[0x30] on x86_32 and QWORD GS:[0x60] on x86_64.
16 |
17 | Arguments:
18 |
19 | None
20 |
21 | Return Value:
22 |
23 | TRUE - if debugger was detected
24 | FALSE - otherwise
25 | --*/
26 | {
27 | #if defined (ENV64BIT)
28 | PPEB pPeb = (PPEB)__readgsqword(0x60);
29 |
30 | #elif defined(ENV32BIT)
31 | PPEB pPeb = (PPEB)__readfsdword(0x30);
32 |
33 | #endif
34 |
35 | return pPeb->BeingDebugged == 1;
36 | }
37 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/BeingDebugged.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL IsDebuggerPresentPEB();
4 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/CheckRemoteDebuggerPresent.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CheckRemoteDebuggerPresent.h"
3 |
4 | BOOL
5 | CheckRemoteDebuggerPresentAPI (
6 | VOID
7 | )
8 | /*++
9 |
10 | Routine Description:
11 |
12 | CheckRemoteDebuggerPresent() is another Win32 Debugging API function;
13 | it can be used to check if a remote process is being debugged. However,
14 | we can also use this as another method for checking if our own process
15 | is being debugged. This API internally calls the NTDLL export
16 | NtQueryInformationProcess function with the PROCESSINFOCLASS set to
17 | 7 (ProcessDebugPort).
18 |
19 | Arguments:
20 |
21 | None
22 |
23 | Return Value:
24 |
25 | TRUE - if debugger was detected
26 | FALSE - otherwise
27 | --*/
28 | {
29 | BOOL bIsDbgPresent = FALSE;
30 | CheckRemoteDebuggerPresent(GetCurrentProcess(), &bIsDbgPresent);
31 | return bIsDbgPresent;
32 | }
33 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/CheckRemoteDebuggerPresent.h:
--------------------------------------------------------------------------------
1 | BOOL CheckRemoteDebuggerPresentAPI();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/CloseHandle_InvalidHandle.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 |
4 | /*
5 | APIs making use of the ZwClose syscall (such as CloseHandle, indirectly)
6 | can be used to detect a debugger. When a process is debugged, calling ZwClose
7 | with an invalid handle will generate a STATUS_INVALID_HANDLE (0xC0000008) exception.
8 | As with all anti-debugs that rely on information made directly available.
9 | */
10 |
11 |
12 | BOOL NtClose_InvalideHandle()
13 | {
14 | auto NtClose_ = static_cast(API::GetAPI(API_IDENTIFIER::API_NtClose));
15 |
16 | __try {
17 | NtClose_(reinterpret_cast(0x99999999ULL));
18 | }
19 | __except (EXCEPTION_EXECUTE_HANDLER) {
20 | return TRUE;
21 | }
22 |
23 | return FALSE;
24 |
25 | }
26 |
27 | BOOL CloseHandle_InvalideHandle()
28 | {
29 | // Let's try first with user mode API: CloseHandle
30 | __try {
31 | CloseHandle(reinterpret_cast(0x99999999ULL));
32 | }
33 | __except (EXCEPTION_EXECUTE_HANDLER) {
34 | return TRUE;
35 | }
36 |
37 | // Direct call to NtClose to bypass user mode hooks
38 | if (NtClose_InvalideHandle())
39 | return TRUE;
40 | else
41 | return FALSE;
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/CloseHandle_InvalidHandle.h:
--------------------------------------------------------------------------------
1 | BOOL CloseHandle_InvalideHandle();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/HardwareBreakpoints.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "HardwareBreakpoints.h"
4 |
5 | /*
6 | Hardware breakpoints are a technology implemented by Intel in their processor architecture,
7 | and are controlled by the use of special registers known as Dr0-Dr7.
8 | Dr0 through Dr3 are 32 bit registers that hold the address of the breakpoint .
9 | */
10 |
11 |
12 | BOOL HardwareBreakpoints()
13 | {
14 | BOOL bResult = FALSE;
15 |
16 | // This structure is key to the function and is the
17 | // medium for detection and removal
18 | PCONTEXT ctx = PCONTEXT(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE));
19 |
20 | if (ctx) {
21 |
22 | SecureZeroMemory(ctx, sizeof(CONTEXT));
23 |
24 | // The CONTEXT structure is an in/out parameter therefore we have
25 | // to set the flags so Get/SetThreadContext knows what to set or get.
26 | ctx->ContextFlags = CONTEXT_DEBUG_REGISTERS;
27 |
28 | // Get the registers
29 | if (GetThreadContext(GetCurrentThread(), ctx)) {
30 |
31 | // Now we can check for hardware breakpoints, its not
32 | // necessary to check Dr6 and Dr7, however feel free to
33 | if (ctx->Dr0 != 0 || ctx->Dr1 != 0 || ctx->Dr2 != 0 || ctx->Dr3 != 0)
34 | bResult = TRUE;
35 | }
36 |
37 | VirtualFree(ctx, 0, MEM_RELEASE);
38 | }
39 |
40 | return bResult;
41 | }
42 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/HardwareBreakpoints.h:
--------------------------------------------------------------------------------
1 | BOOL HardwareBreakpoints();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/Interrupt_0x2d.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Interrupt_0x2d.h"
4 |
5 | /*
6 | The Interrupt_0x2d function will check to see if a debugger is attached to the current process. It does this by setting up
7 | SEH and using the Int 2D instruction which will only cause an exception if there is no debugger. Also when used in OllyDBG
8 | it will skip a byte in the disassembly which could be used to detect the debugger.
9 |
10 | Vectored Exception Handling is used here because SEH is an anti-debug trick in itself.
11 | */
12 |
13 | extern "C" void __int2d();
14 |
15 | static BOOL SwallowedException = TRUE;
16 |
17 | static LONG CALLBACK VectoredHandler(
18 | _In_ PEXCEPTION_POINTERS ExceptionInfo
19 | )
20 | {
21 | SwallowedException = FALSE;
22 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
23 | {
24 | //The Int 2D instruction already increased EIP/RIP so we don't do that (although it wouldnt hurt).
25 | return EXCEPTION_CONTINUE_EXECUTION;
26 | }
27 | return EXCEPTION_CONTINUE_SEARCH;
28 | }
29 |
30 | BOOL Interrupt_0x2d()
31 | {
32 | PVOID Handle = AddVectoredExceptionHandler(1, VectoredHandler);
33 | SwallowedException = TRUE;
34 | __int2d();
35 | RemoveVectoredExceptionHandler(Handle);
36 | return SwallowedException;
37 | }
38 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/Interrupt_0x2d.h:
--------------------------------------------------------------------------------
1 | BOOL Interrupt_0x2d();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/Interrupt_3.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Interrupt_3.h"
4 |
5 | /*
6 | INT 3 generates a call to trap in the debugger and is triggered by opcode 0xCC within the executing process.
7 | When a debugger is attached, the 0xCC execution will cause the debugger to catch the breakpoint and handle
8 | the resulting exception. If a debugger is not attached, the exception is passed through to a structured
9 | exception handler thus informing the process that no debugger is present.
10 |
11 | Vectored Exception Handling is used here because SEH is an anti-debug trick in itself.
12 | */
13 |
14 | static BOOL SwallowedException = TRUE;
15 |
16 | static LONG CALLBACK VectoredHandler(
17 | _In_ PEXCEPTION_POINTERS ExceptionInfo
18 | )
19 | {
20 | SwallowedException = FALSE;
21 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
22 | {
23 | //Increase EIP/RIP to continue execution.
24 | #ifdef _WIN64
25 | ExceptionInfo->ContextRecord->Rip++;
26 | #else
27 | ExceptionInfo->ContextRecord->Eip++;
28 | #endif
29 | return EXCEPTION_CONTINUE_EXECUTION;
30 | }
31 | return EXCEPTION_CONTINUE_SEARCH;
32 | }
33 |
34 |
35 |
36 | BOOL Interrupt_3()
37 | {
38 | PVOID Handle = AddVectoredExceptionHandler(1, VectoredHandler);
39 | SwallowedException = TRUE;
40 | __debugbreak();
41 | RemoveVectoredExceptionHandler(Handle);
42 | return SwallowedException;
43 | }
44 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/Interrupt_3.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL Interrupt_3();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/IsDebuggerPresent.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "IsDebuggerPresent.h"
3 |
4 | BOOL
5 | IsDebuggerPresentAPI (
6 | VOID
7 | )
8 | /*++
9 |
10 | Routine Description:
11 |
12 | Calls the IsDebuggerPresent() API. This function is part of the
13 | Win32 Debugging API and it returns TRUE if a user mode debugger
14 | is present. Internally, it simply returns the value of the
15 | PEB->BeingDebugged flag.
16 |
17 | Arguments:
18 |
19 | None
20 |
21 | Return Value:
22 |
23 | TRUE - if debugger was detected
24 | FALSE - otherwise
25 | --*/
26 | {
27 | return IsDebuggerPresent();
28 | }
29 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/IsDebuggerPresent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL IsDebuggerPresentAPI();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/LowFragmentationHeap.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "LowFragmentationHeap.h"
3 |
4 |
5 | BOOL
6 | LowFragmentationHeap(
7 | VOID
8 | )
9 | /*++
10 |
11 | Routine Description:
12 | Originally found by Souhail Hammou:
13 | http://rce4fun.blogspot.com/2014/02/anti-debugging-trick-checking-for-low.html
14 | Under a debugger, the process does not have a Low Fragmentation Heap (LFH)
15 | The routine simply checks whether the nt!_HEAP.FrontEndHeap is NULL.
16 |
17 | Arguments:
18 |
19 | None
20 |
21 | Return Value:
22 |
23 | TRUE - if debugger was detected
24 | FALSE - otherwise
25 | --*/
26 | {
27 |
28 | PINT_PTR FrontEndHeap = NULL;
29 |
30 | // Get the default process heap.
31 | HANDLE hHeap = GetProcessHeap();
32 |
33 | // The FrontEndHeap offset of the _HEAP structure
34 | // is found on different locations depending of the OS.
35 |
36 | if (IsWindowsVista() || IsWindows7()) {
37 | #if defined (ENV64BIT)
38 | FrontEndHeap = (PINT_PTR)((CHAR*)hHeap + 0x178);
39 |
40 | #elif defined(ENV32BIT)
41 | FrontEndHeap = (PINT_PTR)((CHAR*)hHeap + 0xd4);
42 | #endif
43 | }
44 |
45 | if (IsWindows8or8PointOne()) {
46 | #if defined (ENV64BIT)
47 | FrontEndHeap = (PINT_PTR)((CHAR*)hHeap + 0x170);
48 |
49 | #elif defined(ENV32BIT)
50 | FrontEndHeap = (PINT_PTR)((CHAR*)hHeap + 0xd0);
51 | #endif
52 | }
53 |
54 | // In Windows 10. the offset changes very often.
55 | // Ignoring it from now.
56 | if (FrontEndHeap && *FrontEndHeap == NULL) {
57 | return TRUE;
58 | }
59 |
60 | return FALSE;
61 | }
62 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/LowFragmentationHeap.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL
4 | LowFragmentationHeap(
5 | VOID
6 | );
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/MemoryBreakpoints_PageGuard.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "MemoryBreakpoints_PageGuard.h"
4 |
5 | /*
6 | In essence, what occurs is that we allocate a dynamic buffer and write a RET to the buffer.
7 | We then mark the page as a guard page and push a potential return address onto the stack. Next, we jump to our page,
8 | and if we're under a debugger, specifically OllyDBG, then we will hit the RET instruction and return to the address we pushed onto
9 | the stack before we jumped to our page. Otherwise, a STATUS_GUARD_PAGE_VIOLATION exception will occur, and we know we're not being
10 | debugged by OllyDBG.
11 | */
12 |
13 | BOOL MemoryBreakpoints_PageGuard()
14 | {
15 | UCHAR *pMem = NULL;
16 | SYSTEM_INFO SystemInfo = { 0 };
17 | DWORD OldProtect = 0;
18 | PVOID pAllocation = NULL; // Get the page size for the system
19 |
20 | // Retrieves information about the current system.
21 | GetSystemInfo(&SystemInfo);
22 |
23 | // Allocate memory
24 | pAllocation = VirtualAlloc(NULL, SystemInfo.dwPageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
25 | if (pAllocation == NULL)
26 | return FALSE;
27 |
28 | // Write a ret to the buffer (opcode 0xc3)
29 | RtlFillMemory(pAllocation, 1, 0xC3);
30 |
31 | // Make the page a guard page
32 | if (VirtualProtect(pAllocation, SystemInfo.dwPageSize, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &OldProtect) == 0)
33 | return FALSE;
34 |
35 | __try
36 | {
37 | ((void(*)())pAllocation)(); // Exception or execution, which shall it be :D?
38 | }
39 | __except (GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
40 | {
41 | VirtualFree(pAllocation, 0, MEM_RELEASE);
42 | return FALSE;
43 | }
44 |
45 | VirtualFree(pAllocation, 0, MEM_RELEASE);
46 | return TRUE;
47 | }
48 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/MemoryBreakpoints_PageGuard.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL MemoryBreakpoints_PageGuard();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ModuleBoundsHookCheck.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL ModuleBoundsHookCheck();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtGlobalFlag.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "NtGlobalFlag.h"
3 |
4 |
5 | BOOL
6 | NtGlobalFlag (
7 | VOID
8 | )
9 | /*++
10 |
11 | Routine Description:
12 |
13 | NtGlobalFlag is a DWORD value inside the process PEB. This value
14 | contains many flags set by the OS that affects the way the process
15 | runs. When a process is being debugged, the flags:
16 | - FLG_HEAP_ENABLE_TAIL_CHECK (0x10)
17 | - FLG_HEAP_ENABLE_FREE_CHECK (0x20)
18 | - FLG_HEAP_VALIDATE_PARAMETERS(0x40) are set for the process
19 |
20 | If the 32-bit executable is being run on a 64-bit system, both the
21 | 32-bit and 64-bit PEBs are checked. The WoW64 PEB address is
22 | fetched via the WoW64 Thread Environment Block (TEB) at FS:[0x18]-0x2000.
23 |
24 | Arguments:
25 |
26 | None
27 |
28 | Return Value:
29 |
30 | TRUE - if debugger was detected
31 | FALSE - otherwise
32 | --*/
33 | {
34 | PDWORD pNtGlobalFlag = NULL, pNtGlobalFlagWoW64 = NULL;
35 |
36 | #if defined (ENV64BIT)
37 | pNtGlobalFlag = (PDWORD)(__readgsqword(0x60) + 0xBC);
38 |
39 | #elif defined(ENV32BIT)
40 | /* NtGlobalFlags for real 32-bits OS */
41 | BYTE* _teb32 = (BYTE*)__readfsdword(0x18);
42 | DWORD _peb32 = *(DWORD*)(_teb32 + 0x30);
43 | pNtGlobalFlag = (PDWORD)(_peb32 + 0x68);
44 |
45 | if (IsWoW64())
46 | {
47 | /* In Wow64, there is a separate PEB for the 32-bit portion and the 64-bit portion
48 | which we can double-check */
49 |
50 | BYTE* _teb64 = (BYTE*)__readfsdword(0x18) - 0x2000;
51 | DWORD64 _peb64 = *(DWORD64*)(_teb64 + 0x60);
52 | pNtGlobalFlagWoW64 = (PDWORD)(_peb64 + 0xBC);
53 | }
54 | #endif
55 |
56 | BOOL normalDetected = pNtGlobalFlag && *pNtGlobalFlag & 0x00000070;
57 | BOOL wow64Detected = pNtGlobalFlagWoW64 && *pNtGlobalFlagWoW64 & 0x00000070;
58 |
59 | if(normalDetected || wow64Detected)
60 | return TRUE;
61 | else
62 | return FALSE;
63 | }
64 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtGlobalFlag.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtGlobalFlag();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugFlags.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQueryInformationProcess_ProcessDebugFlags.h"
4 |
5 | /*
6 | When NtQueryProcessInformation is called with the ProcessDebugFlags class, the function will return the inverse of EPROCESS->NoDebugInherit,
7 | which means that if a debugger is present, then this function will return FALSE if the process is being debugged.
8 | */
9 |
10 | BOOL NtQueryInformationProcess_ProcessDebugFlags()
11 | {
12 | // ProcessDebugFlags
13 | const int ProcessDebugFlags = 0x1f;
14 |
15 | auto NtQueryInfoProcess = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryInformationProcess));
16 |
17 | // Other Vars
18 | NTSTATUS Status;
19 | DWORD NoDebugInherit = 0;
20 |
21 | Status = NtQueryInfoProcess(GetCurrentProcess(), ProcessDebugFlags, &NoDebugInherit, sizeof(DWORD), NULL);
22 | if (Status == 0x00000000 && NoDebugInherit == 0)
23 | return TRUE;
24 | else
25 | return FALSE;
26 | }
27 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugFlags.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtQueryInformationProcess_ProcessDebugFlags();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugObject.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQueryInformationProcess_ProcessDebugObject.h"
4 |
5 | /*
6 | This function uses NtQuerySystemInformation to try to retrieve a handle to the current process's debug object handle.
7 | If the function is successful it'll return true which means we're being debugged or it'll return false if it fails
8 | the process isn't being debugged
9 | */
10 |
11 | BOOL NtQueryInformationProcess_ProcessDebugObject()
12 | {
13 | // ProcessDebugObjectHandle
14 | const int ProcessDebugObjectHandle = 0x1e;
15 |
16 | auto NtQueryInfoProcess = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryInformationProcess));
17 |
18 | // Other Vars
19 | NTSTATUS Status;
20 | HANDLE hDebugObject = NULL;
21 |
22 | #if defined (ENV64BIT)
23 | DWORD dProcessInformationLength = sizeof(ULONG) * 2;
24 | DWORD64 IsRemotePresent = 0;
25 |
26 | #elif defined(ENV32BIT)
27 | DWORD dProcessInformationLength = sizeof(ULONG);
28 | DWORD32 IsRemotePresent = 0;
29 | #endif
30 |
31 | // Regular check
32 | Status = NtQueryInfoProcess(GetCurrentProcess(), ProcessDebugObjectHandle, &hDebugObject, dProcessInformationLength, NULL);
33 |
34 | if (Status != STATUS_PORT_NOT_SET)
35 | return TRUE;
36 | if (hDebugObject != NULL)
37 | return TRUE;
38 |
39 | // Check with overlapping return length and debug object handle buffers to find anti-anti-debuggers
40 | Status = NtQueryInfoProcess(GetCurrentProcess(), ProcessDebugObjectHandle, &hDebugObject, dProcessInformationLength, (PULONG)&hDebugObject);
41 | if (Status != STATUS_PORT_NOT_SET)
42 | return TRUE;
43 | if (hDebugObject == NULL)
44 | return TRUE; // Handle incorrectly zeroed
45 | if ((ULONG)(ULONG_PTR)hDebugObject != dProcessInformationLength)
46 | return TRUE; // Return length incorrectly overwritten
47 |
48 | return FALSE;
49 | }
50 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugObject.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtQueryInformationProcess_ProcessDebugObject();
4 |
5 | #define STATUS_PORT_NOT_SET ((NTSTATUS)0xC0000353L)
6 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugPort.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQueryInformationProcess_ProcessDebugPort.h"
4 |
5 | /*
6 | Instead of calling CheckRemoteDebuggerPresent an individual could also make directly the call to
7 | NtQueryInformationProcess process theirself.
8 | */
9 |
10 | BOOL NtQueryInformationProcess_ProcessDebugPort ()
11 | {
12 | auto NtQueryInfoProcess = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryInformationProcess));
13 |
14 | // ProcessDebugPort
15 | const int ProcessDbgPort = 7;
16 |
17 | // Other Vars
18 | NTSTATUS Status;
19 |
20 | #if defined (ENV64BIT)
21 | DWORD dProcessInformationLength = sizeof(ULONG) * 2;
22 | DWORD64 IsRemotePresent = 0;
23 |
24 | #elif defined(ENV32BIT)
25 | DWORD dProcessInformationLength = sizeof(ULONG);
26 | DWORD32 IsRemotePresent = 0;
27 | #endif
28 |
29 | Status = NtQueryInfoProcess(GetCurrentProcess(), ProcessDbgPort, &IsRemotePresent, dProcessInformationLength, NULL);
30 | if(Status == 0x00000000 && IsRemotePresent != 0)
31 | return TRUE;
32 | else
33 | return FALSE;
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryInformationProcess_ProcessDebugPort.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtQueryInformationProcess_ProcessDebugPort();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryObject_AllTypesInformation.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQueryObject_ObjectInformation.h"
4 |
5 | /*
6 | Windows XP introduced a "debug object". When a debugging session begins, a debug object is created,
7 | and a handle is associated with it. Using the ntdll NtQueryObject() function with class: ObjectAllTypesInformation.
8 | ObjectAllTypesInformation (3) will return a list with all existing object type, we should iterate over objects to
9 | locate "DebugObject". Todo: Support for Win10
10 | */
11 |
12 |
13 | BOOL NtQueryObject_ObjectAllTypesInformation()
14 | {
15 | //NOTE this check is unreliable, a debugger present on the system doesn't mean it's attached to you
16 |
17 | auto NtQueryObject = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryObject));
18 |
19 | // Some vars
20 | ULONG size;
21 | PVOID pMemory = NULL;
22 | POBJECT_ALL_INFORMATION pObjectAllInfo = NULL;
23 | NTSTATUS Status;
24 |
25 | // Get the size of the information needed
26 | Status = NtQueryObject(NULL, 3, &size, sizeof(ULONG), &size);
27 |
28 | // Alocate memory for the list
29 | pMemory = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
30 | if (pMemory == NULL)
31 | return FALSE;
32 |
33 | // Now we can actually retrieve the list
34 | Status = NtQueryObject((HANDLE)-1, 3, pMemory, size, NULL);
35 |
36 | // Status != STATUS_SUCCESS
37 | if (Status != 0x00000000)
38 | {
39 | VirtualFree(pMemory, 0, MEM_RELEASE);
40 | return FALSE;
41 | }
42 |
43 | // We have the information we need
44 | pObjectAllInfo = (POBJECT_ALL_INFORMATION)pMemory;
45 | UCHAR *pObjInfoLocation = (UCHAR*)pObjectAllInfo->ObjectTypeInformation;
46 | ULONG NumObjects = pObjectAllInfo->NumberOfObjects;
47 |
48 | for (UINT i = 0; i < NumObjects; i++)
49 | {
50 |
51 | POBJECT_TYPE_INFORMATION pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)pObjInfoLocation;
52 |
53 | // The debug object will always be present
54 | if (StrCmp(_T("DebugObject"), pObjectTypeInfo->TypeName.Buffer) == 0)
55 | {
56 | // Are there any objects?
57 | if (pObjectTypeInfo->TotalNumberOfObjects > 0)
58 | {
59 | VirtualFree(pMemory, 0, MEM_RELEASE);
60 | return TRUE;
61 | }
62 | else
63 | {
64 | VirtualFree(pMemory, 0, MEM_RELEASE);
65 | return FALSE;
66 | }
67 | }
68 |
69 | // Get the address of the current entries
70 | // string so we can find the end
71 | pObjInfoLocation = (unsigned char*)pObjectTypeInfo->TypeName.Buffer;
72 |
73 | // Add the size
74 | pObjInfoLocation += pObjectTypeInfo->TypeName.MaximumLength;
75 |
76 | // Skip the trailing null and alignment bytes
77 | ULONG_PTR tmp = ((ULONG_PTR)pObjInfoLocation) & -(int)sizeof(void*);
78 |
79 | // Not pretty but it works
80 | if ((ULONG_PTR)tmp != (ULONG_PTR)pObjInfoLocation)
81 | tmp += sizeof(void*);
82 | pObjInfoLocation = ((unsigned char*)tmp);
83 | }
84 |
85 | VirtualFree(pMemory, 0, MEM_RELEASE);
86 | return FALSE;
87 | }
88 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryObject_ObjectInformation.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtQueryObject_ObjectAllTypesInformation();
4 | BOOL NtQueryObject_ObjectTypeInformation();
5 |
6 |
7 | #define DEBUG_READ_EVENT 0x0001
8 | #define DEBUG_PROCESS_ASSIGN 0x0002
9 | #define DEBUG_SET_INFORMATION 0x0004
10 | #define DEBUG_QUERY_INFORMATION 0x0008
11 | #define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
12 | DEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \
13 | DEBUG_QUERY_INFORMATION)
14 |
15 | typedef struct _OBJECT_TYPE_INFORMATION {
16 | UNICODE_STRING TypeName;
17 | ULONG TotalNumberOfHandles;
18 | ULONG TotalNumberOfObjects;
19 | }OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
20 |
21 | typedef struct _OBJECT_ALL_INFORMATION {
22 | ULONG NumberOfObjects;
23 | OBJECT_TYPE_INFORMATION ObjectTypeInformation[1];
24 | }OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION;
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQueryObject_ObjectTypeInformation.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQueryObject_ObjectInformation.h"
4 |
5 | /*
6 | Windows XP introduced a "debug object". When a debugging session begins, a debug object is created,
7 | and a handle is associated with it. Using the ntdll NtQueryObject() function with class: ObjectTypeInformation.
8 | ObjectTypeInformation will return the type information of the supplied handle.
9 | */
10 |
11 |
12 | BOOL NtQueryObject_ObjectTypeInformation()
13 | {
14 | //NOTE this check now only detects if NtQueryObject is hooked to set ObjectInformation->TotalNumberOfObjects = 0
15 |
16 | // We have to import the function
17 | auto NtQueryObject = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryObject));
18 | auto NtCreateDebugObject = static_cast(API::GetAPI(API_IDENTIFIER::API_NtCreateDebugObject));
19 |
20 | // Some vars
21 | HANDLE DebugObjectHandle;
22 | OBJECT_ATTRIBUTES ObjectAttributes;
23 | InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
24 | BYTE memory[0x1000] = { 0 };
25 | POBJECT_TYPE_INFORMATION ObjectInformation = (POBJECT_TYPE_INFORMATION)memory;
26 | NTSTATUS Status;
27 |
28 | NtCreateDebugObject(&DebugObjectHandle, DEBUG_ALL_ACCESS, &ObjectAttributes, FALSE);
29 |
30 | if (API::IsAvailable(API_IDENTIFIER::API_NtQueryObject))
31 | {
32 | Status = NtQueryObject(DebugObjectHandle, ObjectTypeInformation, ObjectInformation, sizeof(memory), 0);
33 |
34 | // Make sure to not screw up later checks
35 | CloseHandle(DebugObjectHandle);
36 |
37 |
38 | if (Status >= 0)
39 | {
40 | if (ObjectInformation->TotalNumberOfObjects == 0)
41 | return TRUE; //There should be at least one object (we just created it).
42 | else
43 | return FALSE;
44 | }
45 | else
46 | {
47 | //NOTE: this should actually never happen on a valid handle (so this check can be bypassed by failing NtQueryObject)
48 | return FALSE;
49 | }
50 | }
51 | else
52 | return FALSE;
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQuerySystemInformation_SystemKernelDebuggerInformation.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtQuerySystemInformation_SystemKernelDebuggerInformation.h"
4 |
5 | /*
6 | When NtQuerySystemInformation is called with the SystemKernelDebuggerInformation class, the function will return
7 | a SYSTEM_KERNEL_DEBUGGER_INFORMATION struct which will reveal the presence of a kernel debugger.
8 | */
9 |
10 | BOOL NtQuerySystemInformation_SystemKernelDebuggerInformation()
11 | {
12 | // SystemKernelDebuggerInformation
13 | const int SystemKernelDebuggerInformation = 0x23;
14 |
15 | // The debugger information struct
16 | SYSTEM_KERNEL_DEBUGGER_INFORMATION KdDebuggerInfo;
17 |
18 | auto NtQuerySystemInformation = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQuerySystemInformation));
19 |
20 | // Call NtQuerySystemInformation
21 | NTSTATUS Status = NtQuerySystemInformation(SystemKernelDebuggerInformation, &KdDebuggerInfo, sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION), NULL);
22 | if (Status >= 0)
23 | {
24 | // KernelDebuggerEnabled almost always implies !KernelDebuggerNotPresent. KernelDebuggerNotPresent can sometimes
25 | // change if the debugger is temporarily disconnected, but either of these means a debugger is enabled.
26 | if (KdDebuggerInfo.KernelDebuggerEnabled || !KdDebuggerInfo.KernelDebuggerNotPresent)
27 | return TRUE;
28 | }
29 | return FALSE;
30 | }
31 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtQuerySystemInformation_SystemKernelDebuggerInformation.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtQuerySystemInformation_SystemKernelDebuggerInformation();
4 |
5 | typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
6 | {
7 | BOOLEAN KernelDebuggerEnabled;
8 | BOOLEAN KernelDebuggerNotPresent;
9 | } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtSetInformationThread_ThreadHideFromDebugger.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtSetInformationThread_ThreadHideFromDebugger.h"
4 |
5 | /*
6 | Calling NtSetInformationThread will attempt with ThreadInformationClass set to x11 (ThreadHideFromDebugger)
7 | to hide a thread from the debugger, Passing NULL for hThread will cause the function to hide the thread the
8 | function is running in. Also, the function returns false on failure and true on success. When the function
9 | is called, the thread will continue to run but a debugger will no longer receive any events related to that thread.
10 |
11 | These checks also look for hooks on the NtSetInformationThread API that try to block ThreadHideFromDebugger.
12 | */
13 |
14 | #ifndef STATUS_INFO_LENGTH_MISMATCH
15 | #define STATUS_INFO_LENGTH_MISMATCH ((DWORD)0xC0000004L)
16 | #endif
17 | #ifndef STATUS_DATATYPE_MISALIGNMENT
18 | #define STATUS_DATATYPE_MISALIGNMENT ((DWORD)0x80000002L)
19 | #endif
20 |
21 |
22 | BOOL NtSetInformationThread_ThreadHideFromDebugger()
23 | {
24 | // this is needed because the bool data type can be at unaligned memory locations, whereas the NtQueryInformationThread API expects 32-bit aligned pointers.
25 | struct AlignedBool
26 | {
27 | alignas(4) bool Value;
28 | };
29 |
30 | // ThreadHideFromDebugger
31 | const int ThreadHideFromDebugger = 0x11;
32 |
33 | auto NtSetInformationThread = static_cast(API::GetAPI(API_IDENTIFIER::API_NtSetInformationThread));
34 | auto NtQueryInformationThread = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryInformationThread));
35 |
36 | NTSTATUS Status;
37 | bool doQITcheck = false;
38 |
39 | // only do the QueryInformationThread check if we're on Vista and the API is available.
40 | // this is because the ThreadHideFromDebugger class can only be queried from Vista onwards.
41 | if (API::IsAvailable(API_IDENTIFIER::API_NtQueryInformationThread))
42 | {
43 | doQITcheck = IsWindowsVistaOrGreater();
44 | }
45 |
46 | AlignedBool isThreadHidden;
47 | isThreadHidden.Value = false;
48 |
49 | // First issue a bogus call with an incorrect length parameter. If it succeeds, we know NtSetInformationThread was hooked.
50 | Status = NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, &isThreadHidden, 12345);
51 | if (Status == 0)
52 | return TRUE;
53 |
54 | // Next try again but give it a bogus thread handle. If it succeeds, again we know NtSetInformationThread was hooked.
55 | Status = NtSetInformationThread((HANDLE)0xFFFF, ThreadHideFromDebugger, NULL, 0);
56 | if (Status == 0)
57 | return TRUE;
58 |
59 | // Now try a legitimate call.
60 | Status = NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);
61 |
62 | if (Status == 0)
63 | {
64 | if (doQITcheck)
65 | {
66 | // note: the ThreadHideFromDebugger query expects a bool (1 byte), not a BOOL (4 bytes)
67 | // if a BOOL is used, the kernel returns 0xC0000004 (STATUS_INFO_LENGTH_MISMATCH) because BOOL is typedef int.
68 |
69 | // first do a legitimate call. this should succeed or return an error such as access denied.
70 | Status = NtQueryInformationThread(GetCurrentThread(), ThreadHideFromDebugger, &isThreadHidden.Value, sizeof(bool), NULL);
71 |
72 | // this shouldn't happen, because we used the correct length. this will only happen if a buggy hook mistakenly expects a BOOL rather than a bool.
73 | if (Status == STATUS_INFO_LENGTH_MISMATCH)
74 | {
75 | // we found a buggy hook that expects some size other than 1
76 | return TRUE;
77 | }
78 |
79 | // if the legitimate call succeeded, continue with additional bogus API call checks
80 | if (Status == 0)
81 | {
82 | AlignedBool bogusIsThreadHidden;
83 | bogusIsThreadHidden.Value = false;
84 |
85 | // now do a bogus call with the wrong size. this will catch buggy hooks that accept BOOL (4 bytes) or just don't have any size checks
86 | Status = NtQueryInformationThread(GetCurrentThread(), ThreadHideFromDebugger, &bogusIsThreadHidden.Value, sizeof(BOOL), NULL);
87 | if (Status != STATUS_INFO_LENGTH_MISMATCH)
88 | {
89 | // we found a buggy hook that allows for incorrect size values
90 | return TRUE;
91 | }
92 |
93 | // NtQueryInformationThread explicitly requires the ThreadInformation pointer to be aligned. as such, it should reject unaligned pointers.
94 | // hooks are almost certainly guaranteed to not retain this behaviour, so it's a very nice way to catch them out.
95 | const size_t UnalignedCheckCount = 8;
96 | bool bogusUnalignedValues[UnalignedCheckCount];
97 | int alignmentErrorCount = 0;
98 | #if _WIN64
99 | // on 64-bit, up to two elements in the array should be aligned.
100 | const size_t MaxAlignmentCheckSuccessCount = 2;
101 | #else
102 | // on 32-bit, there should be either two or four aligned elements (unsure how WoW64 affects this, so I'm just gonna assume 2 or 4 are ok)
103 | const size_t MaxAlignmentCheckSuccessCount = 4;
104 | #endif
105 | for (size_t i = 0; i < UnalignedCheckCount; i++)
106 | {
107 | Status = NtQueryInformationThread(GetCurrentThread(), ThreadHideFromDebugger, &(bogusUnalignedValues[i]), sizeof(BOOL), NULL);
108 | if (Status == STATUS_DATATYPE_MISALIGNMENT)
109 | {
110 | alignmentErrorCount++;
111 | }
112 | }
113 | // if there weren't enough alignment errors, we know that the API must be hooked and not checking alignment properly!
114 | if (UnalignedCheckCount - MaxAlignmentCheckSuccessCount > alignmentErrorCount)
115 | {
116 | return TRUE;
117 | }
118 |
119 | // the legitimate call was successful, and the bogus call was unsuccessful, so return false (no detection) if the HideFromDebugger flag was properly set.
120 | // if the HideFromDebugger flag was not set, i.e. the NtSetInformationThread call lied to us about being successful, then return true (debugger/hook detected)
121 | return isThreadHidden.Value ? FALSE : TRUE;
122 | }
123 | }
124 | }
125 | else
126 | {
127 | // call failed, should've succeeded
128 | return TRUE;
129 | }
130 |
131 | // we didn't find any hooks.
132 | return FALSE;
133 | }
134 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtSetInformationThread_ThreadHideFromDebugger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtSetInformationThread_ThreadHideFromDebugger();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtSystemDebugControl.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | BOOL NtSystemDebugControl_Command() {
4 | auto NtSystemDebugControl_ = static_cast(API::GetAPI(API_IDENTIFIER::API_NtSystemDebugControl));
5 |
6 | auto status = NtSystemDebugControl_(SYSDBG_COMMAND::SysDbgCheckLowMemory, 0, 0, 0, 0, 0);
7 |
8 | const auto STATUS_DEBUGGER_INACTIVE = 0xC0000354L;
9 | const auto STATUS_ACCESS_DENIED = 0xC0000022L;
10 | const auto STATUS_NOT_IMPLEMENTED = 0xC0000002L;
11 |
12 | // some windows build not supports SysDbgCheckLowMemory which returns 0xC0000002L
13 | if (status == STATUS_DEBUGGER_INACTIVE || status == STATUS_NOT_IMPLEMENTED) {
14 | return FALSE;
15 | } else {
16 | // kernel debugger found
17 | if (status != STATUS_ACCESS_DENIED) {
18 | // usermode debugger too
19 | }
20 | return TRUE;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtSystemDebugControl.h:
--------------------------------------------------------------------------------
1 | BOOL NtSystemDebugControl_Command();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtYieldExecution.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "NtYieldExecution.h"
3 |
4 | /*
5 | The ntdll function NtYieldExecution or its kernel32 equivalent SwitchToThread function allows the current
6 | thread to offer to give up the rest of its time slice, and allow the next scheduled thread to
7 | execute. If no threads are scheduled to execute (or when the system is busy in particular ways and will
8 | not allow a switch to occur), then the ntdll NtYieldExecution() function returns the
9 | STATUS_NO_YIELD_PERFORMED (0x40000024) status, which causes the kernel32 SwitchToThread() function to
10 | return a zero. When an application is being debugged, the act of single-stepping through the
11 | code causes debug events and often results in no yield being allowed. However, this is a hopelessly
12 | unreliable method for detecting a debugger because it will also detect the presence of a thread that is running with high priority.
13 | */
14 |
15 |
16 | BOOL NtYieldExecutionAPI()
17 | {
18 | //NOTE: this check is unreliable, don't actually use this in a real environment
19 |
20 | auto NtYieldExecution = static_cast(API::GetAPI(API_IDENTIFIER::API_NtYieldExecution));
21 |
22 | INT iDebugged = 0;
23 |
24 | for (int i = 0; i < 0x20; i++)
25 | {
26 | Sleep(0xf);
27 |
28 | if (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED)
29 | iDebugged++;
30 | }
31 |
32 | if (iDebugged <= 3)
33 | return FALSE;
34 | else
35 | return TRUE;
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/NtYieldExecution.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define STATUS_NO_YIELD_PERFORMED 0x40000024
4 |
5 | BOOL NtYieldExecutionAPI();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/OutputDebugStringAPI.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "OutputDebugStringAPI.h"
4 |
5 | /*
6 | OutputDebugString() is typically used to output a string value to the debugging data stream.
7 | This string is then displayed in the debugger. Due to this fact, the function OutputDebugString()
8 | acts differently based on the existence of a debugger on the running process. If a debugger is
9 | attached to the process, the function will execute normally and no error state will be registered;
10 | however if there is no debugger attached, LastError will be set by the process letting us know that
11 | we are debugger free. To execute this method we set LastError to an arbitrary value of our choosing
12 | and then call OutputDebugString(). We then check GetLastError() and if our error code remains,
13 | we know we are debugger free. This Works only in Windows XP/2000
14 | */
15 |
16 | BOOL OutputDebugStringAPI()
17 | {
18 |
19 | BOOL IsDbgPresent = FALSE;
20 | DWORD Val = 0x29A;
21 |
22 | // This is working only in Windows XP/2000
23 | if (IsWindowsXPOr2k())
24 | {
25 | SetLastError(Val);
26 | OutputDebugString(_T("random"));
27 |
28 | if (GetLastError() == Val)
29 | IsDbgPresent = TRUE;
30 | }
31 |
32 | return IsDbgPresent;
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/OutputDebugStringAPI.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL OutputDebugStringAPI();
4 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/PageExceptionBreakpointCheck.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #ifdef _DEBUG
4 | #define OutputDebugStringDbgOnly(S) OutputDebugString(S)
5 | #else
6 | #define OutputDebugStringDbgOnly(S) do {} while(0);
7 | #endif
8 |
9 | std::vector executablePages = {};
10 |
11 | void PageExceptionInitialEnum()
12 | {
13 | SYSTEM_INFO sysInfo;
14 | GetSystemInfo(&sysInfo);
15 | size_t pageSize = sysInfo.dwPageSize;
16 |
17 | HMODULE hMainModule;
18 | MODULEINFO moduleInfo;
19 |
20 | MEMORY_BASIC_INFORMATION memInfo = { 0 };
21 |
22 | // Get the main module handle from an address stored within it (pointer to this method)
23 | if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)PageExceptionBreakpointCheck, &hMainModule))
24 | {
25 | // Get information about the main module (we want to know the size of it)
26 | if (GetModuleInformation(GetCurrentProcess(), hMainModule, &moduleInfo, sizeof(MODULEINFO)))
27 | {
28 | // cast the module to a pointer
29 | unsigned char* module = static_cast(moduleInfo.lpBaseOfDll);
30 | for (size_t ofs = 0; ofs < moduleInfo.SizeOfImage; ofs += pageSize)
31 | {
32 | if (VirtualQuery(module + ofs, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) >= sizeof(MEMORY_BASIC_INFORMATION))
33 | {
34 | if ((memInfo.Protect & PAGE_EXECUTE) == PAGE_EXECUTE ||
35 | (memInfo.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ ||
36 | (memInfo.Protect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY ||
37 | (memInfo.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE)
38 | {
39 | executablePages.push_back(module + ofs);
40 | }
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
47 | BOOL PageExceptionBreakpointCheck()
48 | {
49 | SYSTEM_INFO sysInfo;
50 | GetSystemInfo(&sysInfo);
51 | size_t pageSize = sysInfo.dwPageSize;
52 |
53 | HMODULE hMainModule;
54 | MODULEINFO moduleInfo;
55 |
56 | MEMORY_BASIC_INFORMATION memInfo = { 0 };
57 |
58 | wchar_t buffer[512];
59 |
60 | // first we check if any of the pages are executable+guard or noaccess
61 |
62 | // Get the main module handle from an address stored within it (pointer to this method)
63 | if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)PageExceptionBreakpointCheck, &hMainModule))
64 | {
65 | // Get information about the main module (we want to know the size of it)
66 | if (GetModuleInformation(GetCurrentProcess(), hMainModule, &moduleInfo, sizeof(MODULEINFO)))
67 | {
68 | // cast the module to a pointer
69 | unsigned char* module = static_cast(moduleInfo.lpBaseOfDll);
70 | for (size_t ofs = 0; ofs < moduleInfo.SizeOfImage; ofs += pageSize)
71 | {
72 | SecureZeroMemory(buffer, 512);
73 | wsprintf(buffer, L"Scanning %p... ", module + ofs);
74 | OutputDebugStringDbgOnly(buffer);
75 | if (VirtualQuery(module + ofs, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) >= sizeof(MEMORY_BASIC_INFORMATION))
76 | {
77 | if (memInfo.AllocationProtect == 0)
78 | OutputDebugStringDbgOnly(L"^ AllocationProtect is zero. Potential shenanigans.");
79 | if (memInfo.Protect == 0)
80 | OutputDebugStringDbgOnly(L"^ Protect is zero. Potential shenanigans.");
81 |
82 | if ((memInfo.Protect & PAGE_EXECUTE) == PAGE_EXECUTE ||
83 | (memInfo.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ ||
84 | (memInfo.Protect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY ||
85 | (memInfo.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE)
86 | {
87 | // this is an executable page
88 | OutputDebugStringDbgOnly(L"^ is executable.");
89 |
90 | if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD ||
91 | (memInfo.AllocationProtect & PAGE_GUARD) == PAGE_GUARD)
92 | {
93 | // this is an executable guard page, page exception debugging detected
94 | OutputDebugStringDbgOnly(L"^ is guard page !!!!!!");
95 | return TRUE;
96 | }
97 | }
98 |
99 | if ((memInfo.Protect & PAGE_NOACCESS) == PAGE_NOACCESS)
100 | {
101 | // this is a NOACCESS page, which shouldn't exist here (alternative way to set page exception BPs)
102 | OutputDebugStringDbgOnly(L"^ is NOACCESS !!!!!!!");
103 | return TRUE;
104 | }
105 | }
106 | else OutputDebugStringDbgOnly(L"^ FAILED!");
107 | }
108 | }
109 |
110 | OutputDebugStringDbgOnly(L"Moving on to delta check...");
111 |
112 | for (PVOID page : executablePages)
113 | {
114 | SecureZeroMemory(buffer, 512);
115 | wsprintf(buffer, L"Scanning delta for %p... ", page);
116 | OutputDebugStringDbgOnly(buffer);
117 |
118 | if (VirtualQuery(page, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) >= sizeof(MEMORY_BASIC_INFORMATION))
119 | {
120 | if (memInfo.AllocationProtect == 0)
121 | OutputDebugStringDbgOnly(L"^ AllocationProtect is zero. Potential shenanigans.");
122 | if (memInfo.Protect == 0)
123 | OutputDebugStringDbgOnly(L"^ Protect is zero. Potential shenanigans.");
124 |
125 | if (!((memInfo.Protect & PAGE_EXECUTE) == PAGE_EXECUTE ||
126 | (memInfo.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ ||
127 | (memInfo.Protect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY ||
128 | (memInfo.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE))
129 | {
130 | // page was executable, now isn't!
131 | OutputDebugStringDbgOnly(L"^ was executable, now isn't !!!!!!");
132 | return TRUE;
133 | }
134 | }
135 | }
136 | }
137 |
138 | return FALSE;
139 | }
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/PageExceptionBreakpointCheck.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void PageExceptionInitialEnum();
4 | BOOL PageExceptionBreakpointCheck();
5 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ParentProcess.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ParentProcess.h"
3 |
4 | #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
5 | #include
6 |
7 | DWORD GetExplorerPIDbyShellWindow()
8 | {
9 | DWORD dwProcessId = 0;
10 |
11 | // Get the PID of explorer by its windows handle
12 | GetWindowThreadProcessId(GetShellWindow(), &dwProcessId);
13 |
14 | return dwProcessId;
15 | }
16 |
17 | DWORD GetParentProcessId()
18 | {
19 | auto NtQueryInfoProcess = static_cast(API::GetAPI(API_IDENTIFIER::API_NtQueryInformationProcess));
20 |
21 | NTSTATUS Status = 0;
22 | ALK_PROCESS_BASIC_INFORMATION pbi;
23 | SecureZeroMemory(&pbi, sizeof(ALK_PROCESS_BASIC_INFORMATION));
24 |
25 | const UINT ProcessBasicInformation = 0;
26 |
27 | Status = NtQueryInfoProcess(GetCurrentProcess(), ProcessBasicInformation, (PVOID)&pbi, sizeof(ALK_PROCESS_BASIC_INFORMATION), 0);
28 |
29 | if (Status != 0)
30 | {
31 | return 0;
32 | }
33 | else
34 | {
35 | return (DWORD)pbi.ParentProcessId;
36 | }
37 | }
38 |
39 | BOOL IsParentExplorerExe()
40 | {
41 | // this check will throw a false positive if you're running an alternative shell.
42 |
43 | DWORD parentPid = GetParentProcessId();
44 |
45 | bool parentPidEqualsExplorerPid = false;
46 |
47 | if (parentPid > 0)
48 | {
49 | // first check
50 | HANDLE hParent = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, parentPid);
51 | if (hParent != INVALID_HANDLE_VALUE)
52 | {
53 | WCHAR winDir[MAX_PATH];
54 | WCHAR parentProcessPath[MAX_PATH];
55 | if (GetModuleFileNameExW(hParent, NULL, parentProcessPath, MAX_PATH) && GetWindowsDirectory(winDir, MAX_PATH))
56 | {
57 | CloseHandle(hParent);
58 |
59 | // get path to X:\Windows\explorer.exe
60 | auto expectedPath = std::experimental::filesystem::path(winDir);
61 | expectedPath = expectedPath.append("explorer.exe");
62 |
63 | // get path to parent process
64 | auto actualPath = std::experimental::filesystem::path(parentProcessPath);
65 |
66 | // if the paths are equivalent, no detection.
67 | return std::experimental::filesystem::equivalent(expectedPath, actualPath) ? FALSE : TRUE;
68 | }
69 | CloseHandle(hParent);
70 | }
71 |
72 | // if the first check couldn't be completed, fall back to the shell window approach.
73 | // this check is less ideal because it throws false positives if you have explorer process isolation enabled (i.e. one process per explorer window)
74 | DWORD explorerPid = GetExplorerPIDbyShellWindow();
75 | if (explorerPid > 0)
76 | {
77 | if (parentPid != explorerPid)
78 | {
79 | return TRUE;
80 | }
81 | }
82 | }
83 |
84 | return FALSE;
85 | }
86 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ParentProcess.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef struct _ALK_PROCESS_BASIC_INFORMATION {
4 | PVOID Reserved1;
5 | void* PebBaseAddress;
6 | PVOID Reserved2[2];
7 | ULONG_PTR UniqueProcessId;
8 | ULONG_PTR ParentProcessId;
9 | } ALK_PROCESS_BASIC_INFORMATION;
10 |
11 | BOOL IsParentExplorerExe();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessHeap_Flags.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "ProcessHeap_Flags.h"
4 |
5 | /*
6 | When a program is run under a debugger, and is created using the debug process creation flags, the heap flags are changed.
7 | These Flags exit at a different location depending upon the version of the operating system.
8 | On Windows XP, these flags exist at 0x0C offset from heap base in 32bit system and offset 0x14 in 64bits
9 | On Windows 7, these flags exist at 0x40 offset from heap base in 32bit system and offset 0x70 in 64bits.
10 | */
11 |
12 | #if defined (ENV64BIT)
13 | PUINT32 GetHeapFlags_x64()
14 | {
15 | PINT64 pProcessHeap = NULL;
16 | PUINT32 pHeapFlags = NULL;
17 | if (IsWindowsVistaOrGreater()){
18 | pProcessHeap = (PINT64)(__readgsqword(0x60) + 0x30);
19 | pHeapFlags = (PUINT32)(*pProcessHeap + 0x70);
20 | }
21 |
22 | else {
23 | pProcessHeap = (PINT64)(__readgsqword(0x60) + 0x30);
24 | pHeapFlags = (PUINT32)(*pProcessHeap + 0x14);
25 | }
26 |
27 | return pHeapFlags;
28 | }
29 |
30 | #elif defined(ENV32BIT)
31 | PUINT32 GetHeapFlags_x86()
32 | {
33 | PUINT32 pProcessHeap, pHeapFlags = NULL;
34 |
35 | if (IsWindowsVistaOrGreater()){
36 | pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
37 | pHeapFlags = (PUINT32)(*pProcessHeap + 0x40);
38 | }
39 |
40 | else {
41 | pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
42 | pHeapFlags = (PUINT32)(*pProcessHeap + 0x0C);
43 | }
44 |
45 | return pHeapFlags;
46 | }
47 | #endif
48 |
49 |
50 | BOOL HeapFlags()
51 | {
52 | PUINT32 pHeapFlags = NULL;
53 |
54 | #if defined (ENV64BIT)
55 | pHeapFlags = GetHeapFlags_x64();
56 |
57 | #elif defined(ENV32BIT)
58 | pHeapFlags = GetHeapFlags_x86();
59 |
60 | #endif
61 |
62 | if (*pHeapFlags > 2)
63 | return TRUE;
64 | else
65 | return FALSE;
66 | }
67 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessHeap_Flags.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL HeapFlags();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessHeap_ForceFlags.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "ProcessHeap_ForceFlags.h"
4 |
5 | /*
6 | When a program is run under a debugger, and is created using the debug process creation flags. The heap flags are changed.
7 | These Flags exit at a different location depending upon the version of the operating system.
8 | On Windows XP, these flags exist at 0x10 offset from heap base in 32bit system and offset 0x18 in bits.
9 | On Windows 7, these flags exist at 0x44 offset from heap base in 32bit system and offset 0x74 in 64bits.
10 | */
11 |
12 |
13 | #if defined (ENV64BIT)
14 | PUINT32 GetForceFlags_x64()
15 | {
16 | PINT64 pProcessHeap = NULL;
17 | PUINT32 pHeapForceFlags = NULL;
18 | if (IsWindowsVistaOrGreater()){
19 | pProcessHeap = (PINT64)(__readgsqword(0x60) + 0x30);
20 | pHeapForceFlags = (PUINT32)(*pProcessHeap + 0x74);
21 | }
22 |
23 | else {
24 | pProcessHeap = (PINT64)(__readgsqword(0x60) + 0x30);
25 | pHeapForceFlags = (PUINT32)(*pProcessHeap + 0x18);
26 | }
27 |
28 | return pHeapForceFlags;
29 | }
30 |
31 | #elif defined(ENV32BIT)
32 | PUINT32 GetForceFlags_x86()
33 | {
34 | PUINT32 pProcessHeap, pHeapForceFlags = NULL;
35 | if (IsWindowsVistaOrGreater())
36 | {
37 | pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
38 | pHeapForceFlags = (PUINT32)(*pProcessHeap + 0x44);
39 |
40 | }
41 |
42 | else {
43 | pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
44 | pHeapForceFlags = (PUINT32)(*pProcessHeap + 0x10);
45 | }
46 |
47 | return pHeapForceFlags;
48 | }
49 | #endif
50 |
51 | BOOL HeapForceFlags()
52 | {
53 | PUINT32 pHeapForceFlags = NULL;
54 |
55 | #if defined (ENV64BIT)
56 | pHeapForceFlags = GetForceFlags_x64();
57 |
58 | #elif defined(ENV32BIT)
59 | pHeapForceFlags = GetForceFlags_x86();
60 |
61 | #endif
62 |
63 | if (*pHeapForceFlags > 0)
64 | return TRUE;
65 | else
66 | return FALSE;
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessHeap_ForceFlags.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL HeapForceFlags();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessJob.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "ProcessJob.h"
4 |
5 | /*
6 | * ProcessJob - Contributed by Graham Sutherland (https://github.com/gsuberland)
7 | *
8 | * Checks whether the process is part of a job object and, if so, any non-whitelisted processes are part of that job.
9 | *
10 | * Debuggers and other analysis applications usually place processes inside a job so that child processes will exit
11 | * when the parent process exits.
12 | * You can observe this with Visual Studio by running al-khaser with Debug -> Start Without Debugging.
13 | *
14 | */
15 |
16 | BOOL ProcessJob()
17 | {
18 | BOOL foundProblem = FALSE;
19 |
20 | DWORD jobProcessStructSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 1024;
21 | JOBOBJECT_BASIC_PROCESS_ID_LIST* jobProcessIdList = static_cast(malloc(jobProcessStructSize));
22 |
23 | if (jobProcessIdList) {
24 |
25 | SecureZeroMemory(jobProcessIdList, jobProcessStructSize);
26 |
27 | jobProcessIdList->NumberOfProcessIdsInList = 1024;
28 |
29 | if (QueryInformationJobObject(NULL, JobObjectBasicProcessIdList, jobProcessIdList, jobProcessStructSize, NULL))
30 | {
31 | int ok_processes = 0;
32 | for (DWORD i = 0; i < jobProcessIdList->NumberOfAssignedProcesses; i++)
33 | {
34 | ULONG_PTR processId = jobProcessIdList->ProcessIdList[i];
35 |
36 | // is this the current process? if so that's ok
37 | if (processId == (ULONG_PTR)GetCurrentProcessId())
38 | {
39 | ok_processes++;
40 | }
41 | else
42 | {
43 |
44 | // find the process name for this job process
45 | HANDLE hJobProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)processId);
46 | if (hJobProcess != NULL)
47 | {
48 | const int processNameBufferSize = 4096;
49 | LPTSTR processName = static_cast(malloc(sizeof(TCHAR) * processNameBufferSize));
50 | if (processName) {
51 | SecureZeroMemory(processName, sizeof(TCHAR) * processNameBufferSize);
52 |
53 | if (GetProcessImageFileName(hJobProcess, processName, processNameBufferSize) > 0)
54 | {
55 | String pnStr(processName);
56 |
57 | // ignore conhost.exe (this hosts the al-khaser executable in a console)
58 | if (pnStr.find(String(L"\\Windows\\System32\\conhost.exe")) != std::string::npos)
59 | {
60 | ok_processes++;
61 | }
62 | }
63 |
64 | free(processName);
65 | }
66 | CloseHandle(hJobProcess);
67 | }
68 | }
69 | }
70 |
71 | // if we found other processes in the job other than the current process and conhost, report a problem
72 | foundProblem = ok_processes != jobProcessIdList->NumberOfAssignedProcesses;
73 | }
74 |
75 | free(jobProcessIdList);
76 | }
77 | return foundProblem;
78 | }
79 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ProcessJob.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef UNICODE
4 | typedef std::string String;
5 | #else
6 | typedef std::wstring String;
7 | #endif
8 |
9 | BOOL ProcessJob();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/ScanForModules.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL ScanForModules_EnumProcessModulesEx_32bit();
4 | BOOL ScanForModules_EnumProcessModulesEx_64bit();
5 | BOOL ScanForModules_EnumProcessModulesEx_All();
6 | BOOL ScanForModules_ToolHelp32();
7 | BOOL ScanForModules_LDR_Direct();
8 | BOOL ScanForModules_LdrEnumerateLoadedModules();
9 | BOOL ScanForModules_MemoryWalk_GMI();
10 | BOOL ScanForModules_MemoryWalk_Hidden();
11 | BOOL ScanForModules_DotNetModuleStructures();
12 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SeDebugPrivilege.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SeDebugPrivilege.h"
4 |
5 | /*
6 | If we're being debugged and the process has SeDebugPrivileges privileges then OpenProcess call will be successful.
7 | This requires administrator privilege !
8 | In Windows XP, Vista and 7, calling OpenProcess with PROCESS_ALL_ACCESS will fait even with SeDebugPrivilege enabled,
9 | That's why I used PROCESS_QUERY_LIMITED_INFORMATION
10 | */
11 |
12 |
13 | DWORD GetCsrssProcessId()
14 | {
15 | if (API::IsAvailable(API_IDENTIFIER::API_CsrGetProcessId))
16 | {
17 | auto CsrGetProcessId = static_cast(API::GetAPI(API_IDENTIFIER::API_CsrGetProcessId));
18 |
19 | return CsrGetProcessId();
20 | }
21 | else
22 | return GetProcessIdFromName(_T("csrss.exe"));
23 | }
24 |
25 |
26 | BOOL CanOpenCsrss()
27 | {
28 | HANDLE hCsrss = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCsrssProcessId());
29 | if (hCsrss != NULL)
30 | {
31 | CloseHandle(hCsrss);
32 | return TRUE;
33 | }
34 | else
35 | return FALSE;
36 | }
37 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SeDebugPrivilege.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL CanOpenCsrss();
4 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SetHandleInformation_API.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SetHandleInformation_API.h"
4 |
5 |
6 | BOOL SetHandleInformatiom_ProtectedHandle()
7 | {
8 | /* some vars */
9 | HANDLE hMutex;
10 |
11 | /* Create a mutex so we can get a handle */
12 | hMutex = CreateMutex(NULL, FALSE, _T("Random name"));
13 |
14 | if (hMutex) {
15 |
16 | /* Protect our handle */
17 | SetHandleInformation(hMutex, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
18 |
19 |
20 | __try {
21 | /* Then, let's try close it */
22 | CloseHandle(hMutex);
23 | }
24 |
25 | __except (EXCEPTION_EXECUTE_HANDLER) {
26 | return TRUE;
27 | }
28 |
29 | }
30 |
31 | return FALSE;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SetHandleInformation_API.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL SetHandleInformatiom_ProtectedHandle();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SharedUserData_KernelDebugger.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SharedUserData_KernelDebugger.h"
4 |
5 | /*
6 | NtQuerySystemInformation can be used to detect the presence of a kernel debugger. However, the
7 | same information can be obtained from user mode with no system calls at all. This is done by
8 | reading from the KUSER_SHARED_DATA struct, which is has a fixed user mode address of 0x7FFE0000 in all versions
9 | of Windows in both 32 and 64 bit. In kernel mode it is located at 0xFFDF0000 (32 bit) or 0xFFFFF78000000000 (64 bit).
10 | Detailed information about KUSER_SHARED_DATA can be found here: http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kuser_shared_data.htm
11 | */
12 |
13 | BOOL SharedUserData_KernelDebugger()
14 | {
15 | // The fixed user mode address of KUSER_SHARED_DATA
16 | const ULONG_PTR UserSharedData = 0x7FFE0000;
17 |
18 | // UserSharedData->KdDebuggerEnabled is a BOOLEAN according to ntddk.h, which gives the false impression that it is
19 | // either true or false. However, this field is actually a set of bit flags, and is only zero if no debugger is present.
20 | const UCHAR KdDebuggerEnabledByte = *(UCHAR*)(UserSharedData + 0x2D4); // 0x2D4 = the offset of the field
21 |
22 | // Extract the flags.
23 | // The meaning of these is the same as in NtQuerySystemInformation(SystemKernelDebuggerInformation).
24 | // Normally if a debugger is attached, KdDebuggerEnabled is true, KdDebuggerNotPresent is false and the byte is 0x3.
25 | const BOOLEAN KdDebuggerEnabled = (KdDebuggerEnabledByte & 0x1) == 0x1;
26 | const BOOLEAN KdDebuggerNotPresent = (KdDebuggerEnabledByte & 0x2) == 0;
27 |
28 | if (KdDebuggerEnabled || !KdDebuggerNotPresent)
29 | return TRUE;
30 |
31 | return FALSE;
32 | }
33 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SharedUserData_KernelDebugger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL SharedUserData_KernelDebugger();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SoftwareBreakpoints.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SoftwareBreakpoints.h"
4 |
5 |
6 | /*
7 | Software breakpoints aka INT 3 represented in the IA-32 instruction set with the opcode CC (0xCC).
8 | Given a memory addresse and size, it is relatively simple to scan for the byte 0xCC -> if(pTmp[i] == 0xCC)
9 | An obfuscated method would be to check if our memory byte xored with 0x55 is equal 0x99 for example ...
10 | */
11 |
12 | VOID My_Critical_Function()
13 | {
14 | int a = 1;
15 | int b = 2;
16 | int c = a + b;
17 | _tprintf(_T("I am critical function, you should protect against int3 bps %d"), c);
18 | }
19 |
20 |
21 | VOID Myfunction_Adresss_Next()
22 | {
23 | My_Critical_Function();
24 | /*
25 | There is no guaranteed way of determining the size of a function at run time(and little reason to do so)
26 | however if you assume that the linker located functions that are adjacent in the source code sequentially in memory,
27 | then the following may give an indication of the size of a function Critical_Function by using :
28 | int Critical_Function_length = (int)Myfunction_Adresss_Next - (int)Critical_Function
29 | Works only if you compile the file in Release mode.
30 | */
31 | };
32 |
33 | BOOL SoftwareBreakpoints()
34 | {
35 | //NOTE this check might not work on x64 because of alignment 0xCC bytes
36 | size_t sSizeToCheck = (size_t)(Myfunction_Adresss_Next)-(size_t)(My_Critical_Function);
37 | PUCHAR Critical_Function = (PUCHAR)My_Critical_Function;
38 |
39 | for (size_t i = 0; i < sSizeToCheck; i++) {
40 | if (Critical_Function[i] == 0xCC) // Adding another level of indirection : 0xCC xor 0x55 = 0x99
41 | return TRUE;
42 | }
43 | return FALSE;
44 | }
45 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/SoftwareBreakpoints.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL SoftwareBreakpoints();
4 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/TLS_callbacks.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "TLS_callbacks.h"
4 |
5 | // The Thread Local Storage (TLS) callback is called before the execution of the EntryPoint of the application
6 | // Malware takes advantages to perform anti-debug and anti-vm checks.
7 | // There could be more than one callback, and sometimes, inside one call back, one can create one in the fly.
8 |
9 |
10 | volatile bool has_run = false;
11 |
12 | VOID WINAPI tls_callback(PVOID hModule, DWORD dwReason, PVOID pContext)
13 | {
14 | if (!has_run)
15 | {
16 | has_run = true;
17 | tls_callback_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
18 | tls_callback_process_event = CreateEvent(NULL, FALSE, FALSE, NULL);
19 | }
20 |
21 | if (dwReason == DLL_THREAD_ATTACH)
22 | {
23 | OutputDebugString(L"TLS callback: thread attach");
24 | tls_callback_thread_data = 0xDEADBEEF;
25 | SetEvent(tls_callback_thread_event);
26 | }
27 |
28 | if (dwReason == DLL_PROCESS_ATTACH)
29 | {
30 | OutputDebugString(L"TLS callback: process attach");
31 | tls_callback_process_data = 0xDEADBEEF;
32 | SetEvent(tls_callback_process_event);
33 | }
34 | }
35 |
36 | DWORD WINAPI TLSCallbackDummyThread(
37 | _In_ LPVOID lpParameter
38 | )
39 | {
40 | OutputDebugString(L"TLS callback: dummy thread launched");
41 | return 0;
42 | }
43 |
44 | BOOL TLSCallbackThread()
45 | {
46 | const int BLOWN = 1000;
47 |
48 | if (CreateThread(NULL, 0, &TLSCallbackDummyThread, NULL, 0, NULL) == NULL)
49 | {
50 | OutputDebugString(L"TLS callback: couldn't start dummy thread");
51 | }
52 |
53 | int fuse = 0;
54 | while (tls_callback_thread_event == NULL && ++fuse != BLOWN) { SwitchToThread(); }
55 | if (fuse >= BLOWN)
56 | {
57 | OutputDebugString(L"TLSCallbackThread timeout on event creation.");
58 | return TRUE;
59 | }
60 |
61 | DWORD waitStatus = WaitForSingleObject(tls_callback_thread_event, 5000);
62 | if (waitStatus != WAIT_OBJECT_0)
63 | {
64 | if (waitStatus == WAIT_FAILED)
65 | OutputDebugString(L"TLSCallbackThread wait failed.");
66 | else if (waitStatus == WAIT_ABANDONED)
67 | OutputDebugString(L"TLSCallbackThread wait abandoned.");
68 | else
69 | OutputDebugString(L"TLSCallbackThread timeout on event wait.");
70 | return TRUE;
71 | }
72 |
73 | if (tls_callback_thread_data != 0xDEADBEEF)
74 | OutputDebugString(L"TLSCallbackThread data did not match.");
75 | else
76 | OutputDebugString(L"All seems fine for TLSCallbackThread.");
77 |
78 | return tls_callback_thread_data == 0xDEADBEEF ? FALSE : TRUE;
79 | }
80 |
81 | BOOL TLSCallbackProcess()
82 | {
83 | const int BLOWN = 1000;
84 |
85 | int fuse = 0;
86 | while (tls_callback_process_event == NULL && ++fuse != BLOWN) { SwitchToThread(); }
87 | if (fuse >= BLOWN)
88 | {
89 | OutputDebugString(L"TLSCallbackProcess timeout on event creation.");
90 | return TRUE;
91 | }
92 |
93 | DWORD waitStatus = WaitForSingleObject(tls_callback_process_event, 5000);
94 | if (waitStatus != WAIT_OBJECT_0)
95 | {
96 | if (waitStatus == WAIT_FAILED)
97 | OutputDebugString(L"TLSCallbackProcess wait failed.");
98 | else if (waitStatus == WAIT_ABANDONED)
99 | OutputDebugString(L"TLSCallbackProcess wait abandoned.");
100 | else
101 | OutputDebugString(L"TLSCallbackProcess timeout on event wait.");
102 | return TRUE;
103 | }
104 |
105 | if (tls_callback_process_data != 0xDEADBEEF)
106 | OutputDebugString(L"TLSCallbackProcess data did not match.");
107 | else
108 | OutputDebugString(L"All seems fine for TLSCallbackProcess.");
109 |
110 | return tls_callback_process_data == 0xDEADBEEF ? FALSE : TRUE;
111 | }
112 |
113 | #ifdef _WIN64
114 | #pragma comment (linker, "/INCLUDE:_tls_used")
115 | #pragma comment (linker, "/INCLUDE:tls_callback_func")
116 | #else
117 | #pragma comment (linker, "/INCLUDE:__tls_used")
118 | #pragma comment (linker, "/INCLUDE:_tls_callback_func")
119 | #endif
120 |
121 |
122 | #ifdef _WIN64
123 | #pragma const_seg(".CRT$XLF")
124 | EXTERN_C const
125 | #else
126 | #pragma data_seg(".CRT$XLF")
127 | EXTERN_C
128 | #endif
129 |
130 | PIMAGE_TLS_CALLBACK tls_callback_func = tls_callback;
131 |
132 | #ifdef _WIN64
133 | #pragma const_seg()
134 | #else
135 | #pragma data_seg()
136 | #endif //_WIN64
137 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/TLS_callbacks.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | static volatile HANDLE tls_callback_thread_event = 0;
4 | static volatile HANDLE tls_callback_process_event = 0;
5 | static volatile UINT32 tls_callback_thread_data = 0;
6 | static volatile UINT32 tls_callback_process_data = 0;
7 |
8 | VOID WINAPI tls_callback(PVOID hModule, DWORD dwReason, PVOID pContext);
9 | BOOL TLSCallbackThread();
10 | BOOL TLSCallbackProcess();
11 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/TrapFlag.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "TrapFlag.h"
4 |
5 | /*
6 | This technique is similar to exceptions based debugger detections.
7 | You enable the trap flag in the current process and check whether
8 | an exception is raised or not. If an exception is not raised, you
9 | can assume that a debugger has “swallowed” the exception for us,
10 | and that the program is being traced. The beauty of this approach
11 | is that it detects every debugger, user mode or kernel mode,
12 | because they all use the trap flag for tracing a program.
13 |
14 | Vectored Exception Handling is used here because SEH is an
15 | anti-debug trick in itself.
16 | */
17 |
18 | static BOOL SwallowedException = TRUE;
19 |
20 | static LONG CALLBACK VectoredHandler(
21 | _In_ PEXCEPTION_POINTERS ExceptionInfo
22 | )
23 | {
24 | SwallowedException = FALSE;
25 |
26 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
27 | return EXCEPTION_CONTINUE_EXECUTION;
28 |
29 | return EXCEPTION_CONTINUE_SEARCH;
30 | }
31 |
32 |
33 |
34 | BOOL TrapFlag()
35 | {
36 | PVOID Handle = AddVectoredExceptionHandler(1, VectoredHandler);
37 | SwallowedException = TRUE;
38 |
39 | #ifdef _WIN64
40 | UINT64 eflags = __readeflags();
41 | #else
42 | UINT eflags = __readeflags();
43 | #endif
44 |
45 | // Set the trap flag
46 | eflags |= 0x100;
47 | __writeeflags(eflags);
48 |
49 | RemoveVectoredExceptionHandler(Handle);
50 | return SwallowedException;
51 | }
52 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/TrapFlag.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL TrapFlag();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/UnhandledExceptionFilter_Handler.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "UnhandledExceptionFilter_Handler.h"
3 |
4 |
5 | /*
6 | When an exception occurs, and no registered Exception Handlers exist (neither Structured nor
7 | Vectored), or if none of the registered handlers handles the exception, then the kernel32
8 | UnhandledExceptionFilter() function will be called as a last resort.
9 | */
10 |
11 | BOOL bIsBeinDbg = TRUE;
12 |
13 | LONG WINAPI UnhandledExcepFilter(PEXCEPTION_POINTERS pExcepPointers)
14 | {
15 | // If a debugger is present, then this function will not be reached.
16 | bIsBeinDbg = FALSE;
17 | return EXCEPTION_CONTINUE_EXECUTION;
18 | }
19 |
20 |
21 | BOOL UnhandledExcepFilterTest ()
22 | {
23 | LPTOP_LEVEL_EXCEPTION_FILTER Top = SetUnhandledExceptionFilter(UnhandledExcepFilter);
24 | RaiseException(EXCEPTION_FLT_DIVIDE_BY_ZERO, 0, 0, NULL);
25 | SetUnhandledExceptionFilter(Top);
26 | return bIsBeinDbg;
27 | }
28 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/UnhandledExceptionFilter_Handler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL UnhandledExcepFilterTest();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/WUDF_IsDebuggerPresent.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "WUDF_IsDebuggerPresent.h"
3 |
4 | BOOL WUDF_IsAnyDebuggerPresent()
5 | {
6 | if (API::IsAvailable(API_IDENTIFIER::API_WudfIsAnyDebuggerPresent))
7 | {
8 | auto WudfIsAnyDebuggerPresent = static_cast(API::GetAPI(API_IDENTIFIER::API_WudfIsAnyDebuggerPresent));
9 | return WudfIsAnyDebuggerPresent() == 0 ? FALSE : TRUE;
10 | }
11 | else
12 | return FALSE;
13 | }
14 |
15 | BOOL WUDF_IsKernelDebuggerPresent()
16 | {
17 | if (API::IsAvailable(API_IDENTIFIER::API_WudfIsKernelDebuggerPresent))
18 | {
19 | auto WudfIsKernelDebuggerPresent = static_cast(API::GetAPI(API_IDENTIFIER::API_WudfIsKernelDebuggerPresent));
20 | return WudfIsKernelDebuggerPresent() == 0 ? FALSE : TRUE;
21 | }
22 | else
23 | return FALSE;
24 | }
25 |
26 | BOOL WUDF_IsUserDebuggerPresent()
27 | {
28 | if (API::IsAvailable(API_IDENTIFIER::API_WudfIsUserDebuggerPresent))
29 | {
30 | auto WudfIsUserDebuggerPresent = static_cast(API::GetAPI(API_IDENTIFIER::API_WudfIsUserDebuggerPresent));
31 | return WudfIsUserDebuggerPresent() == 0 ? FALSE : TRUE;
32 | }
33 | else
34 | return FALSE;
35 | }
36 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/WUDF_IsDebuggerPresent.h:
--------------------------------------------------------------------------------
1 | BOOL WUDF_IsAnyDebuggerPresent();
2 | BOOL WUDF_IsKernelDebuggerPresent();
3 | BOOL WUDF_IsUserDebuggerPresent();
4 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/WriteWatch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL VirtualAlloc_WriteWatch_BufferOnly();
4 | BOOL VirtualAlloc_WriteWatch_APICalls();
5 | BOOL VirtualAlloc_WriteWatch_IsDebuggerPresent();
6 | BOOL VirtualAlloc_WriteWatch_CodeWrite();
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/int2d_x64.asm:
--------------------------------------------------------------------------------
1 | .code
2 |
3 | __int2d proc
4 | mov rax, 0
5 | int 2dh
6 | nop
7 | ret
8 | __int2d endp
9 |
10 | end
11 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/int2d_x86.asm:
--------------------------------------------------------------------------------
1 | .model flat
2 | .code
3 |
4 | ___int2d proc
5 | mov eax, 0
6 | int 2dh
7 | nop
8 | ret
9 | ___int2d endp
10 |
11 | end
12 |
--------------------------------------------------------------------------------
/al-khaser/AntiDebug/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/AntiDisassm/AntiDisassm.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "AntiDisassm.h"
4 |
5 |
6 | extern "C" void __AsmConstantCondition();
7 | extern "C" void __AsmJmpSameTarget();
8 | extern "C" void __AsmImpossibleDisassm();
9 | extern "C" void __AsmFunctionPointer(DWORD);
10 | extern "C" void __AsmReturnPointerAbuse(DWORD64);
11 | #ifndef _WIN64
12 | extern "C" void __AsmSEHMisuse();
13 | #endif
14 |
15 | /*
16 | This technique is composed of a single conditional jump instruction placed where the condition
17 | will always be the same.
18 | */
19 | VOID AntiDisassmConstantCondition()
20 | {
21 | __AsmConstantCondition();
22 | }
23 |
24 | /*
25 | The most common anti-disassembly technique seen in the wild is two back-to back
26 | conditional jump instructions that both point to the same target. For example,
27 | if a jz XYZ is followed by jnz XYZ, the location XYZ will always be jumped to
28 | */
29 | VOID AntiDisassmAsmJmpSameTarget()
30 | {
31 | __AsmJmpSameTarget();
32 | }
33 |
34 |
35 | /*
36 | By using a data byte placed strategically after a conditional jump instruction
37 | with the idea that disassembly starting at this byte will prevent the real instruction
38 | that follows from being disassembled because the byte that inserted is the opcode for
39 | a multibyte instruction.
40 |
41 | */
42 | VOID AntiDisassmImpossibleDiasassm()
43 | {
44 | __AsmImpossibleDisassm();
45 | }
46 |
47 |
48 | /*
49 | If function pointers are used in handwritten assembly or crafted in a nonstandard way
50 | in source code, the results can be difficult to reverse engineer without dynamic analysis.
51 | */
52 | VOID AntiDisassmFunctionPointer()
53 | {
54 |
55 | DWORD Number = 2;
56 | __AsmFunctionPointer(Number);
57 | }
58 |
59 |
60 | /*
61 | The most obvious result of this technique is that the disassembler doesn�t show any
62 | code cross - reference to the target being jumped to.
63 | */
64 | VOID AntiDisassmReturnPointerAbuse()
65 | {
66 | __AsmReturnPointerAbuse(666);
67 | }
68 |
69 | #ifndef _WIN64
70 | VOID AntiDisassmSEHMisuse()
71 | {
72 | __AsmSEHMisuse();
73 | }
74 | #endif
--------------------------------------------------------------------------------
/al-khaser/AntiDisassm/AntiDisassm.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID AntiDisassmConstantCondition();
4 | VOID AntiDisassmAsmJmpSameTarget();
5 | VOID AntiDisassmImpossibleDiasassm();
6 | VOID AntiDisassmFunctionPointer();
7 | VOID AntiDisassmReturnPointerAbuse();
8 | VOID AntiDisassmSEHMisuse();
--------------------------------------------------------------------------------
/al-khaser/AntiDisassm/AntiDisassm_x64.asm:
--------------------------------------------------------------------------------
1 |
2 | .code
3 |
4 | __AsmConstantCondition proc
5 | xor rax, rax
6 | jz L_END
7 | db 0e8h
8 | L_END:
9 | nop
10 | ret
11 | __AsmConstantCondition endp
12 |
13 |
14 | __AsmJmpSameTarget proc
15 | jz L_END
16 | jnz L_END
17 | db 0e8h
18 | L_END:
19 | nop
20 | ret
21 | __AsmJmpSameTarget endp
22 |
23 |
24 | __AsmImpossibleDisassm proc
25 | push rax
26 |
27 | mov ax, 05EBh ; db 066h, 0B8h, 0EBh, 005h
28 | xor eax, eax ; db 033h, 0C0h
29 | db 074h, 0fah
30 | db 0e8h ; call
31 |
32 | pop rax
33 | ret
34 | __AsmImpossibleDisassm endp
35 |
36 | ; a dummy function
37 | func2 proc
38 | mov rax, r8
39 | shl rax, 2
40 | ret
41 | func2 endp
42 |
43 |
44 | __AsmFunctionPointer proc
45 | push rax
46 | push rcx
47 | push rsi
48 | mov rcx, offset func2
49 | mov r8, 02h
50 | call rcx
51 | mov rsi, rax
52 | mov r8, 03h
53 | call rcx
54 | lea rax, [rsi+rax+1]
55 | pop rsi
56 | pop rcx
57 | pop rax
58 | ret
59 | __AsmFunctionPointer endp
60 |
61 |
62 | __AsmReturnPointerAbuse proc
63 | call $+5
64 | add qword ptr[rsp], 6
65 | ret
66 |
67 | push rax
68 | mov rax, rcx
69 | imul rax, 40h
70 | pop rax
71 | ret
72 | __AsmReturnPointerAbuse endp
73 |
74 |
75 | end
76 |
--------------------------------------------------------------------------------
/al-khaser/AntiDisassm/AntiDisassm_x86.asm:
--------------------------------------------------------------------------------
1 | .model flat, c
2 |
3 | .code
4 |
5 | __AsmConstantCondition proc
6 | xor eax, eax
7 | jz L_END
8 | db 0e8h
9 | L_END:
10 | nop
11 | ret
12 | __AsmConstantCondition endp
13 |
14 |
15 | __AsmJmpSameTarget proc
16 | jz L_END
17 | jnz L_END
18 | db 0e8h
19 | L_END:
20 | nop
21 | ret
22 | __AsmJmpSameTarget endp
23 |
24 |
25 | __AsmImpossibleDisassm proc
26 | push eax
27 |
28 | mov ax, 05EBh ; db 066h, 0B8h, 0EBh, 005h
29 | xor eax, eax ; db 033h, 0C0h
30 | db 074h, 0fah
31 | db 0e8h ; call
32 |
33 | pop eax
34 | ret
35 | __AsmImpossibleDisassm endp
36 |
37 | ; a dummy function
38 | func2 proc arg_0:DWORD
39 | mov eax, [arg_0]
40 | shl eax, 2
41 | pop ebp
42 | retn
43 | func2 endp
44 |
45 |
46 | __AsmFunctionPointer proc arg_0:DWORD
47 |
48 | LOCAL var_4:DWORD
49 |
50 | push ecx
51 | push esi
52 | mov [var_4], offset func2
53 | push 03h
54 | call [var_4]
55 | add esp, 4
56 | mov esi, eax
57 | mov eax, [arg_0]
58 | push eax
59 | call [var_4]
60 | add esp, 4
61 | lea eax, [esi+eax+1]
62 | pop esi
63 | mov esp, ebp
64 | pop ebp
65 | retn
66 | __AsmFunctionPointer endp
67 |
68 | __AsmReturnPointerAbuse proc
69 |
70 | call $+5
71 | add dword ptr[esp], 5
72 | retn
73 |
74 | push eax
75 | mov eax, [ebp+8]
76 | imul eax, 40h
77 | pop eax
78 | retn
79 | __AsmReturnPointerAbuse endp
80 |
81 | ; another dummy function
82 | func3 proc
83 | mov esp, [esp+8]
84 | ASSUME FS:NOTHING
85 | mov eax, dword ptr fs:[0]
86 | ASSUME FS:ERROR
87 | mov eax, [eax]
88 | mov eax, [eax]
89 | ASSUME FS:NOTHING
90 | mov dword ptr fs:[0], eax
91 | ASSUME FS:ERROR
92 | add esp, 8
93 | pop ebp
94 | retn
95 | func3 endp
96 |
97 | __AsmSEHMisuse proc
98 | push ebp
99 | mov eax, offset func3
100 | push eax
101 | ASSUME FS:NOTHING
102 | push dword ptr fs:[0]
103 | mov dword ptr fs:[0], esp
104 | ASSUME FS:ERROR
105 | xor ecx, ecx
106 | div ecx
107 | call func2
108 | retn
109 | __AsmSEHMisuse endp
110 |
111 | end
112 |
--------------------------------------------------------------------------------
/al-khaser/AntiDisassm/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/AntiDump/ErasePEHeaderFromMemory.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "ErasePEHeaderFromMemory.h"
4 |
5 | /* This function will erase the current images PE header from memory preventing a successful image if dumped */
6 |
7 |
8 | VOID ErasePEHeaderFromMemory()
9 | {
10 | _tprintf(_T("[*] Erasing PE header from memory\n"));
11 | DWORD OldProtect = 0;
12 |
13 | // Get base address of module
14 | char *pBaseAddr = (char*)GetModuleHandle(NULL);
15 |
16 | // Change memory protection
17 | VirtualProtect(pBaseAddr, 4096, // Assume x86 page size
18 | PAGE_READWRITE, &OldProtect);
19 |
20 | // Erase the header
21 | SecureZeroMemory(pBaseAddr, 4096);
22 | }
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/al-khaser/AntiDump/ErasePEHeaderFromMemory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID ErasePEHeaderFromMemory();
--------------------------------------------------------------------------------
/al-khaser/AntiDump/SizeOfImage.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SizeOfImage.h"
4 |
5 | // Any unreasonably large value will work say for example 0x100000 or 100,000h
6 |
7 | VOID SizeOfImage()
8 | {
9 |
10 | #if defined (ENV64BIT)
11 | PPEB pPeb = (PPEB)__readgsqword(0x60);
12 | #elif defined(ENV32BIT)
13 | PPEB pPeb = (PPEB)__readfsdword(0x30);
14 | #endif
15 |
16 | _tprintf(_T("[*] Increasing SizeOfImage in PE Header to: 0x100000\n"));
17 |
18 | // The following pointer hackery is because winternl.h defines incomplete PEB types
19 | PLIST_ENTRY InLoadOrderModuleList = (PLIST_ENTRY)pPeb->Ldr->Reserved2[1]; // pPeb->Ldr->InLoadOrderModuleList
20 | PLDR_DATA_TABLE_ENTRY tableEntry = CONTAINING_RECORD(InLoadOrderModuleList, LDR_DATA_TABLE_ENTRY, Reserved1[0] /*InLoadOrderLinks*/);
21 | PULONG pEntrySizeOfImage = (PULONG)&tableEntry->Reserved3[1]; // &tableEntry->SizeOfImage
22 | *pEntrySizeOfImage = (ULONG)((INT_PTR)tableEntry->DllBase + 0x100000);
23 | }
24 |
--------------------------------------------------------------------------------
/al-khaser/AntiDump/SizeOfImage.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID SizeOfImage();
--------------------------------------------------------------------------------
/al-khaser/AntiDump/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Generic.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID loaded_dlls();
4 | VOID known_file_names();
5 | VOID known_usernames();
6 | VOID known_hostnames();
7 | VOID other_known_sandbox_environment_checks();
8 | BOOL NumberOfProcessors();
9 | BOOL idt_trick();
10 | BOOL ldt_trick();
11 | BOOL gdt_trick();
12 | BOOL str_trick();
13 | BOOL number_cores_wmi();
14 | BOOL disk_size_wmi();
15 | BOOL setupdi_diskdrive();
16 | BOOL mouse_movement();
17 | BOOL lack_user_input();
18 | BOOL memory_space();
19 | BOOL dizk_size_deviceiocontrol();
20 | BOOL disk_size_getdiskfreespace();
21 | BOOL accelerated_sleep();
22 | BOOL cpuid_is_hypervisor();
23 | BOOL cpuid_hypervisor_vendor();
24 | BOOL serial_number_bios_wmi();
25 | BOOL model_computer_system_wmi();
26 | BOOL manufacturer_computer_system_wmi();
27 | BOOL current_temperature_acpi_wmi();
28 | BOOL process_id_processor_wmi();
29 | BOOL power_capabilities();
30 | BOOL hybridanalysismacdetect();
31 | BOOL cpu_fan_wmi();
32 | BOOL caption_video_controller_wmi();
33 | BOOL query_license_value();
34 | BOOL cachememory_wmi();
35 | BOOL physicalmemory_wmi();
36 | BOOL memorydevice_wmi();
37 | BOOL memoryarray_wmi();
38 | BOOL voltageprobe_wmi();
39 | BOOL portconnector_wmi();
40 | BOOL smbiosmemory_wmi();
41 | BOOL perfctrs_thermalzoneinfo_wmi();
42 | BOOL cim_memory_wmi();
43 | BOOL cim_numericsensor_wmi();
44 | BOOL cim_physicalconnector_wmi();
45 | BOOL cim_sensor_wmi();
46 | BOOL cim_slot_wmi();
47 | BOOL cim_temperaturesensor_wmi();
48 | BOOL cim_voltagesensor_wmi();
49 | BOOL pirated_windows();
50 | BOOL registry_services_disk_enum();
51 | BOOL registry_disk_enum();
52 | BOOL number_SMBIOS_tables();
53 | BOOL firmware_ACPI();
54 | BOOL hosting_check();
55 | VOID looking_glass_vdd_processes();
56 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/HyperV.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "HyperV.h"
3 |
4 |
5 | BOOL check_hyperv_driver_objects()
6 | {
7 | auto driverList = enumerate_object_directory(L"\\Driver");
8 | if (driverList == nullptr)
9 | {
10 | return FALSE;
11 | }
12 | for (wchar_t* driver : *driverList)
13 | {
14 | if (StrCmpCW(driver, L"VMBusHID") == 0)
15 | {
16 | return TRUE;
17 | }
18 | if (StrCmpCW(driver, L"vmbus") == 0)
19 | {
20 | return TRUE;
21 | }
22 | if (StrCmpCW(driver, L"vmgid") == 0)
23 | {
24 | return TRUE;
25 | }
26 | if (StrCmpCW(driver, L"IndirectKmd") == 0)
27 | {
28 | return TRUE;
29 | }
30 | if (StrCmpCW(driver, L"HyperVideo") == 0)
31 | {
32 | return TRUE;
33 | }
34 | if (StrCmpCW(driver, L"hyperkbd") == 0)
35 | {
36 | return TRUE;
37 | }
38 | }
39 | return FALSE;
40 | }
41 |
42 |
43 | BOOL check_hyperv_global_objects()
44 | {
45 | auto globalObjs = enumerate_object_directory(L"\\GLOBAL??");
46 | if (globalObjs == nullptr)
47 | {
48 | return FALSE;
49 | }
50 | for (wchar_t* globalObj : *globalObjs)
51 | {
52 | if (StrStrW(globalObj, L"VMBUS#") != NULL)
53 | {
54 | return TRUE;
55 | }
56 | if (StrCmpCW(globalObj, L"VDRVROOT") == 0)
57 | {
58 | return TRUE;
59 | }
60 | if (StrCmpCW(globalObj, L"VmGenerationCounter") == 0)
61 | {
62 | return TRUE;
63 | }
64 | if (StrCmpCW(globalObj, L"VmGid") == 0)
65 | {
66 | return TRUE;
67 | }
68 | }
69 | return FALSE;
70 | }
71 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/HyperV.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL check_hyperv_driver_objects();
4 | BOOL check_hyperv_global_objects();
5 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/KVM.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 |
4 | /*
5 | Check against kvm registry keys
6 | */
7 | VOID kvm_reg_keys()
8 | {
9 | /* Array of strings of blacklisted registry keys */
10 | const TCHAR* szKeys[] = {
11 | _T("SYSTEM\\ControlSet001\\Services\\vioscsi"),
12 | _T("SYSTEM\\ControlSet001\\Services\\viostor"),
13 | _T("SYSTEM\\ControlSet001\\Services\\VirtIO-FS Service"),
14 | _T("SYSTEM\\ControlSet001\\Services\\VirtioSerial"),
15 | _T("SYSTEM\\ControlSet001\\Services\\BALLOON"),
16 | _T("SYSTEM\\ControlSet001\\Services\\BalloonService"),
17 | _T("SYSTEM\\ControlSet001\\Services\\netkvm"),
18 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_1AF4*"),
19 | };
20 |
21 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
22 |
23 | /* Check one by one */
24 | for (int i = 0; i < dwlength; i++)
25 | {
26 | TCHAR msg[256] = _T("");
27 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
28 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
29 | print_results(TRUE, msg);
30 | else
31 | print_results(FALSE, msg);
32 | }
33 | }
34 |
35 | /*
36 | Check against kvm blacklisted files
37 | */
38 | VOID kvm_files()
39 | {
40 | /* Array of strings of blacklisted paths */
41 | const TCHAR* szPaths[] = {
42 | _T("System32\\drivers\\balloon.sys"),
43 | _T("System32\\drivers\\netkvm.sys"),
44 | _T("System32\\drivers\\pvpanic.sys"),
45 | _T("System32\\drivers\\viofs.sys"),
46 | _T("System32\\drivers\\viogpudo.sys"),
47 | _T("System32\\drivers\\vioinput.sys"),
48 | _T("System32\\drivers\\viorng.sys"),
49 | _T("System32\\drivers\\vioscsi.sys"),
50 | _T("System32\\drivers\\vioser.sys"),
51 | _T("System32\\drivers\\viostor.sys"),
52 |
53 | };
54 |
55 | /* Getting Windows Directory */
56 | WORD dwlength = sizeof(szPaths) / sizeof(szPaths[0]);
57 | TCHAR szWinDir[MAX_PATH] = _T("");
58 | TCHAR szPath[MAX_PATH] = _T("");
59 | PVOID OldValue = NULL;
60 |
61 | GetWindowsDirectory(szWinDir, MAX_PATH);
62 |
63 | if (IsWoW64()) {
64 | Wow64DisableWow64FsRedirection(&OldValue);
65 | }
66 |
67 | /* Check one by one */
68 | for (int i = 0; i < dwlength; i++)
69 | {
70 | PathCombine(szPath, szWinDir, szPaths[i]);
71 | TCHAR msg[256] = _T("");
72 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking file %s "), szPath);
73 | if (is_FileExists(szPath))
74 | print_results(TRUE, msg);
75 | else
76 | print_results(FALSE, msg);
77 | }
78 |
79 | if (IsWoW64()) {
80 | Wow64RevertWow64FsRedirection(&OldValue);
81 | }
82 | }
83 |
84 | /*
85 | Check against kvm blacklisted directories
86 | */
87 | BOOL kvm_dir()
88 | {
89 | TCHAR szProgramFile[MAX_PATH];
90 | TCHAR szPath[MAX_PATH] = _T("");
91 | TCHAR szTarget[MAX_PATH] = _T("Virtio-Win\\");
92 |
93 | if (IsWoW64())
94 | ExpandEnvironmentStrings(_T("%ProgramW6432%"), szProgramFile, ARRAYSIZE(szProgramFile));
95 | else
96 | SHGetSpecialFolderPath(NULL, szProgramFile, CSIDL_PROGRAM_FILES, FALSE);
97 |
98 | PathCombine(szPath, szProgramFile, szTarget);
99 | return is_DirectoryExists(szPath);
100 | }
--------------------------------------------------------------------------------
/al-khaser/AntiVM/KVM.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID kvm_reg_keys();
4 | VOID kvm_files();
5 | BOOL kvm_dir();
6 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Parallels.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Parallels.h"
4 |
5 | /*
6 | Check against Parallels registry keys
7 | */
8 | VOID parallels_reg_keys()
9 | {
10 | /* Array of strings of blacklisted registry keys */
11 | const TCHAR* szKeys[] = {
12 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_1AB8*"),
13 | };
14 |
15 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
16 |
17 | /* Check one by one */
18 | for (int i = 0; i < dwlength; i++)
19 | {
20 | TCHAR msg[256] = _T("");
21 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
22 |
23 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
24 | print_results(TRUE, msg);
25 | else
26 | print_results(FALSE, msg);
27 | }
28 | }
29 |
30 | /*
31 | Check for process list
32 | */
33 |
34 | VOID parallels_process()
35 | {
36 | const TCHAR *szProcesses[] = {
37 | _T("prl_cc.exe"),
38 | _T("prl_tools.exe"),
39 | };
40 |
41 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
42 | for (int i = 0; i < iLength; i++)
43 | {
44 | TCHAR msg[256] = _T("");
45 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking Parallels processes: %s"), szProcesses[i]);
46 | if (GetProcessIdFromName(szProcesses[i]))
47 | print_results(TRUE, msg);
48 | else
49 | print_results(FALSE, msg);
50 | }
51 | }
52 |
53 |
54 | /*
55 | Check Parallels NIC MAC address
56 | */
57 | BOOL parallels_check_mac()
58 | {
59 | // Parallels, Inc.
60 | return check_mac_addr(_T("\x00\x1C\x42"));
61 | }
62 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Parallels.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID parallels_reg_keys();
4 | VOID parallels_process();
5 | BOOL parallels_check_mac();
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Qemu.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Qemu.h"
4 |
5 | /*
6 | Registry key values
7 | */
8 |
9 | VOID qemu_reg_key_value()
10 | {
11 | /* Array of strings of blacklisted registry key values */
12 | const TCHAR *szEntries[][3] = {
13 | { _T("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"), _T("Identifier"), _T("QEMU") },
14 | { _T("HARDWARE\\Description\\System"), _T("SystemBiosVersion"), _T("QEMU") },
15 | };
16 |
17 | WORD dwLength = sizeof(szEntries) / sizeof(szEntries[0]);
18 |
19 | for (int i = 0; i < dwLength; i++)
20 | {
21 | TCHAR msg[256] = _T("");
22 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szEntries[i][0]);
23 | if (Is_RegKeyValueExists(HKEY_LOCAL_MACHINE, szEntries[i][0], szEntries[i][1], szEntries[i][2]))
24 | print_results(TRUE, msg);
25 | else
26 | print_results(FALSE, msg);
27 | }
28 | }
29 |
30 |
31 | /*
32 | Check against QEMU registry keys
33 | */
34 | VOID qemu_reg_keys()
35 | {
36 | /* Array of strings of blacklisted registry keys */
37 | const TCHAR* szKeys[] = {
38 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_1B36*"),
39 | };
40 |
41 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
42 |
43 | /* Check one by one */
44 | for (int i = 0; i < dwlength; i++)
45 | {
46 | TCHAR msg[256] = _T("");
47 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
48 |
49 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
50 | print_results(TRUE, msg);
51 | else
52 | print_results(FALSE, msg);
53 | }
54 | }
55 |
56 | /*
57 | Check for process list
58 | */
59 |
60 | VOID qemu_processes()
61 | {
62 | const TCHAR *szProcesses[] = {
63 | _T("qemu-ga.exe"), // QEMU guest agent.
64 | _T("vdagent.exe"), // SPICE guest tools.
65 | _T("vdservice.exe"), // SPICE guest tools.
66 | };
67 |
68 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
69 | for (int i = 0; i < iLength; i++)
70 | {
71 | TCHAR msg[256] = _T("");
72 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking qemu processes %s "), szProcesses[i]);
73 | if (GetProcessIdFromName(szProcesses[i]))
74 | print_results(TRUE, msg);
75 | else
76 | print_results(FALSE, msg);
77 | }
78 | }
79 |
80 | /*
81 | Check against blacklisted directories.
82 | */
83 | VOID qemu_dir()
84 | {
85 | TCHAR szProgramFile[MAX_PATH];
86 | TCHAR szPath[MAX_PATH] = _T("");
87 |
88 | const TCHAR* szDirectories[] = {
89 | _T("qemu-ga"), // QEMU guest agent.
90 | _T("SPICE Guest Tools"), // SPICE guest tools.
91 | };
92 |
93 | WORD iLength = sizeof(szDirectories) / sizeof(szDirectories[0]);
94 | for (int i = 0; i < iLength; i++)
95 | {
96 | TCHAR msg[256] = _T("");
97 |
98 | if (IsWoW64())
99 | ExpandEnvironmentStrings(_T("%ProgramW6432%"), szProgramFile, ARRAYSIZE(szProgramFile));
100 | else
101 | SHGetSpecialFolderPath(NULL, szProgramFile, CSIDL_PROGRAM_FILES, FALSE);
102 |
103 | PathCombine(szPath, szProgramFile, szDirectories[i]);
104 |
105 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking QEMU directory %s "), szPath);
106 | if (is_DirectoryExists(szPath))
107 | print_results(TRUE, msg);
108 | else
109 | print_results(FALSE, msg);
110 | }
111 | }
112 |
113 |
114 | /*
115 | Check for SMBIOS firmware
116 | */
117 | BOOL qemu_firmware_SMBIOS()
118 | {
119 | BOOL result = FALSE;
120 |
121 | DWORD smbiosSize = 0;
122 | PBYTE smbios = get_system_firmware(static_cast('RSMB'), 0x0000, &smbiosSize);
123 | if (smbios != NULL)
124 | {
125 | PBYTE qemuString1 = (PBYTE)"qemu";
126 | size_t StringLen = 4;
127 | PBYTE qemuString2 = (PBYTE)"QEMU";
128 |
129 | if (find_str_in_data(qemuString1, StringLen, smbios, smbiosSize) ||
130 | find_str_in_data(qemuString2, StringLen, smbios, smbiosSize))
131 | {
132 | result = TRUE;
133 | }
134 |
135 | free(smbios);
136 | }
137 |
138 | return result;
139 | }
140 |
141 |
142 | /*
143 | Check for ACPI firmware
144 | */
145 | BOOL qemu_firmware_ACPI()
146 | {
147 | BOOL result = FALSE;
148 |
149 | PDWORD tableNames = static_cast(malloc(4096));
150 |
151 | if (tableNames) {
152 | SecureZeroMemory(tableNames, 4096);
153 | DWORD tableSize = enum_system_firmware_tables(static_cast('ACPI'), tableNames, 4096);
154 |
155 | // API not available
156 | if (tableSize == -1)
157 | return FALSE;
158 |
159 | DWORD tableCount = tableSize / 4;
160 | if (tableSize < 4 || tableCount == 0)
161 | {
162 | result = TRUE;
163 | }
164 | else
165 | {
166 | const char* strings[] = {
167 | "FWCF", // fw_cfg name
168 | "QEMU0002", // fw_cfg HID/CID
169 | "BOCHS", // OEM ID
170 | "BXPC" // OEM Table ID
171 | };
172 |
173 | for (DWORD i = 0; i < tableCount; i++)
174 | {
175 | DWORD tableSize = 0;
176 | PBYTE table = get_system_firmware(static_cast('ACPI'), tableNames[i], &tableSize);
177 |
178 | if (table) {
179 |
180 | for (DWORD j = 0; j < sizeof(strings) / sizeof(char*); j++)
181 | {
182 | if (!find_str_in_data((PBYTE)strings[j], strlen(strings[j]), table, tableSize))
183 | {
184 | free(table);
185 | result = TRUE;
186 | goto out;
187 | }
188 | }
189 |
190 | free(table);
191 | }
192 | }
193 |
194 | DWORD tableSize = 0;
195 | PBYTE table = get_system_firmware(static_cast('ACPI'), static_cast('PCAF'), &tableSize);
196 |
197 | if (table) {
198 | if (tableSize < 45)
199 | {
200 | return FALSE; // Corrupted table
201 | }
202 |
203 | // Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue (in hex)
204 | // [02Dh 0045 001h ] PM Profile : 00 [Unspecified] - hardcoded in QEMU src
205 | if ((BYTE) table[45] == (BYTE)0)
206 | {
207 | result = TRUE;
208 | }
209 |
210 | free(table);
211 | }
212 | }
213 | out:
214 | free(tableNames);
215 | }
216 | return result;
217 | }
218 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Qemu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID qemu_reg_key_value();
4 | VOID qemu_reg_keys();
5 | VOID qemu_processes();
6 | VOID qemu_dir();
7 | BOOL qemu_firmware_ACPI();
8 | BOOL qemu_firmware_SMBIOS();
9 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Services.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Services.h"
4 |
5 | BOOL VMDriverServices()
6 | {
7 | const int KnownServiceCount = 13;
8 | const TCHAR* KnownVMServices[KnownServiceCount] = {
9 | L"VBoxWddm",
10 | L"VBoxSF", //VirtualBox Shared Folders
11 | L"VBoxMouse", //VirtualBox Guest Mouse
12 | L"VBoxGuest", //VirtualBox Guest Driver
13 | L"vmci", //VMWare VMCI Bus Driver
14 | L"vmhgfs", //VMWare Host Guest Control Redirector
15 | L"vmmouse",
16 | L"vmmemctl", //VMWare Guest Memory Controller Driver
17 | L"vmusb",
18 | L"vmusbmouse",
19 | L"vmx_svga",
20 | L"vmxnet",
21 | L"vmx86"
22 | };
23 |
24 | SC_HANDLE hSCM = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
25 | if (hSCM != NULL)
26 | {
27 | ENUM_SERVICE_STATUS_PROCESS* services = NULL;
28 | DWORD serviceCount = 0;
29 | if (get_services(hSCM, SERVICE_DRIVER, &services, &serviceCount))
30 | {
31 | bool ok = true;
32 |
33 | for (DWORD i = 0; i < serviceCount; i++)
34 | {
35 | for (int s = 0; s < KnownServiceCount; s++)
36 | {
37 | if (StrCmpIW(services[i].lpServiceName, KnownVMServices[s]) == 0)
38 | {
39 | ok = false;
40 | break;
41 | }
42 | }
43 | }
44 |
45 | free(services);
46 |
47 | if (ok)
48 | {
49 | CloseServiceHandle(hSCM);
50 | return FALSE;
51 | }
52 |
53 | }
54 | else
55 | {
56 | printf("Failed to get services list.\n");
57 | }
58 | CloseServiceHandle(hSCM);
59 | }
60 | else
61 | {
62 | printf("Failed to get SCM handle.\n");
63 | }
64 |
65 | return TRUE;
66 | }
67 |
68 | BOOL get_services(_In_ SC_HANDLE hServiceManager, _In_ DWORD serviceType, _Out_ ENUM_SERVICE_STATUS_PROCESS** servicesBuffer, _Out_ DWORD* serviceCount)
69 | {
70 | DWORD serviceBufferSize = 1024 * sizeof(ENUM_SERVICE_STATUS_PROCESS);
71 | ENUM_SERVICE_STATUS_PROCESS* services = static_cast(malloc(serviceBufferSize));
72 |
73 | if (serviceCount) //assume failure
74 | *serviceCount = 0;
75 |
76 | if (services) {
77 |
78 | SecureZeroMemory(services, serviceBufferSize);
79 |
80 | DWORD remainderBufferSize = 0;
81 | DWORD resumeHandle = 0;
82 | if (EnumServicesStatusEx(hServiceManager, SC_ENUM_PROCESS_INFO, serviceType, SERVICE_STATE_ALL, (LPBYTE)services, serviceBufferSize, &remainderBufferSize, serviceCount, &resumeHandle, NULL) != 0)
83 | {
84 | // success and we enumerated all the services
85 | *servicesBuffer = services;
86 | return TRUE;
87 | }
88 |
89 | DWORD lastError = GetLastError();
90 | if (lastError == ERROR_MORE_DATA)
91 | {
92 | // we didn't get all the services, so we'll just re-enumerate all to make things easy
93 | serviceBufferSize += remainderBufferSize;
94 |
95 | ENUM_SERVICE_STATUS_PROCESS* tmp;
96 |
97 | tmp = static_cast(realloc(services, serviceBufferSize));
98 | if (tmp) {
99 | services = tmp;
100 | SecureZeroMemory(services, serviceBufferSize);
101 | if (EnumServicesStatusEx(hServiceManager, SC_ENUM_PROCESS_INFO, serviceType, SERVICE_STATE_ALL, (LPBYTE)services, serviceBufferSize, &remainderBufferSize, serviceCount, NULL, NULL) != 0)
102 | {
103 | *servicesBuffer = services;
104 | return TRUE;
105 | }
106 | }
107 | }
108 | else
109 | {
110 | printf("ERROR: %u\n", lastError);
111 | }
112 |
113 | free(services);
114 |
115 | }
116 | return FALSE;
117 | }
118 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Services.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL VMDriverServices();
4 | BOOL get_services(_In_ SC_HANDLE hServiceManager, _In_ DWORD serviceType, _Out_ ENUM_SERVICE_STATUS_PROCESS** servicesBuffer, _Out_ DWORD* serviceCount);
5 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/VMWare.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "VMWare.h"
4 |
5 | /*
6 | Check against VMWare registry key values
7 | */
8 | VOID vmware_reg_key_value()
9 | {
10 | /* Array of strings of blacklisted registry key values */
11 | const TCHAR *szEntries[][3] = {
12 | { _T("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"), _T("Identifier"), _T("VMWARE") },
13 | { _T("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"), _T("Identifier"), _T("VMWARE") },
14 | { _T("HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"), _T("Identifier"), _T("VMWARE") },
15 | { _T("SYSTEM\\ControlSet001\\Control\\SystemInformation"), _T("SystemManufacturer"), _T("VMWARE") },
16 | { _T("SYSTEM\\ControlSet001\\Control\\SystemInformation"), _T("SystemProductName"), _T("VMWARE") },
17 | };
18 |
19 | WORD dwLength = sizeof(szEntries) / sizeof(szEntries[0]);
20 |
21 | for (int i = 0; i < dwLength; i++)
22 | {
23 | TCHAR msg[256] = _T("");
24 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s"), szEntries[i][0]);
25 | if (Is_RegKeyValueExists(HKEY_LOCAL_MACHINE, szEntries[i][0], szEntries[i][1], szEntries[i][2]))
26 | print_results(TRUE, msg);
27 | else
28 | print_results(FALSE, msg);
29 | }
30 | }
31 |
32 |
33 |
34 | /*
35 | Check against VMWare registry keys
36 | */
37 | VOID vmware_reg_keys()
38 | {
39 | /* Array of strings of blacklisted registry keys */
40 | const TCHAR* szKeys[] = {
41 | _T("SOFTWARE\\VMware, Inc.\\VMware Tools"),
42 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_15AD*"),
43 | };
44 |
45 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
46 |
47 | /* Check one by one */
48 | for (int i = 0; i < dwlength; i++)
49 | {
50 | TCHAR msg[256] = _T("");
51 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
52 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
53 | print_results(TRUE, msg);
54 | else
55 | print_results(FALSE, msg);
56 | }
57 | }
58 |
59 |
60 | /*
61 | Check against VMWare blacklisted files
62 | */
63 | VOID vmware_files()
64 | {
65 | /* Array of strings of blacklisted paths */
66 | const TCHAR* szPaths[] = {
67 | _T("System32\\drivers\\vmnet.sys"),
68 | _T("System32\\drivers\\vmmouse.sys"),
69 | _T("System32\\drivers\\vmusb.sys"),
70 | _T("System32\\drivers\\vm3dmp.sys"),
71 | _T("System32\\drivers\\vmci.sys"),
72 | _T("System32\\drivers\\vmhgfs.sys"),
73 | _T("System32\\drivers\\vmmemctl.sys"),
74 | _T("System32\\drivers\\vmx86.sys"),
75 | _T("System32\\drivers\\vmrawdsk.sys"),
76 | _T("System32\\drivers\\vmusbmouse.sys"),
77 | _T("System32\\drivers\\vmkdb.sys"),
78 | _T("System32\\drivers\\vmnetuserif.sys"),
79 | _T("System32\\drivers\\vmnetadapter.sys"),
80 | };
81 |
82 | /* Getting Windows Directory */
83 | WORD dwlength = sizeof(szPaths) / sizeof(szPaths[0]);
84 | TCHAR szWinDir[MAX_PATH] = _T("");
85 | TCHAR szPath[MAX_PATH] = _T("");
86 | PVOID OldValue = NULL;
87 |
88 | GetWindowsDirectory(szWinDir, MAX_PATH);
89 |
90 | if (IsWoW64()) {
91 | Wow64DisableWow64FsRedirection(&OldValue);
92 | }
93 |
94 | /* Check one by one */
95 | for (int i = 0; i < dwlength; i++)
96 | {
97 | PathCombine(szPath, szWinDir, szPaths[i]);
98 | TCHAR msg[256] = _T("");
99 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking file %s "), szPath);
100 | if (is_FileExists(szPath))
101 | print_results(TRUE, msg);
102 | else
103 | print_results(FALSE, msg);
104 | }
105 |
106 | if (IsWoW64()) {
107 | Wow64RevertWow64FsRedirection(&OldValue);
108 | }
109 |
110 | }
111 |
112 | /*
113 | Check against VMWare blacklisted directories
114 | */
115 | BOOL vmware_dir()
116 | {
117 | TCHAR szProgramFile[MAX_PATH];
118 | TCHAR szPath[MAX_PATH] = _T("");
119 | TCHAR szTarget[MAX_PATH] = _T("VMWare\\");
120 |
121 | if (IsWoW64())
122 | ExpandEnvironmentStrings(_T("%ProgramW6432%"), szProgramFile, ARRAYSIZE(szProgramFile));
123 | else
124 | SHGetSpecialFolderPath(NULL, szProgramFile, CSIDL_PROGRAM_FILES, FALSE);
125 |
126 | PathCombine(szPath, szProgramFile, szTarget);
127 | return is_DirectoryExists(szPath);
128 | }
129 |
130 |
131 | /*
132 | Check VMWare NIC MAC addresses
133 | */
134 | VOID vmware_mac()
135 | {
136 | /* VMWre blacklisted mac adr */
137 | const TCHAR *szMac[][2] = {
138 | { _T("\x00\x05\x69"), _T("00:05:69") }, // VMWare, Inc.
139 | { _T("\x00\x0C\x29"), _T("00:0c:29") }, // VMWare, Inc.
140 | { _T("\x00\x1C\x14"), _T("00:1C:14") }, // VMWare, Inc.
141 | { _T("\x00\x50\x56"), _T("00:50:56") }, // VMWare, Inc.
142 | };
143 |
144 | WORD dwLength = sizeof(szMac) / sizeof(szMac[0]);
145 |
146 | /* Check one by one */
147 | for (int i = 0; i < dwLength; i++)
148 | {
149 | TCHAR msg[256] = _T("");
150 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking MAC starting with %s"), szMac[i][1]);
151 | if (check_mac_addr(szMac[i][0]))
152 | print_results(TRUE, msg);
153 | else
154 | print_results(FALSE, msg);
155 | }
156 | }
157 |
158 |
159 | /*
160 | Check against VMWare adapter name
161 | */
162 | BOOL vmware_adapter_name()
163 | {
164 | const TCHAR* szAdapterName = _T("VMWare");
165 | if (check_adapter_name(szAdapterName))
166 | return TRUE;
167 | else
168 | return FALSE;
169 | }
170 |
171 |
172 | /*
173 | Check against VMWare pseaudo-devices
174 | */
175 | VOID vmware_devices()
176 | {
177 | const TCHAR *devices[] = {
178 | _T("\\\\.\\HGFS"),
179 | _T("\\\\.\\vmci"),
180 | };
181 |
182 | WORD iLength = sizeof(devices) / sizeof(devices[0]);
183 | for (int i = 0; i < iLength; i++)
184 | {
185 | HANDLE hFile = CreateFile(devices[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
186 | TCHAR msg[256] = _T("");
187 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking device %s "), devices[i]);
188 |
189 | if (hFile != INVALID_HANDLE_VALUE) {
190 | CloseHandle(hFile);
191 | print_results(TRUE, msg);
192 | }
193 | else
194 | print_results(FALSE, msg);
195 | }
196 | }
197 |
198 |
199 | /*
200 | Check for process list
201 | */
202 |
203 | VOID vmware_processes()
204 | {
205 | const TCHAR *szProcesses[] = {
206 | _T("vmtoolsd.exe"),
207 | _T("vmwaretray.exe"),
208 | _T("vmwareuser.exe"),
209 | _T("VGAuthService.exe"),
210 | _T("vmacthlp.exe"),
211 | };
212 |
213 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
214 | for (int i = 0; i < iLength; i++)
215 | {
216 | TCHAR msg[256] = _T("");
217 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking VWware process %s "), szProcesses[i]);
218 | if (GetProcessIdFromName(szProcesses[i]))
219 | print_results(TRUE, msg);
220 | else
221 | print_results(FALSE, msg);
222 | }
223 | }
224 |
225 | /*
226 | Check for SMBIOS firmware
227 | */
228 | BOOL vmware_firmware_SMBIOS()
229 | {
230 | BOOL result = FALSE;
231 | const DWORD Signature = static_cast('RSMB');
232 |
233 | DWORD smbiosSize = 0;
234 | PBYTE smbios = get_system_firmware(static_cast('RSMB'), 0x0000, &smbiosSize);
235 | if (smbios != NULL)
236 | {
237 | PBYTE vmwareString = (PBYTE)"VMware";
238 | size_t vmwwareStringLen = 6;
239 |
240 | if (find_str_in_data(vmwareString, vmwwareStringLen, smbios, smbiosSize))
241 | {
242 | result = TRUE;
243 | }
244 |
245 | free(smbios);
246 | }
247 |
248 | return result;
249 | }
250 |
251 | /*
252 | Check for ACPI firmware
253 | */
254 | BOOL vmware_firmware_ACPI()
255 | {
256 | BOOL result = FALSE;
257 |
258 | PDWORD tableNames = static_cast(malloc(4096));
259 |
260 | if (tableNames == NULL)
261 | return FALSE;
262 |
263 | SecureZeroMemory(tableNames, 4096);
264 | DWORD tableSize = enum_system_firmware_tables(static_cast('ACPI'), tableNames, 4096);
265 |
266 | // API not available
267 | if (tableSize == -1)
268 | return FALSE;
269 |
270 | DWORD tableCount = tableSize / 4;
271 | if (tableSize < 4 || tableCount == 0)
272 | {
273 | result = TRUE;
274 | }
275 | else
276 | {
277 | for (DWORD i = 0; i < tableCount; i++) {
278 | DWORD tableSize = 0;
279 | PBYTE table = get_system_firmware(static_cast('ACPI'), tableNames[i], &tableSize);
280 |
281 | if (table) {
282 |
283 | PBYTE vmwareString = (PBYTE)"VMWARE";
284 | size_t vmwwareStringLen = 6;
285 |
286 | if (find_str_in_data(vmwareString, vmwwareStringLen, table, tableSize)) {
287 | result = TRUE;
288 | }
289 |
290 | free(table);
291 | }
292 | }
293 | }
294 |
295 | free(tableNames);
296 | return result;
297 | }
298 |
299 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/VMWare.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID vmware_reg_key_value();
4 | VOID vmware_reg_keys();
5 | VOID vmware_files();
6 | BOOL vmware_dir();
7 | VOID vmware_mac();
8 | BOOL vmware_adapter_name();
9 | VOID vmware_devices();
10 | VOID vmware_processes();
11 | BOOL vmware_firmware_SMBIOS();
12 | BOOL vmware_firmware_ACPI();
--------------------------------------------------------------------------------
/al-khaser/AntiVM/VirtualBox.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID vbox_reg_key_value();
4 | VOID vbox_reg_keys();
5 | VOID vbox_files();
6 | BOOL vbox_dir();
7 |
8 | BOOL vbox_check_mac();
9 | VOID vbox_devices();
10 | BOOL vbox_window_class();
11 | BOOL vbox_network_share();
12 | VOID vbox_processes();
13 | BOOL vbox_mac_wmi();
14 | BOOL vbox_eventlogfile_wmi();
15 | BOOL vbox_firmware_SMBIOS();
16 | BOOL vbox_firmware_ACPI();
17 | BOOL vbox_bus_wmi();
18 | BOOL vbox_baseboard_wmi();
19 | BOOL vbox_pnpentity_pcideviceid_wmi();
20 | BOOL vbox_pnpentity_controllers_wmi();
21 | BOOL vbox_pnpentity_vboxname_wmi();
22 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/VirtualPC.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "VirtualPC.h"
4 |
5 | /*
6 | Check for process list
7 | */
8 |
9 | VOID virtual_pc_process()
10 | {
11 | const TCHAR *szProcesses[] = {
12 | _T("VMSrvc.exe"),
13 | _T("VMUSrvc.exe"),
14 | };
15 |
16 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
17 | for (int i = 0; i < iLength; i++)
18 | {
19 | TCHAR msg[256] = _T("");
20 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking Virtual PC processes %s "), szProcesses[i]);
21 | if (GetProcessIdFromName(szProcesses[i]))
22 | print_results(TRUE, msg);
23 | else
24 | print_results(FALSE, msg);
25 | }
26 | }
27 |
28 |
29 |
30 | VOID virtual_pc_reg_keys()
31 | {
32 | /* Array of strings of blacklisted registry keys */
33 | const TCHAR* szKeys[] = {
34 | _T("SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters"),
35 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_5333*"),
36 | };
37 |
38 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
39 |
40 | /* Check one by one */
41 | for (int i = 0; i < dwlength; i++)
42 | {
43 | TCHAR msg[256] = _T("");
44 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
45 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
46 | print_results(TRUE, msg);
47 | else
48 | print_results(FALSE, msg);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/VirtualPC.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | VOID virtual_pc_process();
5 | VOID virtual_pc_reg_keys();
6 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Wine.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Wine.h"
4 |
5 | /*
6 | Check against Wine export dlls
7 | */
8 | BOOL wine_exports()
9 | {
10 | /* Some vars */
11 | HMODULE hKernel32;
12 |
13 | /* Get kernel32 module handle */
14 | hKernel32 = GetModuleHandle(_T("kernel32.dll"));
15 | if (hKernel32 == NULL) {
16 | print_last_error(_T("GetModuleHandle"));
17 | return FALSE;
18 | }
19 |
20 | /* Check if wine_get_unix_file_name is exported by this dll */
21 | if (GetProcAddress(hKernel32, "wine_get_unix_file_name") == NULL)
22 | return FALSE;
23 | else
24 | return TRUE;
25 | }
26 |
27 | /*
28 | Check against Wine registry keys
29 | */
30 | VOID wine_reg_keys()
31 | {
32 | /* Array of strings of blacklisted registry keys */
33 | const TCHAR* szKeys[] = {
34 | _T("SOFTWARE\\Wine")
35 | };
36 |
37 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
38 |
39 | /* Check one by one */
40 | for (int i = 0; i < dwlength; i++)
41 | {
42 | TCHAR msg[256] = _T("");
43 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
44 | if (Is_RegKeyExists(HKEY_CURRENT_USER, szKeys[i]))
45 | print_results(TRUE, msg);
46 | else
47 | print_results(FALSE, msg);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Wine.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL wine_exports();
4 | VOID wine_reg_keys();
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Xen.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Xen.h"
4 |
5 | /*
6 | Check against Xen registry keys
7 | */
8 | VOID xen_reg_keys()
9 | {
10 | /* Array of strings of blacklisted registry keys */
11 | const TCHAR* szKeys[] = {
12 | _T("SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_5853*"),
13 | };
14 |
15 | WORD dwlength = sizeof(szKeys) / sizeof(szKeys[0]);
16 |
17 | /* Check one by one */
18 | for (int i = 0; i < dwlength; i++)
19 | {
20 | TCHAR msg[256] = _T("");
21 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
22 | if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
23 | print_results(TRUE, msg);
24 | else
25 | print_results(FALSE, msg);
26 | }
27 | }
28 |
29 | /*
30 | Check for process list
31 | */
32 |
33 | VOID xen_process()
34 | {
35 | const TCHAR *szProcesses[] = {
36 | _T("xenservice.exe"),
37 | };
38 |
39 | WORD iLength = sizeof(szProcesses) / sizeof(szProcesses[0]);
40 | for (int i = 0; i < iLength; i++)
41 | {
42 | TCHAR msg[256] = _T("");
43 | _stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking Citrix Xen process %s"), szProcesses[i]);
44 | if (GetProcessIdFromName(szProcesses[i]))
45 | print_results(TRUE, msg);
46 | else
47 | print_results(FALSE, msg);
48 | }
49 | }
50 |
51 |
52 |
53 | /*
54 | Check Xen NIC MAC address
55 | */
56 | BOOL xen_check_mac()
57 | {
58 | // Xensource, Inc.
59 | return check_mac_addr(_T("\x00\x16\x3E"));
60 | }
61 |
--------------------------------------------------------------------------------
/al-khaser/AntiVM/Xen.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID xen_reg_keys();
4 | VOID xen_process();
5 | BOOL xen_check_mac();
--------------------------------------------------------------------------------
/al-khaser/AntiVM/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/CreateRemoteThread.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "CreateRemoteThread.h"
4 |
5 | BOOL CreateRemoteThread_Injection()
6 | {
7 | /* Some vars */
8 | DWORD dwProcessId;
9 | HANDLE hProcess = NULL, hRemoteThread = NULL;
10 | HMODULE hKernel32;
11 | FARPROC LoadLibraryAddress;
12 | LPVOID lpBaseAddress = NULL;
13 | TCHAR lpDllName[] = _T("InjectedDLL.dll");
14 | TCHAR lpDllPath[MAX_PATH];
15 | SIZE_T dwSize;
16 | BOOL bStatus = FALSE, bDebugPrivilegeEnabled;
17 |
18 | /* Get Process ID from Process name */
19 | dwProcessId = GetProcessIdFromName(_T("notepad.exe"));
20 | if (dwProcessId == NULL)
21 | return FALSE;
22 | _tprintf(_T("\t[+] Getting proc id: %u\n"), dwProcessId);
23 |
24 | /* Set Debug privilege */
25 | bDebugPrivilegeEnabled = SetDebugPrivileges();
26 | _tprintf(_T("\t[+] Setting Debug Privileges [%d]\n"), bDebugPrivilegeEnabled);
27 | if (!bDebugPrivilegeEnabled)
28 | return FALSE;
29 |
30 | /* Obtain a handle the process */
31 | hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
32 | if (hProcess == NULL) {
33 | print_last_error(_T("OpenProcess"));
34 | goto Cleanup;
35 | }
36 |
37 | /* Obtain a handle to kernel32 */
38 | hKernel32 = GetModuleHandle(_T("kernel32.dll"));
39 | if (hKernel32 == NULL) {
40 | print_last_error(_T("GetModuleHandle"));
41 | goto Cleanup;
42 | }
43 |
44 | /* Get LoadLibrary address */
45 | _tprintf(_T("\t[+] Looking for LoadLibrary in kernel32\n"));
46 | LoadLibraryAddress = GetProcAddress(hKernel32, "LoadLibraryW");
47 | if (LoadLibraryAddress == NULL) {
48 | print_last_error(_T("GetProcAddress"));
49 | goto Cleanup;
50 | }
51 | _tprintf(_T("\t[+] Found at 0x%p\n"), LoadLibraryAddress);
52 |
53 | /* Get the full path of the dll */
54 | GetFullPathName(lpDllName, MAX_PATH, lpDllPath, NULL);
55 | _tprintf(_T("\t[+] Full DLL Path: %s\n"), lpDllPath);
56 |
57 | /* Calculate the number of bytes needed for the DLL's pathname */
58 | dwSize = _tcslen(lpDllPath) * sizeof(TCHAR);
59 |
60 | /* Allocate memory into the remote process */
61 | _tprintf(_T("\t[+] Allocating space for the path of the DLL\n"));
62 | lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
63 | if (lpBaseAddress == NULL) {
64 | print_last_error(_T("VirtualAllocEx"));
65 | goto Cleanup;
66 | }
67 |
68 | /* Write to the remote process */
69 | printf("\t[+] Writing into the current process space at 0x%p\n", lpBaseAddress);
70 | if (!WriteProcessMemory(hProcess, lpBaseAddress, lpDllPath, dwSize, NULL)) {
71 | print_last_error(_T("WriteProcessMemory"));
72 | goto Cleanup;
73 | }
74 |
75 | /* Create the more thread */
76 | hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryAddress, lpBaseAddress, NULL, 0);
77 | if (hRemoteThread == NULL) {
78 | print_last_error(_T("CreateRemoteThread"));
79 | }
80 | else {
81 | _tprintf(_T("Remote thread has been created successfully ...\n"));
82 | WaitForSingleObject(hRemoteThread, INFINITE);
83 | CloseHandle(hRemoteThread);
84 |
85 | /* assign function success return result */
86 | bStatus = TRUE;
87 | }
88 |
89 | Cleanup:
90 | /* If lpBaseAddress initialized then hProcess is initialized too because of upper check. */
91 | if (lpBaseAddress) {
92 | VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
93 | }
94 | if (hProcess) CloseHandle(hProcess);
95 |
96 | return bStatus;
97 | }
98 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/CreateRemoteThread.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL CreateRemoteThread_Injection();
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/GetSetThreadContext.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "GetSetThreadContext.h"
4 |
5 | BOOL GetSetThreadContext_Injection()
6 | {
7 | #ifdef _WIN64
8 | return TRUE; //TODO implement this on x64
9 | #else
10 | TCHAR lpApplicationName[] = _T("C:\\Windows\\System32\\svchost.exe");
11 | TCHAR lpApplicationName2[] = _T("C:\\masm32\\examples\\dialogs_later\\basic\\basicdlg.exe");
12 | BOOL bResult = FALSE;
13 |
14 | STARTUPINFO StartupInfo;
15 | PROCESS_INFORMATION ProcessInfo;
16 |
17 | PCONTEXT pContext = NULL;
18 | HANDLE hFile = INVALID_HANDLE_VALUE;
19 |
20 | SecureZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
21 | SecureZeroMemory(&ProcessInfo, sizeof(PPROCESS_INFORMATION));
22 |
23 | do { /* not a loop */
24 |
25 | // Create the hollowed process in suspended mode
26 | if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo)) {
27 | print_last_error(_T("CreateProcess"));
28 | break;
29 | }
30 |
31 | // Allocate space for context structure
32 | LPVOID pTargetImageBase = NULL;
33 |
34 | pContext = PCONTEXT(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE));
35 | if (pContext == NULL) {
36 | print_last_error(_T("VirtualAlloc"));
37 | break;
38 | }
39 |
40 | // Get the thread context of target
41 | pContext->ContextFlags = CONTEXT_FULL;
42 | if (!GetThreadContext(ProcessInfo.hThread, pContext)) {
43 | print_last_error(_T("GetThreadContext"));
44 | break;
45 | }
46 |
47 | // Read the image base address of target
48 | ReadProcessMemory(ProcessInfo.hProcess, LPCVOID(pContext->Ebx + 8), pTargetImageBase, 4, NULL);
49 |
50 | // Opening source image
51 | hFile = CreateFile(lpApplicationName2, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
52 | if (hFile == INVALID_HANDLE_VALUE)
53 | {
54 | print_last_error(_T("CreateFile"));
55 | break;
56 | }
57 |
58 | // Reading the file
59 | DWORD dwSize = GetFileSize(hFile, 0);
60 | DWORD dwBytesRead;
61 | PBYTE pBuffer = static_cast(MALLOC(dwSize));
62 |
63 | if (pBuffer == NULL) {
64 | print_last_error(_T("HeapAlloc"));
65 | break;
66 | }
67 | else {
68 |
69 | SecureZeroMemory(pBuffer, dwSize);
70 |
71 | ReadFile(hFile, pBuffer, dwSize, &dwBytesRead, 0);
72 | PIMAGE_SECTION_HEADER pImageSectionHeader;
73 |
74 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
75 | if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
76 | {
77 | PIMAGE_NT_HEADERS32 pNTHeaders = PIMAGE_NT_HEADERS(DWORD(pBuffer) + pDosHeader->e_lfanew);
78 | if (pNTHeaders->Signature == IMAGE_NT_SIGNATURE)
79 | {
80 |
81 | if (DWORD(pTargetImageBase) == pNTHeaders->OptionalHeader.ImageBase)
82 | {
83 | pNtUnmapViewOfSection NtUnmapViewOfSection;
84 | NtUnmapViewOfSection = (pNtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
85 | NtUnmapViewOfSection(ProcessInfo.hProcess, pTargetImageBase);
86 | }
87 |
88 | LPVOID pImageBase;
89 |
90 | pImageBase = VirtualAllocEx(ProcessInfo.hProcess, LPVOID(pNTHeaders->OptionalHeader.ImageBase),
91 | pNTHeaders->OptionalHeader.SizeOfImage,
92 | MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
93 |
94 | if (pImageBase == NULL) {
95 | print_last_error(_T("VirtualAllocEx"));
96 | break;
97 | }
98 | else {
99 |
100 | WriteProcessMemory(ProcessInfo.hProcess, pImageBase, pBuffer, pNTHeaders->OptionalHeader.SizeOfHeaders, NULL);
101 | for (int Count = 0; Count < pNTHeaders->FileHeader.NumberOfSections; Count++)
102 | {
103 | pImageSectionHeader = PIMAGE_SECTION_HEADER(DWORD(pBuffer) + pDosHeader->e_lfanew + 248 + (Count * 40));
104 | WriteProcessMemory(ProcessInfo.hProcess, LPVOID(DWORD(pImageBase) + pImageSectionHeader->VirtualAddress),
105 | LPVOID(DWORD(pBuffer) + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL);
106 | }
107 | WriteProcessMemory(ProcessInfo.hProcess, LPVOID(pContext->Ebx + 8), LPVOID(&pNTHeaders->OptionalHeader.ImageBase), 4, NULL);
108 | pContext->Eax = DWORD(pImageBase) + pNTHeaders->OptionalHeader.AddressOfEntryPoint;
109 | SetThreadContext(ProcessInfo.hThread, LPCONTEXT(pContext));
110 |
111 | LONG dwRet;
112 |
113 | dwRet = ResumeThread(ProcessInfo.hThread);
114 | bResult = (dwRet != -1);
115 | }
116 | }
117 | }
118 |
119 | FREE(pBuffer);
120 | }
121 |
122 | } while (FALSE); /* not a loop */
123 |
124 | /* Cleanup */
125 | if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread);
126 | if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess);
127 | if (pContext) VirtualFree(pContext, 0, MEM_RELEASE);
128 | if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
129 |
130 | return bResult;
131 | #endif
132 | }
133 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/GetSetThreadContext.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL GetSetThreadContext_Injection();
4 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/InjectedDLL/InjectedDLL.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "InjectedDLL.h"
3 |
4 | LRESULT CALLBACK MyProc(INT code, WPARAM wParam, LPARAM lParam);
5 |
6 | LRESULT CALLBACK MyProc(INT code, WPARAM wParam, LPARAM lParam)
7 | {
8 | //here goes our code
9 | TCHAR str[MAX_PATH] = _T("");
10 | _stprintf(str, _T("[Al-khaser] - Injected from process: %d"), GetCurrentProcessId());
11 | OutputDebugString(str);
12 | return CallNextHookEx(NULL, code, wParam, lParam); //this is needed to let other applications set other hooks on this target
13 | }
14 |
15 |
16 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
17 | {
18 | switch (dwReason)
19 | {
20 | case DLL_PROCESS_ATTACH:
21 | OutputDebugString(_T("[Al-khaser] - DLL is attached"));
22 | break;
23 |
24 | case DLL_PROCESS_DETACH:
25 | OutputDebugString(_T("[Al-khaser] - DLL is detached"));
26 | break;
27 |
28 | case DLL_THREAD_ATTACH:
29 | OutputDebugString(_T("[Al-khaser] - Thread is atached"));
30 | break;
31 |
32 | case DLL_THREAD_DETACH:
33 | OutputDebugString(_T("[Al-khaser] - Thread is detached"));
34 | break;
35 | }
36 |
37 | /* Returns TRUE on success, FALSE on failure */
38 | return TRUE;
39 | }
40 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/InjectedDLL/InjectedDLL.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/InjectedDLL/InjectedDLL.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {BFB018FC-33D1-4351-B6EA-1CA77336A0E4}
23 | Win32Proj
24 | InjectedDLL
25 | 8.1
26 |
27 |
28 |
29 | DynamicLibrary
30 | true
31 | v140_xp
32 | Unicode
33 |
34 |
35 | DynamicLibrary
36 | false
37 | v140_xp
38 | true
39 | Unicode
40 |
41 |
42 | DynamicLibrary
43 | true
44 | v140
45 | Unicode
46 |
47 |
48 | DynamicLibrary
49 | false
50 | v140
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 |
84 |
85 |
86 |
87 |
88 | Level3
89 | Disabled
90 | WIN32;_DEBUG;_WINDOWS;_USRDLL;INJECTEDDLL_EXPORTS;%(PreprocessorDefinitions)
91 | MultiThreaded
92 | false
93 |
94 |
95 | Windows
96 | true
97 | definitions.def
98 |
99 |
100 |
101 |
102 |
103 |
104 | Level3
105 | Disabled
106 | _DEBUG;_WINDOWS;_USRDLL;INJECTEDDLL_EXPORTS;%(PreprocessorDefinitions)
107 |
108 |
109 | Windows
110 | true
111 | definitions.def
112 |
113 |
114 |
115 |
116 | Level3
117 |
118 |
119 | MaxSpeed
120 | true
121 | true
122 | WIN32;NDEBUG;_WINDOWS;_USRDLL;INJECTEDDLL_EXPORTS;%(PreprocessorDefinitions)
123 | MultiThreaded
124 |
125 |
126 | Windows
127 | true
128 | true
129 | true
130 | definitions.def
131 |
132 |
133 |
134 |
135 | Level3
136 |
137 |
138 | MaxSpeed
139 | true
140 | true
141 | NDEBUG;_WINDOWS;_USRDLL;INJECTEDDLL_EXPORTS;%(PreprocessorDefinitions)
142 |
143 |
144 | Windows
145 | true
146 | true
147 | true
148 | definitions.def
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/InjectedDLL/InjectedDLL.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 | Header Files
25 |
26 |
27 |
28 |
29 | Source Files
30 |
31 |
32 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/InjectedDLL/definitions.def:
--------------------------------------------------------------------------------
1 | LIBRARY
2 | EXPORTS
3 | MyProc
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/NtCreateThreadEx.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "NtCreateThreadEx.h"
4 |
5 | BOOL NtCreateThreadEx_Injection()
6 | {
7 | // some vars
8 | HMODULE hNtdll;
9 | DWORD dwProcessId;
10 | HANDLE hProcess = NULL;
11 | TCHAR lpDllName[] = _T("InjectedDLL.dll");
12 | TCHAR lpDllPath[MAX_PATH];
13 | LPVOID lpBaseAddress = NULL;
14 | BOOL bStatus = FALSE;
15 | HMODULE hKernel32;
16 | FARPROC LoadLibraryAddress;
17 | HANDLE hRemoteThread = NULL;
18 | NTSTATUS Status;
19 | SIZE_T dwSize;
20 | CLIENT_ID ClientId;
21 | PS_ATTRIBUTE_LIST PsAttrList;
22 |
23 | // we have to import our function
24 | pNtCreateThreadEx NtCreateThreadEx = NULL;
25 |
26 | /*
27 | GetLastError cannot be used with NtCreateThreadEx because this service does not set Win32 LastError value.
28 | Native status code must be translated to Win32 error code and set manually.
29 | */
30 | pRtlNtStatusToDosError RtlNtStatusToDosErrorPtr = NULL;
31 |
32 | /* Get Process ID from Process name */
33 | dwProcessId = GetProcessIdFromName(_T("notepad.exe"));
34 | if (dwProcessId == 0)
35 | return FALSE;
36 | _tprintf(_T("\t[+] Getting proc id: %u\n"), dwProcessId);
37 |
38 | /* Obtain a handle the process */
39 | hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
40 | if (hProcess == NULL) {
41 | print_last_error(_T("OpenProcess"));
42 | goto Cleanup;
43 | }
44 |
45 | /* Get module handle of ntdll */
46 | hNtdll = GetModuleHandle(_T("ntdll.dll"));
47 | if (hNtdll == NULL) {
48 | print_last_error(_T("GetModuleHandle"));
49 | goto Cleanup;
50 | }
51 |
52 | /* Obtain a handle to kernel32 */
53 | hKernel32 = GetModuleHandle(_T("kernel32.dll"));
54 | if (hKernel32 == NULL) {
55 | print_last_error(_T("GetModuleHandle"));
56 | goto Cleanup;
57 | }
58 |
59 | /* Get routine pointer, failure is not critical */
60 | RtlNtStatusToDosErrorPtr = (pRtlNtStatusToDosError)GetProcAddress(hNtdll, "RtlNtStatusToDosError");
61 |
62 | // Get the address NtCreateThreadEx
63 | _tprintf(_T("\t[+] Looking for NtCreateThreadEx in ntdll\n"));
64 | NtCreateThreadEx = (pNtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");
65 | if (NtCreateThreadEx == NULL) {
66 | print_last_error(_T("GetProcAddress"));
67 | goto Cleanup;
68 | }
69 | _tprintf(_T("\t[+] Found at 0x%p\n"), NtCreateThreadEx);
70 |
71 | /* Get LoadLibrary address */
72 | _tprintf(_T("\t[+] Looking for LoadLibrary in kernel32\n"));
73 | LoadLibraryAddress = GetProcAddress(hKernel32, "LoadLibraryW");
74 | if (LoadLibraryAddress == NULL) {
75 | print_last_error(_T("GetProcAddress"));
76 | goto Cleanup;
77 | }
78 | _tprintf(_T("\t[+] Found at 0x%p\n"), LoadLibraryAddress);
79 |
80 | /* Get the full path of the dll */
81 | GetFullPathName(lpDllName, MAX_PATH, lpDllPath, NULL);
82 | _tprintf(_T("\t[+] Full DLL Path: %s\n"), lpDllPath);
83 |
84 | /* Calculate the number of bytes needed for the DLL's pathname */
85 | dwSize = _tcslen(lpDllPath) * sizeof(TCHAR);
86 |
87 | /* Allocate memory into the remote process */
88 | _tprintf(_T("\t[+] Allocating space for the path of the DLL\n"));
89 | lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
90 | if (lpBaseAddress == NULL) {
91 | print_last_error(_T("VirtualAllocEx"));
92 | goto Cleanup;
93 | }
94 |
95 | /* Write to the remote process */
96 | printf("\t[+] Writing into the current process space at 0x%p\n", lpBaseAddress);
97 | if (!WriteProcessMemory(hProcess, lpBaseAddress, lpDllPath, dwSize, NULL)) {
98 | print_last_error(_T("WriteProcessMemory"));
99 | goto Cleanup;
100 | }
101 |
102 | /* Create the more thread */
103 | SecureZeroMemory(&PsAttrList, sizeof(PsAttrList));
104 |
105 | /* Setup attributes entry */
106 | PsAttrList.TotalLength = sizeof(PS_ATTRIBUTE_LIST);
107 | PsAttrList.Attributes[0].Attribute = PS_ATTRIBUTE_CLIENT_ID;
108 | PsAttrList.Attributes[0].Size = sizeof(CLIENT_ID);
109 | PsAttrList.Attributes[0].u1.ValuePtr = &ClientId;
110 |
111 | Status = NtCreateThreadEx(&hRemoteThread, THREAD_ALL_ACCESS, NULL, hProcess,
112 | (LPTHREAD_START_ROUTINE)LoadLibraryAddress, lpBaseAddress, 0, 0, 0, 0, &PsAttrList);
113 |
114 | if (!NT_SUCCESS(Status)) {
115 | if (RtlNtStatusToDosErrorPtr) {
116 | SetLastError(RtlNtStatusToDosErrorPtr(Status));
117 | }
118 | else {
119 | SetLastError(ERROR_INTERNAL_ERROR);
120 | }
121 | print_last_error(_T("NtCreateThreadEx"));
122 | }
123 |
124 | else {
125 | _tprintf(_T("Remote thread has been created successfully ...\n"));
126 | WaitForSingleObject(hRemoteThread, INFINITE);
127 | CloseHandle(hRemoteThread);
128 |
129 | /* assign function success return result */
130 | bStatus = TRUE;
131 | }
132 |
133 | Cleanup:
134 | /* If lpBaseAddress initialized then hProcess is initialized too because of upper check. */
135 | if (lpBaseAddress) {
136 | VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
137 | }
138 | if (hProcess) CloseHandle(hProcess);
139 |
140 | return bStatus;
141 | }
142 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/NtCreateThreadEx.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL NtCreateThreadEx_Injection();
4 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/QueueUserAPC.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "QueueUserAPC.h"
4 |
5 | //
6 | // Check whatever InjectedDLL.dll was loaded, because this dll
7 | // does not provide any other way of caller notification.
8 | //
9 | BOOL IsDllInjected(DWORD dwProcessId, LPTSTR DllName)
10 | {
11 | BOOL bFound = FALSE;
12 | HANDLE hSnapshot;
13 |
14 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
15 | if (hSnapshot != INVALID_HANDLE_VALUE) {
16 |
17 | MODULEENTRY32 me32;
18 | me32.dwSize = sizeof(MODULEENTRY32);
19 |
20 | if (Module32First(hSnapshot, &me32)) {
21 |
22 | do {
23 |
24 | if (StrCmpI(me32.szModule, DllName) == 0) {
25 | bFound = TRUE;
26 | break;
27 | }
28 |
29 | } while (Module32Next(hSnapshot, &me32));
30 |
31 | }
32 |
33 | CloseHandle(hSnapshot);
34 | }
35 |
36 | return bFound;
37 | }
38 |
39 | BOOL QueueUserAPC_Injection()
40 | {
41 | TCHAR lpDllName[] = _T("InjectedDLL.dll");
42 | TCHAR lpDllPath[MAX_PATH];
43 |
44 | HANDLE hThreadSnapshot = INVALID_HANDLE_VALUE;
45 |
46 | DWORD dwTargetProcessId, dwCurrentProcessId = GetCurrentProcessId();
47 |
48 | HANDLE hProcess = NULL;
49 | HANDLE hThread = NULL;
50 |
51 | HMODULE hKernel32;
52 |
53 | FARPROC LoadLibraryAddress;
54 | LPVOID lpBaseAddress = NULL;
55 | BOOL bStatus = FALSE;
56 |
57 |
58 | /* Get Process ID from Process name */
59 |
60 | //
61 | // calc used because it has multiple threads and some of them maybe alertable.
62 | //
63 | dwTargetProcessId = GetProcessIdFromName(_T("calc.exe"));
64 | if (dwTargetProcessId == 0)
65 | dwTargetProcessId = GetProcessIdFromName(_T("win32calc.exe"));//w10 classic calc
66 |
67 | if (dwTargetProcessId == 0) {
68 | print_last_error(_T("GetProcessIdFromName"));
69 | return FALSE;
70 | }
71 |
72 | /* Obtain a hmodule of kernel32 */
73 | hKernel32 = GetModuleHandle(_T("kernel32.dll"));
74 | if (hKernel32 == NULL) {
75 | print_last_error(_T("GetModuleHandle"));
76 | return FALSE;
77 | }
78 |
79 | /* Get LoadLibrary address */
80 | _tprintf(_T("\t[+] Looking for LoadLibrary in kernel32\n"));
81 | LoadLibraryAddress = GetProcAddress(hKernel32, "LoadLibraryW");
82 | if (LoadLibraryAddress == NULL) {
83 | print_last_error(_T("GetProcAddress"));
84 | return FALSE;
85 | }
86 | _tprintf(_T("\t[+] Found at 0x%p\n"), LoadLibraryAddress);
87 |
88 | _tprintf(_T("\t[+] Getting proc id: %u\n"), dwTargetProcessId);
89 |
90 | /* Obtain a handle the process */
91 | hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTargetProcessId);
92 | if (hProcess == NULL) {
93 | print_last_error(_T("OpenProcess"));
94 | return FALSE;
95 | }
96 |
97 | do { // not a loop
98 |
99 | /* Get the full path of the dll */
100 | GetFullPathName(lpDllName, MAX_PATH, lpDllPath, NULL);
101 | _tprintf(_T("\t[+] Full DLL Path: %s\n"), lpDllPath);
102 |
103 | // The maximum size of the string buffer.
104 | SIZE_T WriteBufferSize = _tcslen(lpDllPath) * sizeof(TCHAR);
105 |
106 | /* Allocate memory into the remote process */
107 | _tprintf(_T("\t[+] Allocating space for the path of the DLL\n"));
108 | lpBaseAddress = VirtualAllocEx(hProcess, NULL, WriteBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
109 | if (lpBaseAddress == NULL) {
110 | print_last_error(_T("VirtualAllocEx"));
111 | break;
112 | }
113 |
114 | /* Write to the remote process */
115 | printf("\t[+] Writing into the current process space at 0x%p\n", lpBaseAddress);
116 | if (!WriteProcessMemory(hProcess, lpBaseAddress, lpDllPath, WriteBufferSize, NULL)) {
117 | print_last_error(_T("WriteProcessMemory"));
118 | break;
119 | }
120 |
121 | hThreadSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
122 | if (hThreadSnapshot == INVALID_HANDLE_VALUE)
123 | break;
124 |
125 | THREADENTRY32 te32;
126 | te32.dwSize = sizeof(THREADENTRY32);
127 |
128 | //
129 | // Brute force threads to find suitable alertable thread for APC injection (if any).
130 | //
131 | if (Thread32First(hThreadSnapshot, &te32)) {
132 | do {
133 | if (te32.th32OwnerProcessID == dwTargetProcessId) {
134 |
135 | hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
136 | if (hThread) {
137 |
138 | if (QueueUserAPC((PAPCFUNC)LoadLibraryAddress, hThread, (ULONG_PTR)lpBaseAddress)) {
139 |
140 | if (IsDllInjected(dwTargetProcessId, lpDllName)) {
141 | bStatus = TRUE;
142 | }
143 | }
144 | CloseHandle(hThread);
145 | }
146 | }
147 |
148 | // dll injected - leave
149 | if (bStatus) {
150 | _tprintf(_T("\t[+] Dll has been injected successfully ...\n"));
151 | break;
152 | }
153 |
154 | } while (Thread32Next(hThreadSnapshot, &te32));
155 | }
156 |
157 | } while (FALSE); // not a loop
158 |
159 | //
160 | // Cleanup.
161 | //
162 | if (hThreadSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hThreadSnapshot);
163 |
164 | if (lpBaseAddress) {
165 | VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
166 | }
167 |
168 | CloseHandle(hProcess);
169 |
170 | return bStatus;
171 | }
172 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/QueueUserAPC.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL QueueUserAPC_Injection();
4 |
5 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/RtlCreateUserThread.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "RtlCreateUserThread.h"
4 |
5 | BOOL RtlCreateUserThread_Injection()
6 | {
7 | // some vars
8 | HMODULE hNtdll;
9 | DWORD dwProcessId;
10 | HANDLE hProcess;
11 | TCHAR lpDllName[] = _T("InjectedDLL.dll");
12 | TCHAR lpDllPath[MAX_PATH];
13 | LPVOID lpBaseAddress = NULL;
14 | BOOL bStatus = FALSE;
15 | HMODULE hKernel32;
16 | FARPROC LoadLibraryAddress;
17 | HANDLE hRemoteThread = NULL;
18 | SIZE_T dwSize;
19 | NTSTATUS Status;
20 |
21 | // we have to import our function
22 | pRtlCreateUserThread RtlCreateUserThread = NULL;
23 |
24 | /*
25 | GetLastError cannot be used with RtlCreateUserThread because this routine does not set Win32 LastError value.
26 | Native status code must be translated to Win32 error code and set manually.
27 | */
28 | pRtlNtStatusToDosError RtlNtStatusToDosErrorPtr = NULL;
29 |
30 | /* Get Process ID from Process name */
31 | dwProcessId = GetProcessIdFromName(_T("notepad.exe"));
32 | if (dwProcessId == NULL)
33 | return FALSE;
34 | _tprintf(_T("\t[+] Getting proc id: %u\n"), dwProcessId);
35 |
36 | /* Obtain a handle the process */
37 | hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
38 | if (hProcess == NULL) {
39 | print_last_error(_T("OpenProcess"));
40 | return FALSE;
41 | }
42 |
43 | /* Get module handle of ntdll */
44 | hNtdll = GetModuleHandle(_T("ntdll.dll"));
45 | if (hNtdll == NULL) {
46 | print_last_error(_T("GetModuleHandle"));
47 | goto Cleanup;
48 | }
49 |
50 | /* Get routine pointer, failure is not critical */
51 | RtlNtStatusToDosErrorPtr = (pRtlNtStatusToDosError)GetProcAddress(hNtdll, "RtlNtStatusToDosError");
52 |
53 | /* Obtain a handle to kernel32 */
54 | hKernel32 = GetModuleHandle(_T("kernel32.dll"));
55 | if (hKernel32 == NULL) {
56 | print_last_error(_T("GetModuleHandle"));
57 | goto Cleanup;
58 | }
59 |
60 | // Get the address RtlCreateUserThread
61 | _tprintf(_T("\t[+] Looking for RtlCreateUserThread in ntdll\n"));
62 | RtlCreateUserThread = (pRtlCreateUserThread)GetProcAddress(hNtdll, "RtlCreateUserThread");
63 | if (RtlCreateUserThread == NULL) {
64 | print_last_error(_T("GetProcAddress"));
65 | goto Cleanup;
66 | }
67 | _tprintf(_T("\t[+] Found at 0x%p\n"), RtlCreateUserThread);
68 |
69 | /* Get LoadLibrary address */
70 | _tprintf(_T("\t[+] Looking for LoadLibrary in kernel32\n"));
71 | LoadLibraryAddress = GetProcAddress(hKernel32, "LoadLibraryW");
72 | if (LoadLibraryAddress == NULL) {
73 | print_last_error(_T("GetProcAddress"));
74 | goto Cleanup;
75 | }
76 | _tprintf(_T("\t[+] Found at 0x%p\n"), LoadLibraryAddress);
77 |
78 | /* Get the full path of the dll */
79 | GetFullPathName(lpDllName, MAX_PATH, lpDllPath, NULL);
80 | _tprintf(_T("\t[+] Full DLL Path: %s\n"), lpDllPath);
81 |
82 | /* Calculate the number of bytes needed for the DLL's pathname */
83 | dwSize = _tcslen(lpDllPath) * sizeof(TCHAR);
84 |
85 | /* Allocate memory into the remote process */
86 | _tprintf(_T("\t[+] Allocating space for the path of the DLL\n"));
87 | lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
88 | if (lpBaseAddress == NULL) {
89 | print_last_error(_T("VirtualAllocEx"));
90 | goto Cleanup;
91 | }
92 |
93 | /* Write to the remote process */
94 | printf("\t[+] Writing into the current process space at 0x%p\n", lpBaseAddress);
95 | if (!WriteProcessMemory(hProcess, lpBaseAddress, lpDllPath, dwSize, NULL)) {
96 | print_last_error(_T("WriteProcessMemory"));
97 | goto Cleanup;
98 | }
99 |
100 | /* Create the more thread */
101 | Status = RtlCreateUserThread(hProcess, NULL, 0, 0, 0, 0, LoadLibraryAddress, lpBaseAddress, &hRemoteThread, NULL);
102 | if (!NT_SUCCESS(Status)) {
103 | if (RtlNtStatusToDosErrorPtr) {
104 | SetLastError(RtlNtStatusToDosErrorPtr(Status));
105 | }
106 | else {
107 | SetLastError(ERROR_INTERNAL_ERROR);
108 | }
109 | print_last_error(_T("RtlCreateUserThread"));
110 | }
111 | else {
112 | _tprintf(_T("Remote thread has been created successfully ...\n"));
113 | WaitForSingleObject(hRemoteThread, INFINITE);
114 | CloseHandle(hRemoteThread);
115 |
116 | /* assign function success return result */
117 | bStatus = TRUE;
118 | }
119 | Cleanup:
120 | /* hProcess is always initialized here. */
121 | if (lpBaseAddress) {
122 | VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
123 | }
124 | CloseHandle(hProcess);
125 |
126 | return bStatus;
127 | }
128 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/RtlCreateUserThread.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL RtlCreateUserThread_Injection();
4 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/SetWindowsHooksEx.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "SetWindowsHooksEx.h"
4 |
5 | BOOL SetWindowsHooksEx_Injection()
6 | {
7 | TCHAR lpDllName[] = _T("InjectedDLL.dll");
8 | TCHAR lpDllPath[MAX_PATH];
9 | HOOKPROC myFunctionAddress;
10 | HMODULE hOurDll;
11 | DWORD dwProcessId, dwThreadId;
12 | HHOOK hHook;
13 |
14 | /* Get Process ID from Process name */
15 | dwProcessId = GetProcessIdFromName(_T("notepad.exe"));
16 | if (dwProcessId == NULL)
17 | return FALSE;
18 | _tprintf(_T("\t[+] Getting proc id: %u\n"), dwProcessId);
19 |
20 | /* Get thread id from process id */
21 | dwThreadId = GetMainThreadId(dwProcessId);
22 | if (dwThreadId == NULL)
23 | return FALSE;
24 | _tprintf(_T("\t[+] Getting main thread id of proc id: %u\n"), dwThreadId);
25 |
26 | /* Get the full path of the dll to be injected */
27 | GetFullPathName(lpDllName, MAX_PATH, lpDllPath, NULL);
28 | _tprintf(_T("\t[+] Full DLL Path: %s\n"), lpDllPath);
29 |
30 | /* Obtain a handle to our injected dll */
31 | hOurDll = LoadLibrary(lpDllPath);
32 | if (hOurDll == NULL) {
33 | print_last_error(_T("LoadLibrary"));
34 | return FALSE;
35 | }
36 |
37 | /* Get 'MyProc' address */
38 | _tprintf(_T("\t[+] Looking for 'MyProc' in our dll\n"));
39 | myFunctionAddress = (HOOKPROC)GetProcAddress(hOurDll, "MyProc");
40 | if (myFunctionAddress == NULL) {
41 | print_last_error(_T("GetProcAddress"));
42 | return FALSE;
43 | }
44 | _tprintf(_T("\t[+] Found at 0x%p\n"), myFunctionAddress);
45 |
46 | /* Injection happens here */
47 | hHook = SetWindowsHookEx(WH_KEYBOARD, myFunctionAddress, hOurDll, dwThreadId);
48 | if (hHook == NULL) {
49 | print_last_error(_T("SetWindowsHookEx"));
50 | return FALSE;
51 | }
52 |
53 | /* Unhook */
54 | _tprintf(_T("SetWindowsHookEx created successfully ...\n"));
55 |
56 | /* When we want to remove the hook */
57 | // UnhookWindowsHookEx(hHook);
58 |
59 | return TRUE;
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/SetWindowsHooksEx.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL SetWindowsHooksEx_Injection();
--------------------------------------------------------------------------------
/al-khaser/CodeInjection/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/OfficeMacro/al-khaser.docm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayoubfaouzi/al-khaser/c0602534742d4eb02d02482b9dabffa02d250d28/al-khaser/OfficeMacro/al-khaser.docm
--------------------------------------------------------------------------------
/al-khaser/OfficeMacro/macros.vba:
--------------------------------------------------------------------------------
1 | Sub Document_Close()
2 |
3 | On Error Resume Next
4 |
5 | ActiveDocument.Range.Text = "Al-khaser 0.69 by Lord Noteworthy" & vbCrLf & vbCrLf & "Public malware techniques used in the wild: Virtual Machine, Emulation, Debuggers, Sandbox detection." & vbCrLf
6 |
7 | checkFileMRU
8 | End Sub
9 |
10 |
11 | Public Sub checkFileMRU()
12 |
13 | printMsg "[*] Checking Application.RecentFiles.Count ..."
14 |
15 | ActiveDocument.Range.Text = ActiveDocument.Range.Text & msg
16 | If Application.RecentFiles.Count < 3 Then
17 | printMsg "BAD"
18 | Else
19 | printMsg "GOOD"
20 | End If
21 |
22 | End Sub
23 |
24 |
25 | Public Function printMsg(msg)
26 |
27 | ActiveDocument.Range.Text = ActiveDocument.Range.Text & msg
28 |
29 | End Function
--------------------------------------------------------------------------------
/al-khaser/Shared/APIs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum API_IDENTIFIER
4 | {
5 | API_CsrGetProcessId,
6 | API_EnumSystemFirmwareTables,
7 | API_GetActiveProcessorCount,
8 | API_GetSystemFirmwareTable,
9 | API_GetNativeSystemInfo,
10 | API_GetProductInfo,
11 | API_EnumProcessModulesEx_Kernel,
12 | API_EnumProcessModulesEx_PSAPI,
13 | API_IsWow64Process,
14 | API_LdrEnumerateLoadedModules,
15 | API_NtClose,
16 | API_NtSystemDebugControl,
17 | API_NtCreateDebugObject,
18 | API_NtDelayExecution,
19 | API_NtOpenDirectoryObject,
20 | API_NtQueryInformationThread,
21 | API_NtQueryInformationProcess,
22 | API_NtQueryLicenseValue,
23 | API_NtQueryDirectoryObject,
24 | API_NtQueryObject,
25 | API_NtQuerySystemInformation,
26 | API_NtSetInformationThread,
27 | API_NtWow64QueryInformationProcess64,
28 | API_NtWow64QueryVirtualMemory64,
29 | API_NtWow64ReadVirtualMemory64,
30 | API_NtYieldExecution,
31 | API_RtlGetVersion,
32 | API_RtlInitUnicodeString,
33 | API_WudfIsAnyDebuggerPresent,
34 | API_WudfIsKernelDebuggerPresent,
35 | API_WudfIsUserDebuggerPresent,
36 | };
37 |
38 | enum API_OS_VERSION
39 | {
40 | NONE,
41 | WIN_XP,
42 | WIN_XP_SP1,
43 | WIN_XP_SP2,
44 | WIN_XP_SP3,
45 | WIN_VISTA,
46 | WIN_VISTA_SP1,
47 | WIN_VISTA_SP2,
48 | WIN_7,
49 | WIN_7_SP1,
50 | WIN_80,
51 | WIN_81,
52 | WIN_10,
53 | VERSION_MAX
54 | };
55 |
56 | enum API_OS_BITS
57 | {
58 | ANY,
59 | X86_ONLY,
60 | X64_ONLY,
61 | };
62 |
63 | struct VERSION_FUNCTION_MAP
64 | {
65 | API_OS_VERSION Version;
66 | bool(*Function)();
67 |
68 | VERSION_FUNCTION_MAP(API_OS_VERSION version, bool(*function)())
69 | {
70 | Version = version;
71 | Function = function;
72 | }
73 |
74 | VERSION_FUNCTION_MAP()
75 | {
76 | }
77 | };
78 |
79 | struct API_DATA
80 | {
81 | API_IDENTIFIER Identifier;
82 | const char* Library;
83 | const char* EntryName;
84 | API_OS_BITS PlatformBits;
85 | API_OS_VERSION MinVersion;
86 | API_OS_VERSION RemovedInVersion;
87 | bool Available;
88 | bool ExpectedAvailable;
89 | void* Pointer;
90 |
91 | API_DATA(API_IDENTIFIER identifier, const char* lib, const char* name, API_OS_BITS bits, API_OS_VERSION minVersion, API_OS_VERSION removedInVersion)
92 | {
93 | Identifier = identifier;
94 | Library = lib;
95 | EntryName = name;
96 | PlatformBits = bits;
97 | MinVersion = minVersion;
98 | RemovedInVersion = removedInVersion;
99 | Available = false;
100 | ExpectedAvailable = false;
101 | Pointer = nullptr;
102 | }
103 | };
104 |
105 | const VERSION_FUNCTION_MAP VersionFunctionMap[] = {
106 | { API_OS_VERSION::NONE, nullptr },
107 | { API_OS_VERSION::WIN_XP, IsWindowsXPOrGreater },
108 | { API_OS_VERSION::WIN_XP_SP1, IsWindowsXPSP1OrGreater },
109 | { API_OS_VERSION::WIN_XP_SP2, IsWindowsXPSP2OrGreater },
110 | { API_OS_VERSION::WIN_XP_SP3, IsWindowsXPSP3OrGreater },
111 | { API_OS_VERSION::WIN_VISTA, IsWindowsVistaOrGreater },
112 | { API_OS_VERSION::WIN_VISTA_SP1, IsWindowsVistaSP1OrGreater },
113 | { API_OS_VERSION::WIN_VISTA_SP2, IsWindowsVistaSP2OrGreater },
114 | { API_OS_VERSION::WIN_7, IsWindows7OrGreater },
115 | { API_OS_VERSION::WIN_7_SP1, IsWindows7SP1OrGreater },
116 | { API_OS_VERSION::WIN_80, IsWindows8OrGreater },
117 | { API_OS_VERSION::WIN_81, IsWindows8Point1OrGreater },
118 | { API_OS_VERSION::WIN_10, IsWindows10OrGreater },
119 | };
120 |
121 | class API
122 | {
123 | private:
124 | static bool ShouldFunctionExistOnCurrentPlatform(API_OS_BITS bits, API_OS_VERSION minVersion, API_OS_VERSION removedInVersion);
125 | public:
126 | static void Init();
127 | static void PrintAvailabilityReport();
128 | static bool IsAvailable(API_IDENTIFIER api);
129 | static void* GetAPI(API_IDENTIFIER api);
130 | };
--------------------------------------------------------------------------------
/al-khaser/Shared/ApiTypeDefs.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/al-khaser/Shared/ApiTypeDefs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef DWORD(NTAPI* pCsrGetId)(VOID);
4 | typedef BOOL(WINAPI* pEnumProcessModulesEx)(
5 | HANDLE hProcess,
6 | HMODULE *lphModule,
7 | DWORD cb,
8 | LPDWORD lpcbNeeded,
9 | DWORD dwFilterFlag);
10 | typedef UINT(WINAPI* pEnumSystemFirmwareTables)(DWORD, PVOID, DWORD);
11 | typedef DWORD(WINAPI* pGetActiveProcessorCount)(WORD);
12 | typedef UINT(WINAPI* pGetSystemFirmwareTable)(DWORD, DWORD, PVOID, DWORD);
13 | typedef void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
14 | typedef BOOL(WINAPI *pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
15 | typedef BOOL(WINAPI *pIsWow64Process) (HANDLE, PBOOL);
16 | typedef DWORD(WINAPI * pRtlCreateUserThread)(
17 | IN HANDLE ProcessHandle,
18 | IN PSECURITY_DESCRIPTOR SecurityDescriptor,
19 | IN BOOL CreateSuspended,
20 | IN ULONG StackZeroBits,
21 | IN OUT PULONG StackReserved,
22 | IN OUT PULONG StackCommit,
23 | IN LPVOID StartAddress,
24 | IN LPVOID StartParameter,
25 | OUT HANDLE ThreadHandle,
26 | OUT LPVOID ClientID
27 | );
28 | typedef NTSTATUS(WINAPI* pNtClose)(HANDLE);
29 | typedef enum _SYSDBG_COMMAND {
30 | SysDbgQueryModuleInformation,
31 | SysDbgQueryTraceInformation,
32 | SysDbgSetTracepoint,
33 | SysDbgSetSpecialCall,
34 | SysDbgClearSpecialCalls,
35 | SysDbgQuerySpecialCalls,
36 | SysDbgBreakPoint,
37 | SysDbgQueryVersion,
38 | SysDbgReadVirtual,
39 | SysDbgWriteVirtual,
40 | SysDbgReadPhysical,
41 | SysDbgWritePhysical,
42 | SysDbgReadControlSpace,
43 | SysDbgWriteControlSpace,
44 | SysDbgReadIoSpace,
45 | SysDbgWriteIoSpace,
46 | SysDbgReadMsr,
47 | SysDbgWriteMsr,
48 | SysDbgReadBusData,
49 | SysDbgWriteBusData,
50 | SysDbgCheckLowMemory,
51 | SysDbgEnableKernelDebugger,
52 | SysDbgDisableKernelDebugger,
53 | SysDbgGetAutoKdEnable,
54 | SysDbgSetAutoKdEnable,
55 | SysDbgGetPrintBufferSize,
56 | SysDbgSetPrintBufferSize,
57 | SysDbgGetKdUmExceptionEnable,
58 | SysDbgSetKdUmExceptionEnable,
59 | SysDbgGetTriageDump,
60 | SysDbgGetKdBlockEnable,
61 | SysDbgSetKdBlockEnable,
62 | } SYSDBG_COMMAND, * PSYSDBG_COMMAND;
63 | typedef NTSTATUS(NTAPI* pNtSystemDebugControl)(
64 | IN SYSDBG_COMMAND Command,
65 | IN PVOID InputBuffer,
66 | IN ULONG InputBufferLength,
67 | OUT PVOID OutputBuffer,
68 | IN ULONG OutputBufferLength,
69 | OUT PULONG ReturnLength);
70 | typedef NTSTATUS(WINAPI *pNtCreateDebugObject)(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN ULONG);
71 | typedef NTSTATUS(WINAPI *pNtCreateThreadEx)(
72 | OUT PHANDLE ThreadHandle,
73 | IN ACCESS_MASK DesiredAccess,
74 | IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
75 | IN HANDLE ProcessHandle,
76 | IN PVOID StartRoutine,
77 | IN OPTIONAL PVOID Argument,
78 | IN ULONG CreateFlags, //THREAD_CREATE_FLAGS_*
79 | IN OPTIONAL ULONG_PTR ZeroBits,
80 | IN OPTIONAL SIZE_T StackSize,
81 | IN OPTIONAL SIZE_T MaximumStackSize,
82 | IN OPTIONAL PPS_ATTRIBUTE_LIST AttributeList
83 | );
84 | typedef NTSTATUS(WINAPI *pNtDelayExecution)(IN BOOLEAN, IN PLARGE_INTEGER);
85 | typedef NTSTATUS(WINAPI *pNtQueryInformationProcess)(IN HANDLE, IN UINT, OUT PVOID, IN ULONG, OUT PULONG);
86 | typedef NTSTATUS(WINAPI *pNtQueryInformationThread)(HANDLE, UINT, PVOID, ULONG, PULONG);
87 |
88 | typedef NTSTATUS(NTAPI *pNtQueryLicenseValue)(
89 | IN PUNICODE_STRING ValueName,
90 | OUT OPTIONAL PULONG Type,
91 | OUT PVOID Data,
92 | IN ULONG DataSize,
93 | OUT PULONG ResultDataSize);
94 |
95 | typedef VOID (NTAPI *pRtlInitUnicodeString)(
96 | _Out_ PUNICODE_STRING DestinationString,
97 | _In_opt_ PCWSTR SourceString);
98 |
99 |
100 | typedef NTSTATUS(WINAPI *pNtQueryDirectoryObject)(_In_ HANDLE, _Out_opt_ PVOID, _In_ ULONG, _In_ BOOLEAN, _In_ BOOLEAN, _Inout_ PULONG, _Out_opt_ PULONG);
101 | typedef NTSTATUS(WINAPI *pNtOpenDirectoryObject)(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
102 |
103 | typedef NTSTATUS(WINAPI *pNtQueryObject)(IN HANDLE, IN UINT, OUT PVOID, IN ULONG, OUT PULONG);
104 | typedef NTSTATUS(WINAPI *pNtQuerySystemInformation)(IN UINT, OUT PVOID, IN ULONG, OUT PULONG);
105 | typedef NTSTATUS(WINAPI *pNtSetInformationThread)(HANDLE, UINT, PVOID, ULONG);
106 | typedef NTSTATUS(WINAPI* pNtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
107 | typedef NTSTATUS(WINAPI* pNtYieldExecution)();
108 | typedef NTSTATUS(WINAPI* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
109 | typedef ULONG (NTAPI* pRtlNtStatusToDosError)(IN NTSTATUS Status);
110 | typedef NTSTATUS(NTAPI * pNtWow64QueryInformationProcess64)(
111 | IN HANDLE ProcessHandle,
112 | ULONG ProcessInformationClass,
113 | OUT PVOID ProcessInformation,
114 | IN ULONG ProcessInformationLength,
115 | OUT PULONG ReturnLength OPTIONAL);
116 | typedef NTSTATUS(WINAPI *pNtWow64ReadVirtualMemory64)(
117 | HANDLE ProcessHandle,
118 | PVOID64 BaseAddress,
119 | PVOID Buffer,
120 | ULONGLONG BufferSize,
121 | PULONGLONG NumberOfBytesRead
122 | );
123 | typedef NTSTATUS(NTAPI *pNtWow64QueryVirtualMemory64)(
124 | IN HANDLE ProcessHandle,
125 | IN PVOID64 BaseAddress,
126 | IN DWORD MemoryInformationClass,
127 | OUT PMEMORY_BASIC_INFORMATION64 MemoryInformation,
128 | IN ULONG64 Size,
129 | OUT PULONG64 ReturnLength OPTIONAL);
130 | typedef NTSTATUS(NTAPI *pLdrEnumerateLoadedModules)(
131 | IN BOOLEAN ReservedFlag,
132 | IN PLDR_ENUM_CALLBACK EnumProc,
133 | IN PVOID Context);
134 | typedef INT(NTAPI *pWudfIsAnyDebuggerPresent)();
135 | typedef INT(NTAPI *pWudfIsKernelDebuggerPresent)();
136 | typedef INT(NTAPI *pWudfIsUserDebuggerPresent)();
137 |
--------------------------------------------------------------------------------
/al-khaser/Shared/Common.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Common.h"
3 |
4 | VOID print_detected()
5 | {
6 | /* Get handle to standard output */
7 | HANDLE nStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
8 | CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
9 | SecureZeroMemory(&ConsoleScreenBufferInfo, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
10 |
11 | /* Save the original console color */
12 | GetConsoleScreenBufferInfo(nStdHandle, &ConsoleScreenBufferInfo);
13 | WORD OriginalColors = *(&ConsoleScreenBufferInfo.wAttributes);
14 |
15 | SetConsoleTextAttribute(nStdHandle, 12);
16 | _tprintf(TEXT("[ BAD ]\n"));
17 | SetConsoleTextAttribute(nStdHandle, OriginalColors);
18 | }
19 |
20 | VOID print_not_detected()
21 | {
22 | /* Get handle to standard output */
23 | HANDLE nStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
24 | CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
25 | SecureZeroMemory(&ConsoleScreenBufferInfo, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
26 |
27 | /* Save the original console color */
28 | GetConsoleScreenBufferInfo(nStdHandle, &ConsoleScreenBufferInfo);
29 | WORD OriginalColors = *(&ConsoleScreenBufferInfo.wAttributes);
30 |
31 | SetConsoleTextAttribute(nStdHandle, 10);
32 | _tprintf(TEXT("[ GOOD ]\n"));
33 | SetConsoleTextAttribute(nStdHandle, OriginalColors);
34 | }
35 |
36 | VOID print_category(const TCHAR* text)
37 | {
38 | /* Get handle to standard output */
39 | HANDLE nStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
40 | CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
41 | SecureZeroMemory(&ConsoleScreenBufferInfo, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
42 |
43 | /* Save the original console color */
44 | GetConsoleScreenBufferInfo(nStdHandle, &ConsoleScreenBufferInfo);
45 | WORD OriginalColors = *(&ConsoleScreenBufferInfo.wAttributes);
46 |
47 | SetConsoleTextAttribute(nStdHandle, 13);
48 | _tprintf(TEXT("\n-------------------------[%s]-------------------------\n"), text);
49 | SetConsoleTextAttribute(nStdHandle, OriginalColors);
50 | }
51 |
52 | VOID _print_check_text(const TCHAR* szMsg)
53 | {
54 | _tprintf(TEXT("[*] %s"), szMsg);
55 |
56 | /* align the result according to the length of the text */
57 | size_t spaces_to_padd = 95 - _tcslen(szMsg);
58 | while (spaces_to_padd > 0) {
59 | _tprintf(TEXT(" "));
60 | spaces_to_padd--;
61 | }
62 | }
63 |
64 | VOID _print_check_result(int result, const TCHAR* szMsg)
65 | {
66 | if (result == TRUE)
67 | print_detected();
68 | else
69 | print_not_detected();
70 |
71 | /* log to file*/
72 | TCHAR buffer[256] = _T("");
73 | _stprintf_s(buffer, sizeof(buffer) / sizeof(TCHAR), _T("[*] %s -> %d"), szMsg, result);
74 | LOG_PRINT(buffer);
75 | }
76 |
77 | VOID print_results(int result, TCHAR* szMsg)
78 | {
79 | _print_check_text(szMsg);
80 | _print_check_result(result, szMsg);
81 | }
82 |
83 | // note: templated version of this function is in Common.h
84 | VOID exec_check(int(*callback)(), const TCHAR* szMsg)
85 | {
86 | /* Print the text to screen so we can see what's currently running */
87 | _print_check_text(szMsg);
88 |
89 | /* Call our check */
90 | int result = callback();
91 |
92 | /* Print / Log the result */
93 | if (szMsg)
94 | _print_check_result(result, szMsg);
95 | }
96 |
97 | VOID resize_console_window()
98 | {
99 | // Change the window title:
100 | SetConsoleTitle(_T("Al-Khaser - by Lord Noteworthy"));
101 |
102 | // Get console window handle
103 | HWND wh = GetConsoleWindow();
104 |
105 | // Move window to required position
106 | MoveWindow(wh, 100, 100, 900, 900, TRUE);
107 | }
108 |
109 |
110 | VOID print_os()
111 | {
112 | TCHAR szOS[MAX_PATH] = _T("");
113 | if (GetOSDisplayString(szOS))
114 | {
115 | //_tcscpy_s(szOS, MAX_PATH, szOS);
116 | _tprintf(_T("\n[*] You are running: %s\n"), szOS);
117 | }
118 | }
119 |
120 | VOID print_last_error(LPCTSTR lpszFunction)
121 | {
122 | // Retrieve the system error message for the last-error code
123 |
124 | LPVOID lpMsgBuf;
125 | LPVOID lpDisplayBuf;
126 | DWORD dw = GetLastError();
127 |
128 | if (FormatMessage(
129 | FORMAT_MESSAGE_ALLOCATE_BUFFER |
130 | FORMAT_MESSAGE_FROM_SYSTEM |
131 | FORMAT_MESSAGE_IGNORE_INSERTS,
132 | NULL,
133 | dw,
134 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
135 | (LPTSTR)&lpMsgBuf,
136 | 0, NULL) == 0)
137 | {
138 | //FormatMessage failed, return
139 | return;
140 | }
141 |
142 | // Display the error message and exit the process
143 |
144 | lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
145 | (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
146 |
147 | if (lpDisplayBuf) {
148 |
149 | StringCchPrintf((LPTSTR)lpDisplayBuf,
150 | LocalSize(lpDisplayBuf) / sizeof(TCHAR),
151 | TEXT("%s failed with error %u: %s"),
152 | lpszFunction, dw, lpMsgBuf);
153 |
154 | _tprintf((LPCTSTR)lpDisplayBuf);
155 |
156 | LocalFree(lpDisplayBuf);
157 | }
158 | LocalFree(lpMsgBuf);
159 | }
160 |
161 | WCHAR* ascii_to_wide_str(CHAR* lpMultiByteStr)
162 | {
163 |
164 | /* Get the required size */
165 | INT iNumChars = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, -1, NULL, 0);
166 |
167 | /* Allocate new wide string */
168 |
169 | SIZE_T Size = (1 + iNumChars) * sizeof(WCHAR);
170 |
171 | WCHAR *lpWideCharStr = reinterpret_cast(malloc(Size));
172 |
173 | if (lpWideCharStr) {
174 | SecureZeroMemory(lpWideCharStr, Size);
175 | /* Do the conversion */
176 | iNumChars = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, -1, lpWideCharStr, iNumChars);
177 | }
178 | return lpWideCharStr;
179 | }
180 |
181 | CHAR* wide_str_to_multibyte (TCHAR* lpWideStr)
182 | {
183 | errno_t status;
184 | int *pRetValue = NULL;
185 | CHAR *mbchar = NULL;
186 | size_t sizeInBytes = 0;
187 |
188 | status = wctomb_s(pRetValue, mbchar, sizeInBytes, *lpWideStr);
189 | return mbchar;
190 | }
191 |
192 | BOOL IsHexString(WCHAR* szStr) {
193 | std::wstring s(szStr);
194 |
195 | if (std::find_if(s.begin(), s.end(), [](wchar_t c) {return !std::isxdigit(static_cast(c)); }) == s.end())
196 | return TRUE;
197 | else
198 | return FALSE;
199 | }
200 |
--------------------------------------------------------------------------------
/al-khaser/Shared/Common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | VOID print_detected() ;
4 | VOID print_not_detected() ;
5 | VOID print_category(const TCHAR* text);
6 | VOID print_last_error(LPCTSTR lpszFunction);
7 | VOID print_os();
8 | WCHAR* ascii_to_wide_str(CHAR* lpMultiByteStr);
9 | CHAR* wide_str_to_multibyte(TCHAR* lpWideStr);
10 | BOOL IsHexString(WCHAR* szStr);
11 | VOID resize_console_window();
12 | VOID print_results(int result, TCHAR* szMsg);
13 | VOID _print_check_text(const TCHAR* szMsg);
14 | VOID _print_check_result(int result, const TCHAR* szMsg);
15 |
16 | VOID exec_check(int(*callback)(), const TCHAR* szMsg);
17 |
18 | // this must be defined in this header file
19 | // see: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
20 | template
21 | VOID exec_check(int(*callback)(T param), T param, const TCHAR* szMsg)
22 | {
23 | /* Print the text to screen so we can see what's currently running */
24 | _print_check_text(szMsg);
25 |
26 | /* Call our check */
27 | int result = callback(param);
28 |
29 | /* Print / Log the result */
30 | if (szMsg)
31 | _print_check_result(result, szMsg);
32 | }
--------------------------------------------------------------------------------
/al-khaser/Shared/Utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL IsWoW64();
4 | PVOID64 GetPeb64();
5 | BOOL Is_RegKeyValueExists(HKEY hKey, const TCHAR* lpSubKey, const TCHAR* lpValueName, const TCHAR* search_str);
6 | BOOL Is_RegKeyExists(HKEY hKey, const TCHAR* lpSubKey);
7 | BOOL is_FileExists(TCHAR* szPath);
8 | BOOL is_DirectoryExists(TCHAR* szPath);
9 | BOOL check_mac_addr(const TCHAR* szMac);
10 | BOOL check_adapter_name(const TCHAR* szName);
11 | BOOL GetOSDisplayString(LPTSTR pszOS);
12 | BOOL IsWindowsVista();
13 | BOOL IsWindows7();
14 | BOOL IsWindows8or8PointOne();
15 | DWORD GetProccessIDByName(TCHAR* szProcessNameTarget);
16 | DWORD GetProcessIdFromName(LPCTSTR ProcessName);
17 | BOOL SetPrivilege(HANDLE, LPCTSTR, BOOL);
18 | BOOL SetDebugPrivileges(VOID);
19 | DWORD GetMainThreadId(DWORD pid);
20 | BOOL InitWMI(IWbemServices **pSvc, IWbemLocator **pLoc, const TCHAR* szNetworkResource);
21 | BOOL ExecWMIQuery(IWbemServices **pSvc, IWbemLocator **pLoc, IEnumWbemClassObject **pEnumerator, const TCHAR* szQuery);
22 | ULONG get_idt_base();
23 | ULONG get_ldt_base();
24 | ULONG get_gdt_base();
25 | BOOL IsElevated();
26 | BOOL find_str_in_data(PBYTE needle, size_t needleLen, PBYTE haystack, size_t haystackLen);
27 | UINT enum_system_firmware_tables(_In_ DWORD FirmwareTableProviderSignature, _Out_ PVOID pFirmwareTableBuffer, _In_ DWORD BufferSize);
28 | PBYTE get_system_firmware(_In_ DWORD signature, _In_ DWORD table, _Out_ PDWORD pBufferSize);
29 | bool attempt_to_read_memory(void* addr, void* buf, int size);
30 | bool attempt_to_read_memory_wow64(PVOID buffer, DWORD size, PVOID64 address);
31 | bool attempt_to_read_memory_wow64(PVOID buffer, DWORD size, ULONGLONG address);
32 | std::vector* enumerate_memory();
33 | std::vector* enumerate_memory_wow64();
34 | std::vector* enumerate_object_directory(const wchar_t* path);
35 |
36 | #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, x)
37 | #define FREE(x) HeapFree(GetProcessHeap(), 0, x)
38 |
39 | #if _WIN32 || _WIN64
40 | #if _WIN64
41 | #define ENV64BIT
42 | #else
43 | #define ENV32BIT
44 | #endif
45 | #endif
--------------------------------------------------------------------------------
/al-khaser/Shared/VersionHelpers.h:
--------------------------------------------------------------------------------
1 | /******************************************************************
2 | * *
3 | * VersionHelpers.h -- This module defines helper functions to *
4 | * promote version check with proper *
5 | * comparisons. *
6 | * *
7 | * Copyright (c) Microsoft Corp. All rights reserved. *
8 | * *
9 | ******************************************************************/
10 | #pragma once
11 |
12 | #include "winapifamily.h"
13 |
14 | #ifdef _MSC_VER
15 | #pragma once
16 | #endif // _MSC_VER
17 |
18 | #pragma region Application Family
19 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
20 |
21 | #include // for _In_, etc.
22 |
23 | #if !defined(__midl) && !defined(SORTPP_PASS)
24 |
25 | #if (NTDDI_VERSION >= NTDDI_WINXP)
26 |
27 | #ifdef __cplusplus
28 |
29 | #define VERSIONHELPERAPI inline bool
30 |
31 | #else // __cplusplus
32 |
33 | #define VERSIONHELPERAPI FORCEINLINE BOOL
34 |
35 | #endif // __cplusplus
36 |
37 | VERSIONHELPERAPI
38 | IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
39 | {
40 | OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
41 | DWORDLONG const dwlConditionMask = VerSetConditionMask(
42 | VerSetConditionMask(
43 | VerSetConditionMask(
44 | 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
45 | VER_MINORVERSION, VER_GREATER_EQUAL),
46 | VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
47 |
48 | osvi.dwMajorVersion = wMajorVersion;
49 | osvi.dwMinorVersion = wMinorVersion;
50 | osvi.wServicePackMajor = wServicePackMajor;
51 |
52 | return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
53 | }
54 |
55 | VERSIONHELPERAPI
56 | IsWindowsVersionOrLesser(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
57 | {
58 | OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
59 | DWORDLONG const dwlConditionMask = VerSetConditionMask(
60 | VerSetConditionMask(
61 | 0, VER_MAJORVERSION, VER_EQUAL),
62 | VER_MINORVERSION, VER_LESS_EQUAL);
63 |
64 | osvi.dwMajorVersion = wMajorVersion;
65 | osvi.dwMinorVersion = wMinorVersion;
66 | osvi.wServicePackMajor = wServicePackMajor;
67 |
68 | return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask) != FALSE;
69 | }
70 |
71 | VERSIONHELPERAPI
72 | IsWindowsXPOrGreater()
73 | {
74 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
75 | }
76 |
77 | VERSIONHELPERAPI
78 | IsWindowsXPSP1OrGreater()
79 | {
80 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
81 | }
82 |
83 | VERSIONHELPERAPI
84 | IsWindowsXPSP2OrGreater()
85 | {
86 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
87 | }
88 |
89 | VERSIONHELPERAPI
90 | IsWindowsXPSP3OrGreater()
91 | {
92 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
93 | }
94 |
95 | VERSIONHELPERAPI
96 | IsWindowsVistaOrGreater()
97 | {
98 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
99 | }
100 |
101 | VERSIONHELPERAPI
102 | IsWindowsVistaSP1OrGreater()
103 | {
104 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
105 | }
106 |
107 | VERSIONHELPERAPI
108 | IsWindowsVistaSP2OrGreater()
109 | {
110 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
111 | }
112 |
113 | VERSIONHELPERAPI
114 | IsWindows7OrGreater()
115 | {
116 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
117 | }
118 |
119 | VERSIONHELPERAPI
120 | IsWindows7SP1OrGreater()
121 | {
122 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
123 | }
124 |
125 | VERSIONHELPERAPI
126 | IsWindows8OrGreater()
127 | {
128 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
129 | }
130 |
131 | VERSIONHELPERAPI
132 | IsWindows8Point1OrGreater()
133 | {
134 | return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
135 | }
136 |
137 | VERSIONHELPERAPI
138 | IsWindows10OrGreater()
139 | {
140 | return IsWindowsVersionOrGreater(10, 0, 0);
141 | }
142 |
143 | VERSIONHELPERAPI
144 | IsWindowsServer()
145 | {
146 | OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, 0, VER_NT_WORKSTATION };
147 | DWORDLONG const dwlConditionMask = VerSetConditionMask( 0, VER_PRODUCT_TYPE, VER_EQUAL );
148 |
149 | return !VerifyVersionInfoW(&osvi, VER_PRODUCT_TYPE, dwlConditionMask);
150 | }
151 |
152 |
153 |
154 | VERSIONHELPERAPI
155 | IsWindowsXPOr2k()
156 | {
157 | return IsWindowsVersionOrLesser(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
158 | }
159 |
160 |
161 | #endif // NTDDI_VERSION
162 |
163 | #endif // defined(__midl)
164 |
165 | #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
166 | #pragma endregion
167 |
--------------------------------------------------------------------------------
/al-khaser/Shared/WinStructs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef struct _LDR_MODULE {
4 | LIST_ENTRY InLoadOrderModuleList;
5 | LIST_ENTRY InMemoryOrderModuleList;
6 | LIST_ENTRY InInitializationOrderModuleList;
7 | PVOID BaseAddress;
8 | PVOID EntryPoint;
9 | ULONG SizeOfImage;
10 | UNICODE_STRING FullDllName;
11 | UNICODE_STRING BaseDllName;
12 | ULONG Flags;
13 | SHORT LoadCount;
14 | SHORT TlsIndex;
15 | LIST_ENTRY HashTableEntry;
16 | ULONG TimeDateStamp;
17 | } LDR_MODULE, *PLDR_MODULE;
18 |
19 | typedef LONG KPRIORITY;
20 |
21 | typedef struct _THREAD_BASIC_INFORMATION {
22 | NTSTATUS ExitStatus;
23 | PVOID TebBaseAddress;
24 | CLIENT_ID ClientId;
25 | KAFFINITY AffinityMask;
26 | KPRIORITY Priority;
27 | KPRIORITY BasePriority;
28 | } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
29 |
30 | typedef struct _PROCESS_BASIC_INFORMATION_WOW64 {
31 | PVOID Reserved1[2];
32 | PVOID64 PebBaseAddress;
33 | PVOID Reserved2[4];
34 | ULONG_PTR UniqueProcessId[2];
35 | PVOID Reserved3[2];
36 | } PROCESS_BASIC_INFORMATION_WOW64;
37 |
38 | typedef struct _PEB64 {
39 | BYTE Reserved1[2];
40 | BYTE BeingDebugged;
41 | BYTE Reserved2[1];
42 | PVOID64 Reserved3[2];
43 | PVOID64 Ldr;
44 | PVOID64 ProcessParameters;
45 | BYTE Reserved4[104];
46 | PVOID64 Reserved5[52];
47 | PVOID64 PostProcessInitRoutine;
48 | BYTE Reserved6[128];
49 | PVOID64 Reserved7[1];
50 | ULONG SessionId;
51 | } PEB64, *PPEB64;
52 |
53 | typedef struct _PEB_LDR_DATA64 {
54 | BYTE Reserved1[8];
55 | PVOID64 Reserved2[3];
56 | LIST_ENTRY64 InMemoryOrderModuleList;
57 | } PEB_LDR_DATA64, *PPEB_LDR_DATA64;
58 |
59 | typedef struct _UNICODE_STRING64 {
60 | USHORT Length;
61 | USHORT MaximumLength;
62 | PVOID64 Buffer;
63 | } UNICODE_STRING64;
64 |
65 | typedef struct _LDR_DATA_TABLE_ENTRY64 {
66 | PVOID64 Reserved1[2];
67 | LIST_ENTRY64 InMemoryOrderLinks;
68 | PVOID64 Reserved2[2];
69 | PVOID64 DllBase;
70 | PVOID64 Reserved3[2];
71 | UNICODE_STRING64 FullDllName;
72 | BYTE Reserved4[8];
73 | PVOID64 Reserved5[3];
74 | union {
75 | ULONG CheckSum;
76 | PVOID64 Reserved6;
77 | } DUMMYUNIONNAME;
78 | ULONG TimeDateStamp;
79 | } LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
80 |
81 | /*++ NtCreateThreadEx specific */
82 |
83 | typedef struct _PS_ATTRIBUTE {
84 | ULONG Attribute;
85 | SIZE_T Size;
86 | union
87 | {
88 | ULONG Value;
89 | PVOID ValuePtr;
90 | } u1;
91 | PSIZE_T ReturnLength;
92 | } PS_ATTRIBUTE, *PPS_ATTRIBUTE;
93 |
94 | typedef struct _PS_ATTRIBUTE_LIST {
95 | SIZE_T TotalLength;
96 | PS_ATTRIBUTE Attributes[1];
97 | } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;
98 |
99 | #define PS_ATTRIBUTE_NUMBER_MASK 0x0000ffff
100 | #define PS_ATTRIBUTE_THREAD 0x00010000
101 | #define PS_ATTRIBUTE_INPUT 0x00020000
102 | #define PS_ATTRIBUTE_ADDITIVE 0x00040000
103 |
104 | #define PsAttributeValue(Number, Thread, Input, Additive) \
105 | (((Number) & PS_ATTRIBUTE_NUMBER_MASK) | \
106 | ((Thread) ? PS_ATTRIBUTE_THREAD : 0) | \
107 | ((Input) ? PS_ATTRIBUTE_INPUT : 0) | \
108 | ((Additive) ? PS_ATTRIBUTE_ADDITIVE : 0))
109 |
110 | typedef enum _PS_ATTRIBUTE_NUM {
111 | PsAttributeClientId = 3,
112 | } PS_ATTRIBUTE_NUM;
113 |
114 | #define PS_ATTRIBUTE_CLIENT_ID \
115 | PsAttributeValue(PsAttributeClientId, TRUE, FALSE, FALSE)
116 |
117 | /* NtCreateThreadEx specific --*/
118 |
119 | typedef struct _SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION
120 | {
121 | ULONG NumberOfLogicalProcessors;
122 | ULONG NumberOfCores;
123 | } SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION, *PSYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION;
124 |
125 |
126 | typedef struct _OBJECT_DIRECTORY_INFORMATION
127 | {
128 | UNICODE_STRING Name;
129 | UNICODE_STRING TypeName;
130 | } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
131 |
132 | typedef VOID(NTAPI LDR_ENUM_CALLBACK)(_In_ PLDR_DATA_TABLE_ENTRY ModuleInformation, _In_ PVOID Parameter, _Out_ BOOLEAN *Stop);
133 | typedef LDR_ENUM_CALLBACK *PLDR_ENUM_CALLBACK;
134 |
--------------------------------------------------------------------------------
/al-khaser/Shared/log.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "log.h"
3 |
4 | static int SESSION_TRACKER; //Keeps track of session
5 |
6 | TCHAR* print_time()
7 | {
8 | size_t size = 0;
9 | TCHAR *buf;
10 | errno_t err;
11 | TCHAR timestr[32];
12 |
13 | /* get current calendar time */
14 | time_t const sourceTime = time(NULL);
15 | tm tmDest = { 0 };
16 | err = localtime_s(&tmDest, &sourceTime);
17 | if (err)
18 | {
19 | print_last_error(_T("localtime_s"));
20 | exit(1);
21 | }
22 |
23 | // Converts a time_t time value to a tm structure, and corrects for the local time zone.
24 | err = _tasctime_s(timestr, 32, &tmDest);
25 | if (err)
26 | {
27 | print_last_error(_T("_tasctime_s"));
28 | exit(1);
29 | }
30 |
31 | //Getting rid of \n
32 | timestr[_tcsclen(timestr) - 1] = 0;
33 |
34 | //Additional +2 for square braces
35 | size = (_tcsclen(timestr) + 1 + 2) * sizeof(TCHAR);
36 | buf = (TCHAR*)malloc(size);
37 | if (buf) {
38 | memset(buf, 0x0, size);
39 | _stprintf_s(buf, size / sizeof(TCHAR), _T("[%s]"), timestr);
40 | }
41 | return buf;
42 | }
43 | void log_print(const TCHAR* filename, const TCHAR *fmt, ...)
44 | {
45 | va_list list;
46 | const TCHAR *p, *r;
47 | int e;
48 |
49 | FILE *fp = NULL;
50 | errno_t error;
51 |
52 | TCHAR *pszTime;
53 |
54 | if (SESSION_TRACKER > 0)
55 | error = _tfopen_s(&fp, _T("log.txt"), _T("a+"));
56 | else
57 | error = _tfopen_s(&fp, _T("log.txt"), _T("w"));
58 |
59 | // file create/open failed
60 | if ((error != 0) || (fp == NULL))
61 | return;
62 |
63 | pszTime = print_time();
64 | if (pszTime) {
65 | _ftprintf(fp, _T("%s "), pszTime);
66 | free(pszTime);
67 | }
68 | va_start(list, fmt);
69 |
70 | for (p = fmt; *p; ++p)
71 | {
72 | if (*p != '%')//If simple string
73 | fputc(*p, fp);
74 |
75 | else
76 | {
77 | switch (*++p)
78 | {
79 | /* string */
80 | case 's':
81 | {
82 | r = va_arg(list, TCHAR *);
83 | _ftprintf(fp, _T("%s"), r);
84 | continue;
85 | }
86 |
87 | /* integer */
88 | case 'd':
89 | {
90 | e = va_arg(list, int);
91 | _ftprintf(fp, _T("%d"), e);
92 | continue;
93 | }
94 |
95 | default:
96 | fputc(*p, fp);
97 | }
98 | }
99 | }
100 | va_end(list);
101 | fputc('\n', fp);
102 | SESSION_TRACKER++;
103 | fclose(fp);
104 | }
105 |
--------------------------------------------------------------------------------
/al-khaser/Shared/log.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIDEN2(x) L##x
4 | #define WIDEN(x) WIDEN2(x)
5 | #define __WFILE__ WIDEN(__FILE__)
6 |
7 | #ifdef UNICODE
8 | #define __TFILE__ __WFILE__
9 | #else
10 | #define __TFILE__ __FILE__
11 | #endif
12 |
13 | void log_print(const TCHAR* filename, const TCHAR *fmt, ...);
14 |
15 | #define LOG_PRINT(...) log_print(__TFILE__, __VA_ARGS__ )
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/al-khaser/Shared/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/TimingAttacks/pch.h:
--------------------------------------------------------------------------------
1 | #include "../pch.h"
--------------------------------------------------------------------------------
/al-khaser/TimingAttacks/timing.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | BOOL timing_SetTimer(UINT delayInMillis);
4 | BOOL timing_NtDelayexecution(UINT delayInMillis);
5 | BOOL timing_timeSetEvent(UINT delayInMillis);
6 | BOOL timing_WaitForSingleObject(UINT delayInMillis);
7 | BOOL timing_WaitForMultipleObjects(UINT delayInMillis);
8 | BOOL timing_sleep_loop(UINT delayInMillis);
9 | BOOL rdtsc_diff_locky();
10 | BOOL rdtsc_diff_vmexit();
11 | BOOL timing_IcmpSendEcho(UINT delayInMillis);
12 | BOOL timing_CreateWaitableTimer(UINT delayInMillis);
13 | BOOL timing_CreateTimerQueueTimer(UINT delayInMillis);
14 | VOID CALLBACK CallbackCTQT(PVOID lParam, BOOLEAN TimerOrWaitFired);
15 |
--------------------------------------------------------------------------------
/al-khaser/al-khaser.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/al-khaser/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/al-khaser/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed
2 |
3 | #include "pch.h"
4 |
5 | // In general, ignore this file, but keep it around if you are using pre-compiled headers.
6 |
--------------------------------------------------------------------------------
/al-khaser/pch.h:
--------------------------------------------------------------------------------
1 | // Tips for Getting Started:
2 | // 1. Use the Solution Explorer window to add/manage files
3 | // 2. Use the Team Explorer window to connect to source control
4 | // 3. Use the Output window to see build output and other messages
5 | // 4. Use the Error List window to view errors
6 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
7 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
8 |
9 | #ifndef PCH_H
10 | #define PCH_H
11 |
12 | // add headers that you want to pre-compile here
13 |
14 |
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include // Device guids
41 | #include // IOCTL
42 | #include // cpuid()
43 | #include // 64-bit wchar atoi
44 | #include // check_power_modes()
45 | #include
46 | #include
47 | #include
48 | #include // SLIsGenuineLocal
49 | #include
50 |
51 | #pragma comment(lib, "Ws2_32.lib")
52 | #pragma comment(lib, "wbemuuid.lib")
53 | #pragma comment(lib, "Shlwapi.lib")
54 | #pragma comment(lib, "Mpr.lib")
55 | #pragma comment(lib, "Iphlpapi.lib")
56 | #pragma comment(lib, "Shlwapi.lib")
57 | #pragma comment(lib, "Psapi.lib")
58 | #pragma comment(lib, "wbemuuid.lib")
59 | #pragma comment(lib, "Winmm.lib")
60 | #pragma comment(lib, "setupapi.lib")
61 | #pragma comment(lib, "powrprof.lib")
62 | #pragma comment(lib, "Slwga.lib")
63 |
64 | #include "Shared/Common.h"
65 | #include "Shared/VersionHelpers.h"
66 | #include "Shared/log.h"
67 | #include "Shared/Utils.h"
68 | #include "Shared/WinStructs.h"
69 | #include "Shared/ApiTypeDefs.h"
70 | #include "Shared/APIs.h"
71 | #include "Shared/winapifamily.h"
72 |
73 | /* AntiDebugs headers */
74 | #include "AntiDebug/CheckRemoteDebuggerPresent.h"
75 | #include "AntiDebug/IsDebuggerPresent.h"
76 | #include "AntiDebug/BeingDebugged.h"
77 | #include "AntiDebug/ProcessHeap_Flags.h"
78 | #include "AntiDebug/ProcessHeap_ForceFlags.h"
79 | #include "AntiDebug/NtGlobalFlag.h"
80 | #include "AntiDebug/NtQueryInformationProcess_ProcessDebugPort.h"
81 | #include "AntiDebug/NtQueryInformationProcess_ProcessDebugFlags.h"
82 | #include "AntiDebug/NtQueryInformationProcess_ProcessDebugObject.h"
83 | #include "AntiDebug/NtSetInformationThread_ThreadHideFromDebugger.h"
84 | #include "AntiDebug/CloseHandle_InvalidHandle.h"
85 | #include "AntiDebug/NtSystemDebugControl.h"
86 | #include "AntiDebug/UnhandledExceptionFilter_Handler.h"
87 | #include "AntiDebug/OutputDebugStringAPI.h"
88 | #include "AntiDebug/HardwareBreakpoints.h"
89 | #include "AntiDebug/SoftwareBreakpoints.h"
90 | #include "AntiDebug/Interrupt_0x2d.h"
91 | #include "AntiDebug/Interrupt_3.h"
92 | #include "AntiDebug/TrapFlag.h"
93 | #include "AntiDebug/MemoryBreakpoints_PageGuard.h"
94 | #include "AntiDebug/ParentProcess.h"
95 | #include "AntiDebug/SeDebugPrivilege.h"
96 | #include "AntiDebug/NtQueryObject_ObjectInformation.h"
97 | #include "AntiDebug/NtYieldExecution.h"
98 | #include "AntiDebug/SetHandleInformation_API.h"
99 | #include "AntiDebug/TLS_callbacks.h"
100 | #include "AntiDebug/NtQuerySystemInformation_SystemKernelDebuggerInformation.h"
101 | #include "AntiDebug/SharedUserData_KernelDebugger.h"
102 | #include "AntiDebug/ProcessJob.h"
103 | #include "AntiDebug/WriteWatch.h"
104 | #include "AntiDebug/PageExceptionBreakpointCheck.h"
105 | #include "AntiDebug/ModuleBoundsHookCheck.h"
106 | #include "AntiDebug/ScanForModules.h"
107 | #include "AntiDebug/WUDF_IsDebuggerPresent.h"
108 | #include "AntiDebug/LowFragmentationHeap.h"
109 |
110 |
111 | /* Anti dumping headers */
112 | #include "AntiDump/ErasePEHeaderFromMemory.h"
113 | #include "AntiDump/SizeOfImage.h"
114 |
115 | /* Anti VM headers */
116 | #include "AntiVM/VirtualBox.h"
117 | #include "AntiVM/VMware.h"
118 | #include "AntiVM/Wine.h"
119 | #include "AntiVM/Generic.h"
120 | #include "AntiVM/VirtualPC.h"
121 | #include "AntiVM/QEMU.h"
122 | #include "AntiVM/Xen.h"
123 | #include "AntiVM/KVM.h"
124 | #include "AntiVM/Parallels.h"
125 | #include "AntiVM/Services.h"
126 | #include "AntiVM/HyperV.h"
127 |
128 | /* Code Injections Headers */
129 | #include "CodeInjection/CreateRemoteThread.h"
130 | #include "CodeInjection/SetWindowsHooksEx.h"
131 | #include "CodeInjection/NtCreateThreadEx.h"
132 | #include "CodeInjection/RtlCreateUserThread.h"
133 | #include "CodeInjection/QueueUserAPC.h"
134 | #include "CodeInjection/GetSetThreadContext.h"
135 |
136 | /* Delay Execution */
137 | #include "TimingAttacks/timing.h"
138 |
139 | /* Anti-Analysis */
140 | #include "AntiAnalysis/process.h"
141 |
142 | /* Anti-Disassembly */
143 | #include "AntiDisassm/AntiDisassm.h"
144 |
145 |
146 | #endif //PCH_H
147 |
--------------------------------------------------------------------------------