Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge feat/confloader to dev/0.0.1 #9

Merged
merged 46 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2a8b141
Add: file configuration for JSON YAMLTOML and in-line
Esgr0bar May 12, 2024
d03e0ad
Delete configuration.rs
Esgr0bar May 12, 2024
2ebf899
Delete test.json
Esgr0bar May 12, 2024
36763c7
re-upload file at the right place
Esgr0bar May 12, 2024
d26347e
upload json to test configuration parser
Esgr0bar May 12, 2024
c25d6ce
Update configuration.rs : comment example main to allow merge without…
Esgr0bar May 16, 2024
bab8ccd
Create test.toml
Esgr0bar May 24, 2024
43fb2e0
Rename test.TOML to test.toml
Esgr0bar May 24, 2024
b5171f3
Create test.yaml
Esgr0bar May 24, 2024
3df6238
Create test.xml
Esgr0bar May 24, 2024
419c001
Update configuration.rs to handle only toml and use anyhow::Error
Esgr0bar May 28, 2024
1b8dc70
Update configuration.rs : update documentation
Esgr0bar May 28, 2024
fbeb6fb
Update Cargo.toml
Esgr0bar May 28, 2024
4c2bdb4
Update Cargo.toml
Esgr0bar May 28, 2024
7522baf
fix: after review comment
Esgr0bar Jun 10, 2024
73c30fb
add: common traits
Esgr0bar Jun 10, 2024
1c30090
Delete configuration.rs
Esgr0bar Jun 10, 2024
d217116
Delete lib.rs
Esgr0bar Jun 10, 2024
afe9999
Delete utils.rs
Esgr0bar Jun 10, 2024
6ab1f48
Delete config_struct.rs
Esgr0bar Jun 10, 2024
949eeea
Delete architecture.rs
Esgr0bar Jun 10, 2024
afe9559
Add files via upload
Esgr0bar Jun 10, 2024
8aa0b59
feat: added some generic traits/structs, started configuration refactor
standard3 Jun 18, 2024
142b7df
del: useless struct
standard3 Jun 18, 2024
0e61d34
fix: added &self to generic traits
standard3 Jun 18, 2024
a055036
feat: riscv base structs
standard3 Jun 18, 2024
bd3b9fd
feat: added machine struct
standard3 Jun 18, 2024
d53d989
chore: common traits on riscv mmumode
standard3 Jun 18, 2024
38433e9
fmt: removed useless docstrings
standard3 Jun 18, 2024
d29f5b0
del: useless tests files
standard3 Jun 18, 2024
7cd604d
chore: easily identifiable addresses
standard3 Jun 18, 2024
ad93938
feat: MemoryRegion impl, added MemorySpace, Machine generic struct
standard3 Jun 18, 2024
437fd3b
feat: created TryFromPath and FromPath traits
standard3 Jun 18, 2024
b377b99
wip: moved configuration to root
standard3 Jun 18, 2024
297e772
fix: implement from_path to every machine
standard3 Jun 19, 2024
037f927
fix: clippy è_é
standard3 Jun 19, 2024
0ae4e35
fix: removed false assertion
standard3 Jun 19, 2024
aa5299d
feat: renamed test to riscv sample
standard3 Jun 19, 2024
a2962e8
del: useless file
standard3 Jun 19, 2024
372ff63
feat: configuration integration test
standard3 Jun 19, 2024
8e7ab58
fix: moved machine generic in the good order
standard3 Jun 19, 2024
3191018
feat: riscv cpu & mmu
standard3 Jun 19, 2024
190acde
feat: changed public machine API, removed useless traits, added integ…
standard3 Jun 19, 2024
f67ed6a
fix: bad memory regions
standard3 Jun 19, 2024
4bbd76b
fix: typo
standard3 Jun 19, 2024
4113a76
fmt: changed fake data by todo! macros
standard3 Jun 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ keywords = ["forensics", "memory forensics"]
exclude = [".github", "CONTRIBUTING.md", "CODE_OF_CONDUCT.md", "assets"]
license = "GPL-3.0"

authors = ["Théo Abel <theo.abel53@gmail.com>"] # todo: add other contributors
authors = ["Théo Abel <theo.abel53@gmail.com>", "Nathan Dandrimont <nathan.dandrimont@ecole2600.com>"] # todo: add other contributors

[dependencies]
serde = { version = "1.0", features = ["derive"] }
toml = "0.8.12"
anyhow = "1.0"
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,26 @@ todo
- Add support for Binary Code Analysis with `miasm`

