mirror of
https://github.com/Noratrieb/portability.git
synced 2026-01-14 15:55:04 +01:00
meh
This commit is contained in:
parent
d8c08d9359
commit
5dbb27d9d7
4 changed files with 122 additions and 97 deletions
|
|
@ -9,4 +9,4 @@ bytemuck = { version = "1.21.0", features = ["derive"] }
|
||||||
memmap2 = "0.9.5"
|
memmap2 = "0.9.5"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows = { version = "0.59.0", features = ["Win32_System_Memory", "Win32_Security"] }
|
windows = { version = "0.59.0", features = ["Win32_System_Memory", "Win32_Security", "Win32_System_SystemInformation"] }
|
||||||
|
|
|
||||||
40
src/lib.rs
40
src/lib.rs
|
|
@ -1,4 +1,4 @@
|
||||||
mod mmap;
|
mod sys;
|
||||||
|
|
||||||
use std::{ffi::CStr, fmt::Debug, fs::File};
|
use std::{ffi::CStr, fmt::Debug, fs::File};
|
||||||
|
|
||||||
|
|
@ -253,9 +253,19 @@ pub fn execute(file: File, pe: &[u8]) {
|
||||||
// just some arbitrary offset that probably won't collide with anything
|
// just some arbitrary offset that probably won't collide with anything
|
||||||
let base = optional_header.image_base as usize + 0xFFFFFF0000;
|
let base = optional_header.image_base as usize + 0xFFFFFF0000;
|
||||||
|
|
||||||
assert_eq!(base & (4096 - 1), 0);
|
let allocation_granularity = crate::sys::allocation_granularity();
|
||||||
|
|
||||||
let map = unsafe { crate::mmap::map(file).unwrap() };
|
assert_eq!(base & (allocation_granularity - 1), 0);
|
||||||
|
|
||||||
|
let total_size = section_table.last().unwrap().virtual_address as usize;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
crate::sys::anon_write_map(
|
||||||
|
total_size.next_multiple_of(allocation_granularity),
|
||||||
|
std::ptr::with_exposed_provenance(base),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// allocate the sections.
|
// allocate the sections.
|
||||||
for section in section_table {
|
for section in section_table {
|
||||||
|
|
@ -267,32 +277,30 @@ pub fn execute(file: File, pe: &[u8]) {
|
||||||
.characteristics
|
.characteristics
|
||||||
.contains(SectionFlags::IMAGE_SCN_MEM_EXECUTE)
|
.contains(SectionFlags::IMAGE_SCN_MEM_EXECUTE)
|
||||||
{
|
{
|
||||||
crate::mmap::Mode::Execute
|
crate::sys::Mode::Execute
|
||||||
} else if section
|
} else if section
|
||||||
.characteristics
|
.characteristics
|
||||||
.contains(SectionFlags::IMAGE_SCN_MEM_WRITE)
|
.contains(SectionFlags::IMAGE_SCN_MEM_WRITE)
|
||||||
{
|
{
|
||||||
crate::mmap::Mode::Write
|
crate::sys::Mode::Write
|
||||||
} else {
|
} else {
|
||||||
crate::mmap::Mode::Read
|
crate::sys::Mode::Read
|
||||||
};
|
};
|
||||||
let address =
|
let address =
|
||||||
std::ptr::with_exposed_provenance::<()>(base + section.virtual_address as usize);
|
std::ptr::with_exposed_provenance::<()>(base + section.virtual_address as usize);
|
||||||
dbg!(section);
|
dbg!(section);
|
||||||
|
|
||||||
// assert stuff is aligned (yes 4096 as a hardcoded page is bad)
|
|
||||||
//assert_eq!(section.pointer_to_raw_data & (4096 - 1), 0);
|
|
||||||
assert_eq!(address.addr() & (4096 - 1), 0);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
map.view(
|
std::slice::from_raw_parts_mut(
|
||||||
mode,
|
address.cast_mut().cast::<u8>(),
|
||||||
section.pointer_to_raw_data as u64,
|
|
||||||
section.size_of_raw_data as usize,
|
section.size_of_raw_data as usize,
|
||||||
address,
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.copy_from_slice(
|
||||||
};
|
&pe[section.pointer_to_raw_data as usize..][..section.size_of_raw_data as usize],
|
||||||
|
);
|
||||||
|
|
||||||
|
crate::sys::protect(address, section.virtual_size as usize, mode).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//let import_directory_table: &[ImportDirectoryTableEntry] = bytemuck::cast_slice(&file[optional_header.import_table.virtual_address as usize..][..optional_header.import_table.size as usize]);
|
//let import_directory_table: &[ImportDirectoryTableEntry] = bytemuck::cast_slice(&file[optional_header.import_table.virtual_address as usize..][..optional_header.import_table.size as usize]);
|
||||||
|
|
|
||||||
80
src/mmap.rs
80
src/mmap.rs
|
|
@ -1,80 +0,0 @@
|
||||||
//! memmap2 doesn't support MAP_FIXED so here's our own!
|
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
pub(crate) struct MapView(*const ());
|
|
||||||
|
|
||||||
pub(crate) enum Mode {
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
Execute,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
mod imp {
|
|
||||||
use std::{ffi::c_void, fs::File, io, os::windows::io::AsRawHandle, u32};
|
|
||||||
|
|
||||||
use windows::Win32::{
|
|
||||||
Foundation::HANDLE,
|
|
||||||
System::Memory::{FILE_MAP_COPY, FILE_MAP_EXECUTE, FILE_MAP_READ, PAGE_EXECUTE_READ},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{MapView, Mode};
|
|
||||||
|
|
||||||
pub(crate) struct Map(HANDLE);
|
|
||||||
|
|
||||||
pub(crate) unsafe fn map(file: File) -> io::Result<Map> {
|
|
||||||
windows::Win32::System::Memory::CreateFileMappingA(
|
|
||||||
HANDLE(file.as_raw_handle()),
|
|
||||||
None,
|
|
||||||
PAGE_EXECUTE_READ,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.map(Map)
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Map {
|
|
||||||
pub(crate) unsafe fn view(
|
|
||||||
&self,
|
|
||||||
mode: Mode,
|
|
||||||
file_offset: u64,
|
|
||||||
size: usize,
|
|
||||||
address: *const (),
|
|
||||||
) -> Result<MapView, io::Error> {
|
|
||||||
let addr = unsafe {
|
|
||||||
windows::Win32::System::Memory::MapViewOfFileEx(
|
|
||||||
self.0,
|
|
||||||
match mode {
|
|
||||||
Mode::Read => FILE_MAP_READ,
|
|
||||||
Mode::Write => FILE_MAP_COPY,
|
|
||||||
Mode::Execute => FILE_MAP_READ | FILE_MAP_EXECUTE,
|
|
||||||
},
|
|
||||||
(file_offset << 32) as u32,
|
|
||||||
file_offset as u32,
|
|
||||||
size,
|
|
||||||
Some(address as *const c_void),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if addr.Value.is_null() {
|
|
||||||
Err(io::Error::last_os_error())
|
|
||||||
} else {
|
|
||||||
Ok(MapView(addr.Value as *const ()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Map {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let _ = unsafe { windows::Win32::Foundation::CloseHandle(self.0) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(unix)]
|
|
||||||
mod imp {
|
|
||||||
compile_error!("no unix yet lol skill issue");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) use imp::*;
|
|
||||||
97
src/sys.rs
Normal file
97
src/sys.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
//! memmap2 doesn't support MAP_FIXED so here's our own!
|
||||||
|
|
||||||
|
pub(crate) enum Mode {
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
Execute,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod imp {
|
||||||
|
use std::{ffi::c_void, io, u32};
|
||||||
|
|
||||||
|
use windows::Win32::{
|
||||||
|
Foundation::INVALID_HANDLE_VALUE,
|
||||||
|
System::{
|
||||||
|
Memory::{FILE_MAP_EXECUTE, FILE_MAP_WRITE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_READONLY, PAGE_READWRITE},
|
||||||
|
SystemInformation::SYSTEM_INFO,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Mode;
|
||||||
|
|
||||||
|
pub(crate) fn allocation_granularity() -> usize {
|
||||||
|
let mut info = SYSTEM_INFO::default();
|
||||||
|
unsafe {
|
||||||
|
windows::Win32::System::SystemInformation::GetSystemInfo(&mut info);
|
||||||
|
}
|
||||||
|
info.dwAllocationGranularity as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn page_size() -> usize {
|
||||||
|
let mut info = SYSTEM_INFO::default();
|
||||||
|
unsafe {
|
||||||
|
windows::Win32::System::SystemInformation::GetSystemInfo(&mut info);
|
||||||
|
}
|
||||||
|
info.dwPageSize as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn anon_write_map(size: usize, address: *const ()) -> io::Result<()> {
|
||||||
|
let map = windows::Win32::System::Memory::CreateFileMappingA(
|
||||||
|
INVALID_HANDLE_VALUE,
|
||||||
|
None,
|
||||||
|
PAGE_EXECUTE_READWRITE,
|
||||||
|
(size >> 32) as u32,
|
||||||
|
size as u32,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
eprintln!("created {address:p} {size:x}");
|
||||||
|
|
||||||
|
debug_assert_eq!(address.addr() & (allocation_granularity() - 1), 0);
|
||||||
|
debug_assert_eq!(size & (allocation_granularity() - 1), 0);
|
||||||
|
|
||||||
|
let addr = unsafe {
|
||||||
|
windows::Win32::System::Memory::MapViewOfFileEx(
|
||||||
|
map,
|
||||||
|
FILE_MAP_WRITE | FILE_MAP_EXECUTE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
size,
|
||||||
|
Some(address as *const c_void),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = unsafe { windows::Win32::Foundation::CloseHandle(map) };
|
||||||
|
|
||||||
|
if addr.Value.is_null() {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn protect(address: *const (), size: usize, mode: Mode) -> io::Result<()> {
|
||||||
|
debug_assert_eq!(address.addr() & (page_size() - 1), 0);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
windows::Win32::System::Memory::VirtualProtect(
|
||||||
|
address.cast::<c_void>(),
|
||||||
|
size,
|
||||||
|
match mode {
|
||||||
|
Mode::Read => PAGE_READONLY,
|
||||||
|
Mode::Write => PAGE_READWRITE,
|
||||||
|
Mode::Execute => PAGE_EXECUTE_READ,
|
||||||
|
},
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
mod imp {
|
||||||
|
compile_error!("no unix yet lol skill issue");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use imp::*;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue