mirror of
https://github.com/Noratrieb/portability.git
synced 2026-01-14 15:55:04 +01:00
test
This commit is contained in:
parent
389721d5d0
commit
5595df2249
6 changed files with 83 additions and 9 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,3 +2,5 @@
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
|
!/test/*.exe
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,4 @@ a PE loader for educational purposes.
|
||||||
- https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
- https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
- https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail
|
- https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail
|
||||||
- https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2
|
- https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2
|
||||||
|
- https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
|
||||||
|
|
|
||||||
57
src/lib.rs
57
src/lib.rs
|
|
@ -1,6 +1,11 @@
|
||||||
mod sys;
|
mod sys;
|
||||||
|
|
||||||
use std::{ffi::CStr, fmt::Debug, fs::File};
|
use std::{
|
||||||
|
ffi::CStr,
|
||||||
|
fmt::Debug,
|
||||||
|
fs::File,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, bytemuck::Zeroable, bytemuck::Pod)]
|
#[derive(Clone, Copy, Debug, bytemuck::Zeroable, bytemuck::Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -250,8 +255,8 @@ pub fn execute(pe: &[u8]) {
|
||||||
);
|
);
|
||||||
dbg!(section_table);
|
dbg!(section_table);
|
||||||
|
|
||||||
// just some arbitrary offset that probably won't collide with anything
|
// let's always load it at the image base for now...
|
||||||
let base = optional_header.image_base as usize + 0xFFFFFF0000;
|
let base = optional_header.image_base as usize;
|
||||||
|
|
||||||
let allocation_granularity = crate::sys::allocation_granularity();
|
let allocation_granularity = crate::sys::allocation_granularity();
|
||||||
|
|
||||||
|
|
@ -312,8 +317,18 @@ pub fn execute(pe: &[u8]) {
|
||||||
dbg!(import_directory);
|
dbg!(import_directory);
|
||||||
|
|
||||||
let name = CStr::from_bytes_until_nul(&a[import_directory.name_rva as usize..]).unwrap();
|
let name = CStr::from_bytes_until_nul(&a[import_directory.name_rva as usize..]).unwrap();
|
||||||
|
if name.is_empty() {
|
||||||
|
// Trailing null import directory.
|
||||||
|
break;
|
||||||
|
}
|
||||||
dbg!(name);
|
dbg!(name);
|
||||||
|
|
||||||
|
let dll = find_dll(name);
|
||||||
|
match dll {
|
||||||
|
Some(path) => eprintln!(" found {name:?} at {path:?}"),
|
||||||
|
None => eprintln!(" COULD NOT FIND {name:?}"),
|
||||||
|
}
|
||||||
|
|
||||||
let import_lookups = bytemuck::cast_slice::<u8, u64>(
|
let import_lookups = bytemuck::cast_slice::<u8, u64>(
|
||||||
&a[import_directory.import_lookup_table_rva as usize..],
|
&a[import_directory.import_lookup_table_rva as usize..],
|
||||||
);
|
);
|
||||||
|
|
@ -335,6 +350,15 @@ pub fn execute(pe: &[u8]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eprintln!("YOLO");
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let entrypoint = std::mem::transmute::<usize, unsafe fn() -> !>(
|
||||||
|
optional_header.address_of_entry_point as usize,
|
||||||
|
);
|
||||||
|
entrypoint();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_header(pe: &[u8]) -> (&CoffHeader, usize) {
|
fn parse_header(pe: &[u8]) -> (&CoffHeader, usize) {
|
||||||
|
|
@ -357,3 +381,30 @@ fn parse_header(pe: &[u8]) -> (&CoffHeader, usize) {
|
||||||
(signature_pointer as usize) + 4 + std::mem::size_of::<CoffHeader>(),
|
(signature_pointer as usize) + 4 + std::mem::size_of::<CoffHeader>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_dll(name: &CStr) -> Option<PathBuf> {
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
|
||||||
|
let name = name.to_str().unwrap();
|
||||||
|
if name.starts_with("api-") {
|
||||||
|
// This is an API set, essentially a virtual alias
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let system = sys::system_directory().unwrap();
|
||||||
|
eprintln!(" searching {system:?} for {name}");
|
||||||
|
let from_system = std::fs::read_dir(system).unwrap().find(|child| {
|
||||||
|
child
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.file_name()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.eq_ignore_ascii_case(name)
|
||||||
|
});
|
||||||
|
if let Some(from_system) = from_system {
|
||||||
|
return Some(from_system.unwrap().path());
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ fn main() {
|
||||||
.open(
|
.open(
|
||||||
std::env::args()
|
std::env::args()
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.unwrap_or_else(|| "example_exe.exe".into()),
|
.unwrap_or_else(|| "test/example_exe.exe".into()),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
||||||
|
|
|
||||||
28
src/sys.rs
28
src/sys.rs
|
|
@ -8,13 +8,16 @@ pub(crate) enum Mode {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use std::{ffi::c_void, io, u32};
|
use std::{ffi::c_void, io, path::PathBuf, u32};
|
||||||
|
|
||||||
use windows::Win32::{
|
use windows::Win32::{
|
||||||
Foundation::INVALID_HANDLE_VALUE,
|
Foundation::INVALID_HANDLE_VALUE,
|
||||||
System::{
|
System::{
|
||||||
Memory::{FILE_MAP_EXECUTE, FILE_MAP_WRITE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_READONLY, PAGE_READWRITE},
|
Memory::{
|
||||||
SystemInformation::SYSTEM_INFO,
|
FILE_MAP_EXECUTE, FILE_MAP_WRITE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE,
|
||||||
|
PAGE_READONLY, PAGE_READWRITE,
|
||||||
|
},
|
||||||
|
SystemInformation::{GetSystemDirectoryW, SYSTEM_INFO},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,7 +39,10 @@ mod imp {
|
||||||
info.dwPageSize as usize
|
info.dwPageSize as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn anon_write_map<'a>(size: usize, address: *const ()) -> io::Result<&'a mut [u8]> {
|
pub(crate) unsafe fn anon_write_map<'a>(
|
||||||
|
size: usize,
|
||||||
|
address: *const (),
|
||||||
|
) -> io::Result<&'a mut [u8]> {
|
||||||
let map = windows::Win32::System::Memory::CreateFileMappingA(
|
let map = windows::Win32::System::Memory::CreateFileMappingA(
|
||||||
INVALID_HANDLE_VALUE,
|
INVALID_HANDLE_VALUE,
|
||||||
None,
|
None,
|
||||||
|
|
@ -88,6 +94,20 @@ mod imp {
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn system_directory() -> io::Result<PathBuf> {
|
||||||
|
let mut buf = vec![0; 1024];
|
||||||
|
let ret = unsafe { GetSystemDirectoryW(Some(&mut buf)) };
|
||||||
|
if ret == 0 {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(std::char::decode_utf16(buf)
|
||||||
|
.map(Result::unwrap)
|
||||||
|
.take_while(|c| *c != '\0')
|
||||||
|
.collect::<String>()
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod imp {
|
mod imp {
|
||||||
|
|
|
||||||
BIN
test/example_exe.exe
Normal file
BIN
test/example_exe.exe
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue