Skip to content

Commit a9ffc48

Browse files
author
etke
committed
Add proc maps for windows target
1 parent 463785a commit a9ffc48

File tree

5 files changed

+817
-190
lines changed

5 files changed

+817
-190
lines changed

Cargo.lock

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ serde_derive = "1.0.137"
3838
serde_json = "1.0.81"
3939
sysinfo = "0.24.2"
4040

41+
[target.'cfg(target_os="windows")'.dependencies]
42+
windows = { version = "0.38.0", features = ["Win32_Foundation", "Win32_Security", "Win32_System_Diagnostics_Debug", "Win32_System_Diagnostics_ToolHelp", "Win32_System_Kernel", "Win32_System_Memory", "Win32_System_Threading"] }
43+
4144
[lib]
4245
name = "checksec"
4346
path = "src/lib.rs"

src/binary.rs

Lines changed: 1 addition & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
#[cfg(feature = "color")]
22
use colored::Colorize;
33
use serde::{Deserialize, Serialize};
4-
use std::fmt;
5-
#[cfg(all(feature = "maps", target_os = "linux"))]
6-
use std::fs;
7-
#[cfg(all(feature = "maps", target_os = "linux"))]
8-
use std::io::Error;
9-
#[cfg(all(feature = "maps", target_os = "linux"))]
10-
use std::io::ErrorKind;
11-
#[cfg(all(feature = "maps", target_os = "linux"))]
12-
use std::path::PathBuf;
13-
use std::usize;
4+
use std::{fmt, usize};
145