```rust
use anyhow::Result;
use libmmu::architectures::{ RiscV, RiscVMMUMode };
use libmmu::utils::{ MemorySpace, SpaceType, MachineConfig };

fn main() {
fn main() -> Result<()> {
let dumpfile = ...;
let outfolder = ...;

let memspaces = MemorySpace::new()
.add(SpaceType::RAM, 0x0000000080000000, 0x000000017fffffff)
.add(SpaceType::ROM, 0x0000000000000000, 0x0000000000011fff);

let conf = MachineConfig::<RiscV>::new()
.dumpfile("dump.raw")
.mmu(RiscVMMUMode::SV39)
.memspaces(memspaces)
.outfile("output");
let machine = Machine::new(
MachineType::RiscV(MMUMode:SV32),
memspaces,
dumpfile,
outfolder
)?;

conf.resolve_spaces()
machine.resolve_spaces()?;
}
```

Expand Down
2 changes: 2 additions & 0 deletions src/architecture.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod generic;
pub mod riscv;
170 changes: 170 additions & 0 deletions src/architecture/generic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{hash, path::PathBuf};

use super::riscv::MMUMode as RiscVMMUMode;

/// Enumerates types of memory regions.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum MemoryRegionType {
#[default]
RAM,
ROM,
}

/// Represents a memory region with a start and end address.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct MemoryRegion {
pub region_type: MemoryRegionType,
pub start_address: u64,
pub end_address: u64,
}

impl MemoryRegion {
pub fn new(
region_type: MemoryRegionType,
start_address: u64,
end_address: u64,
) -> Result<Self> {
// Check that addresses are valid memory addresses
if start_address >= end_address {
return Err(anyhow::anyhow!(
"Invalid memory region, start address is greater than or equal to end address"
));
}

Ok(Self {
region_type,
start_address,
end_address,
})
}

/// Returns the size of the memory region.
pub fn size(&self) -> u64 {
self.end_address - self.start_address
}

/// Returns true if the memory region contains the address.
/// A memory region contains an address if the address is greater than or equal to the start address and less than the end address.
pub fn contains(&self, address: u64) -> bool {
self.start_address <= address && address < self.end_address
}

/// Returns true if the two memory regions are overlapping.
/// Two memory regions are overlapping if the start address of one region is less than the end address of the other region.
pub fn is_overlapping(&self, other: &MemoryRegion) -> bool {
self.contains(other.start_address) || other.contains(self.start_address)
}

/// Returns true if the two memory regions are adjacent.
/// Two memory regions are adjacent if the end address of one region is equal to the start address of the other region.
pub fn is_adjacent(&self, other: &MemoryRegion) -> bool {
self.start_address == other.end_address || other.start_address == self.end_address
}
}

/// Represents a memory space with regions.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct MemorySpace {
pub regions: Vec<MemoryRegion>,
}

impl MemorySpace {
pub fn new() -> Self {
Self {
regions: Vec::new(),
}
}

pub fn add(&mut self, region: MemoryRegion) -> Result<&mut Self> {
// Check if the memory region is overlapping with another region
if self.regions.iter().any(|r| r.is_overlapping(&region)) {
return Err(anyhow::anyhow!(
"Memory region is overlapping with another region"
));
}

self.regions.push(region);
Ok(self)
}
}

/// Represents a CPU register with a value.
/// Depending on the architecture, the *validity* changes.
pub trait CPURegister {
type Value: hash::Hash + Eq + Copy + Default;

fn is_valid(&self) -> Result<Self::Value>;
}

/// Represents a page table entry with an address and flags.
/// It holds the mapping between a virtual address of a page and the address of a physical frame.
/// There is also auxiliary information about the page such as a present bit, a dirty or modified bit,
/// address space or process ID information, amongst others.
pub trait PageTableEntry {
type Address: hash::Hash + Eq + Copy + Default;
type Flags: hash::Hash + Eq + Copy + Default;

fn is_dirty(&self) -> bool;
fn is_accessed(&self) -> bool;
fn is_global(&self) -> bool;
fn is_readable(&self) -> bool;
fn is_writable(&self) -> bool;
fn is_executable(&self) -> bool;
}

/// Represents a page table with entries.
/// It is a data structure used in a virtual memory system to manage the mapping between virtual addresses and physical addresses.
/// It is used to translate virtual addresses to physical addresses and to manage the memory permissions of the pages.
/// It is also used to store additional information about the pages, such as the status of the page, the address space or process ID, amongst others.
pub trait PageTable {
type Entries: hash::Hash + Eq + Copy + Default + PageTableEntry;

// fn apply_on_entries(function: FnMut(PageTableEntry) -> Vec<?> ) -> ? // FIXME: to be defined, but is it necessary?
}

/// Enumerates types of supported machines.
/// This enum is used to specify the type of machine that is being parsed.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MachineType {
RiscV(RiscVMMUMode),
}

