├── .gitignore
├── Plouton-UEFI
├── .gitignore
├── Dockerfile
├── Plouton-UEFI.code-workspace
├── Plouton
│ ├── logging
│ │ ├── log_levels.h
│ │ ├── logging.h
│ │ ├── memory_log.h
│ │ └── memory_log.c
│ ├── hardware
│ │ ├── audio
│ │ │ ├── dummy.c
│ │ │ ├── audioDriver.h
│ │ │ ├── corsair_wireless.c
│ │ │ ├── creative_usb_speakers.c
│ │ │ ├── logitech_g_pro_x_wireless.c
│ │ │ ├── logitech_g_pro_x_2_wireless.c
│ │ │ └── hyperx_cloud_2.c
│ │ ├── timerRTC.h
│ │ ├── mouse
│ │ │ ├── dummy.c
│ │ │ ├── mouseDriver.h
│ │ │ ├── logitech_g_pro.c
│ │ │ └── logitech_g_pro_superlight.c
│ │ ├── timerPCH.h
│ │ ├── timerRTC.c
│ │ ├── serial.h
│ │ ├── xhci.h
│ │ ├── timerPCH.c
│ │ ├── serial.c
│ │ └── README.md
│ ├── target
│ │ ├── targets.h
│ │ ├── cs2
│ │ │ ├── structuresCS2.h
│ │ │ ├── README.md
│ │ │ ├── offsetsCS2.h
│ │ │ ├── math.h
│ │ │ └── cheatCS2.h
│ │ ├── README.md
│ │ └── hermes
│ │ │ ├── README.md
│ │ │ └── hermes.h
│ ├── memory
│ │ ├── string.h
│ │ ├── sigScan.h
│ │ ├── memoryMapUEFI.h
│ │ ├── string.c
│ │ ├── memory.h
│ │ ├── sigScan.c
│ │ └── memoryMapUEFI.c
│ ├── Plouton.inf
│ ├── plouton.h
│ ├── general
│ │ └── config.h
│ ├── os
│ │ └── windows
│ │ │ ├── NTKernelTools.h
│ │ │ └── windows.h
│ └── floats
│ │ └── floatlib.h
├── docker_build.sh
├── edk2-overrides
│ └── Conf
│ │ └── target.txt
└── README.md
├── images
├── XHCI_Endpoints.png
├── logo_plouton.jpg
├── XHCI_DeviceContexts.png
├── XHCI_RootPortNumber.png
├── UEFITool_ReplaceBody.png
├── XHCI_MemoryBaseAddress.png
└── XHCI_DeviceContextArrayBase.png
├── .gitmodules
├── PloutonLogViewer
├── App.xaml
├── .gitignore
├── PloutonLogViewer.csproj
├── PloutonLogViewer.sln
├── README.md
├── App.xaml.cs
├── Resources
│ ├── StringResources.zh-CN.xaml
│ └── StringResources.en-US.xaml
├── PhysicalMemoryReader.cs
└── MainWindow.xaml
├── LICENSE.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 |
--------------------------------------------------------------------------------
/Plouton-UEFI/.gitignore:
--------------------------------------------------------------------------------
1 | .bash_history
2 | .vs/
--------------------------------------------------------------------------------
/images/XHCI_Endpoints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/XHCI_Endpoints.png
--------------------------------------------------------------------------------
/images/logo_plouton.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/logo_plouton.jpg
--------------------------------------------------------------------------------
/images/XHCI_DeviceContexts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/XHCI_DeviceContexts.png
--------------------------------------------------------------------------------
/images/XHCI_RootPortNumber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/XHCI_RootPortNumber.png
--------------------------------------------------------------------------------
/images/UEFITool_ReplaceBody.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/UEFITool_ReplaceBody.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Plouton-UEFI/edk2"]
2 | path = Plouton-UEFI/edk2
3 | url = git@github.com:tianocore/edk2.git
4 |
--------------------------------------------------------------------------------
/images/XHCI_MemoryBaseAddress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/XHCI_MemoryBaseAddress.png
--------------------------------------------------------------------------------
/images/XHCI_DeviceContextArrayBase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pRain1337/plouton/HEAD/images/XHCI_DeviceContextArrayBase.png
--------------------------------------------------------------------------------
/Plouton-UEFI/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 | MAINTAINER Jussi Hietanen
3 |
4 | RUN \
5 | apt-get update && \
6 | apt-get -y install ccache build-essential python python-pip qemu sudo git \
7 | nano libgcc-5-dev uuid-dev nasm iasl wget zip xorg-dev p7zip-full
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton-UEFI.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {
8 | "C_Cpp.default.includePath": [
9 | "${workspaceFolder}/edk2/MdePkg/Include",
10 | "${workspaceFolder}/edk2/MdePkg/Include/X64"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/logging/log_levels.h:
--------------------------------------------------------------------------------
1 | #ifndef __plouton_log_levels_h__
2 | #define __plouton_log_levels_h__
3 |
4 | #define LOG_LEVEL_NONE 0
5 | #define LOG_LEVEL_ERROR 1
6 | #define LOG_LEVEL_INFO 2
7 | #define LOG_LEVEL_VERB 3
8 | #define LOG_LEVEL_DBG 4
9 |
10 |
11 |
12 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/dummy.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_DUMMY
4 |
5 | /*
6 | * Function: initAudioXHCI
7 | * --------------------
8 | * Dummy function for the dummy device.
9 | *
10 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
11 | *
12 | * returns: The audioProfile struct, initialized set As TRUE if it was found
13 | *
14 | */
15 | audioProfile_t initAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
16 | {
17 | audioProfile_t ret = { TRUE, 0, 0 };
18 | return ret;
19 | }
20 |
21 | #endif
--------------------------------------------------------------------------------
/PloutonLogViewer/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/PloutonLogViewer/.gitignore:
--------------------------------------------------------------------------------
1 | # Build results
2 | bin/
3 | obj/
4 | Debug/
5 | Release/
6 | *.user
7 | *.userosscache
8 | *.suo
9 | *.cache
10 | *.pidb
11 | *.log
12 | *.sln.docstates
13 |
14 | # VS generated
15 | .vs/
16 | _ReSharper*/
17 | *.resharper
18 | *.DotSettings.user
19 |
20 | # NuGet
21 | packages/
22 | *.nupkg
23 | *.snupkg
24 | **/packages/*
25 | !**/packages/build/
26 |
27 | # Rider / JetBrains
28 | .idea/
29 |
30 | # Others
31 | *.tmp
32 | *.bak
33 | *.swp
34 | *.orig
35 | *.psess
36 | *.vsp
37 | *.vspscc
38 | *.pubxml.user
39 | *.Publish.xml
40 | TestResult*/
41 | TestResults*/
42 | *.coverage
43 | *.coveragexml
44 |
45 | # Local configuration
46 | *.local.json
47 |
--------------------------------------------------------------------------------
/Plouton-UEFI/docker_build.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | # Ensure docker
4 | if [ ! -f /.dockerenv ]; then
5 | echo "This file should be run inside a docker container! See README.md"
6 | exit 1
7 | fi
8 |
9 | # Prepare EDK2 base
10 | pushd edk2
11 | make -C BaseTools
12 | . edksetup.sh
13 | popd
14 |
15 | # Copy Plouton-related files and changes
16 | cp -r Plouton/ edk2/
17 | cp -r edk2-overrides/* edk2
18 |
19 | # Build EDK2 UEFI firmware image with Plouton
20 | pushd edk2
21 | . edksetup.sh
22 | build -DSMM_REQUIRE
23 | popd
24 |
25 | # Clean-up Plouton-related changes
26 | # --> Not everything! edk2-overrides need to be reverted using git:
27 | # run "git restore ." (inside edk2 directory)
28 | # to get completely clean state
29 | rm -rf edk2/Plouton
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/targets.h:
--------------------------------------------------------------------------------
1 | #ifndef __plouton_targets_h__
2 | #define __plouton_targets_h__
3 |
4 | #include
5 | #include "cs2/cheatCS2.h"
6 | #include "hermes/hermes.h"
7 |
8 |
9 | // Define function pointer types
10 | #ifdef __GNUC__
11 | typedef BOOLEAN EFIAPI (*InitCheat)(VOID);
12 | typedef VOID EFIAPI (*CheatLoop)(VOID);
13 | #else
14 | typedef BOOLEAN (*InitCheat)(VOID);
15 | typedef VOID (*CheatLoop)(VOID);
16 | #endif
17 |
18 | typedef struct {
19 | char name[64];
20 | InitCheat cheatInitFun;
21 | CheatLoop cheatLoopFun;
22 | BOOLEAN initialized;
23 | BOOLEAN isGame;
24 | EFI_PHYSICAL_ADDRESS dirBase;
25 | } TargetEntry;
26 |
27 | TargetEntry targets[] = {
28 | { "cs2.exe", InitCheatCS2, CheatCs2Main, FALSE , TRUE},
29 | { "hermes.exe", initializeHermes, pollCommands, FALSE, FALSE }
30 | };
31 |
32 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/timerRTC.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for onboard real time clock related functions
4 | *
5 | --*/
6 |
7 | // edk2 includes
8 | #include
9 | #include
10 |
11 | #ifndef __plouton_timer_rtc_h__
12 | #define __plouton_timer_rtc_h__
13 |
14 | // Structures
15 |
16 | // Definitions
17 |
18 |
19 | /*
20 | * CMOS Register offsets
21 | */
22 | #define CMOS_PORT_ADDRESS 0x70
23 | #define CMOS_PORT_DATA 0x71
24 |
25 | // Functions
26 |
27 | /*
28 | * Function: readCMOSRegister
29 | * --------------------
30 | * Reads the specified register from the RTC using the CMOS IO buffer.
31 | */
32 | UINT8 readCMOSRegister(INT32 reg);
33 |
34 | /*
35 | * Function: getCMOSTime
36 | * --------------------
37 | * Writes the current time in the global variables 'currentSecond' and 'currentMinute' that was read using the RTC.
38 | */
39 | VOID getCMOSTime();
40 |
41 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/cs2/structuresCS2.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for structures used in cs2
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_structures_cs_h__
8 | #define __plouton_structures_cs_h__
9 |
10 | // our includes
11 | #include "../../floats/floatlib.h"
12 |
13 | // These lists are used to indicate if features should be active
14 | static const UINT8 weaponList[] = {7, 8, 10, 13, 14, 16, 25, 27, 28, 29, 35, 39};; // Rifle List
15 | static const UINT8 smgList[] = {17, 19, 23, 24, 26, 33, 34}; // smg List
16 | static const UINT8 pistolList[] = { 1, 2, 3, 4, 30, 32, 36, 61, 64 }; // Pistol List,
17 | static const UINT8 sniperList[] = {9, 11, 38, 40}; // Sniper List
18 |
19 | // basic game data structs
20 | typedef struct _CS2CutlVector {
21 | UINT64 size; // Size of the vector
22 | UINT64 data; // Pointer to the vector
23 | } CS2CUtlVector, * PCS2CutlVector;
24 |
25 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/mouse/dummy.c:
--------------------------------------------------------------------------------
1 | #include "mouseDriver.h"
2 |
3 | #ifdef MOUSE_DRIVER_DUMMY
4 |
5 | /*
6 | * Function: initDummyMouseXHCI
7 | * --------------------
8 | * Dummy function for the dummy device.
9 | *
10 | * MouseDriverTdCheck: Pointer to the "MouseDriverTdCheck" function that is used to verify the device packets
11 | *
12 | * returns: The mouseProfile struct, initialized set As TRUE if it was found
13 | *
14 | */
15 | mouseProfile_t EFIAPI initDummyMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun)
16 | {
17 | mouseProfile_t ret = { TRUE, 0, 0, 0, 0, 0, 0 };
18 | return ret;
19 | }
20 |
21 | /*
22 | * Function: mouseDummyDriverTdCheck
23 | * --------------------
24 | * Dummy function to check the TD buffers.
25 | *
26 | * TDPointerPhys: UINT64 (EFI_PHYSICAL_ADDRESS) to the TD that should be checked
27 | *
28 | * returns: TRUE if the check passed, FALSE otherwise
29 | *
30 | */
31 | BOOLEAN EFIAPI mouseDummyDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys)
32 | {
33 | return FALSE;
34 | }
35 |
36 | #endif
--------------------------------------------------------------------------------
/PloutonLogViewer/PloutonLogViewer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0-windows
6 | enable
7 | true
8 | false
9 | win-x64
10 | true
11 |
12 |
13 |
14 |
15 | MSBuild:Compile
16 |
17 |
18 | MSBuild:Compile
19 |
20 |
21 | MSBuild:Compile
22 | PreserveNewest
23 |
24 |
25 | MSBuild:Compile
26 | PreserveNewest
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/string.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for string/memory related functions
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_string_h__
8 | #define __plouton_string_h__
9 |
10 | // edk2 includes
11 | #include
12 | #include
13 |
14 | // Structures
15 |
16 | // Definitions
17 |
18 | // Definition for linux compilers
19 | #ifdef __GNUC__
20 | typedef UINT32 size_t;
21 | #endif
22 |
23 | // Functions
24 |
25 | /*
26 | * Function: toLower
27 | * --------------------
28 | * Converts the given char to lowercase.
29 | */
30 | INT32 toLower(INT32 c);
31 |
32 | /*
33 | * Function: strcmp
34 | * --------------------
35 | * Compares two strings and returns the position where there is a difference.
36 | */
37 | INT32 strcmp(const CHAR8* str1, const CHAR8* str2);
38 |
39 | /*
40 | * Function: nullBuffer
41 | * --------------------
42 | * Nulls a passed memory area.
43 | */
44 | void nullBuffer(EFI_PHYSICAL_ADDRESS buffer, UINT16 size);
45 |
46 | /*
47 | * Function: strlen
48 | * --------------------
49 | * Returns length of an ascii string
50 | */
51 | UINT32 strlen(const char* str);
52 |
53 | #endif
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 pRain & Jussihi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/PloutonLogViewer/PloutonLogViewer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.14.36109.1 d17.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PloutonLogViewer", "PloutonLogViewer.csproj", "{7CFE937E-7C96-1597-5184-698BBA3F8232}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {7CFE937E-7C96-1597-5184-698BBA3F8232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {7CFE937E-7C96-1597-5184-698BBA3F8232}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {7CFE937E-7C96-1597-5184-698BBA3F8232}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {7CFE937E-7C96-1597-5184-698BBA3F8232}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {646913FB-4038-4AE0-987E-D7CC2AAD9FCA}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/PloutonLogViewer/README.md:
--------------------------------------------------------------------------------
1 | # PloutonLogViewer
2 |
3 | This directory contains the source code for Plouton memory log viewer Windows application.
4 |
5 | ## Features
6 | - Reads physical memory via RWEverything driver (RwDrv.sys) and parses the SMM in-memory circular log.
7 | - Can auto-fetch the log buffer physical address from UEFI variable `PloutonLogAddress`, or accept manual input.
8 | - Bilingual UI (English/Chinese), renders logs as `[Timestamp][Level] Message`.
9 |
10 | ## Usage
11 | 1) Start RWEverything (or ensure RwDrv.sys is loaded) and run PloutonLogViewer as Administrator.
12 | 2) Click “Get Address” to read the UEFI variable, or enter the physical address manually (`0x...`).
13 | 3) Click Start to poll logs; Pause to stop; Clear to wipe the UI (does not affect the SMM buffer).
14 | 4) Admin rights are required. The app attempts to enable `SeSystemEnvironmentPrivilege` automatically.
15 |
16 | ## Build
17 | - Windows + Visual Studio / `dotnet build`, project: `PloutonLogViewer.csproj`.
18 | - Log buffer default is 8MB; keep viewer `LogBufferSize` aligned with firmware `MEMORY_LOG_BUFFER_SIZE`.
19 |
20 | ## Layout
21 | - `App.xaml*` / `MainWindow.*`: WPF UI and logic.
22 | - `PhysicalMemoryReader.cs`: IOCTL wrapper for RWEverything physical memory reads.
23 | - `Resources/`: localization strings.
24 | - `.gitignore`: ignores bin/obj/Debug/Release artifacts.
25 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/timerPCH.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for functions related to SMI timer using PCH functionalities
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_timer_pch_h__
8 | #define __plouton_timer_pch_h__
9 |
10 | // our includes
11 | #include "../general/config.h"
12 | #include "serial.h"
13 | #include "../memory/memory.h"
14 |
15 | // edk2 includes
16 | #include
17 | #include
18 |
19 | // Structures
20 |
21 | // Definitions
22 |
23 | // Definitions used in the function which are offset for various XHCI / PCH functions
24 | #define PCH_SMI_EN 0x30 // Enables to toggle SMI generation for various sources
25 | #define PCH_SMI_STS 0x34 // Indicates the reason the PCH triggered a SMI
26 |
27 | #define XHCI_USBLegacySupportControlStatus 0x8470 // Not documented on newer specifications, check out series 200/300 or manually reverse it
28 | #define XHCI_USBStatus 0x84 // Indicates if the SMI was triggered by the XHCI and should be cleared
29 |
30 | // Functions
31 |
32 | /*
33 | * Function: pchInitUSB
34 | * --------------------
35 | * Initializes the PCH timer using the XHCI SMI generation feature.
36 | */
37 | BOOLEAN pchInitUSB();
38 |
39 | /*
40 | * Function: pchClearUSB
41 | * --------------------
42 | * Clears the various status bits that are toggled when a SMI is created from the XHCI PCH timer.
43 | */
44 | VOID pchClearUSB();
45 |
46 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/sigScan.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Contains general definitions for functions for signature scanning
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_sigscan_h__
8 | #define __plouton_sigscan_h__
9 |
10 | // our includes
11 | #include "memoryMapUEFI.h"
12 | #include "memory.h"
13 |
14 | // Structures
15 |
16 | // Definitions
17 |
18 | // General definitions of types of signature scans
19 | enum
20 | {
21 | SIGTYPE_NORMAL = 0x0, // normal
22 | SIGTYPE_READ = 0x1, // rpm at pattern
23 | SIGTYPE_SUBTRACT = 0x2, // subtract img base
24 | };
25 |
26 | #define INRANGE(x,a,b) (x >= a && x <= b)
27 | #define getBits( x ) (INRANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xa))
28 | #define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1]))
29 |
30 | // Functions
31 |
32 | /*
33 | * Function: CompareBytes
34 | * --------------------
35 | * Searches for a given pattern in a given memory buffer pointed to by a pointer.
36 | */
37 | BOOLEAN CompareBytes(const unsigned char* bytes, const char* pattern);
38 |
39 | /*
40 | * Function: virtFindPattern
41 | * --------------------
42 | * Performs a pattern scan on virtual memory for a specific signature.
43 | */
44 | EFI_VIRTUAL_ADDRESS virtFindPattern(EFI_VIRTUAL_ADDRESS base, UINT64 size, UINT64 dirBase, const char* pattern, UINT32 extra, BOOLEAN ripRelative, BOOLEAN substract);
45 |
46 | /*
47 | * Function: physFindPattern
48 | * --------------------
49 | * Performs a pattern scan on physical memory for a specific signature.
50 | */
51 | EFI_PHYSICAL_ADDRESS physFindPattern(EFI_PHYSICAL_ADDRESS base, UINT32 size, const unsigned char* pattern, UINT32 patternLength);
52 |
53 | #endif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Plouton - a System Management Mode (SMM) cheat framework
2 |
3 |
4 |
5 |
6 | *Plouton was the master of the underworld, and thus he was able to command the riches of the earth and the souls of the dead.*
7 |
8 | Plouton is a System Management Mode (SMM) (ring-2, *"underworld"*) PC game cheat framework.
9 | This repository and code were created as proof-of-concept and released as open source, we do not take any responsibility for the further usage of this project.
10 |
11 | Check out this [video demonstration](https://www.youtube.com/watch?v=HoLtvFKOZzY) of Plouton's CS2 cheat implementation.
12 |
13 | # Supported platforms
14 | Plouton supports only Intel-based systems, for AMD-based systems some importants features (e.g. XHCI generating SMIs on USB Events) are not available). The core functionality and memory code would still be applicable, and could be reused.
15 | The core has been tested on Intel generations from Series 200 (Skylake, Kaby Lake) up to Series 700 (Alder Lake, Raptor Lake).
16 | According to the offsets in the Intel Chipset datasheet for the Series 800, it should also be supported but has not been tested.
17 |
18 | # Building
19 |
20 | See [Plouton-UEFI](Plouton-UEFI)
21 |
22 | # Extending
23 |
24 | To extend Plouton to support your game of choice, see [targets](Plouton-UEFI/Plouton/target/)
25 |
26 | To extend Plouton to support your hardware (mouse, audio devices), see [hardware](Plouton-UEFI/Plouton/hardware/)
27 |
28 | To extend for other OS than Windows, sorry, this is not currently possible :-)
29 |
30 | Contributions are welcome!
31 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/Plouton.inf:
--------------------------------------------------------------------------------
1 | [defines]
2 | INF_VERSION = 0x00010005
3 | BASE_NAME = Plouton
4 | FILE_GUID = d73adef7-8749-40b5-83a7-4d9932fc6234
5 | MODULE_TYPE = DXE_SMM_DRIVER
6 | PI_SPECIFICATION_VERSION = 0x0001000A
7 | ENTRY_POINT = UefiMain
8 |
9 | [Sources]
10 | plouton.c
11 | floats/floatlib.c
12 | hardware/serial.c
13 | hardware/timerRTC.c
14 | hardware/timerPCH.c
15 | hardware/xhci.c
16 | memory/string.c
17 | memory/memoryMapUEFI.c
18 | memory/memory.c
19 | memory/sigScan.c
20 | os/windows/NTKernelTools.c
21 | target/cs2/cheatCS2.c
22 | target/cs2/math.c
23 | target/hermes/hermes.c
24 | hardware/audio/dummy.c
25 | hardware/audio/corsair_wireless.c
26 | hardware/audio/creative_usb_speakers.c
27 | hardware/audio/hyperx_cloud_2.c
28 | hardware/audio/logitech_g_pro_x_wireless.c
29 | hardware/audio/logitech_g_pro_x_2_wireless.c
30 | hardware/mouse/dummy.c
31 | hardware/mouse/logitech_g_pro.c
32 | hardware/mouse/logitech_g_pro_superlight.c
33 | logging/memory_log.c
34 |
35 | [Packages]
36 | MdePkg/MdePkg.dec
37 | MdeModulePkg/MdeModulePkg.dec
38 | IntelFrameworkPkg/IntelFrameworkPkg.dec
39 | IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
40 | StdLib/StdLib.dec
41 |
42 | [LibraryClasses]
43 | UefiDriverEntryPoint
44 | UefiBootServicesTableLib
45 | UefiRuntimeServicesTableLib
46 | PcdLib
47 | BaseMemoryLib
48 | DevicePathLib
49 | PciLib
50 |
51 | [Protocols]
52 | gEfiSmmCpuProtocolGuid
53 |
54 | [Depex]
55 | TRUE
56 |
57 | [BuildOptions]
58 | MSFT:*_*_*_CC_FLAGS = -DUSE_COMPILER_INTRINSICS_LIB -D_CRT_SECURE_NO_WARNINGS -D_NO_CRT_STDIO_INLINE -D_OFF_T_DEFINED -D_off_t=int64_t -Doff_t=int64_t /wd4047 /wd4146 /wd4201 /wd4244 /wd4245 /wd4267 /wd4309 /wd4389 /wd4706 /wd4996 /wd4006 /wd4117
59 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/cs2/README.md:
--------------------------------------------------------------------------------
1 | # CS2 implementation
2 | This is a example implementation of a game cheat fully working in SMM.
3 | There is no requirement for any interaction with the normal system, thus it is more complicated for an anti-cheat to detect such a cheat.
4 |
5 | For the implementation, see [cheatCS2.c](cheatCS2.c).
6 |
7 | ## Features
8 | Based on the ability to intercept and manipulate all incoming & outgoing USB packets before they can be interpreted by windows, we have implemented the following features:
9 |
10 | ### Aimbot
11 | A simple configurable aimbot, which allows setting your own aim key, on what weapon types it should be active and what Field of View (FOV) and Smooth value should be used.
12 | If those factors are fullfilled, it will automatically lock on the nearest player in the configured FOV and change the USB packets to move to the nearest bone of the player.
13 | For changing settings, see the top of the [cheatCS2.c](cheatCS2.c) .c file.
14 |
15 | ### Sound ESP
16 | A simple configurable Sound ESP, which allows configuring your own FOV.
17 | If an enemy would be within the configured FOV, the Sound ESP would malform the packets of the headset/speaker and thus trigger a sound which indicates there is an enemy in the FOV.
18 | For changing settings, see the top of the [cheatCS2.c](cheatCS2.c) .c file.
19 |
20 | ## How to update
21 | All offsets / signatures used have been moved into the [offsetsCS2.h](offsetsCS2.h) header file.
22 | The offsets & signatures can both be found online in various forums or in GitHub repositories.
23 |
24 | ## Recommendations when adding features
25 | It is important to keep in mind that the longer you stay in SMM, the more performance you loose.
26 | Our recommendation is, splitting up operations and using caching to prevent unnecessary repetitive operations.
27 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/plouton.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Contains general definitions used in Plouton
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_header_h__
8 | #define __plouton_header_h__
9 |
10 | // our includes
11 | #include "general/config.h"
12 | #include "hardware/serial.h"
13 | #include "hardware/xhci.h"
14 | #include "hardware/timerPCH.h"
15 | #include "hardware/timerRTC.h"
16 | #include "os/windows/NTKernelTools.h"
17 | #include "memory/memory.h"
18 | #include "memory/memoryMapUEFI.h"
19 |
20 | // edk2 includes
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | // Structures
27 |
28 | // Definitions
29 |
30 | // General EFI SMM System table to access runtime functions by edk2
31 | EFI_SMM_SYSTEM_TABLE2* gSmst2;
32 |
33 | // For performance optimization to not trigger all functions at every SMI
34 | BOOLEAN startSeconds = FALSE;
35 |
36 | // Handler for this SMM module
37 | EFI_HANDLE hPloutonHandler;
38 |
39 | // re-init game if it was closed
40 | UINT64 currSMIamount;
41 |
42 | // Optimization features
43 | UINT8 lastMinute = 0; // Minute of the last execution, used in the beginning to not do the full initialization at every SMI but only every minute
44 | UINT16 counter = 0; // Used to count the SMIs received, used so we dont trigger certain scans every SMI
45 |
46 | // Functions
47 |
48 | /*
49 | * Function: FindTarget
50 | * --------------------
51 | * Searches for the built-in targets (games) using the wrapper function and tries to initialize the required features.
52 | */
53 | BOOLEAN FindTarget();
54 |
55 | /*
56 | * Function: UefiMain
57 | * --------------------
58 | * Initializes the main functionalities of the SMM module.
59 | */
60 | EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE* SystemTable);
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/audioDriver.h:
--------------------------------------------------------------------------------
1 | #ifndef __plouton_audio_driver_h__
2 | #define __plouton_audio_driver_h__
3 |
4 | #include
5 | #include
6 | #include "../../general/config.h"
7 |
8 |
9 | // Structures
10 | typedef struct _audioProfile {
11 | BOOLEAN initialized;
12 | UINT64 audioChannels;
13 | EFI_PHYSICAL_ADDRESS audioRingLocation;
14 | } audioProfile_t;
15 |
16 | // Define function pointer types
17 | #ifdef __GNUC__
18 | typedef audioProfile_t EFIAPI (*InitAudioDriverFun)(VOID);
19 | #else
20 | typedef audioProfile_t (*InitAudioDriverFun)(EFI_PHYSICAL_ADDRESS);
21 | #endif
22 |
23 |
24 | // Function defines
25 | #ifdef AUDIO_DRIVER_DUMMY
26 | audioProfile_t EFIAPI initAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
27 | #endif
28 | #ifdef AUDIO_DRIVER_CORSAIR_WIRELESS
29 | audioProfile_t EFIAPI initCorsairWirelessAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
30 | #endif
31 | #ifdef AUDIO_DRIVER_CREATIVE_USB_SPEAKERS
32 | audioProfile_t EFIAPI initCreativeUsbSpeakersAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
33 | #endif
34 | #ifdef AUDIO_DRIVER_HYPERX_CLOUD_2
35 | audioProfile_t EFIAPI initHyperXCloud2AudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
36 | #endif
37 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_2_WIRELESS
38 | audioProfile_t EFIAPI initLogitechGProX2AudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
39 | #endif
40 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_WIRELESS
41 | audioProfile_t EFIAPI initLogitechGProXAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR);
42 | #endif
43 |
44 | static const InitAudioDriverFun InitAudioDriverFuns[] = {
45 | #ifdef AUDIO_DRIVER_DUMMY
46 | initAudioXHCI,
47 | #endif
48 | #ifdef AUDIO_DRIVER_CORSAIR_WIRELESS
49 | initCorsairWirelessAudioXHCI,
50 | #endif
51 | #ifdef AUDIO_DRIVER_CREATIVE_USB_SPEAKERS
52 | initCreativeUsbSpeakersAudioXHCI,
53 | #endif
54 | #ifdef AUDIO_DRIVER_HYPERX_CLOUD_2
55 | initHyperXCloud2AudioXHCI,
56 | #endif
57 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_2_WIRELESS
58 | initLogitechGProX2AudioXHCI,
59 | #endif
60 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_WIRELESS
61 | initLogitechGProXAudioXHCI,
62 | #endif
63 | };
64 |
65 |
66 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/README.md:
--------------------------------------------------------------------------------
1 | # Extending Targets
2 |
3 | In order to extend targets, you should create a new directory for your new target. See this directory for examples.
4 |
5 | Each target should have their own `TargetEntry` structure defined inside the [targets.h](targets.h) file.
6 |
7 | The `TargetEntry` structure requires the target process's name (for example `target.exe`) and two function pointers,
8 | `InitCheat` (`typedef BOOLEAN EFIAPI (*InitCheat)(VOID);`) and `CheatLoop` (`typedef VOID EFIAPI (*CheatLoop)(VOID);`).
9 | Your cheat implementation must implement these two functions. The init function simply initializes your cheat (i.e., finds
10 | the target process and required modules etc. from it, initializes local variables to your cheat). The loop function is
11 | the function that is then run every SMI.
12 |
13 | You also need to edit the [Plouton.inf](../Plouton.inf) and add your implementation's .c files to the list of to-be-compiled objects.
14 |
15 | After you have done aforementioned steps, your cheat should compile and be part of the Plouton framework, and Plouton should
16 | be searching and trying to init/execute your target code, if the target process is found.
17 |
18 | In your implementation, you can call and use all the code available elsewhere in this project. Please see how the example CS2
19 | cheat leverages xhci and memory functionality to parse game data and move mouse / play sound!
20 |
21 | # Example implementations
22 | To showcase the abilities of this project and how it works, we've prepared two example implementations.
23 | ## CS2
24 | We have prepared a fully working implementation for Counter-Strike 2 with the following features:
25 | - Aimbot
26 | - Sound ESP
27 |
28 | For further information, see [cs2](./cs2).
29 |
30 | ## Hermes
31 | We have implemented our previous project, [Hermes](https://github.com/pRain1337/hermes) into this project.
32 | This allows you to use the framework to debug processes / access memory using SMM privileges, which can be especially useful to dump memory and analyze them later.
33 | For further information, see [hermes](Plouton-UEFI/Plouton/target/hermes).
34 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/memoryMapUEFI.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for memory map related functions
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_mm_uefi_h__
8 | #define __plouton_mm_uefi_h__
9 |
10 | // our includes
11 | #include "../general/config.h"
12 | #include "memory.h"
13 |
14 | // edk2 includes
15 | #include
16 |
17 | // Global variables we want to share
18 | extern EFI_MEMORY_DESCRIPTOR* mUefiMemoryMap;
19 | extern UINTN mUefiMemoryMapSize;
20 | extern UINTN mUefiDescriptorSize;
21 |
22 | // Structures
23 |
24 | // Definitions
25 |
26 | // from plouton.c
27 | extern EFI_BOOT_SERVICES* gBS;
28 |
29 |
30 |
31 | // calculate the next memory map descriptor by adding the size of a descriptor to the current entry
32 | #define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
33 | ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
34 |
35 | // calculate the previous memory map descriptor by subtracting the size of a descriptor to the current entry
36 | #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
37 | ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
38 |
39 | // Functions
40 |
41 | /*
42 | * Function: CheckUefiMemoryMap
43 | * --------------------
44 | * Checks if the passed memory map is valid
45 | */
46 | BOOLEAN CheckUefiMemoryMap(EFI_MEMORY_DESCRIPTOR* MemoryMap, UINT64 MemoryMapSize, UINT64 MemoryMapDescriptorSize);
47 |
48 | /*
49 | * Function: SortMemoryMap
50 | * --------------------
51 | * Sorts the passed memory map
52 | */
53 | VOID SortMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR* MemoryMap, IN UINTN MemoryMapSize, IN UINTN DescriptorSize);
54 |
55 | /*
56 | * Function: MergeMemoryMapForNotPresentEntry
57 | * --------------------
58 | * Merges entries in the memory map together
59 | */
60 | VOID MergeMemoryMapForNotPresentEntry(IN OUT EFI_MEMORY_DESCRIPTOR* MemoryMap, IN OUT UINTN* MemoryMapSize, IN UINTN DescriptorSize);
61 |
62 | /*
63 | * Function: InitUefiMemoryMap
64 | * --------------------
65 | * Initialize a copy of the memory map in the passed pointer
66 | */
67 | BOOLEAN InitUefiMemoryMap(UINT64 NewMemoryMap);
68 |
69 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/general/config.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Contains general definitions used in Plouton
4 | *
5 | --*/
6 |
7 | #include "../logging/log_levels.h"
8 |
9 | #ifndef __plouton_config_h__
10 | #define __plouton_config_h__
11 |
12 | /*
13 | * Serial port configuration.
14 | * For EFI_DEBUG_SERIAL_BUILTIN and EFI_DEBUG_SERIAL_PROTOCOL.
15 | * Port 0 is the default port on the motherboard
16 | */
17 | #define SERIAL_BAUDRATE 115200
18 | #define SERIAL_PORT_0 0x3F8
19 |
20 | /*
21 | * This variable is used to indicate if and what serial level debug should be used.
22 | * See logging.h for available options
23 | */
24 | #define SERIAL_DEBUG_LEVEL LOG_LEVEL_INFO
25 |
26 | /*
27 | * Memory logging configuration.
28 | * Set to 1 to enable in-memory logging for debugging purposes.
29 | * Set to 0 to disable in-memory logging.
30 | * When enabled, error messages will be stored in a memory buffer that can be
31 | * inspected with external tools.
32 | */
33 | #define ENABLE_MEMORY_LOG 0
34 |
35 | /*
36 | * Memory log buffer size configuration.
37 | * Available options:
38 | * - MEM_LOG_SIZE_1MB (1MB - 1024 * 1024 bytes)
39 | * - MEM_LOG_SIZE_2MB (2MB - 2 * 1024 * 1024 bytes)
40 | * - MEM_LOG_SIZE_4MB (4MB - 4 * 1024 * 1024 bytes)
41 | * - MEM_LOG_SIZE_8MB (8MB - 8 * 1024 * 1024 bytes)
42 | *
43 | * Larger buffers provide more log history but consume more memory.
44 | * Choose based on your debugging needs and available system memory.
45 | */
46 | #define MEMORY_LOG_BUFFER_SIZE MEM_LOG_SIZE_8MB
47 |
48 | /*
49 | * Minimum log level that will be written to the in-memory log buffer.
50 | * Use LOG_LEVEL_ERROR / LOG_LEVEL_INFO / LOG_LEVEL_VERB / LOG_LEVEL_DBG.
51 | * This is independent from SERIAL_DEBUG_LEVEL to allow keeping serial chatty
52 | * while trimming what gets persisted in memory.
53 | */
54 | #define MEMORY_LOG_MIN_LEVEL LOG_LEVEL_INFO
55 |
56 | // Cheat features
57 | #define ENABLE_SOUND FALSE
58 | #define ENABLE_AIM TRUE
59 |
60 | // DRIVERS
61 | #define MOUSE_DRIVER_LOGITECH_G_PRO
62 | #define MOUSE_DRIVER_LOGITECH_G_PRO_SUPERLIGHT
63 |
64 | #define AUDIO_DRIVER_LOGITECH_G_PRO_X_2_WIRELESS
65 | #define AUDIO_DRIVER_LOGITECH_G_PRO_X_WIRELESS
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/timerRTC.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for onboard real time clock related functions
4 | *
5 | --*/
6 |
7 | // edk2 includes
8 | #include
9 |
10 | // our includes
11 | #include "timerRTC.h"
12 |
13 | // Global variables that indicate the current time of the RTC
14 | UINT8 currentSecond = 0;
15 | UINT8 currentMinute = 0;
16 | UINT8 currentDay = 0;
17 | UINT8 currentMonth = 0;
18 |
19 | /*
20 | * Function: readCMOSRegister
21 | * --------------------
22 | * Reads the passed CMOS register using the IO buffer of the CMOS.
23 | *
24 | * reg: INT32 register that should be read
25 | *
26 | * returns: Nothing
27 | *
28 | */
29 | UINT8 readCMOSRegister(INT32 reg)
30 | {
31 | // Write the register we want to the CMOS Port address
32 | IoWrite8(CMOS_PORT_ADDRESS, reg);
33 |
34 | // Now read the CMOS Data address which will be the value of the register we requested
35 | return IoRead8(CMOS_PORT_DATA);
36 | }
37 |
38 | /*
39 | * Function: getCMOSTime
40 | * --------------------
41 | * Reads out the current time from the RTC using the IO buffer and writes it into the global variables 'currentSecond' and 'currentMinute'.
42 | *
43 | *
44 | * returns: Nothing
45 | *
46 | */
47 | VOID getCMOSTime()
48 | {
49 | // Read the current second (register 0x00)
50 | UINT8 second = readCMOSRegister(0x00);
51 |
52 | // Read the current minute (register 0x02)
53 | UINT8 minute = readCMOSRegister(0x02);
54 |
55 | // Read the current day (register 0x02)
56 | UINT8 day = readCMOSRegister(0x07);
57 |
58 | // Read the current month (register 0x02)
59 | UINT8 month = readCMOSRegister(0x08);
60 |
61 | // Read the register B as it contains important definitions (https://stanislavs.org/helppc/cmos_ram.html)
62 | UINT8 registerB = readCMOSRegister(0xB);
63 |
64 | // check if the data is in binary or not
65 | if (!(registerB & 0x04))
66 | {
67 | // Data is not in binary, means we have to convert it first (see https://wiki.osdev.org/CMOS#Getting_Current_Date_and_Time_from_RTC)
68 | second = (second & 0x0F) + ((second / 16) * 10);
69 | minute = (minute & 0x0F) + ((minute / 16) * 10);
70 | day = (day & 0x0F) + ((day / 16) * 10);
71 | month = (month & 0x0F) + ((month / 16) * 10);
72 | }
73 |
74 | // Pass the data to the global variabes
75 | currentSecond = second;
76 | currentMinute = minute;
77 | currentDay = day;
78 | currentMonth = month;
79 | }
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/serial.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for serial related functions
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_serial_h__
8 | #define __plouton_serial_h__
9 |
10 | // our includes
11 | #include "../general/config.h"
12 | #include "../memory/memory.h"
13 |
14 | // edk2 includes
15 | #include
16 | #include
17 |
18 | // Structures
19 |
20 | // Definitions
21 |
22 | /*
23 | * for printing fix32_t
24 | */
25 | typedef INT64 fix32_t;
26 |
27 | /*
28 | * UART Register Offsets
29 | */
30 | #define BAUD_LOW_OFFSET 0x00
31 | #define BAUD_HIGH_OFFSET 0x01
32 | #define IER_OFFSET 0x01
33 | #define LCR_SHADOW_OFFSET 0x01
34 | #define FCR_SHADOW_OFFSET 0x02
35 | #define IR_CONTROL_OFFSET 0x02
36 | #define FCR_OFFSET 0x02
37 | #define EIR_OFFSET 0x02
38 | #define BSR_OFFSET 0x03
39 | #define LCR_OFFSET 0x03
40 | #define MCR_OFFSET 0x04
41 | #define LSR_OFFSET 0x05
42 | #define MSR_OFFSET 0x06
43 |
44 | /*
45 | * UART Register Bit Defines
46 | */
47 | #define LSR_TXRDY 0x20
48 | #define LSR_RXDA 0x01
49 | #define DLAB 0x01
50 |
51 | /*
52 | * Settings for the serial
53 | */
54 | #define BAUDRATE_MAX 115200
55 |
56 |
57 |
58 | // Function
59 |
60 | /*
61 | * Function: SerialPortInitialize
62 | * --------------------
63 | * Initializes the serial device hardware at the supplied address with the passed Baudrate.
64 | */
65 | VOID SerialPortInitialize(UINT16 Port, UINTN Baudrate);
66 |
67 | /*
68 | * Function: SerialPortWrite
69 | * --------------------
70 | * Writes the passed data to the port and waits for the answer of the serial port
71 | */
72 | VOID SerialPortWrite(UINT16 Port, UINT8 Data);
73 |
74 | /*
75 | * Function: SerialSendData
76 | * --------------------
77 | * Writes a raw memory buffer to the serial using SerialPortWrite
78 | */
79 | VOID SerialSendData(const VOID* buf, UINT8 len);
80 |
81 | /*
82 | * Function: SerialPrintNumber
83 | * --------------------
84 | * Converts a hex or dec number into a string and writes it to the serial using SerialPortWrite
85 | */
86 | VOID SerialPrintNumber(UINT64 _v, INT64 _b);
87 |
88 |
89 | /*
90 | * Function: SerialPrintf
91 | * --------------------
92 | * Print a formatted string to serial console
93 | */
94 | VOID EFIAPI SerialPrintf(const char* fmt, ...);
95 |
96 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/mouse/mouseDriver.h:
--------------------------------------------------------------------------------
1 | #ifndef __plouton_mouse_driver_h__
2 | #define __plouton_mouse_driver_h__
3 |
4 | #include
5 | #include
6 | #include "../../general/config.h"
7 |
8 |
9 | // Structures
10 | typedef struct _mouseProfile {
11 | BOOLEAN initialized;
12 | EFI_PHYSICAL_ADDRESS PhysicalTDLocation;
13 | EFI_PHYSICAL_ADDRESS PhysicalTDLocationButton;
14 | EFI_PHYSICAL_ADDRESS PhysicalTDLocationMove;
15 | EFI_PHYSICAL_ADDRESS PhysicalTDLocation2;
16 | EFI_PHYSICAL_ADDRESS PhysicalTDLocation2Button;
17 | EFI_PHYSICAL_ADDRESS PhysicalTDLocation2Move;
18 | } mouseProfile_t;
19 |
20 | // Define function pointer types
21 | #ifdef __GNUC__
22 | typedef BOOLEAN EFIAPI (*MouseDriverTdCheck)(EFI_PHYSICAL_ADDRESS);
23 | typedef mouseProfile_t EFIAPI (*InitMouseDriver)(MouseDriverTdCheck, EFI_PHYSICAL_ADDRESS);
24 | #else
25 | typedef BOOLEAN (*MouseDriverTdCheck)(EFI_PHYSICAL_ADDRESS);
26 | typedef mouseProfile_t (*InitMouseDriver)(MouseDriverTdCheck, EFI_PHYSICAL_ADDRESS);
27 | #endif
28 |
29 | typedef struct _mouseInitFuns {
30 | InitMouseDriver InitMouseDriverFun;
31 | MouseDriverTdCheck MouseDriverTdCheckFun;
32 | } mouseInitFuns;
33 |
34 | // Function defines
35 | #ifdef MOUSE_DRIVER_DUMMY
36 | mouseProfile_t EFIAPI initDummyMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun);
37 | BOOLEAN EFIAPI mouseDummyDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys);
38 | #endif
39 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO_SUPERLIGHT
40 | mouseProfile_t EFIAPI initLogitechGProSuperlightMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun, EFI_PHYSICAL_ADDRESS MBAR);
41 | BOOLEAN EFIAPI mouseLogitechGProSuperlightDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys);
42 | #endif
43 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO
44 | mouseProfile_t EFIAPI initLogitechGProMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun, EFI_PHYSICAL_ADDRESS MBAR);
45 | BOOLEAN EFIAPI mouseLogitechGProDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys);
46 | #endif
47 |
48 | static const mouseInitFuns InitMouseDriversFuns[] = {
49 | #ifdef MOUSE_DRIVER_DUMMY
50 | { initDummyMouseXHCI, mouseDummyDriverTdCheck},
51 | #endif
52 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO_SUPERLIGHT
53 | { initLogitechGProSuperlightMouseXHCI, mouseLogitechGProSuperlightDriverTdCheck },
54 | #endif
55 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO
56 | { initLogitechGProMouseXHCI, mouseLogitechGProDriverTdCheck },
57 | #endif
58 | };
59 |
60 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/hermes/README.md:
--------------------------------------------------------------------------------
1 | # Hermes implementation
2 | This is a example implementation of our previous Hermes project.
3 | Hermes allows us to communicate with SMM over a shared memory buffer. This way we can send commands to SMM that should be executed with those privileges.
4 | For the implementation, see [hermes.c](hermes.c).
5 |
6 | ## Features
7 | We have added all commands of the Hermes project, see the following list:
8 | | Command | Description | Input | Output |
9 | |---|---|---|---|
10 | | gd | Returns the directory base of the requested process | Process name | Directory Base |
11 | | gmd | Returns essential information of the requested module in a process | Process name & Module name | Module name & Size |
12 | | gm | Returns all module names of the requested process | Process name | Name of every module in a process |
13 | | vr | Reads the memory at the requested virtual memory address | Source Virtual address, Directory Base & Size | Memory read at the address |
14 | | vw | Writes the supplied integer to the requested virtual memory address | Destination Virtual address, Directory Base, Size & Value | - |
15 | | pr | Reads the memory at the requested physical memory address | Source Physical address, Directory Base & Size | Memory read at the address |
16 | | pw | Writes the supplied integer to the requested physical memory address | Destination Physical address, Directory Base, Size & Value | - |
17 | | vto | Converts a virtual memory address to physical | Source Virtual address & Directory Base | Converted Physical address |
18 | | dm | Dumps the requested memory area | Source Virtual address, Directory Base, Size & File name | Memory read is written into the file |
19 | | exit | Exits the client process | - | - |
20 | | help | Displays the help about the commands | - | - |
21 |
22 | ### Client module
23 | If interested in using Hermes, please see the [Hermes project repository](https://github.com/pRain1337/hermes) for how to compile the client binary.
24 |
25 | ## How to use
26 | Install the Plouton SMM module on your motherboard and boot the system with it.
27 | Check the serial output to verify if it initialized as expected.
28 | Start the Hermes client binary with the name "hermes.exe" and verify if communication works by getting the dirbase of Hermes itself.
29 | For this, enter `gd` and then the process name `hermes.exe`, this should return the directory base of the hermes process itself.
30 | Afterwards you can use all other commands mentioned in the above chapter.
31 |
--------------------------------------------------------------------------------
/PloutonLogViewer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Security.Principal;
4 | using System.Windows;
5 |
6 | namespace PloutonLogViewer
7 | {
8 | ///
9 | /// Interaction logic for App.xaml
10 | ///
11 | public partial class App : Application
12 | {
13 | public App()
14 | {
15 | this.DispatcherUnhandledException += App_DispatcherUnhandledException;
16 | }
17 |
18 | protected override void OnStartup(StartupEventArgs e)
19 | {
20 | base.OnStartup(e);
21 |
22 | var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
23 | if (!principal.IsInRole(WindowsBuiltInRole.Administrator))
24 | {
25 | try
26 | {
27 | var exeName = Process.GetCurrentProcess().MainModule?.FileName;
28 | if (exeName != null)
29 | {
30 | var startInfo = new ProcessStartInfo(exeName)
31 | {
32 | Verb = "runas",
33 | UseShellExecute = true
34 | };
35 | Process.Start(startInfo);
36 | }
37 | }
38 | catch (Exception ex)
39 | {
40 | MessageBox.Show("This application requires administrator privileges. Please right-click the application and select 'Run as administrator'.\n\nFailed to restart automatically:\n" + ex.Message, "Administrator Privileges Required", MessageBoxButton.OK, MessageBoxImage.Error);
41 | }
42 |
43 | Application.Current.Shutdown();
44 | return;
45 | }
46 | }
47 |
48 | void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
49 | {
50 | // Create a formatted error message
51 | string errorMessage = $"An unhandled exception occurred: \n\n{e.Exception.Message}\n\nStack Trace:\n{e.Exception.StackTrace}";
52 |
53 | // Show the error in a message box
54 | MessageBox.Show(errorMessage, "Fatal Error", MessageBoxButton.OK, MessageBoxImage.Error);
55 |
56 | // Mark the exception as handled to prevent the application from closing immediately
57 | e.Handled = true;
58 |
59 | // Optionally, shut down the application
60 | Application.Current.Shutdown();
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/string.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for string/memory related functions
4 | *
5 | --*/
6 |
7 | #ifdef __GNUC__
8 | #pragma GCC diagnostic push
9 | #pragma GCC diagnostic ignored "-Wunknown-pragmas"
10 | #endif
11 |
12 | // our includes
13 | #include "string.h"
14 |
15 | /*
16 | * Function: toLower
17 | * --------------------
18 | * Converts the given char to lowercase, used for string comparisons.
19 | *
20 | * c: Char to convert to lowercase
21 | *
22 | * returns:
23 | *
24 | * Credits to: https://github.com/Oliver-1-1/SmmInfect/blob/main/SmmInfect/string.c#L3
25 | *
26 | */
27 | INT32 toLower(INT32 c)
28 | {
29 | return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
30 | }
31 |
32 | /*
33 | * Function: strcmp
34 | * --------------------
35 | * Compares two strings and returns the location of the difference.
36 | *
37 | * str1: Pointer to string number one
38 | * str2: Pointer to string number two
39 | *
40 | * returns: Where a difference happened. 0 if no difference.
41 | *
42 | */
43 | INT32 strcmp(const CHAR8* str1, const CHAR8* str2)
44 | {
45 | // Increase both string positions and check if they are the same
46 | for (; toLower(*str1) == toLower(*str2); ++str1, ++str2)
47 | // Check if string one has already ended -> comparison complete with no difference, return 0
48 | if (*str1 == 0)
49 | return 0;
50 |
51 | // For loop ended before null-terminator of string one was reached, return the relative position of the difference
52 | return *(UINT8*)str1 < *(UINT8*)str2 ? -1 : 1;
53 | }
54 |
55 | // Disable optimizations so it doesnt get replaced by memset
56 | #pragma optimize("", off)
57 |
58 | /*
59 | * Function: nullBuffer
60 | * --------------------
61 | * Compares two strings and returns the location of the difference.
62 | *
63 | * buffer: UINT64 Pointer to a memory buffer that should be nulled
64 | * size: UINT16 size of the memory buffer
65 | *
66 | * returns: Nothing.
67 | *
68 | */
69 | void nullBuffer(EFI_PHYSICAL_ADDRESS buffer, UINT16 size)
70 | {
71 | UINT8* pListChar = (UINT8*)buffer;
72 | for (int i = 0; i < size; i++)
73 | {
74 | // Null each byte
75 | pListChar[i] = 0;
76 | }
77 | }
78 |
79 | // Enable optimizations again
80 | #pragma optimize("", on)
81 |
82 | /*
83 | * Function: strlen
84 | * --------------------
85 | * Gets the length of an ASCII string
86 | *
87 | * str: input string
88 | *
89 | * returns: Length of the input string.
90 | *
91 | */
92 | UINT32 strlen(const char* str)
93 | {
94 | const char* orig = str;
95 | while(*(str++));
96 | return (size_t)(str - orig - 1);
97 | }
98 |
99 |
100 | #ifdef __GNUC__
101 | #pragma GCC diagnostic pop
102 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/logging/logging.h:
--------------------------------------------------------------------------------
1 | #ifndef __plouton_logging_h__
2 | #define __plouton_logging_h__
3 |
4 | #include "log_levels.h"
5 | #include "../hardware/serial.h"
6 | #include "../general/config.h"
7 |
8 | #if ENABLE_MEMORY_LOG
9 | #include "memory_log.h"
10 | #endif
11 |
12 | // color code definition: https://xdevs.com/guide/color_serial/
13 |
14 | #if ENABLE_MEMORY_LOG
15 | #define LOG_ERROR(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_ERROR) { SerialPrintf("\033[0;31m(E) " fmt "\033[0;39;49m", ##__VA_ARGS__); MemoryLogPrintEx(1, "(E) " fmt, ##__VA_ARGS__); } } while (0)
16 | #define LOG_INFO(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_INFO) { SerialPrintf("\033[1;33m(I) " fmt "\033[0;39;49m", ##__VA_ARGS__); MemoryLogPrintEx(2, "(I) " fmt, ##__VA_ARGS__); } } while (0)
17 | #define LOG_VERB(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_VERB) { SerialPrintf("\033[0;32m(V) " fmt "\033[0;39;49m", ##__VA_ARGS__); MemoryLogPrintEx(3, "(V) " fmt, ##__VA_ARGS__); } } while (0)
18 | #define LOG_DBG(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_DBG) { SerialPrintf("\033[0;37m(D) " fmt "\033[0;39;49m", ##__VA_ARGS__); MemoryLogPrintEx(4, "(D) " fmt, ##__VA_ARGS__); } } while (0)
19 | #else
20 | #define LOG_ERROR(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_ERROR) SerialPrintf("\033[0;31m(E) " fmt "\033[0;39;49m", ##__VA_ARGS__); } while (0)
21 | #define LOG_INFO(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_INFO) SerialPrintf("\033[1;33m(I) " fmt "\033[0;39;49m", ##__VA_ARGS__); } while (0)
22 | #define LOG_VERB(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_VERB) SerialPrintf("\033[0;32m(V) " fmt "\033[0;39;49m", ##__VA_ARGS__); } while (0)
23 | #define LOG_DBG(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_DBG) SerialPrintf("\033[0;37m(D) " fmt "\033[0;39;49m", ##__VA_ARGS__); } while (0)
24 | #endif
25 |
26 | /* non color coded variant
27 |
28 | #define LOG_ERROR(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_ERROR) SerialPrintf("[ERR] " fmt, ##__VA_ARGS__); } while (0)
29 | #define LOG_INFO(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_INFO) SerialPrintf("[INF] " fmt, ##__VA_ARGS__); } while (0)
30 | #define LOG_VERB(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_VERB) SerialPrintf("[VRB] " fmt, ##__VA_ARGS__); } while (0)
31 | #define LOG_DBG(fmt, ...) do { if (SERIAL_DEBUG_LEVEL >= LOG_LEVEL_DBG) SerialPrintf("[DBG] " fmt, ##__VA_ARGS__); } while (0)
32 |
33 | */
34 |
35 | /* To overwrite log levels in a function
36 | *
37 | * First undefine the current loglevel, then set the log level you want:
38 | *
39 | * #undef SERIAL_DEBUG_LEVEL
40 | * #define SERIAL_DEBUG_LEVEL LOG_LEVEL_INFO
41 | *
42 | * When finished, do the same and reset the log level:
43 | *
44 | * #undef SERIAL_DEBUG_LEVEL
45 | * #define SERIAL_DEBUG_LEVEL LOG_LEVEL_ERROR
46 | *
47 | * */
48 |
49 | #endif
--------------------------------------------------------------------------------
/PloutonLogViewer/Resources/StringResources.zh-CN.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Plouton 日志查看器
7 | Plouton 日志查看器
8 | 日志缓冲区物理地址:
9 | 获取地址
10 | 状态:
11 | 开始
12 | 暂停
13 | 清空
14 | 语言:
15 |
16 |
17 | 未开始。
18 | 地址不是有效的64位十六进制值。
19 | 正在获取地址...
20 | 成功获取地址:
21 | 获取地址失败,RwDrv.sys(RWEverything)未找到或加载失败。
22 | 读取内存失败。
23 | 监控中...
24 | 已暂停。
25 | 复制到剪贴板失败。
26 | 启用 SeSystemEnvironmentPrivilege 失败,请以管理员身份运行。
27 | 未找到 UEFI 变量 'PloutonLogAddress',SMM 模块是否运行?
28 | UEFI 变量错误 ({0}): {1}
29 | UEFI 变量大小不匹配。预期大小 {1},实际大小 {0}。
30 | 驱动错误
31 | 读写器未初始化。请输入有效地址并开始。
32 | 正在读取日志...
33 | 获取地址的脚本已复制到剪贴板。
34 | 获取地址失败。详见状态信息。
35 |
36 |
37 | 复制
38 | 全部复制
39 | 另存为...
40 | 日志另存为
41 | 全部日志已复制到剪贴板。
42 | 日志已保存至 {0}。
43 | 保存日志文件失败
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/corsair_wireless.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_CORSAIR_WIRELESS
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initCorsairWirelessAudioXHCI
11 | * --------------------
12 | * Tries to initialize the audio driver for the Corsair Wireless Headset.
13 | *
14 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
15 | *
16 | * returns: The audioProfile struct, initialized set As TRUE if it was found
17 | *
18 | */
19 | audioProfile_t initCorsairWirelessAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
20 | {
21 | // This implementation is based on the following documents:
22 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
23 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
24 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
25 |
26 | audioProfile_t ret = { 0, 0 };
27 |
28 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
29 | // Check if we got a valid MBAR
30 | if (MBAR == 0)
31 | {
32 | LOG_ERROR("[XHC] Failed MBAR\r\n");
33 |
34 | // Return 0 to indicate failure
35 | return ret;
36 | }
37 |
38 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
39 |
40 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
41 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
42 |
43 | // Check if we got a valid DCAB
44 | if (DCAB == 0)
45 | {
46 | LOG_ERROR("[XHC] Failed DCAB\r\n");
47 |
48 | // Return 0 to indicate failure
49 | return ret;
50 | }
51 |
52 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
53 |
54 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
55 | // - Endpoint Context Field - offset 0x04, size 32-bit
56 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
57 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
58 | //
59 | // - Endpoint Context Field - offset 0x10, size 32-bit
60 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
61 |
62 | // Check for Hyper X Cloud 2 Headset
63 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0xC0, 0x60, TRUE, NULL); // Hardcoded for now
64 |
65 | if (ret.audioRingLocation == 0)
66 | {
67 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
68 | return ret;
69 | }
70 |
71 | LOG_VERB("[XHC] Found Audio lxw: %x\r\n", ret.audioRingLocation);
72 |
73 | ret.audioChannels = 16;
74 | ret.initialized = TRUE;
75 |
76 | return ret;
77 | }
78 |
79 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/creative_usb_speakers.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_CREATIVE_USB_SPEAKERS
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initCreativeUsbSpeakersAudioXHCI
11 | * --------------------
12 | * Tries to initialize the audio driver for the Creative USB speakers.
13 | *
14 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
15 | *
16 | * returns: The audioProfile struct, initialized set As TRUE if it was found
17 | *
18 | */
19 | audioProfile_t initCreativeUsbSpeakersAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
20 | {
21 | // This implementation is based on the following documents:
22 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
23 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
24 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
25 |
26 | audioProfile_t ret = { 0, 0 };
27 |
28 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
29 | // Check if we got a valid MBAR
30 | if (MBAR == 0)
31 | {
32 | LOG_ERROR("[XHC] Failed MBAR\r\n");
33 |
34 | // Return 0 to indicate failure
35 | return ret;
36 | }
37 |
38 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
39 |
40 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
41 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
42 |
43 | // Check if we got a valid DCAB
44 | if (DCAB == 0)
45 | {
46 | LOG_ERROR("[XHC] Failed DCAB\r\n");
47 |
48 | // Return 0 to indicate failure
49 | return ret;
50 | }
51 |
52 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
53 |
54 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
55 | // - Endpoint Context Field - offset 0x04, size 32-bit
56 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
57 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
58 | //
59 | // - Endpoint Context Field - offset 0x10, size 32-bit
60 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
61 |
62 | // Check for Creative USB Speakers
63 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0xC0, 0x60, TRUE, NULL); // Hardcoded for now
64 |
65 | if (ret.audioRingLocation == 0)
66 | {
67 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
68 | return ret;
69 | }
70 |
71 | LOG_VERB("[XHC] Found Audio lxw: %x\r\n", ret.audioRingLocation);
72 |
73 | ret.audioChannels = 8;
74 | ret.initialized = TRUE;
75 |
76 | return ret;
77 | }
78 |
79 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/logitech_g_pro_x_wireless.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_WIRELESS
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initLogitechGProXAudioXHCI
11 | * --------------------
12 | * Tries to initialize the audio driver for the Logitech G Pro X headset.
13 | *
14 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
15 | *
16 | * returns: The audioProfile struct, initialized set As TRUE if it was found
17 | *
18 | */
19 | audioProfile_t initLogitechGProXAudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
20 | {
21 | // This implementation is based on the following documents:
22 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
23 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
24 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
25 |
26 | audioProfile_t ret = { 0, 0 };
27 |
28 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
29 | // Check if we got a valid MBAR
30 | if (MBAR == 0)
31 | {
32 | LOG_ERROR("[XHC] Failed MBAR\r\n");
33 |
34 | // Return 0 to indicate failure
35 | return ret;
36 | }
37 |
38 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
39 |
40 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
41 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
42 |
43 | // Check if we got a valid DCAB
44 | if (DCAB == 0)
45 | {
46 | LOG_ERROR("[XHC] Failed DCAB\r\n");
47 |
48 | // Return 0 to indicate failure
49 | return ret;
50 | }
51 |
52 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
53 |
54 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
55 | // - Endpoint Context Field - offset 0x04, size 32-bit
56 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
57 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
58 | //
59 | // - Endpoint Context Field - offset 0x10, size 32-bit
60 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
61 |
62 | // Check for Logitech G Pro X Wireless Headset
63 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0x120, 0x90, TRUE, NULL); // Hardcoded for now
64 |
65 | if (ret.audioRingLocation == 0)
66 | {
67 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
68 | return ret;
69 | }
70 |
71 | LOG_VERB("[XHC] Found Audio lxw: %x\r\n", ret.audioRingLocation);
72 |
73 | ret.audioChannels = 8;
74 | ret.initialized = TRUE;
75 |
76 | return ret;
77 | }
78 |
79 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/logitech_g_pro_x_2_wireless.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_LOGITECH_G_PRO_X_2_WIRELESS
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initLogitechGProX2AudioXHCI
11 | * --------------------
12 | * Tries to initialize the audio driver for the Logitech G Pro X 2 headset.
13 | *
14 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
15 | *
16 | * returns: The audioProfile struct, initialized set As TRUE if it was found
17 | *
18 | */
19 | audioProfile_t initLogitechGProX2AudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
20 | {
21 | // This implementation is based on the following documents:
22 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
23 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
24 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
25 |
26 | audioProfile_t ret = { 0, 0 };
27 |
28 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
29 | // Check if we got a valid MBAR
30 | if (MBAR == 0)
31 | {
32 | LOG_ERROR("[XHC] Failed MBAR\r\n");
33 |
34 | // Return 0 to indicate failure
35 | return ret;
36 | }
37 |
38 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
39 |
40 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
41 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
42 |
43 | // Check if we got a valid DCAB
44 | if (DCAB == 0)
45 | {
46 | LOG_ERROR("[XHC] Failed DCAB\r\n");
47 |
48 | // Return 0 to indicate failure
49 | return ret;
50 | }
51 |
52 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
53 |
54 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
55 | // - Endpoint Context Field - offset 0x04, size 32-bit
56 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
57 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
58 | //
59 | // - Endpoint Context Field - offset 0x10, size 32-bit
60 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
61 |
62 | // Check for Logitech G Pro X 2 Wireless Headset
63 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0xC0, 0x60, TRUE, NULL); // Hardcoded for now
64 |
65 | if (ret.audioRingLocation == 0)
66 | {
67 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
68 | return ret;
69 | }
70 |
71 | LOG_VERB("[XHC] Found Audio lxw: %x\r\n", ret.audioRingLocation);
72 |
73 | ret.audioChannels = 8;
74 | ret.initialized = TRUE;
75 |
76 | return ret;
77 | }
78 |
79 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/cs2/offsetsCS2.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for offsets required for cs2 cheat
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_offsets_cs2_h__
8 | #define __plouton_offsets_cs2_h__
9 |
10 | #ifdef __GNUC__
11 | #pragma GCC diagnostic push
12 | #pragma GCC diagnostic ignored "-Wunused-variable"
13 | #endif
14 |
15 | // Structures
16 |
17 | // Definitions
18 |
19 | // Signatures
20 | static const char* sig_dwEntityList = "48 89 35 ? ? ? ? 48 85 F6";
21 | static const char* sig_dwLocalPlayerController = "48 89 05 ? ? ? ? 8B 9E";
22 | static const char* sig_dwCSInput = "48 8B 0D ? ? ? ? 48 8B 01 FF 50 ? 8B DF";
23 |
24 | // Hardcoded offsets
25 | /* --- https://github.com/a2x/cs2-dumper/blob/main/generated/client.dll.hpp --- */
26 | static UINT64 ofs_m_pGameSceneNode = 0x328; // C_BaseEntity -> m_pGameSceneNode
27 | static UINT64 ofs_m_iHealth = 0x344; // C_BaseEntity -> m_iHealth
28 | static UINT64 ofs_m_iTeamNum = 0x3E3; // C_BaseEntity -> m_iTeamNum
29 | static UINT64 ofs_m_vecVelocity = 0x400; // C_BaseEntity -> m_vecVelocity
30 |
31 | static UINT64 ofs_m_bPawnIsAlive = 0x82C; // CCSPlayerController -> m_bPawnIsAlive
32 |
33 | static UINT64 ofs_m_pClippingWeapon = 0x13A0; // C_CSPlayerPawnBase -> m_pClippingWeapon
34 | static UINT64 ofs_m_bGunGameImmunity = 0x13BC; // C_CSPlayerPawnBase -> m_bGunGameImmunity
35 | static UINT64 ofs_m_angEyeAngles = 0x1438; // C_CSPlayerPawnBase -> m_angEyeAngles
36 | static UINT64 ofs_m_iIDEntIndex = 0x1458; // C_CSPlayerPawnBase -> m_iIDEntIndex
37 | static UINT64 ofs_m_entitySpottedState = 0x23D0; // C_CSPlayerPawn -> m_entitySpottedState
38 |
39 | static UINT64 ofs_m_iClip1 = 0x1678; // C_BasePlayerWeapon -> m_iClip1
40 | static UINT64 ofs_m_AttributeManager = 0x1148; // C_EconEntity -> m_AttributeManager
41 | static UINT64 ofs_m_Item = 0x50; // C_AttributeContainer -> m_Item
42 | static UINT64 ofs_m_iItemDefinitionIndex = 0x1BA; // C_EconItemView -> m_iItemDefinitionIndex
43 | static UINT64 ofs_m_aimPunchCache = 0x15A8; // C_CSPlayerPawn -> m_aimPunchCache
44 | static UINT64 ofs_m_modelState = 0x170; // CSkeletonInstance -> m_modelState
45 | static UINT64 ofs_m_bSpottedByMask = 0xC; // EntitySpottedState_t -> m_bSpottedByMask
46 | static UINT64 ofs_m_vecAbsOrigin = 0xD0; // CGameSceneNode -> m_vecAbsOrigin
47 | static UINT64 ofs_m_hPawn = 0x62C; // CBasePlayerController -> m_hPawn
48 | static UINT64 ofs_m_vecViewOffset = 0xCB0; // C_BaseModelEntity -> m_vecViewOffset
49 |
50 | /* --- Hardcoded gift from kidua ---
51 | *
52 | * Found in the function that passes the csinput ptr
53 | * Pattern: E8 ? ? ? ? EB 0E 48 8B 01
54 | *
55 | */
56 | static UINT64 ofs_viewAngles = 0x3D0;
57 |
58 | // Functions
59 |
60 | #ifdef __GNUC__
61 | #pragma GCC diagnostic pop
62 | #endif
63 |
64 | #endif
--------------------------------------------------------------------------------
/PloutonLogViewer/Resources/StringResources.en-US.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Plouton Log Viewer
7 | Plouton Log Viewer
8 | Log buffer physical address:
9 | Get Address
10 | Status:
11 | Start
12 | Pause
13 | Clear
14 | Language:
15 |
16 |
17 | Not started.
18 | Address is not a valid 64-bit hexadecimal value.
19 | Getting address...
20 | Successfully obtained address:
21 | Failed to get address. RwDrv.sys (RWEverything) not found or failed to load.
22 | Failed to read memory.
23 | Monitoring...
24 | Paused.
25 | Failed to copy to clipboard.
26 | Failed to enable SeSystemEnvironmentPrivilege. Please run as Administrator.
27 | UEFI variable 'PloutonLogAddress' not found. Is the SMM module running?
28 | UEFI variable error ({0}): {1}
29 | UEFI variable size mismatch. Expected {1}, got {0}.
30 | Driver Error
31 | Reader not initialized. Please enter a valid address and start.
32 | Reading logs...
33 | Address script copied to clipboard.
34 | Failed to get address. See status for details.
35 |
36 |
37 | Copy
38 | Copy All
39 | Save As...
40 | Save Log As
41 | All logs copied to clipboard.
42 | Log saved to {0}.
43 | Failed to save log file
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/audio/hyperx_cloud_2.c:
--------------------------------------------------------------------------------
1 | #include "audioDriver.h"
2 |
3 | #ifdef AUDIO_DRIVER_HYPERX_CLOUD_2
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initHyperXCloud2AudioXHCI
11 | * --------------------
12 | * Tries to initialize the audio driver for the Hyper X Cloud 2 headset.
13 | *
14 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
15 | *
16 | * returns: The audioProfile struct, initialized set As TRUE if it was found
17 | *
18 | */
19 | audioProfile_t initHyperXCloud2AudioXHCI(EFI_PHYSICAL_ADDRESS MBAR)
20 | {
21 | // This implementation is based on the following documents:
22 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
23 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
24 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
25 |
26 | audioProfile_t ret = { 0, 0 };
27 |
28 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
29 | // Check if we got a valid MBAR
30 | if (MBAR == 0)
31 | {
32 | LOG_ERROR("[XHC] Failed MBAR\r\n");
33 |
34 | // Return 0 to indicate failure
35 | return ret;
36 | }
37 |
38 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
39 |
40 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
41 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
42 |
43 | // Check if we got a valid DCAB
44 | if (DCAB == 0)
45 | {
46 | LOG_ERROR("[XHC] Failed DCAB\r\n");
47 |
48 | // Return 0 to indicate failure
49 | return ret;
50 | }
51 |
52 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
53 |
54 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
55 | // - Endpoint Context Field - offset 0x04, size 32-bit
56 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
57 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
58 | //
59 | // - Endpoint Context Field - offset 0x10, size 32-bit
60 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
61 |
62 | // Check for Hyper X Cloud 2 Headset
63 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0xC0, 0x60, TRUE, NULL); // Hardcoded for now
64 |
65 | if (ret.audioRingLocation == 0)
66 | {
67 | // Another possibility
68 | ret.audioRingLocation = getEndpointRing(DCAB, 1, 0x20, 0x90, TRUE, NULL); // Hardcoded for now
69 |
70 | if (ret.audioRingLocation == 0)
71 | {
72 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
73 | return ret;
74 | }
75 | }
76 |
77 | LOG_VERB("[XHC] Found Audio lxw: %x\r\n", ret.audioRingLocation);
78 |
79 | ret.audioChannels = 8;
80 | ret.initialized = TRUE;
81 |
82 | return ret;
83 | }
84 |
85 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/xhci.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for XHCI manipulation related functions
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_xhci_h__
8 | #define __plouton_xhci_h__
9 |
10 | // our includes
11 | #include "../target/cs2/structuresCS2.h"
12 | #include "../memory/memory.h"
13 | #include "../memory/string.h"
14 | #include "../hardware/serial.h"
15 | #include "../general/config.h"
16 | #include "mouse/mouseDriver.h"
17 |
18 | // edk2 includes
19 | #include
20 |
21 | // Structures
22 |
23 | // Definitions
24 |
25 | // Functions
26 |
27 | // - XHCI Initialization related functions
28 |
29 | /*
30 | * Function: initXHCI
31 | * --------------------
32 | * This initializes the XHCI functions by parsing the necessary structures and then finding a suitable endpoint device we want to manipulate.
33 | */
34 | BOOLEAN initXHCI();
35 |
36 | /*
37 | * Function: audioInitialized
38 | * --------------------
39 | * Tells if the audio driver is initialized.
40 | */
41 | BOOLEAN audioInitialized();
42 |
43 | /*
44 | * Function: mouseInitialized
45 | * --------------------
46 | * Tells if the mouse driver is initialized.
47 | */
48 | BOOLEAN mouseInitialized();
49 |
50 | /*
51 | * Function: getMemoryBaseAddresses
52 | * --------------------
53 | * This function finds all XHCI controllers in the system and writes it into the passed array
54 | */
55 | BOOLEAN getMemoryBaseAddresses(EFI_PHYSICAL_ADDRESS* mbars);
56 |
57 | /*
58 | * Function: getDeviceContextArrayBase
59 | * --------------------
60 | * This function returns the Device Context Array Base (DCAB) which contains all USB devices in the system.
61 | */
62 | EFI_PHYSICAL_ADDRESS getDeviceContextArrayBase(EFI_PHYSICAL_ADDRESS base);
63 |
64 | /*
65 | * Function: getEndpointRing
66 | * --------------------
67 | * This function finds a specific endpoint of a device by searching for specific specifications.
68 | */
69 | EFI_PHYSICAL_ADDRESS getEndpointRing(EFI_PHYSICAL_ADDRESS DCAB, UINT16 contextType, UINT16 contextPacketsize, UINT16 contextAveragetrblength, BOOLEAN isAudio, MouseDriverTdCheck MouseDriverTdCheckFun);
70 |
71 | // - Manipulation related functions
72 |
73 | /*
74 | * Function: MoveMouseXHCI
75 | * --------------------
76 | * This function modifies the x and y coordinates of a USB mouse HID packet.
77 | */
78 | VOID MoveMouseXHCI(INT16 x, INT16 y, BOOLEAN ignoreMax);
79 |
80 | /*
81 | * Function: WriteButtonXHCI2
82 | * --------------------
83 | * This function changes the button state in the second descriptor in a USB mouse HID packet.
84 | */
85 | VOID WriteButtonXHCI2(UINT8 button);
86 |
87 | /*
88 | * Function: WriteButtonXHCI1
89 | * --------------------
90 | * This function changes the button state in the first descriptor in a USB mouse HID packet.
91 | */
92 | VOID WriteButtonXHCI1(UINT8 button);
93 |
94 | /*
95 | * Function: GetButtonXHCI2
96 | * --------------------
97 | * This function gets the current button state from the second descriptor from a USB mouse HID packet.
98 | */
99 | UINT8 GetButtonXHCI2();
100 |
101 | /*
102 | * Function: GetButtonXHCI1
103 | * --------------------
104 | * This function gets the current button state from the first descriptor from a USB mouse HID packet.
105 | */
106 | UINT8 GetButtonXHCI1();
107 |
108 | /*
109 | * Function: BeepXHCI
110 | * --------------------
111 | * This function modifies the data in a USB audio device to produce a noticeable difference.
112 | */
113 | VOID BeepXHCI(UINT32 leftPackets, UINT32 rightPackets, UINT8 multiplication);
114 |
115 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/logging/memory_log.h:
--------------------------------------------------------------------------------
1 | #ifndef __memory_log_h__
2 | #define __memory_log_h__
3 |
4 | #include "../general/config.h"
5 |
6 | #if ENABLE_MEMORY_LOG
7 |
8 | #include
9 | #include
10 |
11 | // Memory log buffer size options
12 | #define MEM_LOG_SIZE_1MB (1024 * 1024)
13 | #define MEM_LOG_SIZE_2MB (2 * 1024 * 1024)
14 | #define MEM_LOG_SIZE_4MB (4 * 1024 * 1024)
15 | #define MEM_LOG_SIZE_8MB (8 * 1024 * 1024)
16 |
17 | // Use the configured buffer size from config.h
18 | #define MEM_LOG_BUFFER_SIZE MEMORY_LOG_BUFFER_SIZE
19 |
20 | // Memory log entry header for structured logging
21 | typedef struct {
22 | UINT32 Timestamp; // Simple timestamp counter
23 | UINT16 EntryLength; // Length of this log entry including header
24 | UINT8 LogLevel; // Log level (ERROR=1, INFO=2, VERB=3, DBG=4)
25 | UINT8 Reserved; // Reserved for alignment
26 | } MEMORY_LOG_ENTRY_HEADER;
27 |
28 | // Maximum size for a single log entry (including header)
29 | #define MAX_LOG_ENTRY_SIZE 1024
30 |
31 | // Track dropped entries (too large / no space)
32 | extern UINTN gMemoryLogDroppedEntries;
33 |
34 | /**
35 | * @brief Initializes the memory logging facility.
36 | *
37 | * This function allocates a block of physical memory to be used as a circular
38 | * buffer for log messages. The physical address of this buffer is printed to
39 | * the serial log for later inspection with tools like RW-Everything.
40 | *
41 | * @param gBS Pointer to the UEFI Boot Services Table.
42 | * @return EFI_STATUS Returns EFI_SUCCESS on successful initialization, or an error code on failure.
43 | */
44 | EFI_STATUS EFIAPI InitMemoryLog(IN EFI_BOOT_SERVICES* gBS);
45 |
46 | /**
47 | * @brief Writes a formatted string to the in-memory log buffer.
48 | *
49 | * This function takes a format string and a variable number of arguments,
50 | * formats them into a string, and writes the result to the circular memory buffer.
51 | * If the buffer is full, it wraps around to the beginning.
52 | *
53 | * @param Format A Null-terminated ASCII format string.
54 | * @param ... A variable number of arguments to format.
55 | */
56 | VOID EFIAPI MemoryLogPrint(IN CONST CHAR8* Format, ...);
57 |
58 | /**
59 | * @brief Writes a formatted string with log level to the in-memory log buffer.
60 | *
61 | * This enhanced version includes structured logging with timestamps and log levels.
62 | *
63 | * @param LogLevel The log level (1=ERROR, 2=INFO, 3=VERB, 4=DBG).
64 | * @param Format A Null-terminated ASCII format string.
65 | * @param ... A variable number of arguments to format.
66 | */
67 | VOID EFIAPI MemoryLogPrintEx(IN UINT8 LogLevel, IN CONST CHAR8* Format, ...);
68 |
69 | /**
70 | * @brief Gets current memory log statistics.
71 | *
72 | * @param TotalSize Pointer to receive total buffer size.
73 | * @param UsedSize Pointer to receive currently used size.
74 | * @param WrapCount Pointer to receive number of buffer wraps.
75 | * @param Dropped Pointer to receive number of dropped entries (optional).
76 | */
77 | VOID EFIAPI GetMemoryLogStats(OUT UINTN* TotalSize, OUT UINTN* UsedSize, OUT UINTN* WrapCount, OUT UINTN* Dropped);
78 |
79 | /**
80 | * @brief Clears the memory log buffer.
81 | */
82 | VOID EFIAPI ClearMemoryLog(VOID);
83 |
84 | #else // ENABLE_MEMORY_LOG
85 |
86 | // When memory logging is disabled, provide stub functions
87 | #define InitMemoryLog(gBS) EFI_SUCCESS
88 | #define MemoryLogPrint(Format, ...)
89 | #define MemoryLogPrintEx(LogLevel, Format, ...)
90 | #define GetMemoryLogStats(TotalSize, UsedSize, WrapCount, Dropped)
91 | #define ClearMemoryLog()
92 |
93 | #endif // ENABLE_MEMORY_LOG
94 |
95 | #endif // __memory_log_h__
96 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/memory.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for memory related functions
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_memory_h__
8 | #define __plouton_memory_h__
9 |
10 | // our includes
11 | #include "../general/config.h"
12 | #include "memoryMapUEFI.h"
13 | #include "../hardware/serial.h"
14 | #include "../os/windows/windows.h"
15 |
16 | // edk2 includes
17 | #include
18 | #include
19 |
20 |
21 | // Structures
22 |
23 | typedef struct _Cache
24 | {
25 | UINT64 vAddress;
26 | UINT64 pAddress;
27 | } Cache, *PCache;
28 |
29 | typedef struct _MapDirEntry
30 | {
31 | UINT8 length;
32 | UINT64 pointer;
33 | } MapDirEntry, *PMapDirEntry;
34 |
35 | #ifdef __GNUC__
36 | typedef UINT32 size_t;
37 | #endif
38 |
39 | // Definitions
40 |
41 | // from plouton.c
42 | extern EFI_SMM_SYSTEM_TABLE2* gSmst2;
43 |
44 | // - Size definitions
45 | #define PAGE_SIZE 0x1000
46 |
47 | // - Pagetable operations
48 | #define PT_PRESENT 0x01
49 | #define PT_RW 0x02
50 |
51 | // Functions
52 |
53 | // - Physical memory
54 |
55 | /*
56 | * Function: pMemCpy
57 | * --------------------
58 | * This function copies data with a given size from the source to a destination physical address and verifies the addresses for validity using the DXE memory map.
59 | */
60 | BOOLEAN pMemCpy(EFI_PHYSICAL_ADDRESS dest, EFI_PHYSICAL_ADDRESS src, size_t n);
61 |
62 | /*
63 | * Function: pMemCpyForce
64 | * --------------------
65 | * This function copies data with a given size from the source to a destination physical address without any verification.
66 | */
67 | BOOLEAN pMemCpyForce(EFI_PHYSICAL_ADDRESS dest, EFI_PHYSICAL_ADDRESS src, size_t n);
68 |
69 | /*
70 | * Function: IsAddressValid
71 | * --------------------
72 | * This function verifies if the given physical address exists in the currently used memory map.
73 | */
74 | BOOLEAN IsAddressValid(EFI_PHYSICAL_ADDRESS address);
75 |
76 | // - Virtual to physical translation
77 |
78 | /*
79 | * Function: VTOP
80 | * --------------------
81 | * This function translates the given virtual address using the directory base to the physical memory address.
82 | */
83 | EFI_PHYSICAL_ADDRESS VTOP(EFI_VIRTUAL_ADDRESS address, EFI_PHYSICAL_ADDRESS directoryBase);
84 |
85 | /*
86 | * Function: VTOPForce
87 | * --------------------
88 | * This function translates the given virtual address using the directory base to the physical memory address without any verification.
89 | */
90 | EFI_PHYSICAL_ADDRESS VTOPForce(EFI_VIRTUAL_ADDRESS address, EFI_PHYSICAL_ADDRESS directoryBase);
91 |
92 | /*
93 | * Function: caching
94 | * --------------------
95 | * This function is a wrapper around VTOP which introduces a simple caching library.
96 | */
97 | EFI_PHYSICAL_ADDRESS caching(EFI_VIRTUAL_ADDRESS address, EFI_PHYSICAL_ADDRESS directoryBase);
98 |
99 | /*
100 | * Function: resetCaching
101 | * --------------------
102 | * Resets the VTOP caching system.
103 | */
104 | VOID resetCaching();
105 |
106 | /*
107 | * Function: getPageTableEntry
108 | * --------------------
109 | * This function returns the given page table entry for a virtual address in the directory base.
110 | */
111 | EFI_PHYSICAL_ADDRESS getPageTableEntry(EFI_VIRTUAL_ADDRESS address, EFI_PHYSICAL_ADDRESS directoryBase);
112 |
113 | // - Virtual memory
114 |
115 | /*
116 | * Function: vMemCpy
117 | * --------------------
118 | * This function reads the memory at the given virtual address and copies it to another virtual address.
119 | */
120 | BOOLEAN vMemCpy(EFI_VIRTUAL_ADDRESS dest, EFI_VIRTUAL_ADDRESS src, size_t size, EFI_PHYSICAL_ADDRESS directoryBaseDest, EFI_PHYSICAL_ADDRESS directoryBaseSrc);
121 |
122 | /*
123 | * Function: vMemRead
124 | * --------------------
125 | * This function reads the memory at the given virtual address while performing physical memory verification.
126 | */
127 | BOOLEAN vMemRead(EFI_PHYSICAL_ADDRESS dest, EFI_VIRTUAL_ADDRESS src, size_t n, EFI_PHYSICAL_ADDRESS directoryBase);
128 |
129 | /*
130 | * Function: vMemReadForce
131 | * --------------------
132 | * This function reads the memory at the given virtual address without performing physical memory verification.
133 | */
134 | BOOLEAN vMemReadForce(EFI_PHYSICAL_ADDRESS dest, EFI_VIRTUAL_ADDRESS src, size_t n, EFI_PHYSICAL_ADDRESS directoryBase);
135 |
136 | /*
137 | * Function: vRead
138 | * --------------------
139 | * This function reads the memory at the given virtual address while performing physical memory verification and using caching in the translation process.
140 | */
141 | BOOLEAN vRead(EFI_PHYSICAL_ADDRESS dest, EFI_VIRTUAL_ADDRESS src, size_t n, EFI_PHYSICAL_ADDRESS directoryBase);
142 |
143 | /*
144 | * Function: vMemWrite
145 | * --------------------
146 | * This function writes the memory to the given virtual address while performing physical memory verification.
147 | */
148 | BOOLEAN vMemWrite(EFI_VIRTUAL_ADDRESS dest, EFI_PHYSICAL_ADDRESS src, size_t size, EFI_PHYSICAL_ADDRESS directoryBase);
149 |
150 | #endif
151 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/hermes/hermes.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for Hermes debugging toolkit
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_hermes_h__
8 | #define __plouton_hermes_h__
9 |
10 | // our includes
11 | #include "../../os/windows/windows.h"
12 | #include "../../os/windows/NTKernelTools.h"
13 | #include "../../general/config.h"
14 | #include "../../logging/logging.h"
15 |
16 | // Structures
17 |
18 | // Use 1 byte alignment to have the struct the same size everywhere
19 | #ifdef __GNUC__
20 | #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
21 | #endif
22 |
23 | #ifdef _MSC_VER
24 | #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
25 | #endif
26 |
27 | // Command Data structures
28 | typedef struct {
29 | UINT64 moduleBase;
30 | UINT64 moduleSize;
31 | } moduleData;
32 |
33 | typedef struct {
34 | UINT64 source;
35 | UINT64 dirbase;
36 | UINT64 size;
37 | } readRequest;
38 |
39 | // Commands
40 | typedef enum {
41 | HERMES_CMD_DUMMY = 0x0, // Dummy for initialization across compilers
42 | HERMES_CMD_GET_DIRBASE, // Command for reading the dirbase of a process
43 | HERMES_CMD_GET_MODULEDATA, // Command for getting information of a module of a process
44 | HERMES_CMD_READ_VIRTUAL, // Command for reading virtual memory
45 | HERMES_CMD_WRITE_VIRTUAL, // Command for writing virtual memory
46 | HERMES_CMD_READ_PHYSICAL, // Command for reading physical memory
47 | HERMES_CMD_WRITE_PHYSICAL, // Command for writing physical memory
48 | HERMES_CMD_VIRTUAL_TO_PHYSICAL, // Command for translating a virtual to a physical address
49 | HERMES_CMD_DUMP_MODULE, // Command for dumping a module (memory range)
50 | HERMES_CMD_GET_MODULES, // Command for returning all modules of a process
51 | HERMES_CMD_MAX // Amount of commands available
52 | } hermes_command_t;
53 |
54 |
55 | // Main Packet
56 | PACK(typedef struct
57 | {
58 | UINT16 begin; // Signals the start of the packet in memory
59 | UINT8 command; // Command that should be executed by smm
60 | UINT64 dataPointer; // Pointer to data that should be used by smm
61 | UINT64 resultPointer; // Pointer to the result, where smm should write
62 | UINT16 end; // Signals the end of the packet in memory
63 | }) hermes_packet;
64 |
65 | // Results
66 | typedef enum {
67 | HERMES_STATUS_DUMMY = 0x0, // Dummy for initialization across compilers
68 | HERMES_STATUS_INVALID_COMMAND, // Invalid command
69 | HERMES_STATUS_INVALID_DATA_PTR, // Invalid data pointer
70 | HERMES_STATUS_INVALID_RES_PTR, // Invalid result pointer
71 | HERMES_STATUS_INVALID_IDENTIFIERS, // Invalid identifiers
72 | HERMES_STATUS_FAIL_FIND_PROC, // Failed finding the process
73 | HERMES_STATUS_FAIL_FIND_DIRBASE, // Failed getting dirbase
74 | HERMES_STATUS_FAIL_FIND_MOD, // Failed finding the module
75 | HERMES_STATUS_FAIL_READ_MOD_BASE, // Failed reading module base
76 | HERMES_STATUS_FAIL_READ_MOD_SIZE, // Failed reading module size
77 | HERMES_STATUS_PROCNAME_TOO_LONG, // Too big process name size
78 | HERMES_STATUS_MODNAME_TOO_LONG, // Too big module name size
79 | HERMES_STATUS_FAIL_VIRT_READ, // Failed reading virtual address
80 | HERMES_STATUS_FAIL_VIRT_WRITE, // Failed writing virtual address
81 | HERMES_STATUS_INVALID_DATA_SOURCE, // Invalid data source
82 | HERMES_STATUS_INVALID_DATA_DIRBASE, // Invalid data dirbase
83 | HERMES_STATUS_INVALID_DATA_SIZE, // Invalid data size
84 | HERMES_STATUS_INVALID_DATA_DEST, // Invalid data destination
85 | HERMES_STATUS_REQ_TOO_LARGE, // Requested size is too big
86 | HERMES_STATUS_FAIL_SBUFF_VIRTW, // Failed reading source buffer for virtual write
87 | HERMES_STATUS_FAIL_ADDR_TRANSLATION, // Failed translating address
88 | HERMES_STATUS_FAIL_SBUFF_PHYSW, // Failed reading source buffer for physical write
89 | HERMES_STATUS_INVALID_MOD_BASE, // Invalid module base
90 | HERMES_STATUS_INVALID_MOD_SIZE, // Invalid module size
91 | HERMES_STATUS_FAIL_PHYS_READ, // Failed reading physical address
92 | HERMES_STATUS_FAIL_PHYS_WRITE, // Failed writing physical address
93 | HERMES_STATUS_OK, // Everything worked
94 | HERMES_STATUS_MAX // Amount of status available
95 | } hermes_status_t;
96 |
97 | // Definitions
98 |
99 | // Functions
100 |
101 | /*
102 | * Function: initializeHermes
103 | * --------------------
104 | * Initializes the bare functionality for using hermes.
105 | */
106 | BOOLEAN EFIAPI initializeHermes();
107 |
108 | /*
109 | * Function: pollCommands
110 | * --------------------
111 | * Function that will check if the Hermes process has been launched and a debug session has been initialized.
112 | */
113 | VOID EFIAPI pollCommands();
114 |
115 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/edk2-overrides/Conf/target.txt:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
3 | #
4 | # This program and the accompanying materials
5 | # are licensed and made available under the terms and conditions of the BSD License
6 | # which accompanies this distribution. The full text of the license may be found at
7 | # http://opensource.org/licenses/bsd-license.php
8 |
9 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 | #
12 | #
13 | # ALL Paths are Relative to WORKSPACE
14 |
15 | # Separate multiple LIST entries with a SINGLE SPACE character, do not use comma characters.
16 | # Un-set an option by either commenting out the line, or not setting a value.
17 |
18 | #
19 | # PROPERTY Type Use Description
20 | # ---------------- -------- -------- -----------------------------------------------------------
21 | # ACTIVE_PLATFORM Filename Recommended Specify the WORKSPACE relative Path and Filename
22 | # of the platform description file that will be used for the
23 | # build. This line is required if and only if the current
24 | # working directory does not contain one or more description
25 | # files.
26 | ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc
27 |
28 | # TARGET List Optional Zero or more of the following: DEBUG, RELEASE, NOOPT
29 | # UserDefined; separated by a space character.
30 | # If the line is missing or no value is specified, all
31 | # valid targets specified in the platform description file
32 | # will attempt to be built. The following line will build
33 | # DEBUG platform target.
34 | TARGET = RELEASE
35 |
36 | # TARGET_ARCH List Optional What kind of architecture is the binary being target for.
37 | # One, or more, of the following, IA32, IPF, X64, EBC, ARM
38 | # or AArch64.
39 | # Multiple values can be specified on a single line, using
40 | # space charaters to separate the values. These are used
41 | # during the parsing of a platform description file,
42 | # restricting the build output target(s.)
43 | # The Build Target ARCH is determined by (precedence high to low):
44 | # Command-line: -a ARCH option
45 | # target.txt: TARGET_ARCH values
46 | # DSC file: [Defines] SUPPORTED_ARCHITECTURES tag
47 | # If not specified, then all valid architectures specified
48 | # in the platform file, for which tools are available, will be
49 | # built.
50 | TARGET_ARCH = X64
51 |
52 | # TOOL_DEFINITION_FILE Filename Optional Specify the name of the filename to use for specifying
53 | # the tools to use for the build. If not specified,
54 | # WORKSPACE/Conf/tools_def.txt will be used for the build.
55 | TOOL_CHAIN_CONF = Conf/tools_def.txt
56 |
57 | # TAGNAME List Optional Specify the name(s) of the tools_def.txt TagName to use.
58 | # If not specified, all applicable TagName tools will be
59 | # used for the build. The list uses space character separation.
60 | TOOL_CHAIN_TAG = GCC5
61 |
62 | # MAX_CONCURRENT_THREAD_NUMBER NUMBER Optional The number of concurrent threads. If not specified or set
63 | # to zero, tool automatically detect number of processor
64 | # threads. Recommend to set this value to one less than the
65 | # number of your computer cores or CPUs. When value set to 1,
66 | # means disable multi-thread build, value set to more than 1,
67 | # means user specify the thread number to build. Not specify
68 | # the default value in this file.
69 | # MAX_CONCURRENT_THREAD_NUMBER = 1
70 |
71 |
72 | # BUILD_RULE_CONF Filename Optional Specify the file name to use for the build rules that are followed
73 | # when generating Makefiles. If not specified, the file:
74 | # WORKSPACE/Conf/build_rule.txt will be used
75 | BUILD_RULE_CONF = Conf/build_rule.txt
76 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/os/windows/NTKernelTools.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for windows NT Kernel parsing and analysis
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_ntkernel_h__
8 | #define __plouton_ntkernel_h__
9 |
10 | // our includes
11 | #include "windows.h"
12 | #include "../../memory/string.h"
13 | #include "../../memory/memoryMapUEFI.h"
14 | #include "../../memory/memory.h"
15 | #include "../../general/config.h"
16 | #include "../../logging/logging.h"
17 |
18 | // Global variables we want to export
19 | extern WinCtx* winGlobal;
20 | extern BOOLEAN setupWindows;
21 |
22 | /*
23 | * source for general structure:
24 | * https://github.com/Heep042/vmread
25 | */
26 |
27 | // Structures
28 |
29 | // Definitions
30 |
31 | // from plouton.c
32 | extern EFI_SMM_SYSTEM_TABLE2* gSmst2;
33 |
34 | // Functions
35 |
36 | /*
37 | * Function: getPML4
38 | * --------------------
39 | * Locates the kernel directory base, kernel entry by parsing the first 0x100 pages in memory.
40 | */
41 | BOOLEAN getPML4(EFI_PHYSICAL_ADDRESS* PML4, EFI_VIRTUAL_ADDRESS* kernelEntry);
42 |
43 | /*
44 | * Function: findNtosKrnl
45 | * --------------------
46 | * Locates the NT Kernel base which will be used to later locate the process list.
47 | */
48 | BOOLEAN findNtosKrnl(EFI_VIRTUAL_ADDRESS kernelEntry, EFI_PHYSICAL_ADDRESS PML4, EFI_VIRTUAL_ADDRESS* ntKernel);
49 |
50 | /*
51 | * Function: getExportList
52 | * --------------------
53 | * Finds the export table of the passed memory address and returns the pointer to the export passed as string.
54 | */
55 | EFI_VIRTUAL_ADDRESS getExportList(EFI_VIRTUAL_ADDRESS moduleBase, EFI_PHYSICAL_ADDRESS directoryBase, const char* exportName);
56 |
57 | /*
58 | * Function: getNTHeader
59 | * --------------------
60 | * Gets the header of the passed memory base and indicates if it is 64 or 32 bit.
61 | */
62 | IMAGE_NT_HEADERS* getNTHeader(EFI_VIRTUAL_ADDRESS moduleBase, EFI_PHYSICAL_ADDRESS directoryBase, UINT8* header, UINT8* is64Bit);
63 |
64 | /*
65 | * Function: parseExportTable
66 | * --------------------
67 | * Parses the given export table to search for the given function name.
68 | */
69 | EFI_VIRTUAL_ADDRESS parseExportTable(EFI_VIRTUAL_ADDRESS moduleBase, EFI_PHYSICAL_ADDRESS directoryBase, const IMAGE_DATA_DIRECTORY* exports, const char* exportName);
70 |
71 | /*
72 | * Function: getNTVersion
73 | * --------------------
74 | * Extracts the NT version of the running NT kernel.
75 | */
76 | UINT16 getNTVersion(EFI_VIRTUAL_ADDRESS moduleBase, EFI_PHYSICAL_ADDRESS directoryBase);
77 |
78 | /*
79 | * Function: getNTBuild
80 | * --------------------
81 | * Extracts the NT build of the running NT kernel.
82 | */
83 | UINT16 getNTBuild(EFI_VIRTUAL_ADDRESS moduleBase, EFI_PHYSICAL_ADDRESS directoryBase);
84 |
85 | /*
86 | * Function: setupOffsets
87 | * --------------------
88 | * Initializes the offset set which will be used in the other functions.
89 | */
90 | BOOLEAN setupOffsets(UINT16 NTVersion, UINT16 NTBuild, WinOffsets* winOffsets);
91 |
92 | /*
93 | * Function: findProcess
94 | * --------------------
95 | * Searches in the process list if the process with the name that was requested exists.
96 | */
97 | EFI_PHYSICAL_ADDRESS findProcess(WinCtx* ctx, const char* processname);
98 |
99 | /*
100 | * Function: dumpSingleProcess
101 | * --------------------
102 | * Searches in the process list for a process with the requested name and extracts important pointers from it.
103 | */
104 | BOOLEAN dumpSingleProcess(const WinCtx* ctx, const char* processname, WinProc* process);
105 |
106 | /*
107 | * Function: GetPeb
108 | * --------------------
109 | * Dumps the 64 bit process environment block (PEB) of the given process.
110 | */
111 | PEB GetPeb(const WinCtx* ctx, const WinProc* process);
112 |
113 | /*
114 | * Function: GetPeb32
115 | * --------------------
116 | * Dumps the 32 bit process environment block (PEB) of the given process.
117 | */
118 | PEB32 GetPeb32(const WinCtx* ctx, const WinProc* process);
119 |
120 | /*
121 | * Function: fillModuleList64
122 | * --------------------
123 | * Dumps the 64 bit module list of the given process in a list and writes specific of one module into the passed strct.
124 | */
125 | BOOLEAN fillModuleList64(const WinCtx* ctx, const WinProc* Process, WinModule* Module, BOOLEAN* x86, EFI_PHYSICAL_ADDRESS moduleList, UINT8* moduleListCount);
126 |
127 | /*
128 | * Function: fillModuleList86
129 | * --------------------
130 | * Dumps the 32 bit module list of the given process in a list and writes specific of one module into the passed strct.
131 | */
132 | BOOLEAN fillModuleList86(const WinCtx* ctx, const WinProc* Process, WinModule* Module, EFI_PHYSICAL_ADDRESS moduleList, UINT8* moduleListCount);
133 |
134 | /*
135 | * Function: dumpSingleModule
136 | * --------------------
137 | * Dumps all modules of the given process based on the architecture of the process.
138 | */
139 | BOOLEAN dumpSingleModule(const WinCtx* ctx, const WinProc* process, WinModule* out_module);
140 |
141 | /*
142 | * Function: dumpModuleNames
143 | * --------------------
144 | * Dumps the modules of the given process based on the architecture of the process and returns all their names.
145 | */
146 | BOOLEAN dumpModuleNames(WinCtx* ctx, WinProc* Process, WinModule* Module, EFI_PHYSICAL_ADDRESS moduleList, UINT8* moduleListCount);
147 |
148 | /*
149 | * Function: InitGlobalWindowsContext
150 | * --------------------
151 | * Initializes the winGlobal struct which is used in the other functions and contains relevant system information.
152 | */
153 | BOOLEAN InitGlobalWindowsContext();
154 |
155 | #endif
--------------------------------------------------------------------------------
/PloutonLogViewer/PhysicalMemoryReader.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.ComponentModel;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace PloutonLogViewer
7 | {
8 | ///
9 | /// Reads physical memory using the RwDrv.sys driver from RWEverything.
10 | /// This implementation is based on the IOCTL interface using a pointer structure.
11 | ///
12 | public class PhysicalMemoryReader : IDisposable
13 | {
14 | private const uint GenericRead = 0x80000000;
15 | private const uint GenericWrite = 0x40000000;
16 | private const uint FileShareRead = 1;
17 | private const uint FileShareWrite = 2;
18 | private const uint OpenExisting = 3;
19 |
20 | ///
21 | /// IOCTL for RwDrv.sys to read a block from physical memory.
22 | ///
23 | private const uint IoctlReadPhysicalMemory = 0x222808;
24 |
25 | private SafeFileHandle _handle = null!;
26 |
27 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
28 | private static extern SafeFileHandle CreateFile(
29 | string lpFileName,
30 | uint dwDesiredAccess,
31 | uint dwShareMode,
32 | IntPtr lpSecurityAttributes,
33 | uint dwCreationDisposition,
34 | uint dwFlagsAndAttributes,
35 | IntPtr hTemplateFile);
36 |
37 | [DllImport("kernel32.dll", SetLastError = true)]
38 | private static extern bool DeviceIoControl(
39 | SafeFileHandle hDevice,
40 | uint dwIoControlCode,
41 | IntPtr lpInBuffer,
42 | uint nInBufferSize,
43 | IntPtr lpOutBuffer,
44 | uint nOutBufferSize,
45 | out uint lpBytesReturned,
46 | IntPtr lpOverlapped);
47 |
48 | ///
49 | /// The structure passed to DeviceIoControl to request a physical memory operation.
50 | /// This mirrors the PhysRw_t structure from the C++ example.
51 | ///
52 | [StructLayout(LayoutKind.Sequential)]
53 | private struct PhysicalReadWriteRequest
54 | {
55 | public ulong PhysicalAddress;
56 | public uint Size; // In units of Access. For byte read, this is the count of bytes.
57 | public uint Access; // 0 for byte, 1 for word, 2 for dword
58 | public ulong Buffer; // Pointer to the user-space buffer
59 | }
60 |
61 | public void Initialize()
62 | {
63 | // The device name for the RwDrv.sys driver.
64 | _handle = CreateFile(
65 | @"\\.\RwDrv",
66 | GenericRead | GenericWrite,
67 | FileShareRead | FileShareWrite,
68 | IntPtr.Zero,
69 | OpenExisting,
70 | 0,
71 | IntPtr.Zero);
72 |
73 | if (_handle.IsInvalid)
74 | {
75 | var errorCode = Marshal.GetLastWin32Error();
76 | throw new Win32Exception(errorCode, $"The handle of the RwDrv.sys driver cannot be opened. Please ensure that RWEverything is installed or that the RwDrv.sys driver has been successfully loaded. Error code: {errorCode}");
77 | }
78 | }
79 |
80 | ///
81 | /// Reads a block of data from physical memory into the provided buffer.
82 | ///
83 | /// The starting physical address.
84 | /// The buffer to fill with data.
85 | public void ReadPhysicalMemory(ulong address, byte[] buffer)
86 | {
87 | if (_handle == null || _handle.IsInvalid)
88 | {
89 | throw new InvalidOperationException("The driver is not initialized or the handle is invalid。");
90 | }
91 | if (buffer == null || buffer.Length == 0)
92 | {
93 | throw new ArgumentException("Buffer cannot be null or empty.", nameof(buffer));
94 | }
95 |
96 | // Pin the managed buffer in memory so the GC doesn't move it, and get its address.
97 | GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
98 | IntPtr pBuffer = pinnedBuffer.AddrOfPinnedObject();
99 |
100 | // This is the structure we send to the driver.
101 | var request = new PhysicalReadWriteRequest
102 | {
103 | PhysicalAddress = address,
104 | Access = 0, // 0 = byte access
105 | Size = (uint)buffer.Length,
106 | Buffer = (ulong)pBuffer.ToInt64()
107 | };
108 |
109 | // Allocate unmanaged memory for the request structure itself.
110 | var pRequest = Marshal.AllocHGlobal(Marshal.SizeOf());
111 |
112 | try
113 | {
114 | Marshal.StructureToPtr(request, pRequest, false);
115 |
116 | if (!DeviceIoControl(
117 | _handle,
118 | IoctlReadPhysicalMemory,
119 | pRequest,
120 | (uint)Marshal.SizeOf(),
121 | pRequest,
122 | (uint)Marshal.SizeOf(),
123 | out _,
124 | IntPtr.Zero))
125 | {
126 | var errorCode = Marshal.GetLastWin32Error();
127 | throw new Win32Exception(errorCode, $"Read the physical address 0x{address:X} Failure。Error code: {errorCode}");
128 | }
129 |
130 | // Data is read directly into our pinned `buffer`. No further action is needed.
131 | }
132 | finally
133 | {
134 | // ALWAYS free the allocated memory and unpin the handle.
135 | Marshal.FreeHGlobal(pRequest);
136 | pinnedBuffer.Free();
137 | }
138 | }
139 |
140 | public void Deinitialize()
141 | {
142 | _handle?.Dispose();
143 | }
144 |
145 | public void Dispose()
146 | {
147 | Deinitialize();
148 | GC.SuppressFinalize(this);
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/cs2/math.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for memory related functions
4 | *
5 | --*/
6 |
7 | #ifndef __aristoteles_math_cs_h__
8 | #define __aristoteles_math_cs_h__
9 |
10 | #include "../../floats/floatlib.h"
11 |
12 | // Structures
13 |
14 | // Vector which contains 4 byte arrays which represents floats
15 | typedef struct _Vector {
16 | unsigned char x[4];
17 | unsigned char y[4];
18 | unsigned char z[4];
19 | } Vector, * PVector;
20 |
21 | // 4D Vector with fix32_t values that were converted from floats
22 | typedef struct _QVector4D
23 | {
24 | fix32_t x;
25 | fix32_t y;
26 | fix32_t z;
27 | fix32_t r;
28 | } QVector4D, * PQVector4D;
29 |
30 | // Alternative vector which contains fix32_t values that were converted from floats
31 | typedef struct _QVector
32 | {
33 | fix32_t x;
34 | fix32_t y;
35 | fix32_t z;
36 | } QVector, * PQVector;
37 |
38 | // Alternative angles which contains fix32_t values that were converted from floats
39 | typedef struct _QAngle
40 | {
41 | fix32_t x;
42 | fix32_t y;
43 | fix32_t z;
44 | } QAngle, * PQAngle;
45 |
46 | // Used to get the bone position
47 | typedef struct _CTransform
48 | {
49 | QVector origin;
50 | fix32_t scale;
51 | QVector4D rotation;
52 | } CTransform, * PCTransform;
53 |
54 | typedef struct _matrix3x4
55 | {
56 | fix32_t m_flMatVal[3][4];
57 | } matrix3x4, * Pmatrix3x4;
58 |
59 |
60 | // Definitions
61 |
62 | // Functions
63 |
64 | // - General functions
65 |
66 | /*
67 | * Function: QAngleNormalize
68 | * --------------------
69 | * This function normalizes the fix32_t angles in the given vector.
70 | */
71 | VOID QAngleNormalize(PQAngle vector);
72 |
73 | /*
74 | * Function: FloatVectorToFixedVector
75 | * --------------------
76 | * This function converts the raw float data into an usable QVector with fix32_t values.
77 | */
78 | QVector FloatVectorToFixedVector(PVector vector);
79 |
80 | // - QVector functions
81 |
82 | /*
83 | * Function: QVectorMul
84 | * --------------------
85 | * This function multiples the values in the vector with the fix32_t value.
86 | */
87 | QVector QVectorMul(QVector vector, fix32_t mul);
88 |
89 | /*
90 | * Function: QVectorDiv
91 | * --------------------
92 | * This function divides the values in the vector with the fix32_t value.
93 | */
94 | QVector QVectorDiv(QVector vector, fix32_t div);
95 |
96 | /*
97 | * Function: QVectorSub
98 | * --------------------
99 | * This function substracts the second vector from the first vector.
100 | */
101 | QVector QVectorSub(QVector vector1, QVector vector2);
102 |
103 | /*
104 | * Function: QVectorAdd
105 | * --------------------
106 | * This function adds the two vectors together.
107 | */
108 | QVector QVectorAdd(QVector vector1, QVector vector2);
109 |
110 | // - QAngle functions
111 |
112 | /*
113 | * Function: QAngleMul
114 | * --------------------
115 | * This function multiplies the values in the angle with the fix32_t value.
116 | */
117 | QAngle QAngleMul(QAngle angle, fix32_t mul);
118 |
119 | /*
120 | * Function: QAngleDiv
121 | * --------------------
122 | * This function divides the values in the angle with the fix32_t value.
123 | */
124 | QAngle QAngleDiv(QAngle angle, fix32_t div);
125 |
126 | /*
127 | * Function: QAngleSub
128 | * --------------------
129 | * This function substracts the second angle from the first angle.
130 | */
131 | QAngle QAngleSub(QAngle angle1, QAngle angle2);
132 |
133 | /*
134 | * Function: QAngleAdd
135 | * --------------------
136 | * This function adds the two angles together.
137 | */
138 | QAngle QAngleAdd(QAngle angle1, QAngle angle2);
139 |
140 | // - FOV functions
141 |
142 | /*
143 | * Function: Length2D
144 | * --------------------
145 | * This function calculates the 2 dimensional length of a vector.
146 | */
147 | fix32_t Length2D(QVector vector);
148 |
149 | /*
150 | * Function: Length3D
151 | * --------------------
152 | * This function calculates the 3 dimensional length of a vector.
153 | */
154 | fix32_t Length3D(QVector vector);
155 |
156 | /*
157 | * Function: QDistanceTo
158 | * --------------------
159 | * This function calculates the distance between two 3 dimensional positions.
160 | */
161 | fix32_t QDistanceTo(QVector from, QVector to);
162 |
163 | /*
164 | * Function: GetScaledFov
165 | * --------------------
166 | * This function calculates the FOV between two angles and the distance of the position.
167 | */
168 | fix32_t GetScaledFov(QAngle viewangles, QAngle aimangles, fix32_t distance);
169 |
170 | // - Transformation functions
171 |
172 | /*
173 | * Function: AngleVectors
174 | * --------------------
175 | * This function converts the input angles into a vector.
176 | */
177 | VOID AngleVectors(PQAngle angles, PQVector forward);
178 |
179 | /*
180 | * Function: VectorAngles
181 | * --------------------
182 | * This function converts the input vector into an angle.
183 | */
184 | VOID VectorAngles(QVector forward, PQAngle angles);
185 |
186 | /*
187 | * Function: VectorTransform
188 | * --------------------
189 | * This function transforms the given vector of the hitbox into a vector position based on the matrix.
190 | */
191 | QVector VectorTransform(QVector in1, matrix3x4 in2);
192 |
193 | // - ViewAngles functions
194 |
195 | /*
196 | * Function: CalcAngle
197 | * --------------------
198 | * This function calculates the required angle change from the source to aim at the destination.
199 | */
200 | QAngle CalcAngle(QVector source, QVector destination);
201 |
202 | /*
203 | * Function: SmoothAngle
204 | * --------------------
205 | * This function calculates the smoothed angle change from the source to aim at the destination.
206 | */
207 | QAngle SmoothAngle(QAngle source, QAngle destination, fix32_t percent);
208 |
209 | /*
210 | * Function: GetHitboxCenter
211 | * --------------------
212 | * This function calculates the center position in a hitbox based on the minimum and maximum position.
213 | */
214 | QVector GetHitboxCenter(CTransform bonedata, QVector bone_min, QVector bone_max);
215 |
216 | // - General math functions
217 |
218 | /*
219 | * Function: SinCos
220 | * --------------------
221 | * This function calculates the sin and cos of a radians.
222 | */
223 | VOID SinCos(fix32_t radians, fix32_t* sine, fix32_t* cosine);
224 |
225 | /*
226 | * Function: DEG2RAD
227 | * --------------------
228 | * This function converts the given degree into a radians.
229 | */
230 | fix32_t DEG2RAD(fix32_t deg);
231 |
232 | /*
233 | * Function: DotProduct
234 | * --------------------
235 | * This function calculates the dot product based on two Vectors.
236 | */
237 | fix32_t DotProduct(QVector first, fix32_t* second);
238 |
239 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/mouse/logitech_g_pro.c:
--------------------------------------------------------------------------------
1 | #include "mouseDriver.h"
2 |
3 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initLogitechGProMouseXHCI
11 | * --------------------
12 | * Tries to initialize the mouse driver for the Logitech G Pro mouse.
13 | *
14 | * MouseDriverTdCheck: Pointer to the "MouseDriverTdCheck" function that is used to verify the device packets
15 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
16 | *
17 | * returns: The mouseProfile struct, initialized set As TRUE if it was found
18 | *
19 | */
20 | mouseProfile_t EFIAPI initLogitechGProMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun, EFI_PHYSICAL_ADDRESS MBAR)
21 | {
22 | // This implementation is based on the following documents:
23 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
24 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
25 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
26 |
27 | mouseProfile_t ret = { 0, 0, 0, 0, 0, 0 };
28 |
29 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
30 | // Check if we got a valid MBAR
31 | if (MBAR == 0)
32 | {
33 | LOG_ERROR("[XHC] Failed MBAR\r\n");
34 |
35 | // Return 0 to indicate failure
36 | return ret;
37 | }
38 |
39 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
40 |
41 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
42 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
43 |
44 | // Check if we got a valid DCAB
45 | if (DCAB == 0)
46 | {
47 | LOG_ERROR("[XHC] Failed DCAB\r\n");
48 |
49 | // Return 0 to indicate failure
50 | return ret;
51 | }
52 |
53 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
54 |
55 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
56 | // - Endpoint Context Field - offset 0x04, size 32-bit
57 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
58 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
59 | //
60 | // - Endpoint Context Field - offset 0x10, size 32-bit
61 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
62 |
63 | //Check for Logitech G Pro Mouse (Normal)
64 | EFI_PHYSICAL_ADDRESS endpointRing = getEndpointRing(DCAB, 7, 0x10, 0x8, FALSE, MouseDriverTdCheckFun); // Hardcoded for now
65 |
66 | // check if we found the device
67 | if (endpointRing == 0)
68 | {
69 | LOG_ERROR("[XHC] Failed finding endpoint ring \r\n");
70 | return ret;
71 | }
72 |
73 | LOG_VERB("[XHC] Found endpoint Ring %p\r\n", endpointRing);
74 |
75 | // Find transferBuffer
76 | // loop is not needed, the ring is filled from top to bottom.
77 | // --> if there is no data at the top, there will not be data in the bottom either.
78 | EFI_PHYSICAL_ADDRESS TDPointerPhys = 0;
79 | EFI_PHYSICAL_ADDRESS TDPointerPhys2 = 0;
80 |
81 | // Copy the first and the second transfer buffer pointers (they are positioned with a distance of 0x20 between)
82 | // We use 0x20 steps, as upon a Normal TRB (Intel eXtensible Host Controller Interface for USB, 4.11.2.1, Page 211, Normal TRB), we have always observed an Event Data TRB (Intel eXtensible Host Controller Interface for USB, 4.11.5.2, Page 230, Event Data TRB)
83 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&TDPointerPhys, endpointRing, sizeof(EFI_PHYSICAL_ADDRESS));
84 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&TDPointerPhys2, endpointRing + 0x20, sizeof(EFI_PHYSICAL_ADDRESS));
85 |
86 | // Check if either of them is 0
87 | if (TDPointerPhys == 0 || TDPointerPhys2 == 0)
88 | {
89 | LOG_ERROR("[XHC] Received invalid transfer buffers for mouse \r\n");
90 |
91 | // Return 0 as the transfer buffers were invalid
92 | return ret;
93 | }
94 |
95 | // We now got the addresses but want to verify if those are really from a Logitech mouse
96 |
97 | // Copy the first byte of each descriptor
98 | UINT8 tempIdentifier = 0;
99 | UINT8 tempIdentifier2 = 0;
100 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifier, TDPointerPhys, sizeof(UINT8));
101 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifier2, TDPointerPhys2, sizeof(UINT8));
102 |
103 | LOG_VERB("[XHC] Temp identifier 0x%x Temp Identifier 2 0x%x \r\n", tempIdentifier, tempIdentifier2);
104 |
105 | // Check if they start with 0x2 or 0x3 (depends on firmware)
106 | if (((tempIdentifier == 0x2 || tempIdentifier == 0x3) && (tempIdentifier2 == 0x2 || tempIdentifier2 == 0x3)))
107 | {
108 | // Now set all global variables so we dont have to recalculate them when doing the actual manipulation
109 | mouseProfile_t ret_valid = { TRUE, TDPointerPhys, TDPointerPhys + 0x1, TDPointerPhys + 0x3, TDPointerPhys2, TDPointerPhys2 + 0x1, TDPointerPhys2 + 0x3 };
110 |
111 | // Return the pointer to the transfer buffer to indicate successful execution
112 | return ret_valid;
113 | }
114 |
115 | return ret;
116 | }
117 |
118 | /*
119 | * Function: mouseLogitechGProDriverTdCheck
120 | * --------------------
121 | * Verifies the TD of the Logitech G Pro mouse.
122 | *
123 | * TDPointerPhys: UINT64 (EFI_PHYSICAL_ADDRESS) to the TD that should be checked
124 | *
125 | * returns: TRUE if the check passed, FALSE otherwise
126 | *
127 | */
128 | BOOLEAN EFIAPI mouseLogitechGProDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys)
129 | {
130 | LOG_VERB("[XHC] Checking TD at 0x%x \r\n", TDPointerPhys);
131 |
132 | // check the identifier at the start of the packet
133 | UINT8 tdCheck = 0;
134 | BOOLEAN status = pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tdCheck, TDPointerPhys, sizeof(UINT8));
135 |
136 | LOG_VERB("[XHC] TD check 0x%x \r\n", tdCheck);
137 |
138 | // Check if it starts with 0x2 or 0x3 (depends on FW version)
139 | if ((tdCheck == 2 || tdCheck == 3) && status == TRUE)
140 | {
141 | // Found device successfully
142 | LOG_DBG("[XHC] Found Normal \r\n");
143 |
144 | return TRUE;
145 | }
146 |
147 | return FALSE;
148 | }
149 |
150 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/timerPCH.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for functions related to SMI timer using PCH functionalities
4 | *
5 | --*/
6 |
7 | // our includes
8 | #include "timerPCH.h"
9 | #include "../logging/logging.h"
10 |
11 | /*
12 | * Function: pchInitUSB
13 | * --------------------
14 | * This function enables the XHCI_SMI_EN function in the XHCI, thus generating a SMI on each USB packet.
15 | * This functionality enables us to generate a lot of SMIs and intercept the USB packets, before they reach the OS.
16 | * This function has to be called early in the boot, as it gets locked otherwise by UEFI
17 | *
18 | * returns: FALSE if it failed, otherwise TRUE
19 | *
20 | */
21 | BOOLEAN pchInitUSB()
22 | {
23 | // This feature has to be enabled in the PCH and close to boot.
24 |
25 | // First we want to get the ABASE from the XHCI device
26 | // Note 23.07.2024 - This device is not present anymore on newer devices after boot.
27 | UINT32 ABASE = PciRead32(PCI_LIB_ADDRESS(0, 31, 2, 0x20));
28 |
29 | // Null the last byte
30 | ABASE = ABASE & 0xFFFFF00;
31 |
32 | LOG_VERB("[TPC] ABASE: %x\r\n", ABASE);
33 |
34 | // Check if we got a valid address
35 | if (ABASE == 0xFFFFF00)
36 | {
37 | // On newer devices, we will get FFFFFFF as address as the BAR2 is missing
38 | // In this case we simply use a hardcoded BAR2 (0x1800), this has been confirmed to be the same on series 300 and 600 chipsets
39 |
40 | // Before proceeding with the hardcoded value, verify it first
41 |
42 | // Null check (this area should be null and it is not reserved on the manual)
43 | UINT32 nullCheck = IoRead32(0x1800 + 0x10);
44 |
45 | // Check if there is something at that location
46 | if (nullCheck != 0)
47 | {
48 | LOG_ERROR("[TPC] Null check failed \r\n");
49 |
50 | // Return false as we were unable to turn on the timer
51 | return FALSE;
52 | }
53 |
54 | // SMI_EN Check, check different bits which are enabled most of the times
55 | UINT32 smiEnCheck = IoRead32(0x1800 + PCH_SMI_EN);
56 |
57 | // Global SMI Enable Bit, should always be set
58 | if ((smiEnCheck & 0x1) == 0)
59 | {
60 | LOG_ERROR("[TPC] SMI EN Global SMI \r\n");
61 |
62 | // Return false as we were unable to turn on the timer
63 | return FALSE;
64 | }
65 |
66 | // TCO SMI Enable Bit, should always be set
67 | if ((smiEnCheck & 0x2000) == 0)
68 | {
69 | LOG_ERROR("[TPC] SMI EN TCO SMI \r\n");
70 |
71 | // Return false as we were unable to turn on the timer
72 | return FALSE;
73 | }
74 |
75 | // Checks passed, set ABASE to hardcoded and continue
76 | ABASE = 0x1800;
77 | }
78 |
79 | // Calculate the address of the SMI_EN variable in the ABASE
80 | UINT32 mSmiEnable = ABASE + PCH_SMI_EN;
81 |
82 | // Read the value of the I/O address which points to SMI_EN
83 | UINT32 SmiEnableVal = 0;
84 | SmiEnableVal = IoRead32(mSmiEnable);
85 |
86 | LOG_VERB("[TPC] SmiEnableVal: %x\r\n", SmiEnableVal);
87 |
88 | // Check if the read was successfull
89 | if (SmiEnableVal == 0xffffffff)
90 | {
91 | // Failed read
92 | LOG_ERROR("[TPC] Failed io read \r\n");
93 |
94 | // Return false as we were unable to turn on the timer
95 | return FALSE;
96 | }
97 |
98 | // Check if the Bit 31 (XHCI_SMI_EN) is already toggled
99 | if ((SmiEnableVal & 0x80000000) == 0)
100 | {
101 | // Not toggled yet, set the bit
102 | SmiEnableVal |= 0x80000000;
103 | // Write the new value to the I/O address
104 | IoWrite32(mSmiEnable, SmiEnableVal);
105 | }
106 |
107 | // Now also enable the SMI generation in the XHCI
108 | // First get the memory base address of the XHCI device
109 | UINT64 MBAR = 0;
110 | if (PciReadBuffer(PCI_LIB_ADDRESS(0, 0x14, 0x0, 0x10), 8, &MBAR) != 8) // See Intel series 200 page 1150
111 | {
112 | LOG_ERROR("[TPC] Failed PciReadBuffer \r\n");
113 |
114 | // Return false as we were unable to turn on the timer
115 | return FALSE;
116 | }
117 |
118 | // Null last bits
119 | MBAR = MBAR & 0xFFFFFFFFFFFFFF00;
120 |
121 | // Verify if we got a valid MBAR
122 | if (MBAR == 0)
123 | {
124 | LOG_VERB("[TPC] Failed MBAR \r\n");
125 |
126 | // Return false as we were unable to turn on the timer
127 | return FALSE;
128 | }
129 |
130 | LOG_VERB("[TPC] MBAR: %x\r\n", MBAR);
131 |
132 | // Now we want to read the 'Usb Legacy Support Control Status' which is not documented anymore on newer specifications
133 |
134 | // First define the pointer to the Usb Legacy Support Control Status
135 | EFI_PHYSICAL_ADDRESS pUSBLEGCTL = MBAR + XHCI_USBLegacySupportControlStatus;
136 |
137 | // Now read only a single byte of it, as sometimes it buggs out when reading more
138 | UINT8 USBLEGCTL = 0;
139 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&USBLEGCTL, pUSBLEGCTL, sizeof(UINT8));
140 |
141 | LOG_VERB("[TPC] ABASE: %x\r\n", USBLEGCTL);
142 |
143 | // Check if its already enabled or not
144 | if ((USBLEGCTL & 1) == 0)
145 | {
146 | // Its off, enable it
147 | USBLEGCTL |= 1;
148 |
149 | LOG_VERB("[TPC] USBLEGCTL2: %x\r\n", USBLEGCTL);
150 |
151 | // Write the change back
152 | pMemCpyForce(pUSBLEGCTL, (EFI_PHYSICAL_ADDRESS)&USBLEGCTL, sizeof(UINT8));
153 | }
154 |
155 | // Return true
156 | return TRUE;
157 | }
158 |
159 | /*
160 | * Function: pchClearUSB
161 | * --------------------
162 | * This function clears the status Bits which are set by the XHCI SMI generation.
163 | * If these bits are not cleared, the system would otherwise get stuck eventually.
164 | *
165 | * returns: Nothing
166 | *
167 | */
168 | VOID pchClearUSB()
169 | {
170 | // First get the memory base address of the XHCI device
171 | EFI_PHYSICAL_ADDRESS MBAR = 0;
172 | if (PciReadBuffer(PCI_LIB_ADDRESS(0, 0x14, 0x0, 0x10), 8, &MBAR) != 8) // See Intel series 200 page 1150
173 | {
174 | LOG_ERROR("[TPC] Failed PciReadBuffer \r\n");
175 |
176 | return;
177 | }
178 |
179 | // Null last bits
180 | MBAR = MBAR & 0xFFFFFFFFFFFFFF00;
181 |
182 | // Check if we got a valid MBAR
183 | if (MBAR == 0)
184 | {
185 | // MBAR is 0, abort
186 | LOG_VERB("[TPC] Zero MBAR \r\n");
187 |
188 | return;
189 | }
190 |
191 | // Now read out the USB Status variale
192 | UINT32 _usbsts = 0;
193 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&_usbsts, MBAR + XHCI_USBStatus, sizeof(UINT32));
194 |
195 | // Check if we read a valid status
196 | if (_usbsts == 0)
197 | {
198 | return;
199 | }
200 |
201 | // Check if there is an incoming SMI from USB
202 | if ((_usbsts & 8) != 0)
203 | {
204 | // There is one, write the bit again to force a reset
205 | _usbsts |= 8;
206 |
207 | // Write it back
208 | pMemCpyForce(MBAR + XHCI_USBStatus, (EFI_PHYSICAL_ADDRESS)&_usbsts, sizeof(UINT32));
209 | }
210 |
211 | return;
212 | }
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/serial.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for serial related functions
4 | *
5 | --*/
6 |
7 | // our includes
8 | #include "serial.h"
9 | #include "../memory/string.h"
10 |
11 | /*
12 | * UART Settings
13 | */
14 | UINT8 m_Data = 8;
15 | UINT8 m_Stop = 1;
16 | UINT8 m_Parity = 0;
17 | UINT8 m_BreakSet = 0;
18 |
19 | /*
20 | * Function: SerialPortInitialize
21 | * --------------------
22 | * Initializes the serial device hardware at the supplied address.
23 | *
24 | * Port: UINT16 pointer to the serial hardware IO buffer
25 | * Baudrate: UINTN Baudrate that should be used for communication
26 | *
27 | * returns: Nothing
28 | *
29 | */
30 | VOID SerialPortInitialize(UINT16 Port, UINTN Baudrate)
31 | {
32 | // Map 5..8 to 0..3
33 | UINT8 Data = (UINT8)(m_Data - (UINT8)5);
34 |
35 | // Calculate divisor for baud generator
36 | UINTN Divisor = BAUDRATE_MAX / Baudrate;
37 |
38 | // Set communications format
39 | UINT8 OutputData = (UINT8)((DLAB << 7) | (m_BreakSet << 6) | (m_Parity << 3) | (m_Stop << 2) | Data);
40 | IoWrite8((UINTN)(Port + LCR_OFFSET), OutputData);
41 |
42 | // Configure baud rate
43 | IoWrite8((UINTN)(Port + BAUD_HIGH_OFFSET), (UINT8)(Divisor >> 8));
44 | IoWrite8((UINTN)(Port + BAUD_LOW_OFFSET), (UINT8)(Divisor & 0xff));
45 |
46 | // Switch back to bank 0
47 | OutputData = (UINT8)((~DLAB << 7) | (m_BreakSet << 6) | (m_Parity << 3) | (m_Stop << 2) | Data);
48 | IoWrite8((UINTN)(Port + LCR_OFFSET), OutputData);
49 | }
50 |
51 | /*
52 | * Function: SerialPortWrite
53 | * --------------------
54 | * Writes the passed UINT8 Data to the serial port and waites for the acknowledgment.
55 | *
56 | * Port: UINT16 pointer to the serial hardware IO buffer
57 | * Data: UINT8 data that is sent to the IO buffer
58 | *
59 | * returns: Nothing
60 | *
61 | */
62 | VOID SerialPortWrite(UINT16 Port, UINT8 Data)
63 | {
64 | // Define the status variable that is used to check if the data can be sent
65 | UINT8 Status = 0;
66 |
67 | do
68 | {
69 | // Get the current status of the serial port
70 | Status = IoRead8(Port + LSR_OFFSET);
71 | } while ((Status & LSR_TXRDY) == 0); // Check if the port is ready
72 |
73 | // Send the byte to the serial port
74 | IoWrite8(Port, Data);
75 |
76 | return;
77 | }
78 |
79 | /*
80 | * Function: SerialPrintString
81 | * --------------------
82 | * Writes the passed null-terminated string to the serial port using SerialPortWrite.
83 | * No check for maximum length included so make sure it is null-terminated.
84 | *
85 | * text: char* pointer to the null-terminated string
86 | *
87 | * returns: Nothing
88 | *
89 | */
90 | VOID SerialPrintString(const char* text)
91 | {
92 | // We initiailize it again to make sure the data is sent
93 | SerialPortInitialize(SERIAL_PORT_0, SERIAL_BAUDRATE);
94 |
95 | // Loop until the position in the char array is 0 (null-terminated)
96 | while (*text)
97 | {
98 | // Send single byte via serial port
99 | SerialPortWrite(SERIAL_PORT_0, *text++);
100 | }
101 |
102 | return;
103 | }
104 |
105 | /*
106 | * Function: SerialPrintChar
107 | * --------------------
108 | * Writes a single character to serial. The serial should be initialized elsewhere!
109 | *
110 | * c: character to write
111 | *
112 | * returns: Nothing
113 | *
114 | */
115 | VOID SerialPrintChar(const char c)
116 | {
117 | SerialPortWrite(SERIAL_PORT_0, c);
118 |
119 | return;
120 | }
121 |
122 | /*
123 | * Function: SerialSendData
124 | * --------------------
125 | * Writes the passed memory buffer directly to serial without converting it in any way using SerialPortWrite.
126 | *
127 | * buf: void* pointer to the memory buffer
128 | * len: UINT8 length of the memory buffer (max. 255)
129 | *
130 | * returns: Nothing
131 | *
132 | */
133 | VOID SerialSendData(const VOID* buf, UINT8 len)
134 | {
135 | // Loop through the memory buffer
136 | for (UINT64 i = 0; i < len; i++)
137 | {
138 | // Send the single byte of the current positionvia serial
139 | SerialPortWrite(SERIAL_PORT_0, ((const char*)buf)[i]);
140 | }
141 |
142 | return;
143 | }
144 |
145 | /*
146 | * Function: SerialPrintNumber
147 | * --------------------
148 | * Converts the passed number to a string using the string library and then writes the string to serial.
149 | *
150 | * _v: UINT64 value that will be converted to a string
151 | * _b: INT64 value that defines the type of passed number (hex - 16 or dec - 10)
152 | *
153 | * returns: Nothing
154 | *
155 | */
156 | VOID SerialPrintNumber(UINT64 _v, INT64 _b)
157 | {
158 | char _r[100];
159 |
160 | // check validity as we only supported bitness between 2 and 36
161 | if (_b < 2 || _b > 36)
162 | {
163 | *_r = 0;
164 | return;
165 | }
166 |
167 | char* ptr = _r;
168 | char* ptr1 = _r;
169 | INT64 tmp_value;
170 |
171 | do {
172 | tmp_value = _v;
173 | _v /= _b;
174 | *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - _v * _b)];
175 | } while (_v);
176 |
177 | // is the value neg?
178 | if (tmp_value < 0 && _b == 10)
179 | {
180 | *ptr++ = '-';
181 | }
182 |
183 | char tmp_char;
184 |
185 | *ptr-- = '\0';
186 | while (ptr1 < ptr)
187 | {
188 | tmp_char = *ptr;
189 | *ptr-- = *ptr1;
190 | *ptr1++ = tmp_char;
191 | }
192 |
193 | // Now write the converted number to the serial
194 | SerialPrintString(_r);
195 |
196 | return;
197 | }
198 |
199 | VOID EFIAPI SerialPrintf(const char* fmt, ...)
200 | {
201 | if(!fmt)
202 | {
203 | return;
204 | }
205 |
206 | SerialPortInitialize(SERIAL_PORT_0, SERIAL_BAUDRATE);
207 |
208 | UINT32 len = strlen(fmt);
209 | VA_LIST vl;
210 | VA_START(vl, fmt);
211 | for(UINT32 i = 0; i < len; i++)
212 | {
213 | if(fmt[i] == '%')
214 | {
215 | // decimal
216 | if(fmt[i+1] == 'd')
217 | {
218 | INT64 d = VA_ARG(vl, INT64);
219 | SerialPrintNumber(d, 10);
220 | i++;
221 | continue;
222 | }
223 | // hex
224 | if(fmt[i+1] == 'x' || fmt[i+1] == 'p')
225 | {
226 | if(fmt[i+1] == 'p')
227 | SerialPrintString("0x");
228 | UINT64 val = VA_ARG(vl, UINT64);
229 | SerialPrintNumber(val, 16);
230 | i++;
231 | continue;
232 | }
233 | // string
234 | if(fmt[i+1] == 's')
235 | {
236 | char* s = VA_ARG(vl, char*);
237 | SerialPrintString(s);
238 | i++;
239 | continue;
240 | }
241 | // character
242 | if(fmt[i+1] == 'c')
243 | {
244 | char c = VA_ARG(vl, int);
245 | SerialPrintChar(c);
246 | i++;
247 | continue;
248 | }
249 | // just in case there was a wrong type input.
250 | // otherwise we would be stuck in an endless loop
251 | i++;
252 | }
253 | else
254 | {
255 | SerialPrintChar(fmt[i]);
256 | }
257 | }
258 | VA_END(vl);
259 | return;
260 | }
261 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/mouse/logitech_g_pro_superlight.c:
--------------------------------------------------------------------------------
1 | #include "mouseDriver.h"
2 |
3 | #ifdef MOUSE_DRIVER_LOGITECH_G_PRO_SUPERLIGHT
4 |
5 | // our includes
6 | #include "../xhci.h"
7 | #include "../../logging/logging.h"
8 |
9 | /*
10 | * Function: initLogitechGProSuperlightMouseXHCI
11 | * --------------------
12 | * Tries to initialize the mouse driver for the Logitech G Pro Superlight mouse.
13 | *
14 | * MouseDriverTdCheck: Pointer to the "MouseDriverTdCheck" function that is used to verify the device packets
15 | * MBAR: EFI_PHYSICAL_ADDRESS pointer to the Memory base address of the XHCI controller
16 | *
17 | * returns: The mouseProfile struct, initialized set As TRUE if it was found
18 | *
19 | */
20 | mouseProfile_t EFIAPI initLogitechGProSuperlightMouseXHCI(MouseDriverTdCheck MouseDriverTdCheckFun, EFI_PHYSICAL_ADDRESS MBAR)
21 | {
22 | // This implementation is based on the following documents:
23 | // - Intel 600 series datasheet see: https://www.intel.com/content/www/us/en/content-details/742460/intel-600-series-chipset-family-for-iot-edge-platform-controller-hub-pch-datasheet-volume-2-of-2.html
24 | // - The SMM Rootkit Revisited: Fun with USB https://papers.put.as/papers/firmware/2014/schiffman2014.pdf
25 | // - eXtensible Host Controller Interface for Universal Serial Bus (xHCI) https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
26 |
27 | mouseProfile_t ret = { 0, 0, 0, 0, 0, 0 };
28 |
29 | // (Intel 600 series datasheet, 18.1.11, Page 822) First we get the MBAR of the XHCI device
30 | // Check if we got a valid MBAR
31 | if (MBAR == 0)
32 | {
33 | LOG_ERROR("[XHC] Failed MBAR\r\n");
34 |
35 | // Return 0 to indicate failure
36 | return ret;
37 | }
38 |
39 | LOG_INFO("[XHC] Found MBAR %p\r\n", MBAR);
40 |
41 | // (Intel eXtensible Host Controller Interface for USB, 5.4, Page 391) Now that we have the MBAR we can access the Memory Mapped registers, use it to get the Device Context Array Base Pointer which contains pointers to the devices.
42 | EFI_PHYSICAL_ADDRESS DCAB = getDeviceContextArrayBase(MBAR);
43 |
44 | // Check if we got a valid DCAB
45 | if (DCAB == 0)
46 | {
47 | LOG_ERROR("[XHC] Failed DCAB\r\n");
48 |
49 | // Return 0 to indicate failure
50 | return ret;
51 | }
52 |
53 | LOG_INFO("[XHC] Found DCAB %p\r\n", DCAB);
54 |
55 | // Now as we have the DCAB, we scan all of the devices for the following specifications:
56 | // - Endpoint Context Field - offset 0x04, size 32-bit
57 | // - Endpoint Type - Bits 5:3 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Endpoint Type (EP Type))
58 | // - Max Packet Size - Bits 31:16 (Intel eXtensible Host Controller Interface for USB, Table 6-9, Page 452, Max Packet Size)
59 | //
60 | // - Endpoint Context Field - offset 0x10, size 32-bit
61 | // - Average TRB Length - Bits 15:0 (Intel eXtensible Host Controller Interface for USB, Table 6-11, Page 453, Average TRB Length)
62 |
63 | //Check for Logitech G Pro Mouse (Superlight)
64 | EFI_PHYSICAL_ADDRESS endpointRing = getEndpointRing(DCAB, 7, 0x40, 0x20, FALSE, MouseDriverTdCheckFun); // Hardcoded for now
65 |
66 | // check if we found the device
67 | if (endpointRing == 0)
68 | {
69 | LOG_ERROR("[XHC] Failed finding endpoint\r\n");
70 | return ret;
71 | }
72 |
73 | LOG_VERB("[XHC] Found endpoint Ring %p\r\n", endpointRing);
74 |
75 | // Find transferBuffer
76 | // loop is not needed, the ring is filled from top to bottom.
77 | // --> if there is no data at the top, there will not be data in the bottom either.
78 | EFI_PHYSICAL_ADDRESS TDPointerPhys = 0;
79 | EFI_PHYSICAL_ADDRESS TDPointerPhys2 = 0;
80 |
81 | // Copy the first and the second transfer buffer pointers (they are positioned with a distance of 0x20 between)
82 | // We use 0x20 steps, as upon a Normal TRB (Intel eXtensible Host Controller Interface for USB, 4.11.2.1, Page 211, Normal TRB), we have always observed an Event Data TRB (Intel eXtensible Host Controller Interface for USB, 4.11.5.2, Page 230, Event Data TRB)
83 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&TDPointerPhys, endpointRing, sizeof(EFI_PHYSICAL_ADDRESS));
84 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&TDPointerPhys2, endpointRing + 0x20, sizeof(EFI_PHYSICAL_ADDRESS));
85 |
86 | // Check if either of them is 0
87 | if (TDPointerPhys == 0 || TDPointerPhys2 == 0)
88 | {
89 | // Return 0 as the transfer buffers were invalid
90 | return ret;
91 | }
92 |
93 | // We now got the addresses but want to verify if those are really from Logitech mouse
94 |
95 | // Copy the first byte of each descriptor
96 | UINT8 tempIdentifier = 0;
97 | UINT8 tempIdentifier2 = 0;
98 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifier, TDPointerPhys, sizeof(UINT8));
99 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifier2, TDPointerPhys2, sizeof(UINT8));
100 |
101 | // Newer mouse using the Logitech superlight protocol dont have those identifiers, different check is required
102 | // Read the superlight identifier at the + 0x8 offset
103 | UINT32 tempIdentifierSL = 0;
104 | UINT32 tempIdentifier2SL = 0;
105 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifierSL, TDPointerPhys + 0x8, sizeof(UINT32));
106 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tempIdentifier2SL, TDPointerPhys2 + 0x8, sizeof(UINT32));
107 |
108 | // Check if they equal to 0x409301
109 | if ((tempIdentifierSL == 0x409301) && (tempIdentifier2SL == 0x409301))
110 | {
111 | // Now set all global variables so we dont have to recalculate them when doing the actual manipulation
112 | mouseProfile_t ret_valid = { TRUE, TDPointerPhys, TDPointerPhys, TDPointerPhys + 0x2, TDPointerPhys2, TDPointerPhys2, TDPointerPhys2 + 0x2 };
113 |
114 | // Return the pointer to the transfer buffer to indicate successful execution
115 | return ret_valid;
116 | }
117 |
118 | return ret;
119 | }
120 |
121 | /*
122 | * Function: mouseLogitechGProSuperlightDriverTdCheck
123 | * --------------------
124 | * Verifies the TD of the Logitech G Pro Superlight mouse.
125 | *
126 | * TDPointerPhys: UINT64 (EFI_PHYSICAL_ADDRESS) to the TD that should be checked
127 | *
128 | * returns: TRUE if the check passed, FALSE otherwise
129 | *
130 | */
131 | BOOLEAN EFIAPI mouseLogitechGProSuperlightDriverTdCheck(EFI_PHYSICAL_ADDRESS TDPointerPhys)
132 | {
133 | LOG_VERB("[XHC] Checking TD at 0x%x \r\n", TDPointerPhys);
134 |
135 | // Check for the Superlight Identifier at offset 8
136 | UINT32 tdCheck = 0;
137 | BOOLEAN status = pMemCpyForce((EFI_PHYSICAL_ADDRESS)&tdCheck, TDPointerPhys + 0x8, sizeof(UINT32));
138 |
139 | LOG_VERB("[XHC] TD check 0x%x \r\n", tdCheck);
140 |
141 | // Check if the identifier is there
142 | if (tdCheck == 0x409301 && status == TRUE)
143 | {
144 | // Found device successfully
145 | LOG_DBG("[XHC] Found Superlight \r\n");
146 |
147 | return TRUE;
148 | }
149 | return FALSE;
150 | }
151 |
152 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/sigScan.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for signature scanning related functions
4 | *
5 | --*/
6 |
7 | // our includes
8 | #include "sigScan.h"
9 | #include "../logging/logging.h"
10 |
11 | /*
12 | * Function: CompareBytes
13 | * --------------------
14 | * Goes through the passed memory buffer and checks for matches on the pattern.
15 | * Checks if it is either a match, ' ' or '?'
16 | *
17 | * bytes: Pointer to the memory buffer to scan
18 | * pattern: Pointer to the pattern that should be scanned for
19 | *
20 | * returns: FALSE if it doesnt match, true if it does match.
21 | *
22 | */
23 | BOOLEAN CompareBytes(const unsigned char* bytes, const char* pattern)
24 | {
25 | // Go through the pattern and bytes equally
26 | for (; *pattern; *pattern != ' ' ? ++bytes : bytes, ++pattern)
27 | {
28 | // check if the pattern expects an expect match at this position
29 | if (*pattern == ' ' || *pattern == '?')
30 | continue;
31 |
32 | // Check if the byte position matches the pattern
33 | if (*bytes != getByte(pattern))
34 | return FALSE;
35 |
36 | // We matched, increase pattern for next match
37 | ++pattern;
38 | }
39 |
40 | // No difference observed, return true
41 | return TRUE;
42 | }
43 |
44 | /*
45 | * Function: virtFindPattern
46 | * --------------------
47 | * Searches for a given pattern in the memory area passed as parameter. Contains various features for special signatures (not just memory based).
48 | *
49 | * base: UINT64 virtual memory base where it should start scanning
50 | * size: UINT64 size starting from base where it should scan
51 | * dirBase: UINT64 directory base which is used to translate virtual to physcical memory
52 | * pattern: Pointer to the pattern that should be scanned for
53 | * extra: UINT32 extra offset that should be added on the found signature
54 | * ripRelative: BOOLEAN that indicates if rip relative addressing should be done (read the address and return it)
55 | * substract: BOOLEAN that indicates if the base should be returned from the address (returns offset)
56 | *
57 | * returns: 0 if the signature was not found or it failed. Otherwise it returns the address where it was found.
58 | *
59 | */
60 | EFI_VIRTUAL_ADDRESS virtFindPattern(EFI_VIRTUAL_ADDRESS base, UINT64 size, UINT64 dirBase, const char* pattern, UINT32 extra, BOOLEAN ripRelative, BOOLEAN substract)
61 | {
62 | // Check if one of the basic parameters (base, size, dirbase) were not properly set
63 | if (base == 0 || size == 0 || dirBase == 0)
64 | {
65 | LOG_ERROR("IPS\r\n");
66 |
67 | return 0;
68 | }
69 |
70 | // Result will be stored in this variable
71 | EFI_VIRTUAL_ADDRESS address = 0;
72 |
73 | // Calculate amount of pages that should be scanned
74 | UINT32 pageAmount = (size / 0x1000) + 1;
75 |
76 | // Temporarily store the memory in SMM
77 | unsigned char buffer[0x2000];
78 |
79 | // Now loop through all pages
80 | for (UINT32 i = 0; i < pageAmount; i++)
81 | {
82 | // Convert the virtual addresses to physical addresses
83 | EFI_PHYSICAL_ADDRESS pSrc1 = VTOPForce(base + (i * 0x1000), dirBase);
84 | EFI_PHYSICAL_ADDRESS pSrc2 = VTOPForce(base + ((i + 1) * 0x1000), dirBase);
85 |
86 | // Check if we successfully converted it
87 | if (pSrc1 == 0 || pSrc2 == 0)
88 | {
89 | // Failed converting, check the whole supplied region to be sure
90 | continue;
91 | }
92 | else
93 | {
94 | // Valid address, copy the memory to SMM
95 | pMemCpy((EFI_PHYSICAL_ADDRESS)buffer, pSrc1, 0x1000);
96 | pMemCpy((EFI_PHYSICAL_ADDRESS)buffer + 0x1000, pSrc2, 0x1000);
97 |
98 | // Compare the memory page by looping through it
99 | for (int j = 0; j < 0x2000; j++)
100 | {
101 | if (CompareBytes((unsigned char *)buffer + j, pattern))
102 | {
103 | // Successfully found the pattern, process it to get the correct result
104 | LOG_VERB("[SIG] Found pattern at %p\r\n", base + (i * 0x1000) + j);
105 |
106 | // Set the starting address where we found the match
107 | address = base + (i * 0x1000) + j;
108 |
109 | // Check if the ripRelative operation should be done
110 | if (ripRelative)
111 | {
112 | // First read the rip displacement at the location
113 | UINT32 displacement = 0;
114 | vMemRead((EFI_PHYSICAL_ADDRESS) &displacement, address + 0x3, sizeof(UINT32), dirBase);
115 |
116 | // Check if we successfully read something
117 | LOG_VERB("[SIG] Read displacement: %x\r\n", displacement);
118 |
119 | // Add displacement to the address
120 | address = address + 0x7 + displacement;
121 | }
122 |
123 | // Check if the substract operation should be done
124 | if (substract)
125 | {
126 | // Substract the base from the address to get the relative offset
127 | address -= base;
128 | }
129 |
130 | // Add the supplied extra, if set
131 | address += extra;
132 |
133 | // Remove the base again so it's an offset
134 | address -= base;
135 |
136 | // Return the result
137 | return address;
138 | }
139 | }
140 | }
141 | }
142 |
143 | // Signature not found, return 0
144 | return 0;
145 | }
146 |
147 | /*
148 | * Function: physFindPattern
149 | * --------------------
150 | * Searches the given physical memory area for a given pattern. Only uses memory based patterns with the wildcard '0xAA'.
151 | *
152 | * base: EFI_PHYSICAL_ADDRESS base where the physical memory area starts
153 | * size: UINT32 size of the physical memory area
154 | * pattern: Pointer to byte array which will contain the pattern
155 | * patternLength: UINT32 size of the pattern byte array
156 | *
157 | * returns: Returns the address to the pattern if found, otherwise returns 0.
158 | *
159 | */
160 | EFI_PHYSICAL_ADDRESS physFindPattern(EFI_PHYSICAL_ADDRESS base, UINT32 size, const unsigned char* pattern, UINT32 patternLength)
161 | {
162 | // Define the wildcard pattern, means this position accepst any byte
163 | unsigned char wildcard = 0xAA;
164 |
165 | // Now loop through the total size of the physical memory given
166 | for (UINT64 i = 0; i < size - patternLength; i++)
167 | {
168 | // Defines if the pattern is at the current position. Will be set to 'false' in case of mismatching bytes.
169 | BOOLEAN found = TRUE;
170 |
171 | // Buffer to temporarily hold the memory
172 | unsigned char buffer[32];
173 |
174 | // copy the memory from the current position into our buffer
175 | pMemCpy((EFI_PHYSICAL_ADDRESS)buffer, base + i, 32);
176 |
177 | // Now go through our buffer for the length of the pattern
178 | for (UINT32 j = 0; j < patternLength; j++)
179 | {
180 | // Check if the current pattern position is a wildcard or if the pattern matches the memory position
181 | if (pattern[j] != wildcard && pattern[j] != ((unsigned char*)buffer)[j])
182 | {
183 | // No match, set found to false
184 | found = FALSE;
185 |
186 | // Break out of the for loop as this memory position is incorrect
187 | break;
188 | }
189 | }
190 |
191 | // Check if we've already found it
192 | if (found != FALSE)
193 | {
194 | // Found it! Return the address based on base + current position
195 | return ((EFI_PHYSICAL_ADDRESS)base + i);
196 | }
197 | }
198 |
199 | // If we get here, it means we have found nothing. Return 0
200 | return 0;
201 | }
202 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/logging/memory_log.c:
--------------------------------------------------------------------------------
1 | #include "memory_log.h"
2 |
3 | #if ENABLE_MEMORY_LOG
4 |
5 | #include "../hardware/serial.h"
6 | #include
7 | #include
8 | #include
9 |
10 | // Global variables to hold the state of our memory logger
11 | EFI_PHYSICAL_ADDRESS gMemoryLogBufferAddress = 0;
12 | UINTN gMemoryLogCursor = 0;
13 | UINTN gMemoryLogWrapCount = 0;
14 | UINT32 gMemoryLogTimestamp = 0;
15 | UINTN gMemoryLogDroppedEntries = 0;
16 |
17 | EFI_STATUS EFIAPI InitMemoryLog(IN EFI_BOOT_SERVICES* gBS)
18 | {
19 | EFI_STATUS Status;
20 |
21 | // Prevent double initialization
22 | if (gMemoryLogBufferAddress != 0)
23 | {
24 | return EFI_SUCCESS;
25 | }
26 |
27 | // Allocate pages for our log buffer
28 | // Calculate the number of pages needed, rounding up if necessary
29 | UINTN PagesNeeded = (MEM_LOG_BUFFER_SIZE + EFI_PAGE_SIZE - 1) / EFI_PAGE_SIZE;
30 |
31 | Status = gBS->AllocatePages(
32 | AllocateAnyPages,
33 | EfiRuntimeServicesData, // Use runtime memory so it persists after ExitBootServices if needed
34 | PagesNeeded,
35 | &gMemoryLogBufferAddress
36 | );
37 |
38 | if (EFI_ERROR(Status))
39 | {
40 | // We can't use our memory logger yet, so fall back to serial
41 | SerialPrintf("Failed to allocate memory for log buffer.\n");
42 | gMemoryLogBufferAddress = 0;
43 | return Status;
44 | }
45 |
46 | // Zero out the buffer
47 | SetMem((VOID*)(UINTN)gMemoryLogBufferAddress, MEM_LOG_BUFFER_SIZE, 0);
48 | gMemoryLogCursor = 0;
49 | gMemoryLogWrapCount = 0;
50 | gMemoryLogTimestamp = 0;
51 |
52 | // IMPORTANT: Log the physical address. The user needs this for their memory inspection tool.
53 | SerialPrintf("\033[1;33m(I) [MEMLOG] Memory Log initialized. Buffer size: %d bytes at physical address: 0x%llx\n\033[0;39;49m",
54 | MEM_LOG_BUFFER_SIZE, gMemoryLogBufferAddress);
55 |
56 | return EFI_SUCCESS;
57 | }
58 |
59 | // Internal helper function for writing log entries
60 | STATIC VOID WriteLogEntry(IN UINT8 LogLevel, IN CONST CHAR8* LogData, IN UINTN LogDataLength)
61 | {
62 | if (gMemoryLogBufferAddress == 0 || LogData == NULL || LogDataLength == 0)
63 | {
64 | return;
65 | }
66 |
67 | if (LogLevel < MEMORY_LOG_MIN_LEVEL)
68 | {
69 | return;
70 | }
71 |
72 | // Calculate total entry size (header + data)
73 | UINTN totalEntrySize = sizeof(MEMORY_LOG_ENTRY_HEADER) + LogDataLength;
74 |
75 | // Check if entry is too large
76 | if (totalEntrySize > MAX_LOG_ENTRY_SIZE)
77 | {
78 | gMemoryLogDroppedEntries++;
79 | return;
80 | }
81 |
82 | // Check for wrap-around (circular buffer logic)
83 | if (gMemoryLogCursor + totalEntrySize >= MEM_LOG_BUFFER_SIZE)
84 | {
85 | // Wrap around to the beginning
86 | gMemoryLogCursor = 0;
87 | gMemoryLogWrapCount++;
88 | }
89 |
90 | // Ensure we don't write beyond buffer boundaries
91 | if (gMemoryLogCursor + totalEntrySize > MEM_LOG_BUFFER_SIZE)
92 | {
93 | gMemoryLogDroppedEntries++;
94 | return; // Entry too large for remaining space
95 | }
96 |
97 | // Create and write the header
98 | MEMORY_LOG_ENTRY_HEADER header;
99 | header.Timestamp = ++gMemoryLogTimestamp;
100 | header.EntryLength = (UINT16)totalEntrySize;
101 | header.LogLevel = LogLevel;
102 | header.Reserved = 0;
103 |
104 | // Write header
105 | CopyMem((VOID*)(UINTN)(gMemoryLogBufferAddress + gMemoryLogCursor),
106 | &header, sizeof(MEMORY_LOG_ENTRY_HEADER));
107 | gMemoryLogCursor += sizeof(MEMORY_LOG_ENTRY_HEADER);
108 |
109 | // Write log data
110 | CopyMem((VOID*)(UINTN)(gMemoryLogBufferAddress + gMemoryLogCursor),
111 | LogData, LogDataLength);
112 | gMemoryLogCursor += LogDataLength;
113 |
114 | // Ensure the end of the buffer is null-terminated for safety when reading
115 | if (gMemoryLogCursor < MEM_LOG_BUFFER_SIZE)
116 | {
117 | *((CHAR8*)(UINTN)(gMemoryLogBufferAddress + gMemoryLogCursor)) = '\0';
118 | }
119 | }
120 |
121 | VOID EFIAPI MemoryLogPrint(IN CONST CHAR8* Format, ...)
122 | {
123 | if (gMemoryLogBufferAddress == 0 || Format == NULL)
124 | {
125 | return;
126 | }
127 |
128 | VA_LIST Marker;
129 | CHAR8 logEntryBuffer[MAX_LOG_ENTRY_SIZE - sizeof(MEMORY_LOG_ENTRY_HEADER)];
130 | UINTN logEntryLength;
131 |
132 | // Format the string
133 | VA_START(Marker, Format);
134 | logEntryLength = AsciiVSPrint(logEntryBuffer, sizeof(logEntryBuffer), Format, Marker);
135 | VA_END(Marker);
136 |
137 | // Sanity check the formatted length
138 | if (logEntryLength == 0 || logEntryLength >= sizeof(logEntryBuffer))
139 | {
140 | return;
141 | }
142 |
143 | // Use default log level (INFO = 2) for backward compatibility
144 | WriteLogEntry(2, logEntryBuffer, logEntryLength);
145 | }
146 |
147 | VOID EFIAPI MemoryLogPrintEx(IN UINT8 LogLevel, IN CONST CHAR8* Format, ...)
148 | {
149 | if (gMemoryLogBufferAddress == 0 || Format == NULL)
150 | {
151 | return;
152 | }
153 |
154 | if (LogLevel < MEMORY_LOG_MIN_LEVEL)
155 | {
156 | return;
157 | }
158 |
159 | VA_LIST Marker;
160 | CHAR8 logEntryBuffer[MAX_LOG_ENTRY_SIZE - sizeof(MEMORY_LOG_ENTRY_HEADER)];
161 | UINTN logEntryLength;
162 |
163 | // Format the string
164 | VA_START(Marker, Format);
165 | logEntryLength = AsciiVSPrint(logEntryBuffer, sizeof(logEntryBuffer), Format, Marker);
166 | VA_END(Marker);
167 |
168 | // Sanity check the formatted length
169 | if (logEntryLength == 0 || logEntryLength >= sizeof(logEntryBuffer))
170 | {
171 | return;
172 | }
173 |
174 | WriteLogEntry(LogLevel, logEntryBuffer, logEntryLength);
175 | }
176 |
177 | VOID EFIAPI GetMemoryLogStats(OUT UINTN* TotalSize, OUT UINTN* UsedSize, OUT UINTN* WrapCount, OUT UINTN* Dropped)
178 | {
179 | if (TotalSize != NULL)
180 | {
181 | *TotalSize = MEM_LOG_BUFFER_SIZE;
182 | }
183 |
184 | if (UsedSize != NULL)
185 | {
186 | if (gMemoryLogWrapCount > 0)
187 | {
188 | *UsedSize = MEM_LOG_BUFFER_SIZE; // Buffer is full if we've wrapped
189 | }
190 | else
191 | {
192 | *UsedSize = gMemoryLogCursor;
193 | }
194 | }
195 |
196 | if (WrapCount != NULL)
197 | {
198 | *WrapCount = gMemoryLogWrapCount;
199 | }
200 |
201 | if (Dropped != NULL)
202 | {
203 | *Dropped = gMemoryLogDroppedEntries;
204 | }
205 | }
206 |
207 | VOID EFIAPI ClearMemoryLog(VOID)
208 | {
209 | if (gMemoryLogBufferAddress != 0)
210 | {
211 | // Clear the buffer
212 | SetMem((VOID*)(UINTN)gMemoryLogBufferAddress, MEM_LOG_BUFFER_SIZE, 0);
213 |
214 | // Reset counters
215 | gMemoryLogCursor = 0;
216 | gMemoryLogWrapCount = 0;
217 | gMemoryLogTimestamp = 0;
218 | gMemoryLogDroppedEntries = 0;
219 |
220 | // Log the clear operation
221 | SerialPrintf("\033[1;33m(I) [MEMLOG] Memory log buffer cleared\n\033[0;39;49m");
222 | }
223 | }
224 |
225 | #endif // ENABLE_MEMORY_LOG
226 |
--------------------------------------------------------------------------------
/PloutonLogViewer/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
41 |
42 |
52 |
53 |
60 |
61 |
64 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/Plouton-UEFI/README.md:
--------------------------------------------------------------------------------
1 | # BUILDING
2 | For building the Plouton module, we have outlined two possibilities, either using a docker container or doing it manually on windows.
3 |
4 | ## Submodule init (EDK2)
5 |
6 | In order to retrieve the right tag of EDK2 (vUDK2018):
7 |
8 | ```
9 | git submodule update --init
10 | ```
11 |
12 | This only needs to be done once
13 |
14 | ## Option 1: Building on Docker (Windows, Linux, OS X)
15 |
16 | 1. Either pull the docker image from dockerhub:
17 |
18 | ```
19 | # docker pull jussihi/edk-builder
20 | ```
21 |
22 | **or**
23 |
24 | Inside this directory (Plouton-UEFI), run
25 |
26 | ```
27 | # docker build --no-cache -t jussihi/edk-builder .
28 | ```
29 |
30 |
31 | 2. Inside this directory, run docker and its build script to build firmware image:
32 |
33 | ```
34 | # docker run --privileged -v .:/root/ -u root -w /root jussihi/edk-builder /bin/bash docker_build.sh
35 | ```
36 |
37 | The resulting OVMF firmware will be inside edk2/Build/OvmfX64/RELEASE_GCC5/FV.
38 |
39 | ## Option 2: Building on Windows
40 | To get started you first have to setup a build environment for [edk2](https://github.com/tianocore/edk2).
41 | We recommend following the instructions from this [video](https://www.youtube.com/watch?v=jrY4oqgHV0o) to setup the build environment on windows, but choosing the vUDK2018 release instead of the newest one, as Plouton has been tested using this version.
42 |
43 | With the edk2 setup ready, you will have to add Plouton as a build target for it to get compiled.
44 | First modify the file `edk2\Conf\target.txt` with the following text:
45 | - Change `ACTIVE_PLATFORM` to `OvmfPkg/OvmfPkgX64.dsc`
46 | - Change `TARGET` to `RELEASE`
47 | - Change `TARGET_ARCH` to `X64`
48 |
49 | edk2 will compile the modules mentioned in `OvmfPkg/OvmfPkgX64.dsc`, thus we have to add the Plouton module in the file `edk2\OvmfPkg\OvmfPkgX64.dsc`.
50 | - Add the path to the Plouton module .INF file from the edk2 build environment at the bottom of the file, e.g. `Plouton-UEFI/Plouton/Plouton.inf`
51 |
52 | Now with all requirements set, open a Visual Studio command prompt, navigate to the edk2 root folder and prepare the environment with `edksetup.bat rebuild`.
53 | When this is finished, navigate to the Plouton folder and enter `build`.
54 |
55 | If you have problems setting it up, we also recommend taking a look at the alternative approach by [Zepta](https://github.com/Oliver-1-1/SmmInfect?tab=readme-ov-file#compiling-and-installation).
56 |
57 | ## Running on real HW
58 |
59 | ### Preparing the firmware image
60 |
61 | As a result of the compilation, you should receive an .EFI file.
62 | This .EFI file will be added to your firmware image, for this we recommend first dumping your firmware image using a external SPI programmer or using onboard tools (Intel Flash Programming tools).
63 | To patch the firmware image, we recommend using the old version of [UEFITool](https://github.com/LongSoft/UEFITool/releases/tag/0.28.0).
64 |
65 | #### How to patch PiSmmCpuDxeSmm
66 | If you are trying to run this SMM module on recent real hardware (after ~2021), you need to patch
67 | your motherboard's `PiSmmCpuDxeSmm` module from the UEFI firmware. Modern
68 | SMM protections setup by edk2 will produce a fault otherwise when accessing
69 | normal OS memory.
70 | You can mimick
71 | [our patch](https://github.com/jussihi/SMM-Rootkit/tree/master/SMM%20Rootkit/UefiCpuPkg)
72 | by Patching this variable initialization out and hard code the variable itself to
73 | 0 with your favorite disassembler (IDA or similar):
74 |
75 | https://github.com/tianocore/edk2/blob/edk2-stable202105/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L387
76 |
77 | Easiest way to find that function (SmmInitPageTable) is to search for the
78 | strings of the error messages:
79 |
80 | https://github.com/tianocore/edk2/blob/edk2-stable202105/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c#L278
81 |
82 | Which is referenced multiple times in the SMI Page fault handler:
83 |
84 | https://github.com/tianocore/edk2/blob/edk2-stable202105/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L1014
85 |
86 | And the page fault handler is initialized in the same function as the variable
87 | initialization (SmmInitPageTable):
88 |
89 | https://github.com/tianocore/edk2/blob/edk2-stable202105/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L476
90 |
91 | After the patch is performed, replace the PE32 Image body of the `PiSmmCpuDxeSmm` in the image.
92 |
93 | #### Adding the Plouton module
94 | To add the plouton module into the firmware image, you can directly replace a SMM module as some of them are not crucial for the system execution.
95 | To locate the less relevant modules, we recommend the newer UEFITool versions or just looking up the GUIDs of the module online.
96 | Simply select the "PE32 Image section" of the module and replace the body with the Plouton .EFI file.
97 | 
98 |
99 | Afterwards save the image using UEFITool.
100 |
101 | ### Flashing the firmware image
102 | Now with the image prepared, you can flash it to the mainboard using an external SPI programmer.
103 | Manufacturers have started to crack down on SPI Protection, thus it is not as easy anymore to just overwrite the SPI chip from the operating system.
104 |
105 | There are numerous guides/manuals how to setup such an external SPI programmer, which is why we will not go further down in the specifics here.
106 | Our recommendations are to use [flashrom](https://flashrom.org/) together with a Raspberry PI and using a SOIC-8 clip to directly attach to the SPI chip.
107 |
108 | **Always make sure to disconnect the power before using any external SPI programmer!**
109 |
110 | Commands used by us together with flashrom:
111 | - Reading:
112 | - `flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -n -r `
113 | - Writing:
114 | - `flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -n -w `
115 |
116 | Good tutorials:
117 | - [[Guide] How to Use a CH341A SPI Programmer/Flasher (with Pictures!)](https://winraid.level1techs.com/t/guide-how-to-use-a-ch341a-spi-programmer-flasher-with-pictures/33041)
118 | - [Recover Bricked BIOS using FlashRom on a Raspberry Pi](https://www.youtube.com/watch?v=KNy-_ZzMnG0)
119 | - [How to flash bios chips with Raspberry Pi](https://tomvanveen.eu/flashing-bios-chip-raspberry-pi/)
120 |
121 | ## FAQ
122 |
123 | ### Flashrom does not recognize the chip
124 | Verify that the clip is properly attached to the chip and connected to the bottom of the chip.
125 | Verify that the wiring has been properly done after the SPI specs.
126 |
127 | ### No serial output after boot
128 |
129 | Sometimes the serial traffic is blocked because of the operating system's own serial
130 | driver. This is at least the case in Windows systems when not booting inside
131 | a (QEMU/KVM) virtual machine.
132 |
133 | #### There are two ways to get serial working on this sort of situation:
134 |
135 | - Block the Operating System from loading the driver.
136 |
137 | On GNU+Linux, you can disable the driver completely if one is loaded. On
138 | Windows systems, you might need to rename/delete the system's serial driver.
139 | The default path to the driver executable is
140 | `C:\Windows\System32\drivers\serial.sys`.
141 |
142 | - Open an SSH client locally
143 |
144 | You can also open the connection to the local serial port using your favorite
145 | serial client. At least on Windows this will prevent Windows own driver from
146 | suppressing the serial output.
147 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/hardware/README.md:
--------------------------------------------------------------------------------
1 | # Supported devices out of the box
2 | The XHCI functionality has been tested together with the Intel XHCI USB Controller.
3 | The following devices have been tested and work together with SMM in their standard configuration.
4 | - Audio devices
5 | - Corsair Wireless Headset
6 | - Creative Pebble V3 Speaker
7 | - Hyper X Cloud 2 Headset
8 | - Logitech G Pro X Headset
9 | - Logitech G Pro X 2 Headset
10 | - Mouse devices
11 | - Logitech G Pro
12 | - Logitech G Pro Superlight
13 |
14 | # Extending devices
15 | Each device that should be supported requires their own .c file, which will only be compiled if the definition has been activated.
16 | To add your own device, the following information has to be gathered first:
17 | - General device:
18 | - The following information of the USB endpoint that is receiving/sending data:
19 | - Context Type
20 | - Max Packet Size
21 | - Average TRB Length
22 | - Mouse specific:
23 | - How the first bytes of the USB packets start (identifier)
24 |
25 | ## Locating USB specific details
26 | These details can be found in two ways, but as a general approach you should identify the Root Port number of the USB device.
27 | To locate the number, we recommend the [System Information Viewer](http://rh-software.com/) where you can open the USB Bus and locate the USB Device and the Port number based on the device name.
28 |
29 | ### Option 1: Enabling logging in SMM
30 | The parsing of the XHCI and logging of these values has already been added as code in the function `getEndpointRing` in [xhci.c](xhci.c).
31 | Simply lower the logging level of these messages, and then check the values of the endpoints of the Root Port number you identified earlier.
32 |
33 | ### Option 2: Manually navigating the XHCI structs
34 | In this option, you will be performing the same steps as the code does in [xhci.c](xhci.c).
35 | To directly access the physical memory and PCI config space, we recommend [RWEverything](https://rweverything.com/).
36 |
37 | #### Memory Base Address (MBAR)
38 | First access the PCI Config space of the XHCI USB Controller (Bus 00, Device 14, Function 00).
39 | At offset 0x10, you can find the 64-bit pointer of the Memory Base address (MBAR). Null the last byte and save this value.
40 | 
41 |
42 | #### Device Context Array Base (DCAB)
43 | Now access this MBAR using the Memory option in RWEverything, and read the 8-bit value of the capability register length.
44 | This length (0x80 in the picture) is used to skip the capability register, as afterwards the Host Operational register follows.
45 | At offset 0x30 in the Host Operational register we can finally read the Device Context Array Base (DCAB) (Final address: MBAR Address + Capability register length + 0x30 = 0xB0).
46 | This points to an array containing pointers to each connected USB device on the system.
47 | 
48 |
49 | #### Device Contexts
50 | Navigate to the DCAB, where there will be an array of 64-byte pointers, each of them for a separate device.
51 | 
52 |
53 | #### Root Port number
54 | Simply navigate to each of those devices now, and check the 8-bit value at offset 0x6 which is the Root Port number.
55 | Search for the device with the same Root Port number as previously identified for your device.
56 | 
57 |
58 | #### Endpoints
59 | At offset 0x20, the array of endpoints starts. Each endpoint struct has a size of 0x20.
60 | Each of these endpoints could be for the input/output data which is required for the interaction.
61 | 
62 |
63 | To identify the right endpoint, navigate to the memory address at offset 0x8, which points to the transfer ring.
64 | Each packet received/sent via this endpoint will be written to this ring top to down, thus the right endpoint can be identified by interacting with the device (e.g. move mouse or play music).
65 |
66 | When the right endpoint is identified, note down the following values:
67 | - Type: Offset 0x4, read 8-bit value, perform a right shift 3 for the type value (3-bit size, in bits 5:3).
68 | - Max packet size: Offset 0x6, 16-bit value.
69 | - Average TRB Length: Offset 0x10, 16-bit value.
70 |
71 | For further information, see our implementation in [xhci.c](xhci.c) or the XHCI specification from Intel (eXtensible Host Controller Interface for Universal Serial Bus (xHCI), Table 6-9 until 6-11).
72 |
73 | To further limit the number of endpoints down and prevent conflicts, also analyze the raw packet that can be found in the transfer ring previously identified.
74 | For newer Logitech mouses, we have identified the magic value "0x409301" at offset 0x8 which we use to 100% identify it as our device.
75 | Investigate if your device has a similar magic value, it is not required but recommended.
76 |
77 | ## Extending driver code
78 | Now with all values gathered, a new driver can be added as code.
79 |
80 | ### Extending Audio devices
81 |
82 | Create a new .c -file for your audio device, and guard it with C `#ifdef`s. Please see an example from the [dummy.c](audio/dummy.c)
83 | file. Inside this file, you should define a `InitAudioDriverFun` function (`typedef audioProfile_t EFIAPI (*InitAudioDriverFun)(VOID);`).
84 | Inside this function, you will be adding the previously identified values in the call to `getEndpointRing`. See the other implementations for further help.
85 | For this, please again see example from [dummy.c](audio/dummy.c). This function should return a `audioProfile_t` structure,
86 | including a `BOOLEAN` whether the device was initialized successfully, the number of audio channels of this device (`UINT64 audioChannels`)
87 | and the memory location of this device's Audio ring (`EFI_PHYSICAL_ADDRESS audioRingLocation`).
88 | To implement, please find examples from the [audio](audio) directory.
89 |
90 | After implementing your driver, add its declaration and entry to the `InitAudioDriverFuns` in [audioDriver.h](audio/audioDriver.h) file.
91 |
92 | You also need to edit the [Plouton.inf](../Plouton.inf) and add your implementation's .c file(s) to the list of to-be-compiled objects.
93 |
94 | After aforementioned steps, you should now be able to use your driver by defining your chosen `#ifdef` guard name inside [config.h](../general/config.h)
95 |
96 | ### Extending Mouse devices
97 |
98 | Extending mouse devices work the similar way as extending for new audio devices, but instead of having a single `InitAudioDriverFun`,
99 | the mouse drivers require two functions: `InitMouseDriver` (`typedef mouseProfile_t EFIAPI (*InitMouseDriver)(MouseDriverTdCheck);`)
100 | and `MouseDriverTdCheck` (`typedef BOOLEAN EFIAPI (*MouseDriverTdCheck)(EFI_PHYSICAL_ADDRESS);`). The latter is used at the very last
101 | stage of `getEndpointRing` in [xhci.c](xhci.c) to make sure that the device is really what we are looking for. Since we have two function pointers,
102 | after implementing the aforementioned functions, you should add their declarations and then add them in a new struct entry
103 | to the `InitMouseDriversFuns` array in [mouseDriver.h](mouse/mouseDriver.h) file. (Instead of just a single function pointer in audio side!)
104 |
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/target/cs2/cheatCS2.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for the functions used for the cs2 cheat
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_cheat_cs2_h__
8 | #define __plouton_cheat_cs2_h__
9 |
10 | // our includes
11 | #include "math.h"
12 | #include "offsetsCS2.h"
13 | #include "structuresCS2.h"
14 | #include "../../memory/sigScan.h"
15 | #include "../../os/windows/windows.h"
16 | #include "../../os/windows/NTKernelTools.h"
17 | #include "../../hardware/serial.h"
18 | #include "../../floats/floatlib.h"
19 | #include "../../hardware/xhci.h"
20 |
21 | // Structures
22 |
23 | // General structures
24 |
25 | // Game Structures
26 |
27 | // Type that is assigned per weapon for different settings
28 | typedef enum {
29 | None = 0x0,
30 | Rifle = 0x1,
31 | Pistol = 0x2,
32 | Sniper = 0x4,
33 | SMG = 0x8
34 | } WeaponType;
35 |
36 | // Aimbot stuff
37 | typedef enum {
38 | Pelvis,
39 | Chest,
40 | Head
41 | } AimbotHitbox;
42 |
43 | typedef struct
44 | {
45 | BOOLEAN found;
46 | INT32 index;
47 | AimbotHitbox hitbox;
48 | fix32_t smooth;
49 | } aimbotTarget;
50 |
51 | typedef struct _w2Mouse
52 | {
53 | INT16 x;
54 | INT16 y;
55 | BOOLEAN found;
56 | } w2Mouse, * Pw2Mouse;
57 |
58 | // Sound ESP stuff
59 | typedef struct _soundTarget
60 | {
61 | INT16 left;
62 | INT16 right;
63 | BOOLEAN found;
64 | } soundTarget, * PsoundTarget;
65 |
66 | // Localplayer Structures
67 | typedef struct _CS2Local {
68 | UINT64 pawn; // Pointer to the localplayer pawn structure
69 | UINT64 controller; // Pointer to the localplayer controller structure
70 | UINT32 team; // Team ID of the localplayer
71 | QVector viewAngles; // Viewangles of the localplayer
72 | UINT64 gameScene; // Pointer to the game scene structure
73 | Vector origin; // Origin Position of the localplayer
74 | Vector vecViewOffset; // Relative position of the eye of the localplayer
75 | QVector cameraPosition; // Camera Position of the localplayer
76 | UINT64 activeWeapon; // Pointer to the weapon structure of the localplayer
77 | UINT32 weaponAmmo; // If the weapon has ammo currently or is empty
78 | UINT16 weaponId; // ID of the weapon that is currently held by the localplayer
79 | WeaponType weaponType; // Type of the current weapon of the localplayer
80 | CS2CUtlVector punchCache; // Pointer to the last cache of the weapon punch
81 | Vector punchAngles; // Actual punch of the current weapon
82 | QAngle recoilAngles; // Already calculated angles with the included punch for RCS
83 | } CS2Local, * PCS2Local;
84 |
85 | // Player structures
86 | typedef struct _CS2Player {
87 | UINT64 pawn; // Pointer to the player pawn structure
88 | UINT64 controller; // Pointer to the player controller structure
89 | UINT32 index; // Index of the player entity for identification
90 | UINT32 health; // Health of the player entity
91 | BOOLEAN alive; // Alive status of the entity
92 | BOOLEAN immune; // Immune status of the entity (in warmup)
93 | UINT32 team; // Team ID of the entity
94 | BOOLEAN spotted; // Spotted status of the entity for the radar
95 | UINT64 gameScene; // Pointer to the game scene structure
96 | UINT64 boneArray; // Pointer to the bone array structure
97 | QVector bonePositionHead; // Vector containing the 3d location of the entity head
98 | QVector bonePositionPelvis; // Vector containing the 3d location of the entity stomach
99 | QVector velocity; // Velocity of the current moving entity
100 | INT32 yawRotation; // Current yaw (Y) rotation of the entity
101 | } CS2Player, * PCS2Player;
102 |
103 | // Definitions
104 |
105 | // Functions
106 |
107 | // Main Functions
108 |
109 | /*
110 | * Function: CheatCs2Main
111 | * --------------------
112 | * Basic cheat loop that calls the update functions and performs the cheat functionalities.
113 | */
114 | VOID EFIAPI CheatCs2Main();
115 |
116 | /*
117 | * Function: InitCheatCS2
118 | * --------------------
119 | * Searches and initializes the basic functions (process, modules and sig scans)
120 | */
121 | BOOLEAN EFIAPI InitCheatCS2();
122 |
123 | // Feature Functions
124 |
125 | /*
126 | * Function: findNewAimbotTarget
127 | * --------------------
128 | * Function that will find the nearest aimbot target and return it.
129 | */
130 | aimbotTarget findNewAimbotTarget(CS2Local localplayer, CS2Player* players, UINT8 playerAmount, fix32_t headIncrease);
131 |
132 | /*
133 | * Function: findNewSoundTarget
134 | * --------------------
135 | * Function that will find the nearest sound ESP target and return it
136 | */
137 | soundTarget findNewSoundTarget(CS2Local localplayer, CS2Player* players, UINT8 playerAmount);
138 |
139 | /*
140 | * Function: aimAtTarget
141 | * --------------------
142 | * Verifies that the target is still up-to-date and calculates the 2D Coordinates that should be moved to aim at at the player.
143 | */
144 | w2Mouse aimAtTarget(CS2Local localplayer, CS2Player* players, UINT8 playerAmount, aimbotTarget aimTarget, BOOLEAN useSmooth);
145 |
146 | // Localplayer Functions
147 |
148 | /*
149 | * Function: getLocalPlayer
150 | * --------------------
151 | * Gets the localplayer structure and writes it into the supplied pointer
152 | */
153 | BOOLEAN getLocalPlayer(PCS2Local localplayer);
154 |
155 | // Player functions
156 |
157 | /*
158 | * Function: getPlayerByIndex
159 | * --------------------
160 | * Reads the player entity at the given index and returns it
161 | */
162 | BOOLEAN getPlayerByIndex(PCS2Player player, UINT16 index, PCS2Local localplayer, BOOLEAN updateTeammates);
163 |
164 | /*
165 | * Function: getPlayerBoneTransform
166 | * --------------------
167 | * Initializes the CTransform struct with the data of the bone of the player.
168 | */
169 | BOOLEAN getPlayerBoneTransform(CTransform* pCTransform, EFI_VIRTUAL_ADDRESS transform_pointer);
170 |
171 | /*
172 | * Function: getPlayerPawn
173 | * --------------------
174 | * Returns the address of the pawn of the player based on the controller pointer.
175 | */
176 | EFI_VIRTUAL_ADDRESS getPlayerPawn(EFI_VIRTUAL_ADDRESS controller);
177 |
178 | /*
179 | * Function: getPlayerController
180 | * --------------------
181 | * Returns the address of the controller of the given entity index
182 | */
183 | EFI_VIRTUAL_ADDRESS getPlayerController(UINT16 index);
184 |
185 | // Calculation functions
186 |
187 | /*
188 | * Function: extrapolatePosition
189 | * --------------------
190 | * Calculates the extrapolated position based on current position and active velocity
191 | */
192 | QVector extrapolatePosition(QVector position, QVector velocity);
193 |
194 | // Weapon type functions
195 |
196 | /*
197 | * Function: checkRifle
198 | * --------------------
199 | * Verifies if the given weapon ID is a rifle.
200 | */
201 | BOOLEAN checkRifle(int weaponid);
202 |
203 | /*
204 | * Function: checkPistol
205 | * --------------------
206 | * Verifies if the given weapon ID is a pistol.
207 | */
208 | BOOLEAN checkPistol(int weaponid);
209 |
210 | /*
211 | * Function: checkSniper
212 | * --------------------
213 | * Verifies if the given weapon ID is a sniper.
214 | */
215 | BOOLEAN checkSniper(int weaponid);
216 |
217 | /*
218 | * Function: checkSMG
219 | * --------------------
220 | * Verifies if the given weapon ID is a SMG.
221 | */
222 | BOOLEAN checkSMG(int weaponid);
223 |
224 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/floats/floatlib.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for fixed point related functionalities
4 | *
5 | * For more general implementation, see https://github.com/jussihi/libfixmath64
6 | *
7 | --*/
8 |
9 | #ifndef __plouton_floatlib_h__
10 | #define __plouton_floatlib_h__
11 |
12 | // our includes
13 | #include "../hardware/serial.h"
14 |
15 | // Structures
16 |
17 | #ifndef INT32_MAX
18 | #define INT32_MAX 0x7fffffffL
19 | #endif
20 | #ifndef INT32_MIN
21 | #define INT32_MIN (-INT32_MAX - 1L)
22 | #endif
23 |
24 | typedef union {
25 | struct {
26 | UINT32 fraction : 23;
27 | UINT32 exp_bias : 8;
28 | UINT32 sign : 1;
29 | } fields;
30 |
31 | INT32 dword;
32 | INT32 float_value;
33 | } IEEE745_float;
34 |
35 | typedef INT64 fix32_t;
36 |
37 | // Definitions
38 |
39 | static const fix32_t FOUR_DIV_PI = 0x0000000145F306DD; /*!< Fix32 value of 4/PI */
40 | static const fix32_t _FOUR_DIV_PI2 = 0xFFFFFFFF983f4277; /*!< Fix32 value of -4/PI² */
41 | static const fix32_t X4_CORRECTION_COMPONENT = 0x3999999A; /*!< Fix32 value of 0.225 */
42 | static const fix32_t PI_DIV_4 = 0x00000000C90FDAA2; /*!< Fix32 value of PI/4 */
43 | static const fix32_t THREE_PI_DIV_4 = 0x000000025B2F8FE6; /*!< Fix32 value of 3PI/4 */
44 |
45 | static const fix32_t fix32_maximum = 0x7FFFFFFFFFFFFFFF; /*!< the maximum value of fix32_t */
46 | static const fix32_t fix32_minimum = 0x8000000000000000; /*!< the maximum value of fix32_t */
47 | static const fix32_t fix32_overflow = 0x8000000000000000; /*!< the value used to indicate overflows when FIXMATH_NO_OVERFLOW is not specified */
48 |
49 | static const fix32_t fix32_pi = 0x00000003243F6A88; /*!< fix32_t value of pi */
50 | static const fix32_t fix32_e = 0x00000002B7E15163; /*!< fix32_t value of e */
51 |
52 | static const fix32_t fix32_fivethousand = 0x138800000000; /*!< fix32_t value of 5000 */
53 | static const fix32_t fix32_1920 = 0x0000078000000000; /*!< fix32_t value of 1920 */
54 | static const fix32_t fix32_1080 = 0x0000043800000000; /*!< fix32_t value of 1080 */
55 | static const fix32_t fix32_thousand = 0x000003e800000000; /*!< fix32_t value of 1000 */
56 | static const fix32_t fix32_360 = 0x0000016800000000; /*!< fix32_t value of 360 */
57 | static const fix32_t fix32_270 = 0x0000010e00000000; /*!< fix32_t value of 270 */
58 | static const fix32_t fix32_180 = 0x000000b400000000; /*!< fix32_t value of 180 */
59 | static const fix32_t fix32_100 = 0x0000006400000000; /*!< fix32_t value of 100 */
60 | static const fix32_t fix32_90 = 0x0000005a00000000; /*!< fix32_t value of 90 */
61 | static const fix32_t fix32_89 = 0x0000005900000000; /*!< fix32_t value of 89 */
62 | static const fix32_t fix32_70 = 0x0000004600000000; /*!< fix32_t value of 70 */
63 | static const fix32_t fix32_50 = 0x0000003200000000; /*!< fix32_t value of 50 */
64 | static const fix32_t fix32_25 = 0x0000001900000000; /*!< fix32_t value of 25 */
65 | static const fix32_t fix32_21 = 0x0000001500000000; /*!< fix32_t value of 21 */
66 | static const fix32_t fix32_20 = 0x0000001400000000; /*!< fix32_t value of 20 */
67 | static const fix32_t fix32_17 = 0x0000001100000000; /*!< fix32_t value of 17 */
68 | static const fix32_t fix32_16 = 0x0000001000000000; /*!< fix32_t value of 16 */
69 | static const fix32_t fix32_15 = 0x0000000f00000000; /*!< fix32_t value of 15 */
70 | static const fix32_t fix32_13 = 0x0000000d00000000; /*!< fix32_t value of 13 */
71 | static const fix32_t fix32_12 = 0x0000000c00000000; /*!< fix32_t value of 12 */
72 | static const fix32_t fix32_10 = 0x0000000a00000000; /*!< fix32_t value of 10 */
73 | static const fix32_t fix32_8 = 0x0000000800000000; /*!< fix32_t value of 8 */
74 | static const fix32_t fix32_7 = 0x0000000600000000; /*!< fix32_t value of 7 */
75 | static const fix32_t fix32_6 = 0x0000000600000000; /*!< fix32_t value of 6 */
76 | static const fix32_t fix32_5 = 0x0000000500000000; /*!< fix32_t value of 5 */
77 | static const fix32_t fix32_4 = 0x0000000400000000; /*!< fix32_t value of 4 */
78 | static const fix32_t fix32_two = 0x0000000200000000; /*!< fix32_t value of 2 */
79 | static const fix32_t fix32_one = 0x0000000100000000; /*!< fix32_t value of 1 */
80 | static const fix32_t fix32_zero = 0x0000000000000000; /*!< fix32_t value of 0 */
81 | static const fix32_t fix32_05 = 0x0000000080000000; /*!< fix32_t value of 0.5f */
82 | static const fix32_t fix32_022 = 0x0000000005A1CAC0; /*!< fix32_t value of 0.022f */
83 | static const fix32_t fix32_0015625 = 0x0000000004000000; /*!< fix32_t value of 0.015625f */
84 | static const fix32_t fix32_neg_one = 0xffffffff00000000; /*!< fix32_t value of -1 */
85 | static const fix32_t fix32_neg_89 = 0xffffffa700000000; /*!< fix32_t value of -89 */
86 | static const fix32_t fix32_neg_180 = 0xffffff4c00000000; /*!< fix32_t value of -180 */
87 | static const fix32_t fix32_neg_360 = 0xfffffe9800000000; /*!< fix32_t value of -360 */
88 |
89 | static const int IEEE745_FLOAT_BIAS = 127;
90 |
91 | // Functions
92 |
93 | /*
94 | * Conversion functions between fix16_t and integer.
95 | * These are inlined to allow compiler to optimize away constant numbers
96 | */
97 |
98 | static inline fix32_t fix32_from_int(INT32 a)
99 | {
100 | return a * fix32_one;
101 | }
102 |
103 | static inline INT64 int_from_fix32(fix32_t a)
104 | {
105 | return a / fix32_one;
106 | }
107 |
108 | /* Macro for defining fix16_t constant values.
109 | The functions above can't be used from e.g. global variable initializers,
110 | and their names are quite long also. This macro is useful for constants
111 | springled alongside code, e.g. F16(1.234).
112 | Note that the argument is evaluated multiple times, and also otherwise
113 | you should only use this for constant values. For runtime-conversions,
114 | use the functions above.
115 | */
116 | #define F16(x) ((fix16_t)(((x) >= 0) ? ((x) * 65536.0 + 0.5) : ((x) * 65536.0 - 0.5)))
117 |
118 | static inline fix32_t fix32_abs(fix32_t x)
119 | {
120 | return (x < 0 ? -x : x);
121 | }
122 |
123 | static inline fix32_t fix32_floor(fix32_t x)
124 | {
125 | return (x & 0xFFFFFFFF00000000ULL);
126 | }
127 |
128 | static inline fix32_t fix32_ceil(fix32_t x)
129 | {
130 | return (x & 0xFFFFFFFF00000000ULL) + (x & 0x00000000FFFFFFFFULL ? fix32_one : 0);
131 | }
132 |
133 | static inline fix32_t fix32_min(fix32_t x, fix32_t y)
134 | {
135 | return (x < y ? x : y);
136 | }
137 |
138 | static inline fix32_t fix32_max(fix32_t x, fix32_t y)
139 | {
140 | return (x > y ? x : y);
141 | }
142 |
143 | static inline fix32_t fix32_clamp(fix32_t x, fix32_t lo, fix32_t hi)
144 | {
145 | return fix32_min(fix32_max(x, lo), hi);
146 | }
147 |
148 | /*
149 | * Comparator function, returns a positive if a is larger,
150 | * negative if b is larger.
151 | */
152 | static inline BOOLEAN fix32_cmp(fix32_t a, fix32_t b)
153 | {
154 | return a == b;
155 | }
156 |
157 | static inline BOOLEAN fix32_larger(fix32_t a, fix32_t b)
158 | {
159 | return a > b;
160 | }
161 |
162 | static inline BOOLEAN fix32_largereq(fix32_t a, fix32_t b)
163 | {
164 | return a >= b;
165 | }
166 |
167 | static inline BOOLEAN fix32_less(fix32_t a, fix32_t b)
168 | {
169 | return a < b;
170 | }
171 |
172 | static inline BOOLEAN fix32_lesseq(fix32_t a, fix32_t b)
173 | {
174 | return a <= b;
175 | }
176 |
177 | /*
178 | * Function: fix32_sqrt
179 | * --------------------
180 | * Converts a float to a an integer with no decimals.
181 | */
182 | INT32 fix32_to_int(fix32_t value);
183 |
184 | /*
185 | * Function: float2int
186 | * --------------------
187 | * xxx.
188 | */
189 | INT32 float2int(const void* value);
190 |
191 | /*
192 | * Function: fix32_from_float
193 | * --------------------
194 | * Converts a float to a fixed point q31.32 integer
195 | */
196 | fix32_t fix32_from_float(const void* value);
197 |
198 | /*
199 | * Function: float_from_fix32
200 | * --------------------
201 | * Converts a q31.32 integer back to IEEE754 floating point.
202 | */
203 | UINT32 float_from_fix32(fix32_t value);
204 |
205 | /*
206 | * Function: fix32_add
207 | * --------------------
208 | * Adds the two given fix32_t together and returns the results.
209 | */
210 | fix32_t fix32_add(fix32_t a, fix32_t b);
211 |
212 | /*
213 | * Function: fix32_sub
214 | * --------------------
215 | * Substracts the second fix32_t from the first fix_32 and returns the result.
216 | */
217 | fix32_t fix32_sub(fix32_t a, fix32_t b);
218 |
219 | /*
220 | * Function: fix32_mul
221 | * --------------------
222 | * Multiplies the two given fix32_t's and returns the result.
223 | */
224 | fix32_t fix32_mul(fix32_t inArg0, fix32_t inArg1);
225 |
226 | /*
227 | * Function: fix32_div
228 | * --------------------
229 | * Divides the first given fix32_t by the second and returns the result.
230 | */
231 | fix32_t fix32_div(fix32_t a, fix32_t b);
232 |
233 | /*
234 | * Function: fix32_sqrt
235 | * --------------------
236 | * Returns the square root of the given fix32_t.
237 | */
238 | fix32_t fix32_sqrt(fix32_t inValue);
239 |
240 | /*
241 | * Function: fix32_sin
242 | * --------------------
243 | * Returns the sine of the given fix32_t using a lookup table.
244 | */
245 | fix32_t fix32_sin(fix32_t inAngle);
246 |
247 | /*
248 | * Function: fix32_cos
249 | * --------------------
250 | * Returns the cosine of the given fix32_t using fix32_sin.
251 | */
252 | fix32_t fix32_cos(fix32_t inAngle);
253 |
254 | /*
255 | * Function: fix32_atan2
256 | * --------------------
257 | * Returns the arctangent of inY/inX..
258 | */
259 | fix32_t fix32_atan2(fix32_t inY , fix32_t inX);
260 |
261 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/os/windows/windows.h:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Header file for windows related structures
4 | *
5 | --*/
6 |
7 | #ifndef __plouton_windows_h__
8 | #define __plouton_windows_h__
9 |
10 | #ifdef __GNUC__
11 | typedef unsigned int size_t;
12 | #endif
13 |
14 | // Definitions for values used in NT Kernel parsing
15 | #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
16 | #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
17 | #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
18 | #define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */
19 | #define IMAGE_NT_SIGNATURE 0x4550 /* PE00 */
20 | #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
21 | #define IMAGE_SIZEOF_SHORT_NAME 8
22 |
23 | // Structures
24 |
25 | // Structures for the result of the NT Kernel initialization which contain information about the kernel and the processes
26 | typedef struct WinExport
27 | {
28 | char* name;
29 | UINT64 address;
30 | } WinExport;
31 |
32 | typedef struct WinExportList
33 | {
34 | WinExport* list;
35 | size_t size;
36 | } WinExportList;
37 |
38 | typedef struct WinOffsets
39 | {
40 | UINT64 apl;
41 | UINT64 imageFileName;
42 | UINT64 stackCount;
43 | UINT64 dirBase;
44 | UINT64 peb;
45 | UINT64 virtualSize;
46 | UINT64 vadroot;
47 | UINT64 imageFilePointer;
48 | UINT64 fileName;
49 | } WinOffsets;
50 |
51 | typedef struct ProcessData
52 | {
53 | UINT64 mapsStart;
54 | UINT64 mapsSize;
55 | UINT8 pid;
56 | } ProcessData;
57 |
58 | typedef struct WinModule
59 | {
60 | UINT64 baseAddress;
61 | UINT64 entryPoint;
62 | UINT64 sizeOfModule;
63 | char* name;
64 | short loadCount;
65 | } WinModule;
66 |
67 | typedef struct WinProc
68 | {
69 | UINT64 process;
70 | UINT64 physProcess;
71 | UINT64 dirBase;
72 | UINT64 pid;
73 | UINT64 size;
74 | UINT64 vadRoot;
75 | char name[16];
76 | } WinProc;
77 |
78 | typedef struct WinCtx
79 | {
80 | ProcessData process;
81 | WinOffsets offsets;
82 | UINT64 ntKernel;
83 | UINT16 ntVersion;
84 | UINT32 ntBuild;
85 | WinExportList ntExports;
86 | WinProc initialProcess;
87 | WinProc gameProcess;
88 | } WinCtx;
89 |
90 | // Various structs used in NT Kernel
91 | typedef struct _IMAGE_DOS_HEADER {
92 | UINT16 e_magic;
93 | UINT16 e_cblp;
94 | UINT16 e_cp;
95 | UINT16 e_crlc;
96 | UINT16 e_cparhdr;
97 | UINT16 e_minalloc;
98 | UINT16 e_maxalloc;
99 | UINT16 e_ss;
100 | UINT16 e_sp;
101 | UINT16 e_csum;
102 | UINT16 e_ip;
103 | UINT16 e_cs;
104 | UINT16 e_lfarlc;
105 | UINT16 e_ovno;
106 | UINT16 e_res[4];
107 | UINT16 e_oemid;
108 | UINT16 e_oeminfo;
109 | UINT16 e_res2[10];
110 | int e_lfanew;
111 | } IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
112 |
113 | typedef struct _IMAGE_EXPORT_DIRECTORY {
114 | UINT32 Characteristics;
115 | UINT32 TimeDateStamp;
116 | UINT16 MajorVersion;
117 | UINT16 MinorVersion;
118 | UINT32 Name;
119 | UINT32 Base;
120 | UINT32 NumberOfFunctions;
121 | UINT32 NumberOfNames;
122 | UINT32 AddressOfFunctions;
123 | UINT32 AddressOfNames;
124 | UINT32 AddressOfNameOrdinals;
125 | } IMAGE_EXPORT_DIRECTORY, * PIMAGE_EXPORT_DIRECTORY;
126 |
127 | typedef struct _IMAGE_FILE_HEADER {
128 | UINT16 Machine;
129 | UINT16 NumberOfSections;
130 | UINT32 TimeDateStamp;
131 | UINT32 PointerToSymbolTable;
132 | UINT32 NumberOfSymbols;
133 | UINT16 SizeOfOptionalHeader;
134 | UINT16 Characteristics;
135 | } IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
136 |
137 | typedef struct _IMAGE_DATA_DIRECTORY {
138 | UINT32 VirtualAddress;
139 | UINT32 Size;
140 | } IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
141 |
142 | typedef struct _IMAGE_OPTIONAL_HEADER64 {
143 | UINT16 Magic;
144 | UINT8 MajorLinkerVersion;
145 | UINT8 MinorLinkerVersion;
146 | UINT32 SizeOfCode;
147 | UINT32 SizeOfInitializedData;
148 | UINT32 SizeOfUninitializedData;
149 | UINT32 AddressOfEntryPoint;
150 | UINT32 BaseOfCode;
151 | UINT64 ImageBase;
152 | UINT32 SectionAlignment;
153 | UINT32 FileAlignment;
154 | UINT16 MajorOperatingSystemVersion;
155 | UINT16 MinorOperatingSystemVersion;
156 | UINT16 MajorImageVersion;
157 | UINT16 MinorImageVersion;
158 | UINT16 MajorSubsystemVersion;
159 | UINT16 MinorSubsystemVersion;
160 | UINT32 Win32VersionValue;
161 | UINT32 SizeOfImage;
162 | UINT32 SizeOfHeaders;
163 | UINT32 CheckSum;
164 | UINT16 Subsystem;
165 | UINT16 DllCharacteristics;
166 | UINT64 SizeOfStackReserve;
167 | UINT64 SizeOfStackCommit;
168 | UINT64 SizeOfHeapReserve;
169 | UINT64 SizeOfHeapCommit;
170 | UINT32 LoaderFlags;
171 | UINT32 NumberOfRvaAndSizes;
172 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
173 | } IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
174 |
175 | typedef struct _IMAGE_NT_HEADERS64 {
176 | UINT32 Signature;
177 | IMAGE_FILE_HEADER FileHeader;
178 | IMAGE_OPTIONAL_HEADER64 OptionalHeader;
179 | } IMAGE_NT_HEADERS64, IMAGE_NT_HEADERS, * PIMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS;
180 |
181 | typedef struct _IMAGE_OPTIONAL_HEADER32 {
182 | UINT16 Magic;
183 | UINT8 MajorLinkerVersion;
184 | UINT8 MinorLinkerVersion;
185 | UINT32 SizeOfCode;
186 | UINT32 SizeOfInitializedData;
187 | UINT32 SizeOfUninitializedData;
188 | UINT32 AddressOfEntryPoint;
189 | UINT32 BaseOfCode;
190 | UINT32 BaseOfData;
191 | UINT32 ImageBase;
192 | UINT32 SectionAlignment;
193 | UINT32 FileAlignment;
194 | UINT16 MajorOperatingSystemVersion;
195 | UINT16 MinorOperatingSystemVersion;
196 | UINT16 MajorImageVersion;
197 | UINT16 MinorImageVersion;
198 | UINT16 MajorSubsystemVersion;
199 | UINT16 MinorSubsystemVersion;
200 | UINT32 Win32VersionValue;
201 | UINT32 SizeOfImage;
202 | UINT32 SizeOfHeaders;
203 | UINT32 CheckSum;
204 | UINT16 Subsystem;
205 | UINT16 DllCharacteristics;
206 | UINT32 SizeOfStackReserve;
207 | UINT32 SizeOfStackCommit;
208 | UINT32 SizeOfHeapReserve;
209 | UINT32 SizeOfHeapCommit;
210 | UINT32 LoaderFlags;
211 | UINT32 NumberOfRvaAndSizes;
212 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
213 | } IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;
214 |
215 | typedef struct _IMAGE_NT_HEADERS32 {
216 | UINT32 Signature;
217 | IMAGE_FILE_HEADER FileHeader;
218 | IMAGE_OPTIONAL_HEADER32 OptionalHeader;
219 | } IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32;
220 |
221 | typedef struct _IMAGE_SECTION_HEADER {
222 | UINT8 Name[IMAGE_SIZEOF_SHORT_NAME];
223 | union {
224 | UINT32 PhysicalAddress;
225 | UINT32 VirtualSize;
226 | } Misc;
227 | UINT32 VirtualAddress;
228 | UINT32 SizeOfRawData;
229 | UINT32 PointerToRawData;
230 | UINT32 PointerToRelocations;
231 | UINT32 PointerToLinenumbers;
232 | UINT16 NumberOfRelocations;
233 | UINT16 NumberOfLinenumbers;
234 | UINT32 Characteristics;
235 | } IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER;
236 |
237 | // 64 bit structures for PEB parsing
238 | typedef struct _UNICODE_STRING
239 | {
240 | UINT16 length;
241 | UINT16 maximum_length;
242 | UINT64 buffer;
243 | } UNICODE_STRING;
244 |
245 | typedef struct _LIST_ENTRY64
246 | {
247 | UINT64 f_link;
248 | UINT64 b_link;
249 | } LIST_ENTRY64;
250 |
251 | typedef struct _LDR_MODULE {
252 | LIST_ENTRY64 InLoadOrderModuleList;
253 | LIST_ENTRY64 InMemoryOrderModuleList;
254 | LIST_ENTRY64 InInitializationOrderModuleList;
255 | UINT64 BaseAddress;
256 | UINT64 EntryPoint;
257 | UINT64 SizeOfImage;
258 | UNICODE_STRING FullDllName;
259 | UNICODE_STRING BaseDllName;
260 | UINT64 Flags;
261 | short LoadCount;
262 | short TlsIndex;
263 | LIST_ENTRY64 HashTableEntry;
264 | UINT64 TimeDateStamp;
265 | } LDR_MODULE, * PLDR_MODULE;
266 |
267 | typedef struct _PEB_LDR_DATA
268 | {
269 | UINT64 Length;
270 | UINT8 Initialized;
271 | UINT64 SsHandle;
272 | LIST_ENTRY64 InLoadOrderModuleList;
273 | LIST_ENTRY64 InMemoryOrderModuleList;
274 | LIST_ENTRY64 InInitializationOrderModuleList;
275 | UINT64 EntryInProgress;
276 | } PEB_LDR_DATA;
277 |
278 | typedef struct _PEB
279 | {
280 | UINT8 InheritedAddressSpace;
281 | UINT8 ReadImageFileExecOptions;
282 | UINT8 BeingFebugged;
283 | UINT8 BitField;
284 | UINT8 Padding0[4];
285 | UINT64 Mutant;
286 | UINT64 ImageBaseAddress;
287 | UINT64 Ldr;
288 | } PEB, PEB64;
289 |
290 | // 32 bit structures for PEB parsing
291 | typedef struct _LIST_ENTRY32
292 | {
293 | UINT32 f_link;
294 | UINT32 b_link;
295 | } LIST_ENTRY32;
296 |
297 | typedef struct _UNICODE_STRING32
298 | {
299 | UINT16 length;
300 | UINT16 maximum_length;
301 | UINT32 buffer;
302 | } UNICODE_STRING32;
303 |
304 | typedef struct _LDR_MODULE32 {
305 | LIST_ENTRY32 InLoadOrderModuleList;
306 | LIST_ENTRY32 InMemoryOrderModuleList;
307 | LIST_ENTRY32 InInitializationOrderModuleList;
308 | UINT32 BaseAddress;
309 | UINT32 EntryPoint;
310 | UINT32 SizeOfImage;
311 | UNICODE_STRING32 FullDllName;
312 | UNICODE_STRING32 BaseDllName;
313 | UINT32 Flags;
314 | short LoadCount;
315 | short TlsIndex;
316 | LIST_ENTRY32 HashTableEntry;
317 | UINT32 TimeDateStamp;
318 | } LDR_MODULE32, * PLDR_MODULE32;
319 |
320 | typedef struct _PEB_LDR_DATA32
321 | {
322 | UINT32 Length;
323 | UINT32 SsHandle;
324 | UINT32 Reserved1;
325 | LIST_ENTRY32 InLoadOrderModuleList;
326 | LIST_ENTRY32 InMemoryOrderModuleList;
327 | LIST_ENTRY32 InInitializationOrderModuleList;
328 | UINT32 EntryInProgress;
329 | } PEB_LDR_DATA32;
330 |
331 | typedef struct _PEB32
332 | {
333 | UINT8 InheritedAddressSpace;
334 | UINT8 ReadImageFileExecOptions;
335 | UINT8 BeingFebugged;
336 | UINT8 BitField;
337 | UINT32 Mutant;
338 | UINT32 ImageBaseAddress;
339 | UINT32 Ldr;
340 | } PEB32;
341 |
342 | // Definitions
343 |
344 | // General definitions used in NTKernelTools.c
345 | #define HEADER_SIZE 0x1000
346 | #define PAGE_OFFSET_SIZE 12
347 | static const UINT64 PMASK = (~0xfull << 8) & 0xfffffffffull;
348 |
349 | // Functions
350 |
351 | #endif
--------------------------------------------------------------------------------
/Plouton-UEFI/Plouton/memory/memoryMapUEFI.c:
--------------------------------------------------------------------------------
1 | /*++
2 | *
3 | * Source file for memory map related functions
4 | *
5 | --*/
6 |
7 | // our includes
8 | #include "memoryMapUEFI.h"
9 | #include "../logging/logging.h"
10 |
11 | // Global memory map related variables
12 | EFI_MEMORY_DESCRIPTOR* mUefiMemoryMap;
13 | UINTN mUefiMemoryMapSize;
14 | UINTN mUefiDescriptorSize;
15 |
16 | /*
17 | * Function: CheckUefiMemoryMap
18 | * --------------------
19 | * Checks if the passed memory map has atleast 3 valid entries.
20 | *
21 | *
22 | * returns: Returns true if there is more than 3 entries, otherwise 0
23 | *
24 | */
25 | BOOLEAN CheckUefiMemoryMap(EFI_MEMORY_DESCRIPTOR* MemoryMap, UINT64 MemoryMapSize, UINT64 MemoryMapDescriptorSize)
26 | {
27 | // Used to count the valid pages
28 | UINTN Counter = 0;
29 |
30 | // Check if we even got valid parameters passed
31 | if (MemoryMap != NULL && MemoryMapSize != 0 && MemoryMapDescriptorSize != 0)
32 | {
33 | // Set the start of the memory map as entry
34 | EFI_MEMORY_DESCRIPTOR* CurMemoryMap = MemoryMap;
35 |
36 | // Calculate the amount of entries by dividing size by descriptor size
37 | UINTN MemoryMapEntryCount = MemoryMapSize / MemoryMapDescriptorSize;
38 |
39 | // Go through all entries
40 | for (UINTN Index = 0; Index < MemoryMapEntryCount; Index++)
41 | {
42 | // Check if the entry has a physical start and number of pages different than 0
43 | if ((CurMemoryMap->PhysicalStart != 0) || (CurMemoryMap->NumberOfPages != 0))
44 | {
45 | // Valid page, increase counter
46 | Counter += 1;
47 | }
48 |
49 | // Set 'CurMemoryMap' to the next entry
50 | CurMemoryMap = NEXT_MEMORY_DESCRIPTOR(CurMemoryMap, MemoryMapDescriptorSize);
51 | }
52 | }
53 |
54 | // Check if there were more than 3 entries
55 | if (Counter >= 3)
56 | {
57 | // Yes, return true
58 | return TRUE;
59 | }
60 |
61 | // Less than 3 entries or invalid parameters, return false
62 | return FALSE;
63 | }
64 |
65 | /*
66 | * Function: SortMemoryMap
67 | * --------------------
68 | * Sorts the passed memory map for nicer presentation
69 | *
70 | * MemoryMap: Pointer to the existing memory map that should be sorted
71 | * MemoryMapSize: Size of the memory map
72 | * DescriptorSize: Size of a single descriptor in the memory map
73 | *
74 | * returns: Nothing
75 | *
76 | */
77 | VOID SortMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR* MemoryMap, IN UINTN MemoryMapSize, IN UINTN DescriptorSize)
78 | {
79 | // Variable used to copy between memory map entries
80 | EFI_MEMORY_DESCRIPTOR TempMemoryMap = { 0, 0, 0, 0, 0 };
81 |
82 | // Calculate the end of the memory map
83 | const EFI_MEMORY_DESCRIPTOR* MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MemoryMap + MemoryMapSize);
84 |
85 | // Select the first entry
86 | EFI_MEMORY_DESCRIPTOR* MemoryMapEntry = MemoryMap;
87 |
88 | // Get the first entry in the memory map
89 | EFI_MEMORY_DESCRIPTOR* NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(MemoryMapEntry, DescriptorSize);
90 |
91 | // Go through the memory map entry until the entry would be out of the memory map size
92 | while (MemoryMapEntry < MemoryMapEnd)
93 | {
94 | // Check if the next memory map entry would be out of the memory map to prevent overflows
95 | while (NextMemoryMapEntry < MemoryMapEnd)
96 | {
97 | // Check if the current memory map entry is bigger than the next entry
98 | if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart)
99 | {
100 | // Its bigger, swap places
101 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)&TempMemoryMap, (EFI_PHYSICAL_ADDRESS)MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
102 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)MemoryMapEntry, (EFI_PHYSICAL_ADDRESS)NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
103 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)NextMemoryMapEntry, (EFI_PHYSICAL_ADDRESS)&TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));
104 | }
105 |
106 | // Set the current memory map entry to the next memory map entry
107 | NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(NextMemoryMapEntry, DescriptorSize);
108 | }
109 |
110 | // We reached the end. Set current and next memory map entry to the same value
111 | MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(MemoryMapEntry, DescriptorSize);
112 | NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(MemoryMapEntry, DescriptorSize);
113 | }
114 |
115 | return;
116 | }
117 |
118 | /*
119 | * Function: MergeMemoryMapForNotPresentEntry
120 | * --------------------
121 | * Removes specific entries from the memory map which should not be touched as they are not present.
122 | *
123 | * MemoryMap: Pointer to the existing memory map that should be sorted
124 | * MemoryMapSize: Size of the memory map
125 | * DescriptorSize: Size of a single descriptor in the memory map
126 | *
127 | * returns: Nothing
128 | *
129 | */
130 | VOID MergeMemoryMapForNotPresentEntry(IN OUT EFI_MEMORY_DESCRIPTOR* MemoryMap, IN OUT UINTN* MemoryMapSize, IN UINTN DescriptorSize)
131 | {
132 | // Define some variables used for parsing
133 | UINT64 MemoryBlockLength;
134 | EFI_MEMORY_DESCRIPTOR* NextMemoryMapEntry;
135 |
136 | // Calculate the end of the memory map
137 | const EFI_MEMORY_DESCRIPTOR* MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MemoryMap + *MemoryMapSize);
138 |
139 | // Get the first entry in the memory map
140 | EFI_MEMORY_DESCRIPTOR* MemoryMapEntry = MemoryMap;
141 | EFI_MEMORY_DESCRIPTOR* NewMemoryMapEntry = MemoryMap;
142 |
143 | // Go through all entries until we are out of the memory map size
144 | while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd)
145 | {
146 | pMemCpyForce((EFI_PHYSICAL_ADDRESS)NewMemoryMapEntry, (EFI_PHYSICAL_ADDRESS)MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
147 |
148 | // Get the next memory map entry
149 | NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(MemoryMapEntry, DescriptorSize);
150 |
151 | do
152 | {
153 | // Get the size of the memory map entry
154 | MemoryBlockLength = (UINT64)(EFI_PAGES_TO_SIZE((UINTN)MemoryMapEntry->NumberOfPages));
155 |
156 | // Make sure the next memory map entry is still inbound of the memory map and the current memory map entry address ends where the next memory map entry address starts
157 | if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) && ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
158 | {
159 | // End is equal to start of next entry -> we can merge them together to get a smaller memory map
160 | MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
161 |
162 | // Make sure the next memory map entry is not the current memory map entry
163 | if (NewMemoryMapEntry != MemoryMapEntry)
164 | {
165 | // Now increase the size in the current entry
166 | NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
167 | }
168 |
169 | // Get the next memory map entry to continue this process
170 | NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(NextMemoryMapEntry, DescriptorSize);
171 | continue;
172 | }
173 | else
174 | {
175 | // Cant merge the entries -> get the next entry
176 | MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR(NextMemoryMapEntry, DescriptorSize);
177 | break;
178 | }
179 | } while (TRUE);
180 |
181 | // Current entries cant be merged, get next entries and repeat process
182 | MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(MemoryMapEntry, DescriptorSize);
183 | NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR(NewMemoryMapEntry, DescriptorSize);
184 | }
185 |
186 | // Update the memory map size as we changed it due to the merges
187 | *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
188 |
189 | return;
190 | }
191 |
192 | /*
193 | * Function: InitUefiMemoryMap
194 | * --------------------
195 | * Gets the current memory map and writes it to the pointer.
196 | *
197 | * NewMemoryMap: Pointer to where the memory map should be written to
198 | *
199 | * returns: TRUE if we got a working memory map
200 | *
201 | */
202 | BOOLEAN InitUefiMemoryMap(UINT64 NewMemoryMap)
203 | {
204 | // Declare some variables used for parsing
205 | UINTN MemoryMapSize = 0;
206 | EFI_MEMORY_DESCRIPTOR* MemoryMap = NULL;
207 | UINTN LocalMapKey;
208 | UINT32 DescriptorVersion;
209 |
210 | EFI_STATUS status = EFI_SUCCESS;
211 |
212 | // Use gBS->GetMemoryMap to get the physical memory map from the DXE service
213 | status = gBS->GetMemoryMap(&MemoryMapSize, MemoryMap, &LocalMapKey, &mUefiDescriptorSize, &DescriptorVersion);
214 |
215 | // As we dont know the size in advance, call the function until we got the right size as long as we get the error EFI_BUFFER_TOO_SMALL
216 | do {
217 | // Allocate a new memory map using the MemoryMapSize we have gotten from calling gBS->GetMemoryMap
218 | status = gBS->AllocatePool(EfiBootServicesData, MemoryMapSize, (VOID**)&MemoryMap);
219 |
220 | // Check if we successfully allocated memory
221 | if (MemoryMap == NULL || status != EFI_SUCCESS)
222 | {
223 | return FALSE;
224 | }
225 |
226 | // Now call gBS->GetMemoryMap again with a big enough buffer
227 | status = gBS->GetMemoryMap(&MemoryMapSize, MemoryMap, &LocalMapKey, &mUefiDescriptorSize, &DescriptorVersion);
228 |
229 | // Check if it still fails
230 | if (EFI_ERROR(status))
231 | {
232 | // It still failed for some reasons... Free it and return NULL
233 | gBS->FreePool(MemoryMap);
234 | MemoryMap = NULL;
235 | }
236 |
237 | } while (status == EFI_BUFFER_TOO_SMALL);
238 |
239 | if (MemoryMap == NULL)
240 | {
241 | LOG_ERROR("Failed init memory map! \r\n");
242 |
243 | return FALSE;
244 | }
245 |
246 | // Now we got a memory map, first sort it!
247 | SortMemoryMap(MemoryMap, MemoryMapSize, mUefiDescriptorSize);
248 |
249 | // As the memory map is sorted, we can now try merging entries to make it smaller
250 | MergeMemoryMapForNotPresentEntry(MemoryMap, &MemoryMapSize, mUefiDescriptorSize);
251 |
252 | // Due to the merging the size has changed, also reflect it in the global variable
253 | mUefiMemoryMapSize = MemoryMapSize;
254 |
255 | // Now copy the memory map from the temporary location to the final location passed in the function parameters
256 | pMemCpyForce(NewMemoryMap, (UINT64)MemoryMap, MemoryMapSize);
257 |
258 | // Now set the location in the global variable
259 | mUefiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)NewMemoryMap;
260 |
261 | // Finally deallocate the pages for the temporary memory map
262 | gBS->FreePool(MemoryMap);
263 |
264 | return TRUE;
265 | }
--------------------------------------------------------------------------------