156
#[cfg(feature = "elf")]
167
use checksec::elf;
@@ -143,179 +134,3 @@ impl Binaries {
143134
Self { binaries }
144135
}
145136
}
146-
147-
#[cfg(all(feature = "maps", target_os = "linux"))]
148-
#[derive(Deserialize, Serialize)]
149-
pub struct Region {
150-
pub start: usize,
151-
pub end: usize,
152-
}
153-
#[cfg(all(feature = "maps", target_os = "linux"))]
154-
impl Region {
155-
pub fn new(start: usize, end: usize) -> Self {
156-
Self { start, end }
157-
}
158-
}
159-
160-
#[cfg(all(feature = "maps", target_os = "linux"))]
161-
#[derive(Deserialize, Serialize)]
162-
pub struct MapFlags {
163-
pub r: bool,
164-
pub w: bool,
165-
pub x: bool,
166-
}
167-
#[cfg(all(feature = "maps", target_os = "linux"))]
168-
impl MapFlags {
169-
pub fn new(flagstr: &str) -> Self {
170-
let r = flagstr.get(0..1) == Some("r");
171-
let w = flagstr.get(1..2) == Some("w");
172-
let x = flagstr.get(2..3) == Some("x");
173-
Self { r, w, x }
174-
}
175-
}
176-
#[cfg(all(not(feature = "color"), feature = "maps", target_os = "linux"))]
177-
impl fmt::Display for MapFlags {
178-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179-
write!(
180-
f,
181-
"{}{}{}",
182-
if self.r { "r" } else { "-" },
183-
if self.w { "w" } else { "-" },
184-
if self.x { "x" } else { "-" }
185-
)
186-
}
187-
}
188-
#[cfg(all(feature = "color", feature = "maps", target_os = "linux"))]
189-
impl fmt::Display for MapFlags {
190-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191-
if self.r & self.w & self.x {
192-
return write!(f, "{}", "rwx".red());
193-
}
194-
write!(
195-
f,
196-
"{}{}{}",
197-
if self.r { "r" } else { "-" },
198-
if self.w { "w" } else { "-" },
199-
if self.x { "x" } else { "-" }
200-
)
201-
}
202-
}
203-
204-
#[cfg(all(feature = "maps", target_os = "linux"))]
205-
#[derive(Deserialize, Serialize)]
206-
pub struct MapEntry {
207-
pub region: Region,
208-
pub flags: MapFlags,
209-
pub pathname: Option<PathBuf>,
210-
}
211-
#[cfg(all(not(feature = "color"), feature = "maps", target_os = "linux"))]
212-
impl fmt::Display for MapEntry {
213-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214-
write!(
215-
f,
216-
"0x{:x}->0x{:x} {} {}",
217-
self.region.start,
218-
self.region.end,
219-
self.flags,
220-
match &self.pathname {
221-
Some(pathname) => pathname.display().to_string(),
222-
None => "".to_string(),
223-
}
224-
)
225-
}
226-
}
227-
#[cfg(all(feature = "color", feature = "maps", target_os = "linux"))]
228-
impl fmt::Display for MapEntry {
229-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230-
if self.flags.r & self.flags.w & self.flags.x {
231-
write!(
232-
f,
233-
"{} {}",
234-
format!(
235-
"0x{:x}->0x{:x} {}",
236-
self.region.start, self.region.end, self.flags
237-
)
238-
.red(),
239-
match &self.pathname {
240-
Some(pathname) => pathname.display().to_string().red(),
241-
None => "".to_string().red(),
242-
}
243-
)
244-
} else {
245-
write!(
246-
f,
247-
"0x{:x}->0x{:x} {} {}",
248-
self.region.start,
249-
self.region.end,
250-
self.flags,
251-
match &self.pathname {
252-
Some(pathname) => pathname.display().to_string(),
253-
None => "".to_string(),
254-
}
255-
)
256-
}
257-
}
258-
}
259-
260-
#[derive(Deserialize, Serialize)]
261-
pub struct Process {
262-
pub pid: usize,
263-
pub binary: Vec<Binary>,
264-
#[cfg(all(feature = "maps", target_os = "linux"))]
265-
pub maps: Option<Vec<MapEntry>>,
266-
}
267-
impl Process {
268-
#[cfg(any(not(feature = "maps"), not(target_os = "linux")))]
269-
pub fn new(pid: usize, binary: Vec<Binary>) -> Self {
270-
Self { pid, binary }
271-
}
272-
#[cfg(all(feature = "maps", target_os = "linux"))]
273-
pub fn new(pid: usize, binary: Vec<Binary>) -> Self {
274-
match Process::parse_maps(pid) {
275-
Ok(maps) => Self { pid, binary, maps: Some(maps) },
276-
Err(_) => Self { pid, binary, maps: None },
277-
}
278-
}
279-
#[cfg(all(feature = "maps", target_os = "linux"))]
280-
pub fn parse_maps(pid: usize) -> Result<Vec<MapEntry>, Error> {
281-
let mut maps: Vec<MapEntry> = Vec::new();
282-
if let Ok(maps_str) = fs::read_to_string(format!("/proc/{}/maps", pid))
283-
{
284-
for line in maps_str.lines() {
285-
let mut split_line = line.split_whitespace();
286-
let (start_str, end_str) = split_line
287-
.next()
288-
.ok_or(ErrorKind::InvalidData)?
289-
.split_once('-')
290-
.ok_or(ErrorKind::InvalidData)?;
291-
let region = Region::new(
292-
usize::from_str_radix(start_str, 16).unwrap_or(0),
293-
usize::from_str_radix(end_str, 16).unwrap_or(0),
294-
);
295-
let flags = MapFlags::new(
296-
split_line.next().ok_or(ErrorKind::InvalidData)?,
297-
);
298-
split_line.next(); // skip offset
299-
split_line.next(); // skip dev
300-
split_line.next(); // skip inode
301-
let pathname =
302-
Some(split_line.collect::<Vec<&str>>().join(" "))
303-
.filter(|x| !x.is_empty())
304-
.map(PathBuf::from);
305-
maps.push(MapEntry { region, flags, pathname });
306-
}
307-
return Ok(maps);
308-
}
309-
Err(Error::last_os_error())
310-
}
311-
}
312-
313-
#[derive(Deserialize, Serialize)]
314-
pub struct Processes {
315-
pub processes: Vec<Process>,
316-
}
317-
impl Processes {
318-
pub fn new(processes: Vec<Process>) -> Self {
319-
Self { processes }
320-
}
321-
}

src/main.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ use colored::Colorize;
2626
use colored_json::to_colored_json_auto;
2727

2828
mod binary;
29+
mod proc;
30+
31+
use binary::{BinSpecificProperties, BinType, Binaries, Binary};
32+
use proc::{Process, Processes};
2933

30-
use binary::{
31-
BinSpecificProperties, BinType, Binaries, Binary, Process, Processes,
32-
};
3334
#[cfg(feature = "elf")]
3435
use checksec::elf;
3536
#[cfg(feature = "macho")]
@@ -103,7 +104,10 @@ fn print_process_results(processes: &Processes, settings: &output::Settings) {
103104
}
104105
}
105106
}
106-
#[cfg(all(target_os = "linux", feature = "maps"))]
107+
#[cfg(all(
108+
feature = "maps",
109+
any(target_os = "linux", target_os = "windows")
110+
))]
107111
if settings.maps {
108112
if let Some(maps) = &process.maps {
109113
println!("{:>12}", "\u{21aa} Maps:");

0 commit comments

Comments
 (0)