Skip to content

Commit f3f2fd2

Browse files
committed
added SMSW x86 instruction demo
1 parent 6e9f20e commit f3f2fd2

12 files changed

+525
-0
lines changed

EVENSTAR.sln

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ VisualStudioVersion = 17.11.35312.102
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReadCRDbgExt", "ReadCRDbgExt\ReadCRDbgExt.vcxproj", "{78BD9103-3B0A-46DF-9261-148EA8F34DF0}"
77
EndProject
8+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReadMSW", "ReadMSW\ReadMSW.vcxproj", "{F9AB9899-9F93-4252-B634-740F19CCC1DC}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Release|x64 = Release|x64
1113
EndGlobalSection
1214
GlobalSection(ProjectConfigurationPlatforms) = postSolution
1315
{78BD9103-3B0A-46DF-9261-148EA8F34DF0}.Release|x64.ActiveCfg = Release|x64
1416
{78BD9103-3B0A-46DF-9261-148EA8F34DF0}.Release|x64.Build.0 = Release|x64
17+
{F9AB9899-9F93-4252-B634-740F19CCC1DC}.Release|x64.ActiveCfg = Release|x64
18+
{F9AB9899-9F93-4252-B634-740F19CCC1DC}.Release|x64.Build.0 = Release|x64
1519
EndGlobalSection
1620
GlobalSection(SolutionProperties) = preSolution
1721
HideSolutionNode = FALSE

ReadMSW/Inc/BaseDataTypes.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// ========================================================================
2+
// File: BaseDataTypes.h
3+
//
4+
// Author: winterknife
5+
//
6+
// Description: Type definitions for common Windows base data types made
7+
// for maintaining uniformity across all User Mode and Kernel Mode code
8+
//
9+
// Modifications:
10+
// 2021-07-31 Created
11+
// 2022-08-13 Updated
12+
// ========================================================================
13+
14+
// ========================================================================
15+
// Pragmas
16+
// ========================================================================
17+
18+
#pragma once
19+
20+
// ========================================================================
21+
// Type definitions
22+
// ========================================================================
23+
24+
#pragma region TYPEDEFS
25+
26+
// 8-bit unsigned integer, range = 0 - 255, unsigned char
27+
typedef unsigned __int8 BYTE, *PBYTE;
28+
29+
// 16-bit unsigned integer, range = 0 - 65535, unsigned short
30+
typedef unsigned __int16 WORD, *PWORD;
31+
32+
// 32-bit unsigned integer, range = 0 - 4294967295, unsigned int or unsigned long
33+
typedef unsigned long DWORD, *PDWORD;
34+
35+
// 64-bit unsigned integer, range = 0 - 18446744073709551615, unsigned long long
36+
typedef unsigned __int64 QWORD, *PQWORD;
37+
38+
// Should be TRUE(1) or FALSE(0), unsigned char or bool
39+
typedef unsigned __int8 BOOLEAN, *PBOOLEAN;
40+
41+
// 8-bit UTF-8/Multibyte/ANSI character, char
42+
typedef __int8 CHAR, *PCHAR;
43+
44+
// 16-bit UTF-16/Wide/UNICODE character, unsigned short
45+
typedef wchar_t WCHAR, *PWCHAR;
46+
47+
// Pointer to any type, size = 4 bytes or 8 bytes depending on code bitness
48+
typedef void* PVOID;
49+
50+
// Pointer to a constant of any type
51+
typedef const void* PCVOID;
52+
53+
// Pointer to constant null-terminated string of ANSI characters
54+
typedef _Null_terminated_ const __int8* PCSTR;
55+
56+
// Pointer to constant null-terminated string of UNICODE characters
57+
typedef _Null_terminated_ const wchar_t* PCWSTR;
58+
59+
// Pointer to constant null-terminated string of ANSI or UNICODE characters depending on character encoding scheme
60+
#if defined(UNICODE)
61+
typedef const __wchar_t* PCTSTR;
62+
#else
63+
typedef const __int8* PCTSTR;
64+
#endif
65+
66+
// 32-bit or 64-bit unsigned integer, range = 0 - 4294967295 or 18446744073709551615 depending on compiler bitness
67+
// Used for casting pointers
68+
#if defined(_WIN64)
69+
typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR;
70+
#else
71+
typedef unsigned long DWORD_PTR, *PDWORD_PTR;
72+
#endif
73+
74+
#pragma endregion