impl Default for MachineType {
fn default() -> Self {
Self::RiscV(RiscVMMUMode::SV32)
}
}

/// Represents a machine with a type, MMU, CPU, memory regions, and an associated dump file.
/// It is used to store the machine's configuration, memory regions, and the dump file that is being used.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct Machine {
/// Type of the machine and its associated MMU mode.
pub machine_type: MachineType,
/// Memory regions of the machine.
pub memory_regions: MemorySpace,
/// Path to the dump file.
pub dumpfile: PathBuf,
/// Path to the output folder.
pub outfolder: PathBuf,
}

impl Machine {
pub fn new(
machine_type: MachineType,
memory_regions: MemorySpace,
dumpfile: PathBuf,
outfolder: PathBuf,
) -> Self {
// TODO: Validate each field

Self {
machine_type,
memory_regions,
dumpfile,
outfolder,
}
}
}
111 changes: 111 additions & 0 deletions src/architecture/riscv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use super::generic::{CPURegister as CPURegisterTrait, PageTableEntry as PageTableEntryTrait};

use anyhow::Result;
use serde::{Deserialize, Serialize};

/// Represents a RISC-V CPU register associated with a value.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, Hash, Eq, PartialEq)]
pub struct CPURegister {
pub value: u64,
}

impl CPURegisterTrait for CPURegister {
type Value = u64;

fn is_valid(&self) -> Result<u64> {
todo!()
}
}

impl CPURegister {
pub fn new(value: u64) -> Self {
Self { value }
}
}

/// Represents a RISC-V page table entry.
/// It holds the mapping between a virtual address of a page and the address of a physical frame.
/// There is also auxiliary information about the page such as a present bit, a dirty or modified bit,
/// address space or process ID information, amongst others.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct PageTableEntry {
pub address: u64,
pub flags: u64,
}

impl PageTableEntry {
pub fn new(address: u64, flags: u64) -> Self {
Self { address, flags }
}

pub fn is_supervisor(&self) -> bool {
todo!()
}
}

impl PageTableEntryTrait for PageTableEntry {
type Address = u64;
type Flags = u64;

// FIXME: Implement the following methods
fn is_dirty(&self) -> bool {
todo!()
}

fn is_accessed(&self) -> bool {
todo!()
}

fn is_global(&self) -> bool {
todo!()
}

fn is_readable(&self) -> bool {
todo!()
}

fn is_writable(&self) -> bool {
todo!()
}

fn is_executable(&self) -> bool {
todo!()
}
}

/// Enumerates RISC-V MMU modes.
/// The MMU modes are used to determine the number of bits used for virtual and physical addresses.
/// The modes are named after the number of bits used for the virtual address space.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, Eq, PartialEq, Default)]
pub enum MMUMode {
#[default]
SV32,
SV39,
SV48,
}

/// Represents a RISC-V CPU.
#[derive(Debug, Clone, Serialize, Deserialize, Default, Hash, Eq, PartialEq)]
pub struct CPU {
pub registers: Vec<CPURegister>,
}

impl CPU {
pub fn new() -> Self {
Self {
registers: Vec::new(),
}
}
}

/// Represents a RISC-V MMU.
#[derive(Debug, Clone, Serialize, Deserialize, Default, Hash, Eq, PartialEq)]
pub struct MMU {
pub mode: MMUMode,
}

impl MMU {
pub fn new(mode: MMUMode) -> Self {
Self { mode }
}
}
19 changes: 19 additions & 0 deletions src/configuration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use anyhow::Result;
use std::fs;
use std::path::Path;

use crate::utils::TryFromPath;

use super::architecture::generic::Machine;

/// Represents a configuration file for a machine.
/// It holds information about the machine's architecture, memory regions, and other relevant information.
/// The configuration file must be written in the TOML format.
impl TryFromPath for Machine {
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved
fn from_path(path: &Path) -> Result<Self> {
let configuration = fs::read_to_string(path)?;
let machine: Machine = toml::from_str(&configuration)?;
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved

Ok(machine)
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod architecture;
pub mod configuration;
pub mod utils;
28 changes: 28 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use anyhow::Result;
use std::path::{Path, PathBuf};

/// Try to convert from a path.
pub trait TryFromPath {
/// Converts from a path reference.
fn from_path(path: &Path) -> Result<Self>
where
Self: Sized;
}

/// Defines a trait for converting from a path.
pub trait FromPath {
/// Converts from a path reference.
fn from_path(path: &Path) -> Self;
}

impl FromPath for String {
fn from_path(path: &Path) -> String {
path.to_string_lossy().into_owned()
}
}

impl FromPath for PathBuf {
fn from_path(path: &Path) -> PathBuf {
path.to_path_buf()
}
}
Loading
Loading