├── .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 | Picture of Plouton 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 |