mem_rs/process_module/
mod.rs

1// This file is part of the mem-rs distribution (https://github.com/FrankvdStam/mem-rs).
2// Copyright (c) 2022 Frank van der Stam.
3// https://github.com/FrankvdStam/mem-rs/blob/main/LICENSE
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, version 3.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17mod read_write;
18
19use std::cell::RefCell;
20use std::mem;
21use std::rc::Rc;
22use windows::Win32::System::Diagnostics::Debug::{IMAGE_NT_HEADERS32, IMAGE_NT_HEADERS64};
23use windows::Win32::System::SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY};
24use crate::memory::{BaseReadWrite, ReadWrite};
25use crate::process_data::ProcessData;
26
27#[allow(dead_code)]
28#[derive(Clone)]
29pub struct ProcessModule
30{
31    process_data: Rc<RefCell<ProcessData>>,
32
33    pub id: usize,
34    pub path: String,
35    pub name: String,
36
37    pub base_address: usize,
38    pub size: usize,
39
40    pub memory: Vec<u8>,
41}
42
43impl Default for ProcessModule
44{
45    fn default() -> Self
46    {
47        ProcessModule
48        {
49            process_data: Rc::new(RefCell::new(ProcessData::default())),
50            id: 0,
51            path: String::new(),
52            name: String::new(),
53            base_address: 0,
54            size: 0,
55            memory: Vec::new(),
56        }
57    }
58}
59
60impl ProcessModule
61{
62    pub fn new(process_data: Rc<RefCell<ProcessData>>, id: usize, path: String, name: String, base: usize, size: usize) -> Self
63    {
64        ProcessModule { process_data, id, path, name, base_address: base, size, memory: Vec::new() }
65    }
66
67    pub fn dump_memory(&mut self)
68    {
69        let mut buffer: Vec<u8> = vec![0; self.size];
70        if !self.read_memory_abs(self.base_address, &mut buffer)
71        {
72            return;
73        }
74        self.memory = buffer;
75
76    }
77
78    pub fn get_exports(&self) -> Vec<(String, usize)>
79    {
80        let mut funcs: Vec<(String, usize)> = Vec::new();
81
82        let mut dos_header_buf: [u8; mem::size_of::<IMAGE_DOS_HEADER>()] = [0; mem::size_of::<IMAGE_DOS_HEADER>()];
83        self.read_memory_abs(self.base_address, &mut dos_header_buf);
84        let dos_header: IMAGE_DOS_HEADER = unsafe{ std::ptr::read(dos_header_buf.as_ptr() as *const _) };
85
86        let export_table_address = if self.process_data.borrow().is_64_bit
87        {
88            let mut nt_headers_buf: [u8; mem::size_of::<IMAGE_NT_HEADERS64>()] = [0; mem::size_of::<IMAGE_NT_HEADERS64>()];
89            self.read_memory_abs(self.base_address + dos_header.e_lfanew as usize, &mut nt_headers_buf);
90            let nt_headers: IMAGE_NT_HEADERS64 = unsafe{ std::ptr::read(nt_headers_buf.as_ptr() as *const _)};
91            nt_headers.OptionalHeader.DataDirectory[0].VirtualAddress
92        }
93        else
94        {
95            let mut nt_headers_buf: [u8; mem::size_of::<IMAGE_NT_HEADERS32>()] = [0; mem::size_of::<IMAGE_NT_HEADERS32>()];
96            self.read_memory_abs(self.base_address + dos_header.e_lfanew as usize, &mut nt_headers_buf);
97            let nt_headers: IMAGE_NT_HEADERS32 =unsafe{  std::ptr::read(nt_headers_buf.as_ptr() as *const _)};
98            nt_headers.OptionalHeader.DataDirectory[0].VirtualAddress
99        };
100
101        if export_table_address == 0
102        {
103            return funcs;
104        }
105
106        let mut export_table_buf: [u8; mem::size_of::<IMAGE_EXPORT_DIRECTORY>()] = [0; mem::size_of::<IMAGE_EXPORT_DIRECTORY>()];
107        self.read_memory_abs(self.base_address + export_table_address as usize, &mut export_table_buf);
108        let export_table: IMAGE_EXPORT_DIRECTORY = unsafe{ std::ptr::read(export_table_buf.as_ptr() as *const _) };
109
110        let name_offset_table = self.base_address + export_table.AddressOfNames as usize;
111        let ordinal_table = self.base_address + export_table.AddressOfNameOrdinals as usize;
112        let function_offset_table = self.base_address + export_table.AddressOfFunctions as usize;
113
114        for i in 0..export_table.NumberOfNames {
115            let mut func_name_offset_buf: [u8; mem::size_of::<u32>()] = [0; mem::size_of::<u32>()];
116            self.read_memory_abs(
117                name_offset_table + i as usize * mem::size_of::<u32>(),
118                &mut func_name_offset_buf,
119            );
120            let func_name_offset: u32 = unsafe{  std::ptr::read(func_name_offset_buf.as_ptr() as *const _)};
121
122            let func_name = read_ascii_string_generic(self, self.base_address + func_name_offset as usize);
123
124            let mut ordinal_index_buf: [u8; mem::size_of::<u16>()] = [0; mem::size_of::<u16>()];
125            self.read_memory_abs(
126                ordinal_table + i as usize * mem::size_of::<u16>(),
127                &mut ordinal_index_buf,
128            );
129            let ordinal_index: u16 = unsafe{ std::ptr::read(ordinal_index_buf.as_ptr() as *const _)};
130
131            let mut func_offset_buf: [u8; mem::size_of::<usize>()] = [0; mem::size_of::<usize>()];
132            self.read_memory_abs(
133                function_offset_table + ordinal_index as usize * mem::size_of::<u32>(),
134                &mut func_offset_buf,
135            );
136            let func_offset: u32 = unsafe{ std::ptr::read(func_offset_buf.as_ptr() as *const _)};
137
138            let func_addr: usize = self.base_address + func_offset as usize;
139
140            funcs.push((func_name, func_addr));
141        }
142        return funcs;
143    }
144}
145
146fn read_ascii_string_generic<T: ReadWrite>(read_write: &T, address: usize) -> String
147{
148    let mut offset: usize = 0;
149    let end_byte: u8 = 0x0;
150
151    let mut output_string: String = String::from("");
152
153    loop {
154        let mut single_char_buf: [u8; 1] = [0];
155        read_write.read_memory_abs(address + offset as usize, &mut single_char_buf);
156        let single_char: u8 = unsafe{ std::ptr::read(single_char_buf.as_ptr() as *const _) };
157
158        if single_char == end_byte {
159            break;
160        }
161
162        output_string.push(single_char as char);
163
164        offset += 1;
165
166        if offset > 512 {
167            panic!("String too long!");
168        }
169    }
170
171    return output_string;
172}