Skip to content

Commit 825aa41

Browse files
committed
PEB Offset Finder
Find and print offsets for PEB and RTL_USER_PROCESS_PARAMETERS
1 parent be6e011 commit 825aa41

File tree

4 files changed

+261
-0
lines changed

4 files changed

+261
-0
lines changed

PEB_Offset_finder/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "PEB_Offset_finder"
3+
version = "0.1.0"
4+
edition = "2024"
5+
authors = ["5mukx"]
6+
7+
[dependencies]
8+
memoffset = "0.9.1"
9+
ntapi = "0.4.1"

PEB_Offset_finder/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## PEB Offset Finder
2+
3+
This is a small program that prints the memory offsets of fields in two important Windows structures
4+
the Process Environment Block (PEB) and RTL_USER_PROCESS_PARAMETERS.
5+
6+
If you’re digging into Windows internals or messing around with low-level system stuff, this tool is handy for figuring out where things are stored in memory.
7+
8+
![ImagG](./image.png)
9+
10+
## What’s It For?
11+
12+
So, why bother with this? The PEB and RTL_USER_PROCESS_PARAMETERS are like treasure maps for Windows processes. They hold some cool details like:
13+
14+
* The current directory (CurrentDirectory)
15+
* Environment variables (Environment)
16+
* Command-line arguments (CommandLine)
17+
* Whether a debugger is attached (BeingDebugged)
18+
* And even pointers to callback tables (KernelCallbackTable)
19+
* And even more .....
20+
21+
If you are into malware development, reverse engineering, or just want to poke around Windows at a low level, knowing the exact offsets of these fields lets you access them directly in memory. This is super useful for example bypassing API by grabbing environment variables without calling GetEnvironmentVariableW? This helps you find Environment in memory.
22+
23+
Understanding Windows: It’s a great way to learn how Windows organizes process data under the hood.
24+
25+
26+
## Credits
27+
28+
* [@5mukx](https://x.com/5mukx)

PEB_Offset_finder/image.png

264 KB
Loading

PEB_Offset_finder/src/main.rs

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
PEB Offset calculator
3+
@5mukx
4+
*/
5+
6+
7+
use ntapi::{
8+
ntpebteb::PEB,
9+
ntrtl::RTL_USER_PROCESS_PARAMETERS,
10+
};
11+
use std::arch::asm;
12+
13+
use memoffset::offset_of;
14+
15+
16+
fn get_peb() -> *mut PEB {
17+
#[cfg(target_arch = "x86_64")]
18+
{
19+
let peb: *mut PEB;
20+
unsafe {asm!("mov {}, gs:[0x60]", out(reg) peb)};
21+
peb
22+
}
23+
#[cfg(target_arch = "x86")]
24+
{
25+
let peb: *mut PEB;
26+
unsafe { asm!("mov {}, fs:[0x30]", out(reg) peb)};
27+
peb
28+
}
29+
}
30+
31+
fn print_peb_offsets() {
32+
println!("[*] PEB Field Offsets:");
33+
println!("----Field: Offset----");
34+
println!("[+] InheritedAddressSpace: {:#x}", offset_of!(PEB, InheritedAddressSpace));
35+
println!("[+] ReadImageFileExecOptions: {:#x}", offset_of!(PEB, ReadImageFileExecOptions));
36+
println!("[+] BeingDebugged: {:#x}", offset_of!(PEB, BeingDebugged));
37+
println!("[+] BitField: {:#x}", offset_of!(PEB, BitField));
38+
println!("[+] Mutant: {:#x}", offset_of!(PEB, Mutant));
39+
println!("[+] ImageBaseAddress: {:#x}", offset_of!(PEB, ImageBaseAddress));
40+
println!("[+] Ldr: {:#x}", offset_of!(PEB, Ldr));
41+
println!("[+] ProcessParameters: {:#x}", offset_of!(PEB, ProcessParameters));
42+
println!("[+] SubSystemData: {:#x}", offset_of!(PEB, SubSystemData));
43+
println!("[+] ProcessHeap: {:#x}", offset_of!(PEB, ProcessHeap));
44+
println!("[+] FastPebLock: {:#x}", offset_of!(PEB, FastPebLock));
45+
println!("[+] AtlThunkSListPtr: {:#x}", offset_of!(PEB, AtlThunkSListPtr));
46+
println!("[+] IFEOKey: {:#x}", offset_of!(PEB, IFEOKey));
47+
println!("[+] CrossProcessFlags: {:#x}", offset_of!(PEB, CrossProcessFlags));
48+
49+
// u handle filed
50+
let u_offset = offset_of!(PEB, u);
51+
println!("[+] u.KernelCallbackTable: {:#x}", u_offset);
52+
println!("[+] u.UserSharedInfoPtr: {:#x}", u_offset);
53+
println!("[+] SystemReserved: {:#x}", offset_of!(PEB, SystemReserved));
54+
println!("[+] AtlThunkSListPtr32: {:#x}", offset_of!(PEB, AtlThunkSListPtr32));
55+
println!("[+] ApiSetMap: {:#x}", offset_of!(PEB, ApiSetMap));
56+
println!("[+] TlsExpansionCounter: {:#x}", offset_of!(PEB, TlsExpansionCounter));
57+
println!("[+] TlsBitmap: {:#x}", offset_of!(PEB, TlsBitmap));
58+
println!("[+] TlsBitmapBits: {:#x}", offset_of!(PEB, TlsBitmapBits));
59+
println!("[+] ReadOnlySharedMemoryBase: {:#x}", offset_of!(PEB, ReadOnlySharedMemoryBase));
60+
println!("[+] SharedData: {:#x}", offset_of!(PEB, SharedData));
61+
println!("[+] ReadOnlyStaticServerData: {:#x}", offset_of!(PEB, ReadOnlyStaticServerData));
62+
println!("[+] AnsiCodePageData: {:#x}", offset_of!(PEB, AnsiCodePageData));
63+
println!("[+] OemCodePageData: {:#x}", offset_of!(PEB, OemCodePageData));
64+
println!("[+] UnicodeCaseTableData: {:#x}", offset_of!(PEB, UnicodeCaseTableData));
65+
println!("[+] NumberOfProcessors: {:#x}", offset_of!(PEB, NumberOfProcessors));
66+
println!("[+] NtGlobalFlag: {:#x}", offset_of!(PEB, NtGlobalFlag));
67+
println!("[+] CriticalSectionTimeout: {:#x}", offset_of!(PEB, CriticalSectionTimeout));
68+
println!("[+] HeapSegmentReserve: {:#x}", offset_of!(PEB, HeapSegmentReserve));
69+
println!("[+] HeapSegmentCommit: {:#x}", offset_of!(PEB, HeapSegmentCommit));
70+
println!("[+] HeapDeCommitTotalFreeThreshold: {:#x}", offset_of!(PEB, HeapDeCommitTotalFreeThreshold));
71+
println!("[+] HeapDeCommitFreeBlockThreshold: {:#x}", offset_of!(PEB, HeapDeCommitFreeBlockThreshold));
72+
println!("[+] NumberOfHeaps: {:#x}", offset_of!(PEB, NumberOfHeaps));
73+
println!("[+] MaximumNumberOfHeaps: {:#x}", offset_of!(PEB, MaximumNumberOfHeaps));
74+
println!("[+] ProcessHeaps: {:#x}", offset_of!(PEB, ProcessHeaps));
75+
println!("[+] GdiSharedHandleTable: {:#x}", offset_of!(PEB, GdiSharedHandleTable));
76+
println!("[+] ProcessStarterHelper: {:#x}", offset_of!(PEB, ProcessStarterHelper));
77+
println!("[+] GdiDCAttributeList: {:#x}", offset_of!(PEB, GdiDCAttributeList));
78+
println!("[+] LoaderLock: {:#x}", offset_of!(PEB, LoaderLock));
79+
println!("[+] OSMajorVersion: {:#x}", offset_of!(PEB, OSMajorVersion));
80+
println!("[+] OSMinorVersion: {:#x}", offset_of!(PEB, OSMinorVersion));
81+
println!("[+] OSBuildNumber: {:#x}", offset_of!(PEB, OSBuildNumber));
82+
println!("[+] OSCSDVersion: {:#x}", offset_of!(PEB, OSCSDVersion));
83+
println!("[+] OSPlatformId: {:#x}", offset_of!(PEB, OSPlatformId));
84+
println!("[+] ImageSubsystem: {:#x}", offset_of!(PEB, ImageSubsystem));
85+
println!("[+] ImageSubsystemMajorVersion: {:#x}", offset_of!(PEB, ImageSubsystemMajorVersion));
86+
println!("[+] ImageSubsystemMinorVersion: {:#x}", offset_of!(PEB, ImageSubsystemMinorVersion));
87+
println!("[+] ActiveProcessAffinityMask: {:#x}", offset_of!(PEB, ActiveProcessAffinityMask));
88+
println!("[+] GdiHandleBuffer: {:#x}", offset_of!(PEB, GdiHandleBuffer));
89+
println!("[+] PostProcessInitRoutine: {:#x}", offset_of!(PEB, PostProcessInitRoutine));
90+
println!("[+] TlsExpansionBitmap: {:#x}", offset_of!(PEB, TlsExpansionBitmap));
91+
println!("[+] TlsExpansionBitmapBits: {:#x}", offset_of!(PEB, TlsExpansionBitmapBits));
92+
println!("[+] SessionId: {:#x}", offset_of!(PEB, SessionId));
93+
println!("[+] AppCompatFlags: {:#x}", offset_of!(PEB, AppCompatFlags));
94+
println!("[+] AppCompatFlagsUser: {:#x}", offset_of!(PEB, AppCompatFlagsUser));
95+
println!("[+] pShimData: {:#x}", offset_of!(PEB, pShimData));
96+
println!("[+] AppCompatInfo: {:#x}", offset_of!(PEB, AppCompatInfo));
97+
println!("[+] CSDVersion: {:#x}", offset_of!(PEB, CSDVersion));
98+
println!("[+] ActivationContextData: {:#x}", offset_of!(PEB, ActivationContextData));
99+
println!("[+] ProcessAssemblyStorageMap: {:#x}", offset_of!(PEB, ProcessAssemblyStorageMap));
100+
println!("[+] SystemDefaultActivationContextData: {:#x}", offset_of!(PEB, SystemDefaultActivationContextData));
101+
println!("[+] SystemAssemblyStorageMap: {:#x}", offset_of!(PEB, SystemAssemblyStorageMap));
102+
println!("[+] MinimumStackCommit: {:#x}", offset_of!(PEB, MinimumStackCommit));
103+
println!("[+] FlsCallback: {:#x}", offset_of!(PEB, FlsCallback));
104+
println!("[+] FlsListHead: {:#x}", offset_of!(PEB, FlsListHead));
105+
println!("[+] FlsBitmap: {:#x}", offset_of!(PEB, FlsBitmap));
106+
println!("[+] FlsBitmapBits: {:#x}", offset_of!(PEB, FlsBitmapBits));
107+
println!("[+] FlsHighIndex: {:#x}", offset_of!(PEB, FlsHighIndex));
108+
println!("[+] WerRegistrationData: {:#x}", offset_of!(PEB, WerRegistrationData));
109+
println!("[+] WerShipAssertPtr: {:#x}", offset_of!(PEB, WerShipAssertPtr));
110+
println!("[+] pUnused: {:#x}", offset_of!(PEB, pUnused));
111+
println!("[+] pImageHeaderHash: {:#x}", offset_of!(PEB, pImageHeaderHash));
112+
println!("[+] TracingFlags: {:#x}", offset_of!(PEB, TracingFlags));
113+
println!("[+] CsrServerReadOnlySharedMemoryBase: {:#x}", offset_of!(PEB, CsrServerReadOnlySharedMemoryBase));
114+
println!("[+] TppWorkerpListLock: {:#x}", offset_of!(PEB, TppWorkerpListLock));
115+
println!("[+] TppWorkerpList: {:#x}", offset_of!(PEB, TppWorkerpList));
116+
println!("[+] WaitOnAddressHashTable: {:#x}", offset_of!(PEB, WaitOnAddressHashTable));
117+
println!("[+] TelemetryCoverageHeader: {:#x}", offset_of!(PEB, TelemetryCoverageHeader));
118+
println!("[+] CloudFileFlags: {:#x}", offset_of!(PEB, CloudFileFlags));
119+
println!("[+] CloudFileDiagFlags: {:#x}", offset_of!(PEB, CloudFileDiagFlags));
120+
println!("[+] PlaceholderCompatibilityMode: {:#x}", offset_of!(PEB, PlaceholderCompatibilityMode));
121+
println!("[+] PlaceholderCompatibilityModeReserved: {:#x}", offset_of!(PEB, PlaceholderCompatibilityModeReserved));
122+
println!("[+] LeapSecondData: {:#x}", offset_of!(PEB, LeapSecondData));
123+
println!("[+] LeapSecondFlags: {:#x}", offset_of!(PEB, LeapSecondFlags));
124+
println!("[+] NtGlobalFlag2: {:#x}", offset_of!(PEB, NtGlobalFlag2));
125+
}
126+
127+
fn print_rtl_user_process_parameters_offsets() {
128+
println!("[*] RTL_USER_PROCESS_PARAMETERS Field Offsets:");
129+
println!("----Field: Offset----");
130+
println!("[+] MaximumLength: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, MaximumLength));
131+
println!("[+] Length: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, Length));
132+
println!("[+] Flags: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, Flags));
133+
println!("[+] DebugFlags: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, DebugFlags));
134+
println!("[+] ConsoleHandle: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ConsoleHandle));
135+
println!("[+] ConsoleFlags: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ConsoleFlags));
136+
println!("[+] StandardInput: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, StandardInput));
137+
println!("[+] StandardOutput: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, StandardOutput));
138+
println!("[+] StandardError: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, StandardError));
139+
println!("[+] CurrentDirectory: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CurrentDirectory));
140+
println!("[+] DllPath: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, DllPath));
141+
println!("[+] ImagePathName: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ImagePathName));
142+
println!("[+] CommandLine: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CommandLine));
143+
println!("[+] Environment: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, Environment));
144+
println!("[+] StartingX: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, StartingX));
145+
println!("[+] StartingY: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, StartingY));
146+
println!("[+] CountX: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CountX));
147+
println!("[+] CountY: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CountY));
148+
println!("[+] CountCharsX: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CountCharsX));
149+
println!("[+] CountCharsY: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CountCharsY));
150+
println!("[+] FillAttribute: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, FillAttribute));
151+
println!("[+] WindowFlags: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, WindowFlags));
152+
println!("[+] ShowWindowFlags: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ShowWindowFlags));
153+
println!("[+] WindowTitle: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, WindowTitle));
154+
println!("[+] DesktopInfo: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, DesktopInfo));
155+
println!("[+] ShellInfo: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ShellInfo));
156+
println!("[+] RuntimeData: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, RuntimeData));
157+
println!("[+] CurrentDirectories: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, CurrentDirectories));
158+
println!("[+] EnvironmentSize: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, EnvironmentSize));
159+
println!("[+] EnvironmentVersion: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, EnvironmentVersion));
160+
println!("[+] PackageDependencyData: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, PackageDependencyData));
161+
println!("[+] ProcessGroupId: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, ProcessGroupId));
162+
println!("[+] LoaderThreads: {:#x}", offset_of!(RTL_USER_PROCESS_PARAMETERS, LoaderThreads));
163+
}
164+
165+
166+
// example runtime
167+
fn validate_offsets_runtime() {
168+
unsafe{
169+
println!("\n[*] Runtime Offset Validation:");
170+
let peb = get_peb();
171+
if peb.is_null() {
172+
println!("[*] PEB is null");
173+
return;
174+
}
175+
let peb_base = peb as usize;
176+
let process_parameters = (*peb).ProcessParameters;
177+
if process_parameters.is_null() {
178+
println!("[*] ProcessParameters is null");
179+
return;
180+
}
181+
let params_base = process_parameters as usize;
182+
183+
// PEB.ProcessParameters
184+
let process_parameters_offset = (process_parameters as usize).wrapping_sub(peb_base);
185+
println!("[*] PEB.ProcessParameters: Calculated Offset = {:#x}, Expected = {:#x}",
186+
process_parameters_offset, offset_of!(PEB, ProcessParameters));
187+
188+
// PEB.u.KernelCallbackTable
189+
let kernel_callback_table_offset = (&(*peb).u as *const _ as usize).wrapping_sub(peb_base);
190+
println!("[*] PEB.u.KernelCallbackTable: Calculated Offset = {:#x}, Expected = {:#x}",
191+
kernel_callback_table_offset, offset_of!(PEB, u));
192+
193+
// Example !
194+
// RTL_USER_PROCESS_PARAMETERS fields
195+
let current_directory_offset = (&(*process_parameters).CurrentDirectory as *const _ as usize).wrapping_sub(params_base);
196+
let command_line_offset = (&(*process_parameters).CommandLine as *const _ as usize).wrapping_sub(params_base);
197+
let environment_offset = (&(*process_parameters).Environment as *const _ as usize).wrapping_sub(params_base);
198+
199+
println!("[*] RTL_USER_PROCESS_PARAMETERS.CurrentDirectory: Calculated Offset = {:#x}, Expected = {:#x}",
200+
current_directory_offset, offset_of!(RTL_USER_PROCESS_PARAMETERS, CurrentDirectory));
201+
202+
println!("[*] RTL_USER_PROCESS_PARAMETERS.CommandLine: Calculated Offset = {:#x}, Expected = {:#x}",
203+
command_line_offset, offset_of!(RTL_USER_PROCESS_PARAMETERS, CommandLine));
204+
205+
println!("[*] RTL_USER_PROCESS_PARAMETERS.Environment: Calculated Offset = {:#x}, Expected = {:#x}",
206+
environment_offset, offset_of!(RTL_USER_PROCESS_PARAMETERS, Environment));
207+
208+
println!("[*] PEB Address: {:#x}", peb_base);
209+
println!("[*] ProcessParameters Address: {:#x}", process_parameters as usize);
210+
println!("[*] u.KernelCallbackTable Address: {:#x}", (*peb).u.KernelCallbackTable as usize);
211+
println!("[*] Environment Address: {:#x}", (*process_parameters).Environment as usize);
212+
}
213+
}
214+
215+
216+
fn main(){
217+
218+
print_peb_offsets();
219+
220+
print_rtl_user_process_parameters_offsets();
221+
222+
validate_offsets_runtime();
223+
224+
}

0 commit comments

Comments
 (0)