1use super::ldr::PebLdrData;
4use super::offsets::PebOffsets;
5use crate::arch::{segment, NativePtr};
6use crate::error::{Result, WraithError};
7use crate::version::WindowsVersion;
8use core::ptr::NonNull;
9
10pub struct Peb {
12 ptr: NonNull<u8>,
13 offsets: &'static PebOffsets,
14}
15
16impl Peb {
17 pub fn current() -> Result<Self> {
19 let ptr = unsafe { segment::get_peb() };
21 let ptr = NonNull::new(ptr).ok_or(WraithError::InvalidPebAccess)?;
22
23 let version = WindowsVersion::current()?;
24 let offsets = PebOffsets::for_version(&version)?;
25
26 Ok(Self { ptr, offsets })
27 }
28
29 pub fn as_ptr(&self) -> *mut u8 {
31 self.ptr.as_ptr()
32 }
33
34 pub fn being_debugged(&self) -> bool {
36 unsafe {
38 let addr = self.ptr.as_ptr().add(self.offsets.being_debugged);
39 *(addr as *const u8) != 0
40 }
41 }
42
43 pub unsafe fn set_being_debugged(&mut self, value: bool) {
48 unsafe {
49 let addr = self.ptr.as_ptr().add(self.offsets.being_debugged);
50 *(addr as *mut u8) = if value { 1 } else { 0 };
51 }
52 }
53
54 pub fn nt_global_flag(&self) -> u32 {
56 unsafe {
57 let addr = self.ptr.as_ptr().add(self.offsets.nt_global_flag);
58 *(addr as *const u32)
59 }
60 }
61
62 pub unsafe fn set_nt_global_flag(&mut self, value: u32) {
67 unsafe {
68 let addr = self.ptr.as_ptr().add(self.offsets.nt_global_flag);
69 *(addr as *mut u32) = value;
70 }
71 }
72
73 pub fn ldr(&self) -> Option<&PebLdrData> {
75 unsafe {
76 let addr = self.ptr.as_ptr().add(self.offsets.ldr);
77 let ldr_ptr = *(addr as *const *const PebLdrData);
78 if ldr_ptr.is_null() {
79 None
80 } else {
81 Some(&*ldr_ptr)
82 }
83 }
84 }
85
86 pub unsafe fn ldr_mut(&mut self) -> Option<&mut PebLdrData> {
91 unsafe {
92 let addr = self.ptr.as_ptr().add(self.offsets.ldr);
93 let ldr_ptr = *(addr as *mut *mut PebLdrData);
94 if ldr_ptr.is_null() {
95 None
96 } else {
97 Some(&mut *ldr_ptr)
98 }
99 }
100 }
101
102 pub fn image_base(&self) -> NativePtr {
104 unsafe {
105 let addr = self.ptr.as_ptr().add(self.offsets.image_base);
106 *(addr as *const NativePtr)
107 }
108 }
109
110 pub fn process_heap(&self) -> NativePtr {
112 unsafe {
113 let addr = self.ptr.as_ptr().add(self.offsets.process_heap);
114 *(addr as *const NativePtr)
115 }
116 }
117
118 pub fn number_of_processors(&self) -> u32 {
120 unsafe {
121 let addr = self.ptr.as_ptr().add(self.offsets.number_of_processors);
122 *(addr as *const u32)
123 }
124 }
125}
126
127unsafe impl Send for Peb {}
129unsafe impl Sync for Peb {}