mirror of
https://github.com/EddieIvan01/memexec
synced 2024-06-28 18:01:54 +00:00
Add a check on .NET executable
This commit is contained in:
parent
cb3defa6ca
commit
db55833355
11
Cargo.toml
11
Cargo.toml
@ -1,17 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "memexec"
|
name = "memexec"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["iv4n <iv4n.cc@qq.com>"]
|
authors = ["iv4n <iv4n.cc@qq.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Lib used to load and execute PE (Portable Executable) in memory without ever touching the disk"
|
description = "A library for loading and executing PE (Portable Executable) without ever touching the disk"
|
||||||
git = "https://github.com/eddieivan01/memexec.git"
|
git = "https://github.com/eddieivan01/memexec.git"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
lto = "fat"
|
|
||||||
codegen-units = 1
|
|
||||||
opt-level = 3
|
|
||||||
panic = "abort"
|
|
||||||
incremental = false
|
|
||||||
|
14
README.md
14
README.md
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
[![](https://img.shields.io/crates/v/memexec)](https://crates.io/crates/memexec) [![](https://img.shields.io/crates/d/memexec?label=downloads%40crates.io&style=social)](https://crates.io/crates/memexec)
|
[![](https://img.shields.io/crates/v/memexec)](https://crates.io/crates/memexec) [![](https://img.shields.io/crates/d/memexec?label=downloads%40crates.io&style=social)](https://crates.io/crates/memexec)
|
||||||
|
|
||||||
Lib used to load and execute PE (Portable Executable) in memory without ever touching the disk
|
A library for loading and executing PE (Portable Executable) without ever touching the disk
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
+ Applicable to EXE and DLL
|
+ Applicable to EXE and DLL (except .NET assembly)
|
||||||
+ Cross-architecture, applicable to x86 and x86_64
|
+ Cross-architecture, applicable to x86 and x86-64
|
||||||
+ Zero-dependency
|
+ Zero-dependency
|
||||||
+ Contains a zero-copy submodule of PE parser
|
+ Contains a simple, zero-copy PE parser submodule
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
|
|
||||||
@ -76,6 +76,12 @@ let pe = PE::new(&buf);
|
|||||||
println!("{:?}", pe);
|
println!("{:?}", pe);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
- [ ] Replace `LoadLibrary` with calling `load_pe_into_mem` recursively
|
||||||
|
|
||||||
|
- [ ] Replace `GetProcAddress` with self-implemented [`LdrpSnapThunk`](https://doxygen.reactos.org/dd/d83/ntdllp_8h.html#ae2196bc7f46cc2a92d36b7c4881ee633), so as to support resolving proc address by `IMAGE_IMPORT_BY_NAME.Hint`
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
The GPLv3 license
|
The GPLv3 license
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//! # memexec
|
|
||||||
//! Lib used to load and execute PE (Portable Executable) in memory without ever touching the disk
|
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(overflowing_literals)]
|
#![allow(overflowing_literals)]
|
||||||
@ -17,7 +14,7 @@ use std::os::raw::c_void;
|
|||||||
|
|
||||||
pub unsafe fn memexec_exe(bs: &[u8]) -> Result<()> {
|
pub unsafe fn memexec_exe(bs: &[u8]) -> Result<()> {
|
||||||
let pe = PE::new(bs)?;
|
let pe = PE::new(bs)?;
|
||||||
let loader = ExeLoader::new(&pe).unwrap();
|
let loader = ExeLoader::new(&pe)?;
|
||||||
Ok(loader.invoke_entry_point())
|
Ok(loader.invoke_entry_point())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +25,7 @@ pub unsafe fn memexec_dll(
|
|||||||
lp_reserved: *const c_void,
|
lp_reserved: *const c_void,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let pe = PE::new(bs)?;
|
let pe = PE::new(bs)?;
|
||||||
let loader = DllLoader::new(&pe).unwrap();
|
let loader = DllLoader::new(&pe)?;
|
||||||
Ok(loader.invoke_entry_point(hmod, reason_for_call, lp_reserved))
|
Ok(loader.invoke_entry_point(hmod, reason_for_call, lp_reserved))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ pub enum Error {
|
|||||||
MismatchedArch,
|
MismatchedArch,
|
||||||
MismatchedLoader,
|
MismatchedLoader,
|
||||||
NoEntryPoint,
|
NoEntryPoint,
|
||||||
|
UnsupportedDotNetExecutable,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -45,7 +45,7 @@ unsafe fn load_pe_into_mem(pe: &PE) -> Result<*const c_void> {
|
|||||||
|
|
||||||
// Step3: handle base relocataion table
|
// Step3: handle base relocataion table
|
||||||
let reloc_entry = &pe.pe_header.nt_header.get_data_directory()[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
let reloc_entry = &pe.pe_header.nt_header.get_data_directory()[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||||
let image_base_offset = base_addr as isize - pe.pe_header.nt_header.get_image_base() as isize;
|
let image_base_offset = base_addr as usize - pe.pe_header.nt_header.get_image_base() as usize;
|
||||||
if image_base_offset != 0 && reloc_entry.VirtualAddress != 0 && reloc_entry.Size != 0 {
|
if image_base_offset != 0 && reloc_entry.VirtualAddress != 0 && reloc_entry.Size != 0 {
|
||||||
let mut reloc_table_ptr =
|
let mut reloc_table_ptr =
|
||||||
base_addr.offset(reloc_entry.VirtualAddress as isize) as *const u8;
|
base_addr.offset(reloc_entry.VirtualAddress as isize) as *const u8;
|
||||||
@ -62,7 +62,7 @@ unsafe fn load_pe_into_mem(pe: &PE) -> Result<*const c_void> {
|
|||||||
if (item >> 12) == IMAGE_REL_BASED {
|
if (item >> 12) == IMAGE_REL_BASED {
|
||||||
let patch_addr = base_addr
|
let patch_addr = base_addr
|
||||||
.offset(reloc_block.VirtualAddress as isize + (item & 0xfff) as isize)
|
.offset(reloc_block.VirtualAddress as isize + (item & 0xfff) as isize)
|
||||||
as *mut isize;
|
as *mut usize;
|
||||||
*patch_addr = *patch_addr + image_base_offset;
|
*patch_addr = *patch_addr + image_base_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,13 +86,14 @@ unsafe fn load_pe_into_mem(pe: &PE) -> Result<*const c_void> {
|
|||||||
|
|
||||||
let dll_name = CStr::from_ptr(base_addr.offset(import_desc.Name as isize) as *const i8)
|
let dll_name = CStr::from_ptr(base_addr.offset(import_desc.Name as isize) as *const i8)
|
||||||
.to_str()?;
|
.to_str()?;
|
||||||
|
// TODO: implement loading module by calling self recursively
|
||||||
let hmod = winapi::load_library(dll_name)?;
|
let hmod = winapi::load_library(dll_name)?;
|
||||||
|
|
||||||
// Whether HNT exists
|
// Whether the ILT (called INT in IDA) exists? (some linkers didn't generate the ILT)
|
||||||
let (mut iat_ptr, mut hnt_ptr) = if import_desc.DUMMYUNIONNAME != 0 {
|
let (mut iat_ptr, mut ilt_ptr) = if import_desc.OriginalFirstThunk != 0 {
|
||||||
(
|
(
|
||||||
base_addr.offset(import_desc.FirstThunk as isize) as *mut IMAGE_THUNK_DATA,
|
base_addr.offset(import_desc.FirstThunk as isize) as *mut IMAGE_THUNK_DATA,
|
||||||
base_addr.offset(import_desc.DUMMYUNIONNAME as isize)
|
base_addr.offset(import_desc.OriginalFirstThunk as isize)
|
||||||
as *const IMAGE_THUNK_DATA,
|
as *const IMAGE_THUNK_DATA,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -103,32 +104,33 @@ unsafe fn load_pe_into_mem(pe: &PE) -> Result<*const c_void> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let thunk_data = *hnt_ptr as isize;
|
let thunk_data = *ilt_ptr as isize;
|
||||||
if thunk_data == 0 {
|
if thunk_data == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let proc_addr;
|
let proc_addr;
|
||||||
if thunk_data & IMAGE_ORDINAL_FLAG == IMAGE_ORDINAL_FLAG {
|
if thunk_data & IMAGE_ORDINAL_FLAG != 0 {
|
||||||
// Import by ordinal number
|
// Import by ordinal number
|
||||||
proc_addr = winapi::get_proc_address_by_ordinal(hmod, thunk_data & 0xffff)?;
|
proc_addr = winapi::get_proc_address_by_ordinal(hmod, thunk_data & 0xffff)?;
|
||||||
} else {
|
} else {
|
||||||
let import_by_name = &*mem::transmute::<PVOID, *const IMAGE_IMPORT_BY_NAME>(
|
// TODO: implement resolving proc address by `IMAGE_IMPORT_BY_NAME.Hint`
|
||||||
|
let hint_name_table = &*mem::transmute::<PVOID, *const IMAGE_IMPORT_BY_NAME>(
|
||||||
base_addr.offset(thunk_data),
|
base_addr.offset(thunk_data),
|
||||||
);
|
);
|
||||||
if 0 == import_by_name.Name {
|
if 0 == hint_name_table.Name {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc_addr = winapi::get_proc_address(
|
proc_addr = winapi::get_proc_address(
|
||||||
hmod,
|
hmod,
|
||||||
CStr::from_ptr(&import_by_name.Name as _).to_str()?,
|
CStr::from_ptr(&hint_name_table.Name as _).to_str()?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
*iat_ptr = proc_addr as IMAGE_THUNK_DATA;
|
*iat_ptr = proc_addr as IMAGE_THUNK_DATA;
|
||||||
iat_ptr = iat_ptr.offset(1);
|
iat_ptr = iat_ptr.offset(1);
|
||||||
hnt_ptr = hnt_ptr.offset(1);
|
ilt_ptr = ilt_ptr.offset(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +145,7 @@ unsafe fn load_pe_into_mem(pe: &PE) -> Result<*const c_void> {
|
|||||||
winapi::nt_protect_vm(
|
winapi::nt_protect_vm(
|
||||||
&(base_addr.offset(section.VirtualAddress as isize)) as _,
|
&(base_addr.offset(section.VirtualAddress as isize)) as _,
|
||||||
&size as _,
|
&size as _,
|
||||||
section.protect_value(),
|
section.get_protection(),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,8 +191,13 @@ impl ExeLoader {
|
|||||||
pub unsafe fn new(pe: &PE) -> Result<ExeLoader> {
|
pub unsafe fn new(pe: &PE) -> Result<ExeLoader> {
|
||||||
check_platform(pe)?;
|
check_platform(pe)?;
|
||||||
if pe.is_dll() {
|
if pe.is_dll() {
|
||||||
Err(Error::MismatchedLoader)
|
return Err(Error::MismatchedLoader);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if pe.is_dot_net() {
|
||||||
|
return Err(Error::UnsupportedDotNetExecutable);
|
||||||
|
}
|
||||||
|
|
||||||
let entry_point = pe.pe_header.nt_header.get_address_of_entry_point();
|
let entry_point = pe.pe_header.nt_header.get_address_of_entry_point();
|
||||||
if entry_point == 0 {
|
if entry_point == 0 {
|
||||||
Err(Error::NoEntryPoint)
|
Err(Error::NoEntryPoint)
|
||||||
@ -200,7 +207,6 @@ impl ExeLoader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn invoke_entry_point(&self) {
|
pub unsafe fn invoke_entry_point(&self) {
|
||||||
mem::transmute::<PVOID, extern "system" fn()>(self.entry_point_va)()
|
mem::transmute::<PVOID, extern "system" fn()>(self.entry_point_va)()
|
||||||
@ -215,8 +221,13 @@ impl DllLoader {
|
|||||||
pub unsafe fn new(pe: &PE) -> Result<DllLoader> {
|
pub unsafe fn new(pe: &PE) -> Result<DllLoader> {
|
||||||
check_platform(pe)?;
|
check_platform(pe)?;
|
||||||
if !pe.is_dll() {
|
if !pe.is_dll() {
|
||||||
Err(Error::MismatchedLoader)
|
return Err(Error::MismatchedLoader);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if pe.is_dot_net() {
|
||||||
|
return Err(Error::UnsupportedDotNetExecutable);
|
||||||
|
}
|
||||||
|
|
||||||
let entry_point = pe.pe_header.nt_header.get_address_of_entry_point();
|
let entry_point = pe.pe_header.nt_header.get_address_of_entry_point();
|
||||||
if entry_point == 0 {
|
if entry_point == 0 {
|
||||||
Err(Error::NoEntryPoint)
|
Err(Error::NoEntryPoint)
|
||||||
@ -226,7 +237,6 @@ impl DllLoader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn invoke_entry_point(
|
pub unsafe fn invoke_entry_point(
|
||||||
&self,
|
&self,
|
||||||
|
@ -28,8 +28,9 @@ impl<'a> ImageNtHeaders<'a> {
|
|||||||
return Err(Error::UnsupportedMachine);
|
return Err(Error::UnsupportedMachine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 32-bit .NET assembly may not set IMAGE_FILE_32BIT_MACHINE
|
||||||
if h.FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0
|
if h.FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0
|
||||||
|| h.FileHeader.Characteristics & IMAGE_FILE_32BIT_MACHINE == 0
|
// || h.FileHeader.Characteristics & IMAGE_FILE_32BIT_MACHINE == 0
|
||||||
{
|
{
|
||||||
return Err(Error::InvalidFileHeaderCharacteristics);
|
return Err(Error::InvalidFileHeaderCharacteristics);
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ impl<'a> ImageNtHeaders<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if h.FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0
|
if h.FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0
|
||||||
|| h.FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE == 0
|
// || h.FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE == 0
|
||||||
{
|
{
|
||||||
return Err(Error::InvalidFileHeaderCharacteristics);
|
return Err(Error::InvalidFileHeaderCharacteristics);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,9 @@ pub(crate) const IMAGE_DOS_SIGNATURE: WORD = 0x5a4d;
|
|||||||
pub(crate) const IMAGE_NT_SIGNATURE: DWORD = 0x00004550;
|
pub(crate) const IMAGE_NT_SIGNATURE: DWORD = 0x00004550;
|
||||||
|
|
||||||
pub(crate) const IMAGE_FILE_EXECUTABLE_IMAGE: WORD = 0x0002; // File is executable (i.e. no unresolved external references).
|
pub(crate) const IMAGE_FILE_EXECUTABLE_IMAGE: WORD = 0x0002; // File is executable (i.e. no unresolved external references).
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) const IMAGE_FILE_LARGE_ADDRESS_AWARE: WORD = 0x0020; // App can handle >2gb addresses
|
pub(crate) const IMAGE_FILE_LARGE_ADDRESS_AWARE: WORD = 0x0020; // App can handle >2gb addresses
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) const IMAGE_FILE_32BIT_MACHINE: WORD = 0x0100; // 32 bit word machine.
|
pub(crate) const IMAGE_FILE_32BIT_MACHINE: WORD = 0x0100; // 32 bit word machine.
|
||||||
pub(crate) const IMAGE_FILE_DLL: WORD = 0x2000; // File is a DLL.
|
pub(crate) const IMAGE_FILE_DLL: WORD = 0x2000; // File is a DLL.
|
||||||
|
|
||||||
@ -39,10 +41,19 @@ pub(crate) const IMAGE_NUMBEROF_DIRECTORY_ENTRIES: usize = 16;
|
|||||||
|
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_EXPORT: usize = 0; // Export Directory
|
pub const IMAGE_DIRECTORY_ENTRY_EXPORT: usize = 0; // Export Directory
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_IMPORT: usize = 1; // Import Directory
|
pub const IMAGE_DIRECTORY_ENTRY_IMPORT: usize = 1; // Import Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_RESOURCE: usize = 2; // Resource Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_EXCEPTION: usize = 3; // Exception Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_SECURITY: usize = 4; // Security Directory
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_BASERELOC: usize = 5; // Base Relocation Table
|
pub const IMAGE_DIRECTORY_ENTRY_BASERELOC: usize = 5; // Base Relocation Table
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_TLS: usize = 9;
|
pub const IMAGE_DIRECTORY_ENTRY_DEBUG: usize = 6; // Debug Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_ARCHITECTURE: usize = 7; // Architecture Specific Data
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_GLOBALPTR: usize = 8; // RVA of GP
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_TLS: usize = 9; // TLS Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG: usize = 10; // Load Configuration Directory
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT: usize = 11; // Bound Import Directory in headers
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_IAT: usize = 12; // Import Address Table
|
pub const IMAGE_DIRECTORY_ENTRY_IAT: usize = 12; // Import Address Table
|
||||||
pub const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT: usize = 13; // Delay Load Import Descriptors
|
pub const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT: usize = 13; // Delay Load Import Descriptors
|
||||||
|
pub const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: usize = 14; // COM Runtime descriptor
|
||||||
|
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
|
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
|
||||||
pub(crate) const IMAGE_REL_BASED_DIR64: WORD = 10;
|
pub(crate) const IMAGE_REL_BASED_DIR64: WORD = 10;
|
||||||
@ -255,7 +266,7 @@ struct_wrapper!(
|
|||||||
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
|
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
DUMMYUNIONNAME: DWORD,
|
OriginalFirstThunk: DWORD,
|
||||||
TimeDateStamp: DWORD,
|
TimeDateStamp: DWORD,
|
||||||
ForwarderChain: DWORD, // -1 if no forwarders
|
ForwarderChain: DWORD, // -1 if no forwarders
|
||||||
Name: DWORD,
|
Name: DWORD,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
mod check;
|
mod check;
|
||||||
pub mod def;
|
|
||||||
pub mod error;
|
|
||||||
mod header;
|
mod header;
|
||||||
mod pe;
|
mod pe;
|
||||||
mod section;
|
mod section;
|
||||||
|
|
||||||
|
pub mod def;
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
pub use header::*;
|
pub use header::*;
|
||||||
pub use pe::*;
|
pub use pe::*;
|
||||||
pub use section::*;
|
pub use section::*;
|
||||||
|
@ -43,4 +43,10 @@ impl<'a> PE<'a> {
|
|||||||
ImageNtHeaders::x64(h) => h.FileHeader.Characteristics & IMAGE_FILE_DLL != 0,
|
ImageNtHeaders::x64(h) => h.FileHeader.Characteristics & IMAGE_FILE_DLL != 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_dot_net(&self) -> bool {
|
||||||
|
let dot_net_desc =
|
||||||
|
&self.pe_header.nt_header.get_data_directory()[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
|
||||||
|
dot_net_desc.Size != 0 && dot_net_desc.VirtualAddress != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,28 +35,28 @@ pub const PAGE_EXECUTE_READ: DWORD = 0x20;
|
|||||||
pub const PAGE_EXECUTE_READWRITE: DWORD = 0x40;
|
pub const PAGE_EXECUTE_READWRITE: DWORD = 0x40;
|
||||||
*/
|
*/
|
||||||
impl IMAGE_SECTION_HEADER {
|
impl IMAGE_SECTION_HEADER {
|
||||||
|
#[inline]
|
||||||
pub fn can_read(&self) -> bool {
|
pub fn can_read(&self) -> bool {
|
||||||
self.Characteristics & IMAGE_SCN_MEM_READ == IMAGE_SCN_MEM_READ
|
self.Characteristics & IMAGE_SCN_MEM_READ != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn can_write(&self) -> bool {
|
pub fn can_write(&self) -> bool {
|
||||||
self.Characteristics & IMAGE_SCN_MEM_WRITE == IMAGE_SCN_MEM_WRITE
|
self.Characteristics & IMAGE_SCN_MEM_WRITE != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn can_exec(&self) -> bool {
|
pub fn can_exec(&self) -> bool {
|
||||||
self.Characteristics & IMAGE_SCN_MEM_EXECUTE == IMAGE_SCN_MEM_EXECUTE
|
self.Characteristics & IMAGE_SCN_MEM_EXECUTE != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn protect_value(&self) -> DWORD {
|
pub fn get_protection(&self) -> DWORD {
|
||||||
match self.can_exec() {
|
match self.can_exec() {
|
||||||
true => match self.can_read() {
|
true => match self.can_read() {
|
||||||
true => {
|
true => match self.can_write() {
|
||||||
if self.can_write() {
|
true => PAGE_EXECUTE_READWRITE,
|
||||||
PAGE_EXECUTE_READWRITE
|
false => PAGE_EXECUTE_READ,
|
||||||
} else {
|
},
|
||||||
PAGE_EXECUTE_READ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false => PAGE_EXECUTE,
|
false => PAGE_EXECUTE,
|
||||||
},
|
},
|
||||||
false => match self.can_read() {
|
false => match self.can_read() {
|
||||||
|
Loading…
Reference in New Issue
Block a user