Skip to content

Commit c24dfa5

Browse files
authored
mprot (#15)
1 parent 7f124fa commit c24dfa5

4 files changed

Lines changed: 46 additions & 7 deletions

File tree

Hauyne.Injector/linux/arch/aarch64.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub const UserRegsStruct = extern struct {
1414
};
1515

1616
pub const SYS_mmap: u64 = 222;
17+
pub const SYS_mprotect: u64 = 226;
1718
pub const syscall_insn_size: u64 = 0;
1819

1920
pub const idle_syscalls = [_]i64{
@@ -50,6 +51,13 @@ pub fn setupMmapRegs(regs: *UserRegsStruct, scratch_size: u64, prot: u64, flags:
5051
regs.regs[5] = 0;
5152
}
5253

54+
pub fn setupMprotectRegs(regs: *UserRegsStruct, addr: u64, len: u64, prot: u64) void {
55+
regs.regs[8] = SYS_mprotect;
56+
regs.regs[0] = addr;
57+
regs.regs[1] = len;
58+
regs.regs[2] = prot;
59+
}
60+
5361
pub fn setupShimRegs(regs: *UserRegsStruct, shim_addr: usize) void {
5462
regs.pc = shim_addr;
5563
}

Hauyne.Injector/linux/arch/x86_64.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub const UserRegsStruct = extern struct {
3737
};
3838

3939
pub const SYS_mmap: u64 = 9;
40+
pub const SYS_mprotect: u64 = 10;
4041
pub const syscall_insn_size: u64 = 2;
4142

4243
pub const idle_syscalls = [_]i64{
@@ -75,6 +76,15 @@ pub fn setupMmapRegs(regs: *UserRegsStruct, scratch_size: u64, prot: u64, flags:
7576
regs.orig_rax = @bitCast(@as(i64, -1));
7677
}
7778

79+
pub fn setupMprotectRegs(regs: *UserRegsStruct, addr: u64, len: u64, prot: u64) void {
80+
regs.rip -= 2;
81+
regs.rax = SYS_mprotect;
82+
regs.rdi = addr;
83+
regs.rsi = len;
84+
regs.rdx = prot;
85+
regs.orig_rax = @bitCast(@as(i64, -1));
86+
}
87+
7888
pub fn setupShimRegs(regs: *UserRegsStruct, shim_addr: usize) void {
7989
regs.rip = shim_addr;
8090
regs.orig_rax = @bitCast(@as(i64, -1));

Hauyne.Injector/linux/linux.zig

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ pub fn inject(
146146
var page = shim.buildScratchPage(so_path, payload_path, type_name, method_name, dlopen_addr, dlsym_addr, pthread_create_addr, pthread_detach_addr, scratch, self_pid);
147147
try ptrace_mod.writeMemory(victim, scratch, &page);
148148

149+
try bootstrapMprotect(victim, saved, scratch + shim.CodePageOff, shim.ScratchSize - shim.CodePageOff, PROT_READ | PROT_EXEC);
150+
149151
try runVictimShim(victim, saved, scratch + shim.VictimShimOff);
150152

151153
try ptrace_mod.setRegs(victim, saved);
@@ -161,7 +163,7 @@ pub fn inject(
161163

162164
fn bootstrapMmap(pid: i32, saved: UserRegsStruct) !usize {
163165
var regs = saved;
164-
arch.setupMmapRegs(&regs, shim.ScratchSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS);
166+
arch.setupMmapRegs(&regs, shim.ScratchSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS);
165167

166168
try ptrace_mod.setRegs(pid, regs);
167169
try continueAndWait(pid, ptrace_mod.PTRACE_SYSCALL, "mmap-enter");
@@ -175,6 +177,20 @@ fn bootstrapMmap(pid: i32, saved: UserRegsStruct) !usize {
175177
return @intCast(ret);
176178
}
177179

180+
fn bootstrapMprotect(pid: i32, saved: UserRegsStruct, addr: usize, len: usize, prot: u64) !void {
181+
var regs = saved;
182+
arch.setupMprotectRegs(&regs, @intCast(addr), @intCast(len), prot);
183+
184+
try ptrace_mod.setRegs(pid, regs);
185+
try continueAndWait(pid, ptrace_mod.PTRACE_SYSCALL, "mprotect-enter");
186+
try continueAndWait(pid, ptrace_mod.PTRACE_SYSCALL, "mprotect-exit");
187+
188+
const after = try ptrace_mod.getRegs(pid);
189+
const ret: i64 = @bitCast(arch.getSyscallResult(after));
190+
if (ret < 0 and ret > -4096)
191+
return error.MprotectInTargetFailed;
192+
}
193+
178194
fn runVictimShim(pid: i32, saved: UserRegsStruct, shim_addr: usize) !void {
179195
var regs = saved;
180196
arch.setupShimRegs(&regs, shim_addr);

Hauyne.Injector/linux/shim.zig

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66

77
const std = @import("std");
88

9-
pub const ScratchSize: usize = 0x2000; // 8 KiB (two pages)
10-
pub const PathOffset: usize = 0x40; // bootstrap .so path (1984)
11-
pub const PayloadOffset: usize = 0x800; // payload triple, NUL-separated (4096)
12-
pub const SymbolOffset: usize = 0x1800; // "hauyne_start\0" (256)
13-
pub const VictimShimOff: usize = 0x1900; // pthread_create + pthread_detach (256)
14-
pub const PayloadShimOff: usize = 0x1A00; // dlopen + dlsym + hauyne_start (1536)
9+
pub const ScratchSize: usize = 0x2000; // 8 KiB (two 4K pages)
10+
11+
// P1 RW: data region, pthread_handle
12+
pub const PathOffset: usize = 0x40; // bootstrap .so path (1984)
13+
pub const PayloadOffset: usize = 0x800; // payload triple, NUL-separated (2048)
14+
15+
// P2 RX: read-only data + executable shims
16+
pub const CodePageOff: usize = 0x1000; // page boundary for mprotect
17+
pub const SymbolOffset: usize = 0x1800; // "hauyne_start\0" (256)
18+
pub const VictimShimOff: usize = 0x1900; // pthread_create + pthread_detach (256)
19+
pub const PayloadShimOff: usize = 0x1A00; // dlopen + dlsym + hauyne_start (1536)
1520

1621
const arch = @import("arch.zig").emitter;
1722

0 commit comments

Comments
 (0)