v0.0.0b
This commit is contained in:
10
sub/pe/Cargo.toml
Normal file
10
sub/pe/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "sub_pe"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
windows = []
|
||||
|
||||
[dependencies]
|
||||
sub_core = { workspace = true }
|
||||
52
sub/pe/src/exports.rs
Normal file
52
sub/pe/src/exports.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use crate::imagebase::ImageBase;
|
||||
use crate::structs::*;
|
||||
|
||||
pub struct ExportIter<'a> {
|
||||
image: &'a ImageBase,
|
||||
export_dir: &'a ImageExportDirectory,
|
||||
export_index: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ExportIter<'a> {
|
||||
type Item = (usize, &'static [u8]);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.export_index < self.export_dir.number_of_name_pointers as usize {
|
||||
true => unsafe {
|
||||
#[inline(always)]
|
||||
unsafe fn u8_nul_terminated(ptr: *const u8) -> &'static [u8] {
|
||||
let mut end = ptr;
|
||||
while *end != 0 { end = end.add(1) }
|
||||
let len = (end as usize) - (ptr as usize);
|
||||
&*core::ptr::slice_from_raw_parts(ptr, len)
|
||||
}
|
||||
|
||||
let export_functions = self.image.offset(self.export_dir.export_address_table_rva) as *const u32;
|
||||
let export_names = self.image.offset(self.export_dir.name_pointer_rva) as *const u32;
|
||||
let export_ordinals = self.image.offset(self.export_dir.ordinal_table_rva) as *const u16;
|
||||
|
||||
let export_name = self.image.offset(*export_names.add(self.export_index));
|
||||
let export_ordinal = *export_ordinals.add(self.export_index);
|
||||
let export_rva = self.image.offset(*export_functions.add(export_ordinal as usize)) as usize;
|
||||
|
||||
self.export_index += 1;
|
||||
|
||||
Some((export_rva, u8_nul_terminated(export_name)))
|
||||
}
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageBase {
|
||||
pub unsafe fn exports(&self) -> Option<ExportIter> {
|
||||
let directory = &self.nt_header().optional_header.data_directory[DIRECTORY_ENTRY_EXPORT];
|
||||
if directory.size == 0 || directory.virtual_address == 0 { return None; }
|
||||
let export_directory = &*(self.offset(directory.virtual_address) as *const ImageExportDirectory);
|
||||
Some(ExportIter {
|
||||
image: self,
|
||||
export_dir: export_directory,
|
||||
export_index: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
81
sub/pe/src/imagebase.rs
Normal file
81
sub/pe/src/imagebase.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use core::ops::{Add, Range, Sub};
|
||||
use sub_core::cast_traits::Upcast;
|
||||
use crate::structs::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageBase(());
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "__ImageBase"]
|
||||
static ImageBasePtr: [u8;0];
|
||||
}
|
||||
|
||||
impl ImageBase {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get() -> &'static ImageBase {
|
||||
unsafe { &*(ImageBasePtr.as_ptr() as *const ImageBase) }
|
||||
}
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_ptr(&self) -> usize {
|
||||
self as *const _ as usize
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn offset<T: Upcast<usize>>(&self, offset: T) -> *const u8 {
|
||||
unsafe { (self as *const _ as *const u8).add(offset.upcast()) }
|
||||
}
|
||||
|
||||
pub unsafe fn dos(&self) -> &ImageDOSHeader {
|
||||
&*(self as *const _ as *const ImageDOSHeader)
|
||||
}
|
||||
|
||||
pub unsafe fn dos_mut(&mut self) -> &mut ImageDOSHeader {
|
||||
&mut *(self as *mut _ as *mut ImageDOSHeader)
|
||||
}
|
||||
|
||||
pub unsafe fn nt_header(&self) -> &'static ImageNTHeaders64 {
|
||||
&*(self.offset(self.dos().e_lfanew) as *const ImageNTHeaders64)
|
||||
}
|
||||
|
||||
pub unsafe fn nt_header_mut(&mut self) -> &'static mut ImageNTHeaders64 {
|
||||
&mut *(self.offset(self.dos().e_lfanew) as *mut ImageNTHeaders64)
|
||||
}
|
||||
|
||||
pub unsafe fn sections(&self) -> &[ImageSectionHeader] {
|
||||
self.nt_header().sections()
|
||||
}
|
||||
|
||||
pub unsafe fn as_range(&self) -> Range<usize> {
|
||||
self.as_ptr()..self.as_ptr() + self.nt_header().optional_header.size_of_image as usize
|
||||
}
|
||||
|
||||
pub unsafe fn as_slice(&self) -> &[u8] {
|
||||
let ptr = self.as_ptr() as *const u8;
|
||||
let size = self.nt_header().optional_header.size_of_image as usize;
|
||||
core::slice::from_raw_parts(ptr, size)
|
||||
}
|
||||
|
||||
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
|
||||
let ptr = self.as_ptr() as *mut u8;
|
||||
let size = self.nt_header().optional_header.size_of_image as usize;
|
||||
core::slice::from_raw_parts_mut(ptr, size)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Add<usize> for &ImageBase {
|
||||
type Output = usize;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
(self as *const _ as usize) + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<usize> for &ImageBase {
|
||||
type Output = usize;
|
||||
fn sub(self, rhs: usize) -> Self::Output {
|
||||
(self as *const _ as usize) + rhs
|
||||
}
|
||||
}
|
||||
28
sub/pe/src/lib.rs
Normal file
28
sub/pe/src/lib.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
#![no_std]
|
||||
|
||||
//
|
||||
// Internal modules
|
||||
//
|
||||
|
||||
pub mod structs;
|
||||
|
||||
#[cfg(feature = "windows")]
|
||||
pub mod imagebase;
|
||||
|
||||
#[cfg(feature = "windows")]
|
||||
pub mod exports;
|
||||
|
||||
//
|
||||
// Export Preludes:
|
||||
//
|
||||
|
||||
pub mod prelude {
|
||||
#[cfg(feature = "windows")]
|
||||
pub use crate::imagebase::ImageBase;
|
||||
}
|
||||
|
||||
pub mod public {
|
||||
#[cfg(feature = "windows")]
|
||||
pub use crate::exports::ExportIter;
|
||||
pub use crate::structs::*;
|
||||
}
|
||||
199
sub/pe/src/structs.rs
Normal file
199
sub/pe/src/structs.rs
Normal file
@@ -0,0 +1,199 @@
|
||||
// ==============================
|
||||
// PE stuff
|
||||
// ==============================
|
||||
|
||||
pub const PE_SIGNATURE: u32 = 0x00004550;
|
||||
pub const DOS_MAGIC: u16 = 0x5A4D;
|
||||
|
||||
pub const IOH_MAGIC_PE32: u16 = 0x10B; // 32 bit executable
|
||||
pub const IOH_MAGIC_PE64: u16 = 0x20B; // 64 bit executable
|
||||
pub const IOH_MAGIC_ROM: u16 = 0x107; // Yes!
|
||||
|
||||
pub const NUMBEROF_DIRECTORY_ENTRIES: usize = 16;
|
||||
|
||||
pub const DIRECTORY_ENTRY_EXPORT: usize = 0x0; // Export Directory
|
||||
pub const DIRECTORY_ENTRY_IMPORT: usize = 0x1; // Import Directory
|
||||
pub const DIRECTORY_ENTRY_RESOURCE: usize = 0x2; // Resource Directory
|
||||
pub const DIRECTORY_ENTRY_EXCEPTION: usize = 0x3; // Exception Directory
|
||||
pub const DIRECTORY_ENTRY_SECURITY: usize = 0x4; // Security Directory
|
||||
pub const DIRECTORY_ENTRY_BASERELOC: usize = 0x5; // Base Relocation Table
|
||||
pub const DIRECTORY_ENTRY_DEBUG: usize = 0x6; // Debug Directory
|
||||
pub const DIRECTORY_ENTRY_ARCHITECTURE: usize = 0x7; // Architecture Specific Data
|
||||
pub const DIRECTORY_ENTRY_GLOBALPTR: usize = 0x8; // RVA of GP
|
||||
pub const DIRECTORY_ENTRY_TLS: usize = 0x9; // TLS Directory
|
||||
pub const DIRECTORY_ENTRY_LOAD_CONFIG: usize = 0xA; // Load Configuration Directory
|
||||
pub const DIRECTORY_ENTRY_BOUND_IMPORT: usize = 0xB; // Bound Import Directory in headers
|
||||
pub const DIRECTORY_ENTRY_IAT: usize = 0xC; // Import Address Table
|
||||
pub const DIRECTORY_ENTRY_DELAY_IMPORT: usize = 0xD; // Delay Load Import Descriptors
|
||||
pub const DIRECTORY_ENTRY_COM_DESCRIPTOR: usize = 0xE; // COM Runtime descriptor
|
||||
|
||||
pub const IMAGE_FILE_MACHINE_I386: u16 = 0x014c;
|
||||
pub const IMAGE_FILE_MACHINE_IA64: u16 = 0x0200;
|
||||
pub const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageDOSHeader {
|
||||
pub e_magic: u16,
|
||||
pub e_cblp: u16,
|
||||
pub e_cp: u16,
|
||||
pub e_crlc: u16,
|
||||
pub e_cparhdr: u16,
|
||||
pub e_minalloc: u16,
|
||||
pub e_maxalloc: u16,
|
||||
pub e_ss: u16,
|
||||
pub e_sp: u16,
|
||||
pub e_csum: u16,
|
||||
pub e_ip: u16,
|
||||
pub e_cs: u16,
|
||||
pub e_lfarlc: u16,
|
||||
pub e_ovno: u16,
|
||||
pub e_res: [u16;4],
|
||||
pub e_oemid: u16,
|
||||
pub e_oeminfo: u16,
|
||||
pub e_res2: [u16;10],
|
||||
pub e_lfanew: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageNTHeaders64 {
|
||||
pub signature: u32,
|
||||
pub file_header: ImageFileHeader,
|
||||
pub optional_header: ImageOptionalHeader64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageFileHeader {
|
||||
pub machine: u16,
|
||||
pub number_of_sections: u16,
|
||||
pub timestamp: u32,
|
||||
pub pointer_to_symbol_table: u32,
|
||||
pub number_of_symbols: u32,
|
||||
pub size_of_optional_header: u16,
|
||||
pub characteristics: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageOptionalHeader64 {
|
||||
pub magic: u16,
|
||||
pub major_linker_version: u8,
|
||||
pub minor_linker_version: u8,
|
||||
pub size_of_code: u32,
|
||||
pub size_of_initialized_data: u32,
|
||||
pub size_of_uninitialized_data: u32,
|
||||
pub address_of_entry_point: u32,
|
||||
pub base_of_code: u32,
|
||||
pub image_base: u64,
|
||||
pub section_alignment: u32,
|
||||
pub file_alignment: u32,
|
||||
pub major_operating_system_version: u16,
|
||||
pub minor_operating_system_version: u16,
|
||||
pub major_image_version: u16,
|
||||
pub minor_image_version: u16,
|
||||
pub major_subsystem_version: u16,
|
||||
pub minor_subsystem_version: u16,
|
||||
pub win32_version_value: u32,
|
||||
pub size_of_image: u32,
|
||||
pub size_of_headers: u32,
|
||||
pub checksum: u32,
|
||||
pub subsystem: u16,
|
||||
pub dll_characteristics: u16,
|
||||
pub size_of_stack_reserve: u64,
|
||||
pub size_of_stack_commit: u64,
|
||||
pub size_of_heap_reserve: u64,
|
||||
pub size_of_heap_commit: u64,
|
||||
pub loader_flags: u32,
|
||||
pub number_of_rva_and_sizes: u32,
|
||||
pub data_directory: [ImageDataDirectory; NUMBEROF_DIRECTORY_ENTRIES]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageDataDirectory {
|
||||
pub virtual_address: u32,
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageSectionHeader {
|
||||
pub name: [u8;8],
|
||||
pub virtual_size: u32,
|
||||
pub virtual_address: u32,
|
||||
pub size_of_raw_data: u32,
|
||||
pub pointer_to_raw_data: u32,
|
||||
pub pointer_to_relocations: u32,
|
||||
pub pointer_to_linenumbers: u32,
|
||||
pub number_of_relocations: u16,
|
||||
pub number_of_linenumbers: u16,
|
||||
pub characteristics: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageImportDescriptor {
|
||||
pub original_first_thunk: u32,
|
||||
pub timestamp: u32,
|
||||
pub forwarder_chain: u32,
|
||||
pub name: u32,
|
||||
pub first_thunk: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageBoundImportDescriptor {
|
||||
pub timestamp: u32,
|
||||
pub offset_module_name: u16,
|
||||
pub number_of_module_forwarder_refs: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageImportByName {
|
||||
pub hint: u16,
|
||||
pub name: [u8]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageBaseRelocation {
|
||||
pub virtual_address: u32,
|
||||
pub size_of_block: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageExportDirectory {
|
||||
/* 0x00 */pub export_flags: u32,
|
||||
/* 0x04 */pub timestamp: u32,
|
||||
/* 0x06 */pub major_version: u16,
|
||||
/* 0x08 */pub minor_version: u16,
|
||||
/* 0x0C */pub name_rva: u32,
|
||||
/* 0x10 */pub ordinal_base: u32,
|
||||
/* 0x14 */pub address_table_entries: u32,
|
||||
/* 0x18 */pub number_of_name_pointers: u32,
|
||||
/* 0x1C */pub export_address_table_rva: u32,
|
||||
/* 0x20 */pub name_pointer_rva: u32,
|
||||
/* 0x24 */pub ordinal_table_rva: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ImageExportAddressEntry {
|
||||
pub export_rva: u32,
|
||||
pub forwarder_rva: u32,
|
||||
}
|
||||
|
||||
impl ImageDataDirectory {
|
||||
pub fn contains(&self, offset: u32) -> bool {
|
||||
// offset - self.virtual_address < self.size
|
||||
offset.overflowing_sub(self.virtual_address).0 < self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageNTHeaders64 {
|
||||
pub fn sections(&self) -> &[ImageSectionHeader] {
|
||||
let section_base
|
||||
= ( &self.optional_header as *const _ as usize )
|
||||
+ self.file_header.size_of_optional_header as usize;
|
||||
unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
section_base as *const ImageSectionHeader,
|
||||
self.file_header.number_of_sections as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user