268 lines
8.2 KiB
Zig
268 lines
8.2 KiB
Zig
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
const data_structures = @import("../data_structures.zig");
|
|
const ArrayList = data_structures.ArrayList;
|
|
const emit = @import("emit.zig");
|
|
pub const Writer = struct {
|
|
in_file: []const u8,
|
|
items: []u8,
|
|
index: usize = 0,
|
|
allocator: Allocator,
|
|
pub fn init(allocator: Allocator) !Writer {
|
|
const file = try std.fs.cwd().readFileAlloc(allocator, "main.exe", 0xfffffffffffff);
|
|
const len = std.mem.alignForward(usize, file.len, 0x1000);
|
|
return Writer{
|
|
.in_file = file,
|
|
.items = try data_structures.mmap(len, .{}),
|
|
.allocator = allocator,
|
|
};
|
|
}
|
|
|
|
pub fn writeToMemory(writer: *Writer, image: *const emit.Result) !void {
|
|
//print("File len: {}", .{writer.in_file.len});
|
|
const dos_header: *const ImageDosHeader = @ptrCast(@alignCast(writer.in_file.ptr));
|
|
//print("File address: {}", .{dos_header.file_address_of_new_exe_header});
|
|
//print("File: {s}", .{writer.in_file[0x40..]});
|
|
for (writer.in_file[0x40..], 0..) |byte, index| {
|
|
_ = index;
|
|
if (byte == 'T') {
|
|
//print("Index: {}", .{index});
|
|
break;
|
|
}
|
|
}
|
|
assert(dos_header.magic_number == ImageDosHeader.magic);
|
|
// assert(dos_header.file_address_of_new_exe_header == @sizeOf(ImageDosHeader));
|
|
//print("{}", .{dos_header});
|
|
const file_header: *const ImageFileHeader = @ptrCast(@alignCast(writer.in_file[dos_header.file_address_of_new_exe_header + 4 ..].ptr));
|
|
_ = file_header;
|
|
//print("File header: {}", .{file_header});
|
|
|
|
writer.append(std.mem.asBytes(&ImageDosHeader{
|
|
.file_address_of_new_exe_header = 208,
|
|
}));
|
|
while (writer.index < 208) : (writer.index += 1) {
|
|
writer.append(&.{0});
|
|
}
|
|
writer.append(std.mem.asBytes(&image_NT_signature));
|
|
writer.append(std.mem.asBytes(&ImageFileHeader{
|
|
.machine = switch (image.target.cpu.arch) {
|
|
.x86_64 => .amd64,
|
|
.aarch64 => .arm64,
|
|
else => @panic("Architecture"),
|
|
},
|
|
.section_count = 3,
|
|
.time_date_stamp = @intCast(std.time.timestamp()),
|
|
}));
|
|
|
|
const kernel32 = blk: {
|
|
var library = Library{
|
|
.name = "KERNEL32.DLL",
|
|
};
|
|
try library.symbols.append(writer.allocator, Symbol{
|
|
.name = "ExitProcess",
|
|
});
|
|
|
|
break :blk library;
|
|
};
|
|
|
|
const libraries = &[_]Library{kernel32};
|
|
_ = libraries;
|
|
|
|
const code = &.{
|
|
0x48, 0x83, 0xec, 0x28, //subq $40, %rsp
|
|
0xb9, 0x2a, 0x00, 0x00, 0x00, //movl $42, %ecx
|
|
0xff, 0x15, 0xf1, 0x0f, 0x00, 0x00, //callq *4081(%rip) # 0x140002000
|
|
0xcc,
|
|
};
|
|
_ = code;
|
|
|
|
const pdata = &.{
|
|
0x00, 0x10,
|
|
0x00, 0x00,
|
|
0x10, 0x10,
|
|
0x00, 0x00,
|
|
0x28, 0x21,
|
|
0x00, 0x00,
|
|
};
|
|
_ = pdata;
|
|
|
|
// TODO
|
|
// writer.append(std.mem.asBytes(ImageOptionalHeader{
|
|
// .magic = ImageOptionalHeader.magic,
|
|
// .size_of_code = code.len,
|
|
// }));
|
|
|
|
unreachable;
|
|
}
|
|
|
|
fn append(writer: *Writer, bytes: []const u8) void {
|
|
const destination = writer.items[writer.index..][0..bytes.len];
|
|
const source = bytes;
|
|
@memcpy(destination, source);
|
|
writer.index += bytes.len;
|
|
}
|
|
|
|
pub fn writeToFile(writer: *Writer, executable_relative_path: []const u8) !void {
|
|
_ = writer;
|
|
_ = executable_relative_path;
|
|
unreachable;
|
|
}
|
|
};
|
|
|
|
const ImageDosHeader = extern struct {
|
|
magic_number: u16 = magic,
|
|
bytes_last_page_of_file: u16 = 0,
|
|
pages_in_file: u16 = 0,
|
|
relocations: u16 = 0,
|
|
size_of_header_in_paragraphs: u16 = 0,
|
|
minimum_extra_paragraphs: u16 = 0,
|
|
maximum_extra_paragraphs: u16 = 0,
|
|
initial_ss_value: u16 = 0,
|
|
initial_sp_value: u16 = 0,
|
|
cheksum: u16 = 0,
|
|
initial_ip_value: u16 = 0,
|
|
initial_cs_value: u16 = 0,
|
|
file_address_of_relocation_table: u16 = 0,
|
|
overlay_number: u16 = 0,
|
|
reserved_words: [4]u16 = .{0} ** 4,
|
|
oem_id: u16 = 0,
|
|
oem_info: u16 = 0,
|
|
reserved_words2: [10]u16 = .{0} ** 10,
|
|
file_address_of_new_exe_header: u32 = @sizeOf(ImageDosHeader),
|
|
|
|
const magic = 0x5a4d;
|
|
|
|
comptime {
|
|
assert(@sizeOf(ImageDosHeader) == 64);
|
|
}
|
|
};
|
|
const image_NT_signature: u32 = 0x00004550;
|
|
|
|
/// COFF header format
|
|
const ImageFileHeader = extern struct {
|
|
machine: ImageFileMachine,
|
|
section_count: u16,
|
|
time_date_stamp: u32,
|
|
symbol_table_offset: u32 = 0,
|
|
symbol_count: u32 = 0,
|
|
size_of_optional_header: u16 = @sizeOf(ImageOptionalHeader),
|
|
characteristics: Characteristics = .{},
|
|
|
|
const Characteristics = packed struct(u16) {
|
|
relocations_stripped: bool = false,
|
|
executable_image: bool = true,
|
|
stripped_line_count: bool = false,
|
|
stripped_local_symbols: bool = false,
|
|
aggressive_ws_trim: bool = false,
|
|
large_address_aware: bool = true,
|
|
reserved: u1 = 0,
|
|
bytes_reversed_lo: bool = false,
|
|
machine_32bit: bool = false,
|
|
stripped_debug: bool = false,
|
|
removable_run_from_swap: bool = false,
|
|
net_run_from_swap: bool = false,
|
|
system: bool = false,
|
|
dll: bool = false,
|
|
up_systems_only: bool = false,
|
|
bytes_reversed_hi: bool = false,
|
|
};
|
|
};
|
|
|
|
const ImageFileMachine = enum(u16) {
|
|
unknown = 0,
|
|
target_host = 0x0001, // Useful for indicating we want to interact with the host and not a WoW guest.
|
|
i386 = 0x014c, // Intel 386.
|
|
r3000 = 0x0162, // MIPS little-endian, 0x160 big-endian
|
|
r4000 = 0x0166, // MIPS little-endian
|
|
r10000 = 0x0168, // MIPS little-endian
|
|
wcemipsv2 = 0x0169, // MIPS little-endian WCE v2
|
|
alpha = 0x0184, // Alpha_AXP
|
|
sh3 = 0x01a2, // SH3 little-endian
|
|
sh3dsp = 0x01a3,
|
|
sh3e = 0x01a4, // SH3E little-endian
|
|
sh4 = 0x01a6, // SH4 little-endian
|
|
sh5 = 0x01a8, // SH5
|
|
arm = 0x01c0, // ARM Little-Endian
|
|
thumb = 0x01c2, // ARM Thumb/Thumb-2 Little-Endian
|
|
armnt = 0x01c4, // ARM Thumb-2 Little-Endian
|
|
am33 = 0x01d3,
|
|
powerpc = 0x01F0, // IBM PowerPC Little-Endian
|
|
powerpcfp = 0x01f1,
|
|
ia64 = 0x0200, // Intel 64
|
|
mips16 = 0x0266, // MIPS
|
|
alpha64 = 0x0284, // ALPHA64
|
|
mipsfpu = 0x0366, // MIPS
|
|
mipsfpu16 = 0x0466, // MIPS
|
|
tricore = 0x0520, // Infineon
|
|
cef = 0x0CEF,
|
|
ebc = 0x0EBC, // EFI Byte Code
|
|
amd64 = 0x8664, // AMD64 (K8)
|
|
m32r = 0x9041, // M32R little-endian
|
|
arm64 = 0xAA64, // ARM64 Little-Endian
|
|
cee = 0xC0EE,
|
|
|
|
const axp64 = ImageFileMachine.alpha64;
|
|
};
|
|
|
|
const ImageOptionalHeader = extern struct {
|
|
magic: u16 = magic,
|
|
major_linker_version: u8 = 0,
|
|
minor_linker_version: u8 = 0,
|
|
size_of_code: u32,
|
|
size_of_initialized_data: u32,
|
|
size_of_uninitialized_data: u32,
|
|
address_of_entry_point: u32,
|
|
base_of_code: u32,
|
|
image_base: u64,
|
|
section_alignment: u32,
|
|
file_alignment: u32,
|
|
major_os_version: u16,
|
|
minor_os_version: u16,
|
|
major_image_version: u16,
|
|
minor_image_version: u16,
|
|
major_subsystem_version: u16,
|
|
minor_subsystem_version: u16,
|
|
win32_version_value: u32,
|
|
size_of_image: u32,
|
|
size_of_headers: u32,
|
|
checksum: u32,
|
|
subsystem: u16,
|
|
dll_characteristics: u16,
|
|
size_of_stack_reserve: u64,
|
|
size_of_stack_commit: u64,
|
|
size_of_heap_reserve: u64,
|
|
size_of_heap_commit: u64,
|
|
loader_flags: u32,
|
|
number_of_RVA_and_sizes: u32,
|
|
data_directory: [image_number_of_directory_entries]ImageDataDirectory,
|
|
|
|
const magic = 0x20b;
|
|
|
|
comptime {
|
|
assert(@sizeOf(ImageOptionalHeader) == 0xf0);
|
|
}
|
|
};
|
|
|
|
const ImageDataDirectory = extern struct {
|
|
virtual_address: u32,
|
|
size: u32,
|
|
};
|
|
|
|
const image_number_of_directory_entries = 0x10;
|
|
|
|
const Library = struct {
|
|
symbols: ArrayList(Symbol) = .{},
|
|
name: []const u8,
|
|
name_virtual_address: u32 = 0,
|
|
virtual_address: u32 = 0,
|
|
image_thunk_virtual_address: u32 = 0,
|
|
};
|
|
|
|
const Symbol = struct {
|
|
name: []const u8,
|
|
name_virtual_address: u32 = 0,
|
|
offset_in_data: u32 = 0,
|
|
};
|