ReadMSW/Inc/Common.h

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// ========================================================================
2+
// File: Common.h
3+
//
4+
// Author: winterknife
5+
//
6+
// Description: Contains the common stuff for this project
7+
//
8+
// Modifications:
9+
// 2021-08-21 Created
10+
// 2025-01-09 Updated
11+
// ========================================================================
12+
13+
// ========================================================================
14+
// Pragmas
15+
// ========================================================================
16+
17+
#pragma once
18+
19+
// Specify program entry point
20+
#pragma comment(linker, "/ENTRY:ExeInit")
21+
22+
// Merge sections
23+
#if defined (_MSC_VER)
24+
#if (_MSC_VER >= 1920)
25+
#pragma comment(linker, "/MERGE:_RDATA=.rdata")
26+
#endif
27+
#endif
28+
29+
// Emit error message at compile time if trying to build for 32-bit x86 target
30+
#if !defined(_WIN64)
31+
#error x86 build target is unsupported!
32+
#endif
33+
34+
// ========================================================================
35+
// Includes
36+
// ========================================================================
37+
38+
#define WIN32_LEAN_AND_MEAN
39+
#include <Windows.h>
40+
#include <intrin.h>
41+
#include "BaseDataTypes.h"
42+
43+
#pragma intrinsic(__stosb)
44+
#pragma intrinsic(__movsb)
45+
#pragma intrinsic(strlen)
46+
#pragma intrinsic(strcmp)
47+
48+
// ========================================================================
49+
// Macros
50+
// ========================================================================
51+
52+
#pragma region MACROS
53+
54+
// Module name
55+
#define __MODULE__ "ReadMSW"
56+
57+
// Comment out for final build
58+
//#define DEBUG_BUILD
59+
60+
// Stringizing operator macro
61+
#ifndef _CRT_STRINGIZE
62+
#define _CRT_STRINGIZE_(x) #x
63+
#define _CRT_STRINGIZE(x) _CRT_STRINGIZE_(x)
64+
#endif
65+
66+
// Get mangled name of a function
67+
#define GET_MANGLED_FUNCTION_NAME __pragma(message(__FILE__ _CRT_STRINGIZE((__LINE__): \nfunction:\t) __FUNCSIG__ " is mangled to: " __FUNCDNAME__))
68+
69+
// To set alternate name of decorated x86 IAT global function pointer
70+
#ifdef _X86_
71+
// Uses undocumented /ALTERNATENAME linker flag
72+
#define ALT_NAME(name, n) __pragma(comment(linker, _CRT_STRINGIZE(/ALTERNATENAME:__imp__##name##@##n####=___imp_##name)))
73+
#else
74+
#define ALT_NAME(name, n)
75+
#endif
76+
77+
// To declare/initialize global IAT function pointers for run-time dynamic linking, use on global scope
78+
#define IMP_FUNC(name, n) EXTERN_C_START PVOID __imp_##name = NULL; EXTERN_C_END ALT_NAME(name, n)
79+
80+
// To declare/initialize local function pointers for run-time dynamic linking, use on local scope
81+
// Warning: will ignore SAL annotations
82+
#define IMP_FUNC_PIC(name) typedef decltype(name) __type_##name; __type_##name* ##name = NULL;
83+
84+
// Check if a function is in a delay loaded module, use on a global scope
85+
#define CHECK_DELAY_LOAD(f) extern "C" extern void* __imp_load_ ##f; void test_delay_load ##f(){ (__imp_load_ ##f) ? 1 : 0; }
86+
87+
// Macro to indicate a specific function to the linker as the first in the link order
88+
#define CODE_BEGIN code_seg(push, ".text")
89+
90+
// Macro to indicate the end of the specific function to the linker
91+
#define CODE_END code_seg(pop)
92+
93+
// Macro to disable all compiler optimizations for a specific function
94+
#define OPTIMIZATION_OFF optimize("", off)
95+
96+
// Macro to re-enable/reset compiler optimizations for a specific function
97+
#define OPTIMIZATION_ON optimize("", on)
98+
99+
// Macro to enable compiler optimizations for generating short sequences of machine code for a specific function
100+
#if defined(_M_IX86)
101+
#define OPTIMIZATION_SIZE optimize("gsy", on)
102+
#else
103+
#define OPTIMIZATION_SIZE optimize("gs", on)
104+
#endif
105+
106+
// Macro to enable compiler optimizations for generating fast sequences of machine code for a specific function
107+
#if defined(_M_IX86)
108+
#define OPTIMIZATION_SPEED optimize("gty", on)
109+
#else
110+
#define OPTIMIZATION_SPEED optimize("gt", on)
111+
#endif
112+
113+
// Macro to fill a block of memory with zeroes given it's address and length in bytes by generating store string instruction(rep stosb)
114+
// Enhanced REP STOSB/MOVSB(ERMSB) are only available since Ivy Bridge Intel microarchitecture(2012/2013)
115+
// Processors that provide support for enhanced MOVSB/STOSB operations are enumerated by the CPUID feature flag: CPUID:(EAX=7H, ECX=0H):EBX.ERMSB[bit 9] = 1
116+
#define ZERO_MEMORY(Destination, Length) __stosb((PBYTE)Destination, 0, Length)
117+
118+
// Macro to copy a block of memory given it's source address, destination address and the number of bytes to copy by generating move string instruction(rep movsb)
119+
#define COPY_MEMORY(Destination, Source, Count) __movsb((PBYTE)Destination, (const PBYTE)Source, Count)
120+
121+
#pragma endregion
122+
123+
// ========================================================================
124+
// C inline routines
125+
// ========================================================================
126+
127+
#pragma region INLINES
128+
129+
// Brief: To compare two blocks of memory and return the number of bytes that match
130+
// Parameter1: pcSource1 = Pointer to the first block of memory
131+
// Parameter2: pcSource2 = Pointer to the second block of memory
132+
// Parameter3: dwptrLength = The number of bytes to compare
133+
// Return: Number of bytes in the two blocks that match, if all bytes match up to the specified Length value, the Length value is returned
134+
extern "C" __forceinline DWORD_PTR __stdcall compare_memory(_In_ const PVOID pcSource1, _In_ const PVOID pcSource2, _In_ DWORD_PTR dwptrLength) {
135+
// Init local variables
136+
DWORD_PTR dwptrIndex = 0;
137+
138+
// Start comparing the two blocks of memory
139+
for (dwptrIndex = 0; (dwptrIndex < dwptrLength) && (((PBYTE)pcSource1)[dwptrIndex] == ((PBYTE)pcSource2)[dwptrIndex]); dwptrIndex++);
140+
141+
return dwptrIndex;
142+
}
143+
144+
#pragma endregion

