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    pub fn get_exports(&self) -> Vec<(String, usize)>
78    {
79        let mut funcs: Vec<(String, usize)> = Vec::new();
80
81        let mut dos_header_buf: [u8; mem::size_of::<IMAGE_DOS_HEADER>()] = [0; mem::size_of::<IMAGE_DOS_HEADER>()];
82        self.read_memory_abs(self.base_address, &mut dos_header_buf);
83        let dos_header: IMAGE_DOS_HEADER = unsafe{ std::ptr::read(dos_header_buf.as_ptr() as *const _) };
84
85        let export_table_address = if self.process_data.borrow().is_64_bit
86        {
87            let mut nt_headers_buf: [u8; mem::size_of::<IMAGE_NT_HEADERS64>()] = [0; mem::size_of::<IMAGE_NT_HEADERS64>()];
88            self.read_memory_abs(self.base_address + dos_header.e_lfanew as usize, &mut nt_headers_buf);
89            let nt_headers: IMAGE_NT_HEADERS64 = unsafe{ std::ptr::read(nt_headers_buf.as_ptr() as *const _)};
90            nt_headers.OptionalHeader.DataDirectory[0].VirtualAddress
91        }
92        else
93        {
94            let mut nt_headers_buf: [u8; mem::size_of::<IMAGE_NT_HEADERS32>()] = [0; mem::size_of::<IMAGE_NT_HEADERS32>()];
95            self.read_memory_abs(self.base_address + dos_header.e_lfanew as usize, &mut nt_headers_buf);
96            let nt_headers: IMAGE_NT_HEADERS32 =unsafe{  std::ptr::read(nt_headers_buf.as_ptr() as *const _)};
97            nt_headers.OptionalHeader.DataDirectory[0].VirtualAddress
98        };
99
100        if export_table_address == 0
101        {
102            return funcs;
103        }
104
105        let mut export_table_buf: [u8; mem::size_of::<IMAGE_EXPORT_DIRECTORY>()] = [0; mem::size_of::<IMAGE_EXPORT_DIRECTORY>()];
106        self.read_memory_abs(self.base_address + export_table_address as usize, &mut export_table_buf);
107        let export_table: IMAGE_EXPORT_DIRECTORY = unsafe{ std::ptr::read(export_table_buf.as_ptr() as *const _) };
108
109        let name_offset_table = self.base_address + export_table.AddressOfNames as usize;
110        let ordinal_table = self.base_address + export_table.AddressOfNameOrdinals as usize;
111        let function_offset_table = self.base_address + export_table.AddressOfFunctions as usize;
112
113        for i in 0..export_table.NumberOfNames {
114            let mut func_name_offset_buf: [u8; mem::size_of::<u32>()] = [0; mem::size_of::<u32>()];
115            self.read_memory_abs(
116                name_offset_table + i as usize * mem::size_of::<u32>(),
117                &mut func_name_offset_buf,
118            );
119            let func_name_offset: u32 = unsafe{  std::ptr::read(func_name_offset_buf.as_ptr() as *const _)};
120
121            let func_name = read_ascii_string_generic(self, self.base_address + func_name_offset as usize);
122
123            let mut ordinal_index_buf: [u8; mem::size_of::<u16>()] = [0; mem::size_of::<u16>()];
124            self.read_memory_abs(
125                ordinal_table + i as usize * mem::size_of::<u16>(),
126                &mut ordinal_index_buf,
127            );
128            let ordinal_index: u16 = unsafe{ std::ptr::read(ordinal_index_buf.as_ptr() as *const _)};
129
130            let mut func_offset_buf: [u8; mem::size_of::<usize>()] = [0; mem::size_of::<usize>()];
131            self.read_memory_abs(
132                function_offset_table + ordinal_index as usize * mem::size_of::<u32>(),
133                &mut func_offset_buf,
134            );
135            let func_offset: u32 = unsafe{ std::ptr::read(func_offset_buf.as_ptr() as *const _)};
136
137            let func_addr: usize = self.base_address + func_offset as usize;
138
139            funcs.push((func_name, func_addr));
140        }
141        return funcs;
142    }
143}
144
145fn read_ascii_string_generic<T: ReadWrite>(read_write: &T, address: usize) -> String
146{
147    let mut offset: usize = 0;
148    let end_byte: u8 = 0x0;
149
150    let mut output_string: String = String::from("");
151
152    loop {
153        let mut single_char_buf: [u8; 1] = [0];
154        read_write.read_memory_abs(address + offset as usize, &mut single_char_buf);
155        let single_char: u8 = unsafe{ std::ptr::read(single_char_buf.as_ptr() as *const _) };
156
157        if single_char == end_byte {
158            break;
159        }
160
161        output_string.push(single_char as char);
162
163        offset += 1;
164
165        if offset > 512 {
166            panic!("String too long!");
167        }
168    }
169
170    return output_string;
171}