use crate::pe::header::{
IMAGE_DIRECTORY_ENTRY_BASERELOC, IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_DIRECTORY_ENTRY_IMPORT,
IMAGE_DOS_SIGNATURE, IMAGE_FILE_MACHINE_I386, IMAGE_NT_OPTIONAL_HDR32_MAGIC,
IMAGE_NT_SIGNATURE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE,
};
const FILE_ALIGN: usize = 0x200;
const SECTION_ALIGN: u32 = 0x1000;
pub const IMAGE_BASE: u32 = 0x1000_0000;
pub const IAT_RVA: u32 = 0x2200;
pub fn build_minimal_dll() -> Vec<u8> {
let mut bytes = vec![0u8; FILE_ALIGN];
bytes[0..2].copy_from_slice(&IMAGE_DOS_SIGNATURE.to_le_bytes());
let pe_off: u32 = 0x40;
bytes[0x3C..0x40].copy_from_slice(&pe_off.to_le_bytes());
let pe = pe_off as usize;
bytes[pe..pe + 4].copy_from_slice(&IMAGE_NT_SIGNATURE.to_le_bytes());
let fh = pe + 4;
bytes[fh..fh + 2].copy_from_slice(&IMAGE_FILE_MACHINE_I386.to_le_bytes());
bytes[fh + 2..fh + 4].copy_from_slice(&3u16.to_le_bytes()); bytes[fh + 4..fh + 8].copy_from_slice(&0u32.to_le_bytes()); bytes[fh + 8..fh + 12].copy_from_slice(&0u32.to_le_bytes()); bytes[fh + 12..fh + 16].copy_from_slice(&0u32.to_le_bytes()); bytes[fh + 16..fh + 18].copy_from_slice(&224u16.to_le_bytes()); bytes[fh + 18..fh + 20].copy_from_slice(&0x2000u16.to_le_bytes());
let oh = fh + 20;
bytes[oh..oh + 2].copy_from_slice(&IMAGE_NT_OPTIONAL_HDR32_MAGIC.to_le_bytes());
bytes[oh + 2] = 6; bytes[oh + 3] = 0; bytes[oh + 4..oh + 8].copy_from_slice(&(FILE_ALIGN as u32).to_le_bytes()); bytes[oh + 8..oh + 12].copy_from_slice(&(FILE_ALIGN as u32).to_le_bytes()); bytes[oh + 12..oh + 16].copy_from_slice(&0u32.to_le_bytes()); bytes[oh + 16..oh + 20].copy_from_slice(&0x1000u32.to_le_bytes()); bytes[oh + 20..oh + 24].copy_from_slice(&0x1000u32.to_le_bytes()); bytes[oh + 24..oh + 28].copy_from_slice(&0x2000u32.to_le_bytes());
bytes[oh + 28..oh + 32].copy_from_slice(&IMAGE_BASE.to_le_bytes());
bytes[oh + 32..oh + 36].copy_from_slice(&SECTION_ALIGN.to_le_bytes());
bytes[oh + 36..oh + 40].copy_from_slice(&(FILE_ALIGN as u32).to_le_bytes());
bytes[oh + 40..oh + 42].copy_from_slice(&4u16.to_le_bytes()); bytes[oh + 42..oh + 44].copy_from_slice(&0u16.to_le_bytes());
bytes[oh + 44..oh + 46].copy_from_slice(&0u16.to_le_bytes()); bytes[oh + 46..oh + 48].copy_from_slice(&0u16.to_le_bytes());
bytes[oh + 48..oh + 50].copy_from_slice(&4u16.to_le_bytes()); bytes[oh + 50..oh + 52].copy_from_slice(&0u16.to_le_bytes());
bytes[oh + 52..oh + 56].copy_from_slice(&0u32.to_le_bytes()); bytes[oh + 56..oh + 60].copy_from_slice(&0x5000u32.to_le_bytes()); bytes[oh + 60..oh + 64].copy_from_slice(&(FILE_ALIGN as u32).to_le_bytes()); bytes[oh + 64..oh + 68].copy_from_slice(&0u32.to_le_bytes()); bytes[oh + 68..oh + 70].copy_from_slice(&3u16.to_le_bytes()); bytes[oh + 70..oh + 72].copy_from_slice(&0u16.to_le_bytes()); bytes[oh + 72..oh + 76].copy_from_slice(&0x10_0000u32.to_le_bytes()); bytes[oh + 76..oh + 80].copy_from_slice(&0x1000u32.to_le_bytes()); bytes[oh + 80..oh + 84].copy_from_slice(&0x10_0000u32.to_le_bytes()); bytes[oh + 84..oh + 88].copy_from_slice(&0x1000u32.to_le_bytes()); bytes[oh + 88..oh + 92].copy_from_slice(&0u32.to_le_bytes()); bytes[oh + 92..oh + 96].copy_from_slice(&16u32.to_le_bytes());
let dirs = oh + 96;
let export_rva = 0x2000u32;
let export_size = EXPORT_TABLE_SIZE as u32;
let import_rva = 0x2100u32;
let import_size = 40u32;
let reloc_rva = 0x4000u32;
let reloc_size = 12u32;
write_dir(
&mut bytes,
dirs,
IMAGE_DIRECTORY_ENTRY_EXPORT,
export_rva,
export_size,
);
write_dir(
&mut bytes,
dirs,
IMAGE_DIRECTORY_ENTRY_IMPORT,
import_rva,
import_size,
);
write_dir(
&mut bytes,
dirs,
IMAGE_DIRECTORY_ENTRY_BASERELOC,
reloc_rva,
reloc_size,
);
let st = dirs + 16 * 8;
write_section(
&mut bytes,
st,
b".text",
0x10,
0x1000,
FILE_ALIGN as u32,
FILE_ALIGN as u32,
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
);
write_section(
&mut bytes,
st + 40,
b".rdata",
0x600,
0x2000,
(FILE_ALIGN * 3) as u32,
(FILE_ALIGN * 2) as u32,
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, );
write_section(
&mut bytes,
st + 80,
b".reloc",
0x10,
0x4000,
FILE_ALIGN as u32,
(FILE_ALIGN * 5) as u32,
IMAGE_SCN_MEM_READ,
);
bytes.resize(FILE_ALIGN * 6, 0);
bytes[FILE_ALIGN] = 0xC2;
bytes[FILE_ALIGN + 1] = 0x0C;
bytes[FILE_ALIGN + 2] = 0x00;
let rdata = FILE_ALIGN * 2;
let off = |rva: u32| rdata + (rva - 0x2000) as usize;
let edir = off(0x2000);
bytes[edir..edir + 4].copy_from_slice(&0u32.to_le_bytes());
bytes[edir + 12..edir + 16].copy_from_slice(&0x2094u32.to_le_bytes());
bytes[edir + 16..edir + 20].copy_from_slice(&1u32.to_le_bytes());
bytes[edir + 20..edir + 24].copy_from_slice(&1u32.to_le_bytes());
bytes[edir + 24..edir + 28].copy_from_slice(&1u32.to_le_bytes());
bytes[edir + 28..edir + 32].copy_from_slice(&0x2080u32.to_le_bytes());
bytes[edir + 32..edir + 36].copy_from_slice(&0x2084u32.to_le_bytes());
bytes[edir + 36..edir + 40].copy_from_slice(&0x2088u32.to_le_bytes());
let aof = off(0x2080);
bytes[aof..aof + 4].copy_from_slice(&0x1000u32.to_le_bytes());
let aon = off(0x2084);
bytes[aon..aon + 4].copy_from_slice(&0x208Cu32.to_le_bytes());
let aoo = off(0x2088);
bytes[aoo..aoo + 2].copy_from_slice(&0u16.to_le_bytes());
let dllmain = off(0x208C);
let s = b"DllMain\0";
bytes[dllmain..dllmain + s.len()].copy_from_slice(s);
let synth = off(0x2094);
let s = b"synth.dll\0";
bytes[synth..synth + s.len()].copy_from_slice(s);
let imp0 = off(0x2100);
bytes[imp0..imp0 + 4].copy_from_slice(&0x2150u32.to_le_bytes()); bytes[imp0 + 4..imp0 + 8].copy_from_slice(&0u32.to_le_bytes()); bytes[imp0 + 8..imp0 + 12].copy_from_slice(&0u32.to_le_bytes()); bytes[imp0 + 12..imp0 + 16].copy_from_slice(&0x2400u32.to_le_bytes()); bytes[imp0 + 16..imp0 + 20].copy_from_slice(&IAT_RVA.to_le_bytes());
let ilt = off(0x2150);
bytes[ilt..ilt + 4].copy_from_slice(&0x2300u32.to_le_bytes()); bytes[ilt + 4..ilt + 8].copy_from_slice(&0u32.to_le_bytes());
let iat = off(IAT_RVA);
bytes[iat..iat + 4].copy_from_slice(&0x2300u32.to_le_bytes());
bytes[iat + 4..iat + 8].copy_from_slice(&0u32.to_le_bytes());
let ibn = off(0x2300);
bytes[ibn..ibn + 2].copy_from_slice(&0u16.to_le_bytes()); let s = b"GetProcessHeap\0";
bytes[ibn + 2..ibn + 2 + s.len()].copy_from_slice(s);
let kn = off(0x2400);
let s = b"kernel32.dll\0";
bytes[kn..kn + s.len()].copy_from_slice(s);
let reloc = FILE_ALIGN * 5;
bytes[reloc..reloc + 4].copy_from_slice(&0u32.to_le_bytes()); bytes[reloc + 4..reloc + 8].copy_from_slice(&8u32.to_le_bytes());
bytes
}
const EXPORT_TABLE_SIZE: usize = 0x100;
fn write_dir(bytes: &mut [u8], base: usize, idx: usize, rva: u32, size: u32) {
let off = base + idx * 8;
bytes[off..off + 4].copy_from_slice(&rva.to_le_bytes());
bytes[off + 4..off + 8].copy_from_slice(&size.to_le_bytes());
}
#[allow(clippy::too_many_arguments)]
fn write_section(
bytes: &mut [u8],
off: usize,
name: &[u8],
virtual_size: u32,
virtual_address: u32,
size_of_raw_data: u32,
pointer_to_raw_data: u32,
characteristics: u32,
) {
for (i, b) in name.iter().take(8).enumerate() {
bytes[off + i] = *b;
}
bytes[off + 8..off + 12].copy_from_slice(&virtual_size.to_le_bytes());
bytes[off + 12..off + 16].copy_from_slice(&virtual_address.to_le_bytes());
bytes[off + 16..off + 20].copy_from_slice(&size_of_raw_data.to_le_bytes());
bytes[off + 20..off + 24].copy_from_slice(&pointer_to_raw_data.to_le_bytes());
bytes[off + 36..off + 40].copy_from_slice(&characteristics.to_le_bytes());
}