1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * Copyright (C) 2021 meme <keegan@sdf.org>
 * Copyright (C) 2021 S Rubenstein <s1341@shmarya.net>
 *
 * Licence: wxWindows Library Licence, Version 3.1
 */

use frida_gum_sys as gum_sys;
use std::ffi::CStr;
use std::marker::PhantomData;

use crate::MemoryRange;

/// The memory protection of an unassociated page.
#[derive(FromPrimitive)]
#[repr(u32)]
pub enum PageProtection {
    NoAccess = gum_sys::_GumPageProtection_GUM_PAGE_NO_ACCESS,
    Read = gum_sys::_GumPageProtection_GUM_PAGE_READ,
    Write = gum_sys::_GumPageProtection_GUM_PAGE_WRITE,
    Execute = gum_sys::_GumPageProtection_GUM_PAGE_EXECUTE,
    ReadWrite =
        gum_sys::_GumPageProtection_GUM_PAGE_READ | gum_sys::_GumPageProtection_GUM_PAGE_WRITE,
    ReadExecute =
        gum_sys::_GumPageProtection_GUM_PAGE_READ | gum_sys::_GumPageProtection_GUM_PAGE_EXECUTE,
    ReadWriteExecute = gum_sys::_GumPageProtection_GUM_PAGE_READ
        | gum_sys::_GumPageProtection_GUM_PAGE_WRITE
        | gum_sys::_GumPageProtection_GUM_PAGE_EXECUTE,
}

/// The file association to a page.
pub struct FileMapping<'a> {
    file_mapping: *const gum_sys::GumFileMapping,
    phantom: PhantomData<&'a gum_sys::GumFileMapping>,
}

impl<'a> FileMapping<'a> {
    pub(crate) fn from_raw(file: *const gum_sys::GumFileMapping) -> Self {
        Self {
            file_mapping: file,
            phantom: PhantomData,
        }
    }

    /// The path of the file mapping on disk.
    pub fn path(&self) -> &str {
        unsafe { CStr::from_ptr((*self.file_mapping).path).to_str().unwrap() }
    }

    /// The offset into the file mapping.
    pub fn offset(&self) -> u64 {
        unsafe { (*self.file_mapping).offset }
    }

    /// The size of the mapping.
    pub fn size(&self) -> u64 {
        unsafe { (*self.file_mapping).size }
    }
}

/// Details a range of virtual memory.
pub struct RangeDetails<'a> {
    range_details: *const gum_sys::GumRangeDetails,
    phantom: PhantomData<&'a gum_sys::GumRangeDetails>,
}

impl<'a> RangeDetails<'a> {
    pub(crate) fn from_raw(range_details: *const gum_sys::GumRangeDetails) -> Self {
        Self {
            range_details,
            phantom: PhantomData,
        }
    }

    /// The range of memory that is detailed.
    pub fn memory_range(&self) -> MemoryRange {
        unsafe { MemoryRange::from_raw((*self.range_details).range) }
    }

    /// The page protection of the range.
    pub fn protection(&self) -> PageProtection {
        let protection = unsafe { (*self.range_details).protection };
        num::FromPrimitive::from_u32(protection).unwrap()
    }

    /// The associated file mapping, if present.
    pub fn file_mapping(&self) -> Option<FileMapping> {
        if self.range_details.is_null() {
            None
        } else {
            Some(unsafe { FileMapping::from_raw((*self.range_details).file) })
        }
    }
}