work
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::x86_64::*,
|
arch::x86_64::*,
|
||||||
backend::{Instr as BInstr, Program, pe::Import},
|
backend::{Instr as BInstr, Program, pe::LibImport},
|
||||||
};
|
};
|
||||||
use std::{fs::OpenOptions, io::Write, os::unix::fs::OpenOptionsExt, process::Command};
|
use std::{fs::OpenOptions, io::Write, os::unix::fs::OpenOptionsExt, process::Command};
|
||||||
|
|
||||||
@@ -72,14 +72,18 @@ fn linux() {
|
|||||||
fn windows() {
|
fn windows() {
|
||||||
let mut program = Program::<X86_64>::default();
|
let mut program = Program::<X86_64>::default();
|
||||||
let entry = program.func([BInstr::Asm(Asm {
|
let entry = program.func([BInstr::Asm(Asm {
|
||||||
instrs: vec![push(39), pop(rax), Instr::Ret],
|
instrs: vec![
|
||||||
|
push(39),
|
||||||
|
pop(rax),
|
||||||
|
Instr::Ret
|
||||||
|
],
|
||||||
})]);
|
})]);
|
||||||
program.entry = Some(entry);
|
program.entry = Some(entry);
|
||||||
let linked = program.compile().expect("failed to compile");
|
let linked = program.compile().expect("failed to compile");
|
||||||
|
|
||||||
let imports = &[Import {
|
let imports = &[LibImport {
|
||||||
name: "KERNEL32.dll".to_string(),
|
name: "KERNEL32.dll".to_string(),
|
||||||
names: ["GetStdHandle", "WriteFile", "ExitProcess"]
|
syms: ["GetStdHandle", "WriteFile", "ExitProcess"]
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.to_vec(),
|
.to_vec(),
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ use crate::backend::pe::data_dir::DataDir;
|
|||||||
|
|
||||||
use super::ByteEncoder;
|
use super::ByteEncoder;
|
||||||
|
|
||||||
pub struct Import {
|
pub struct LibImport {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub names: Vec<String>,
|
pub syms: Vec<SymImport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(data: &mut ByteEncoder, imports: &[Import]) -> DataDir {
|
pub struct SymImport {
|
||||||
|
name: String,
|
||||||
|
usages: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(data: &mut ByteEncoder, imports: &[LibImport]) -> DataDir {
|
||||||
let start = data.pos() as u32;
|
let start = data.pos() as u32;
|
||||||
let idt = data.reserve_arr::<ImportDirTable>(imports.len());
|
let idt = data.reserve_arr::<ImportDirTable>(imports.len());
|
||||||
// null entry to mark end
|
// null entry to mark end
|
||||||
@@ -23,12 +28,12 @@ pub fn encode(data: &mut ByteEncoder, imports: &[Import]) -> DataDir {
|
|||||||
// lookup table
|
// lookup table
|
||||||
data.align(size_of::<ImportLookupEntry>());
|
data.align(size_of::<ImportLookupEntry>());
|
||||||
let lookup_start = data.pos();
|
let lookup_start = data.pos();
|
||||||
let lookup = data.reserve_arr::<ImportLookupEntry>(import.names.len());
|
let lookup = data.reserve_arr::<ImportLookupEntry>(import.syms.len());
|
||||||
data.pad(size_of::<ImportLookupEntry>());
|
data.pad(size_of::<ImportLookupEntry>());
|
||||||
let lookup_end = data.pos();
|
let lookup_end = data.pos();
|
||||||
|
|
||||||
for (i, name) in import.names.iter().enumerate() {
|
for (i, sym) in import.syms.iter().enumerate() {
|
||||||
let rva = hint_name_entry(data, 0, name);
|
let rva = hint_name_entry(data, 0, &sym.name);
|
||||||
data[lookup][i] = ImportLookupEntry::name(rva);
|
data[lookup][i] = ImportLookupEntry::name(rva);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ use crate::backend::LinkedProgram;
|
|||||||
|
|
||||||
use data_dir::*;
|
use data_dir::*;
|
||||||
use header::*;
|
use header::*;
|
||||||
pub use import::Import;
|
pub use import::LibImport;
|
||||||
|
|
||||||
pub fn create(program: &[u8], start_offset: u64, imports: &[Import]) -> Vec<u8> {
|
pub fn create(program: &[u8], start_offset: u64, imports: &[LibImport]) -> Vec<u8> {
|
||||||
let mut data = ByteEncoder::default();
|
let mut data = ByteEncoder::default();
|
||||||
let file_align = 1;
|
let file_align = 1;
|
||||||
let section_align = 1;
|
let section_align = 1;
|
||||||
@@ -105,7 +105,7 @@ pub fn create(program: &[u8], start_offset: u64, imports: &[Import]) -> Vec<u8>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LinkedProgram<u64> {
|
impl LinkedProgram<u64> {
|
||||||
pub fn to_pe(&self, imports: &[Import]) -> Vec<u8> {
|
pub fn to_pe(&self, imports: &[LibImport]) -> Vec<u8> {
|
||||||
create(&self.code, self.entry.expect("no start"), imports)
|
create(&self.code, self.entry.expect("no start"), imports)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub struct Program<A: Arch> {
|
|||||||
pub ro_data: Vec<Data>,
|
pub ro_data: Vec<Data>,
|
||||||
pub funcs: Vec<Func<A>>,
|
pub funcs: Vec<Func<A>>,
|
||||||
pub entry: Option<Symbol>,
|
pub entry: Option<Symbol>,
|
||||||
|
pub external: Vec<External>,
|
||||||
|
|
||||||
sym_count: usize,
|
sym_count: usize,
|
||||||
}
|
}
|
||||||
@@ -23,6 +24,11 @@ pub struct Func<A: Arch> {
|
|||||||
pub sym: Symbol,
|
pub sym: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct External {
|
||||||
|
pub file: String,
|
||||||
|
pub syms: Vec<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Instr<A: Arch> {
|
pub enum Instr<A: Arch> {
|
||||||
Set { dst: VarId, src: Vec<u8> },
|
Set { dst: VarId, src: Vec<u8> },
|
||||||
Call { dst: FnId, args: Vec<VarId> },
|
Call { dst: FnId, args: Vec<VarId> },
|
||||||
@@ -56,6 +62,22 @@ impl<A: Arch> Program<A> {
|
|||||||
sym
|
sym
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn external<const LEN: usize>(
|
||||||
|
&mut self,
|
||||||
|
file: impl Into<String>,
|
||||||
|
names: [impl Into<String>; LEN],
|
||||||
|
) -> [Symbol; LEN] {
|
||||||
|
let syms = names.map(|s| {
|
||||||
|
let sym = self.reserve();
|
||||||
|
sym
|
||||||
|
});
|
||||||
|
self.external.push(External {
|
||||||
|
file: file.into(),
|
||||||
|
syms: syms.to_vec(),
|
||||||
|
});
|
||||||
|
syms
|
||||||
|
}
|
||||||
|
|
||||||
fn reserve(&mut self) -> Symbol {
|
fn reserve(&mut self) -> Symbol {
|
||||||
let res = Symbol(self.sym_count);
|
let res = Symbol(self.sym_count);
|
||||||
self.sym_count += 1;
|
self.sym_count += 1;
|
||||||
@@ -78,6 +100,7 @@ impl<A: Arch> Default for Program<A> {
|
|||||||
funcs: Default::default(),
|
funcs: Default::default(),
|
||||||
entry: Default::default(),
|
entry: Default::default(),
|
||||||
sym_count: Default::default(),
|
sym_count: Default::default(),
|
||||||
|
external: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user