ReadMSW/Inc/ReadMsw.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// ========================================================================
2+
// File: ReadMsw.h
3+
//
4+
// Author: winterknife
5+
//
6+
// Description: Header file for ReadMsw32/64.asm source file
7+
//
8+
// Modifications:
9+
// 2025-01-09 Created
10+
// 2025-01-09 Updated
11+
// ========================================================================
12+
13+
// ========================================================================
14+
// Pragmas
15+
// ========================================================================
16+
17+
#pragma once
18+
19+
// ========================================================================
20+
// Includes
21+
// ========================================================================
22+
23+
#include "Common.h"
24+
25+
// ========================================================================
26+
// Assembly routine declarations
27+
// ========================================================================
28+
29+
#pragma region DECLARATIONS
30+
31+
/// @brief Check if segment-level protection is enabled
32+
/// @param None
33+
/// @return Returns TRUE if protected mode is enabled or FALSE if real-address mode is enabled
34+
_Success_(return != 0) _Must_inspect_result_ _IRQL_requires_max_(DISPATCH_LEVEL)
35+
extern "C" __declspec(noinline) BOOLEAN __fastcall is_protected_mode_enabled(
36+
VOID
37+
);
38+
39+
#pragma endregion

ReadMSW/Lib/msvcrt_x64.lib

230 KB
Binary file not shown.

ReadMSW/Lib/msvcrt_x86.lib

258 KB
Binary file not shown.

ReadMSW/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# EVENSTAR - ReadMSW
2+
3+
## Version
4+
- `v1.0.0`
5+
6+
## Brief
7+
- `ISA: x86`
8+
- `Mode: Real, Protected, Long`
9+
- `Bitness: 16-bit, 32-bit, 64-bit`
10+
- `CPL: 0, 3`
11+
- `OS: Windows`
12+
- `Language: C`
13+
- Sample code that demonstrates the usage of the `SMSW` instruction to fetch the the `Machine Status Word` (bits 0 through 15 of control register `CR0`) and check if the processor is running in `Protected` mode.
14+
15+
## Usage
16+
- There aren't a lot of useful bits in the `MSW`
17+
- One notable exception: `PE (Protection Enable)` bit (0)
18+
- This flag enables Segmentation
19+
- Under normal circumstances, the sample code will always inform that `CR0.PE` bit is set
20+
- Only useful for low-level code such as `OS` and `Hypervisors`
21+
- Another possible use might be for `VM` detection but more testing is needed
22+
```shell
23+
C:\Users\winterknife\Desktop\ACED\EVENSTAR\ReadMSW\Bin\x64>ReadMSW.exe
24+
[*] ReadMSW Built Jan 14 2025 14:12:25
25+
Press any key to continue . . .
26+
Processor Execution Mode == Protected Mode
27+
Press any key to continue . . .
28+
```
29+
30+
## Tested OS Versions
31+
- `Windows 11 24H2 Build 26100 Revision 1882 64-bit`
32+
33+
## References
34+
1. [SMSW—Store Machine Status Word](https://namazso.github.io/x86/html/SMSW.html)

0 commit comments

Comments
 (0)