Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,44 +44,55 @@ jobs:
- name: Build victim
run: dotnet build Hauyne.Victim -c Release -p:TargetFramework=net${{ matrix.dotnet }} --nologo

- name: Test
- name: Configure ptrace
run: |
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
ulimit -c unlimited
echo '/tmp/core.%p' | sudo tee /proc/sys/kernel/core_pattern

- name: Start victim
run: |
rm -f /tmp/Hauyne.txt /tmp/hauyne-victim.pid

dotnet exec Hauyne.Victim/bin/Release/net${{ matrix.dotnet }}/Hauyne.Victim.dll &
sleep 3
echo "VICTIM_PID=$(cat /tmp/hauyne-victim.pid)" >> $GITHUB_ENV
echo "Victim PID: $(cat /tmp/hauyne-victim.pid) (net${{ matrix.dotnet }})"

VICTIM_PID=$(cat /tmp/hauyne-victim.pid)
echo "Victim PID: $VICTIM_PID (net${{ matrix.dotnet }})"

grep -q libhostfxr /proc/$VICTIM_PID/maps

- name: Inject payload
run: |
HAUYNE_DEBUG=1 ./bin/Hauyne.Injector "$VICTIM_PID" "$PWD/bin/net${{ matrix.dotnet }}/Hauyne.Payload.dll"
sleep 2

sleep 3

- name: Verify payload loaded
run: |
if [ ! -f /tmp/Hauyne.txt ]; then
echo "FUCK! Bootstrap log:"
echo "Hauyne.txt missing. Bootstrap:"
find bin -name 'hauyne.log' -exec cat {} \; 2>/dev/null || true
exit 1
fi
echo "PASS: $(cat /tmp/Hauyne.txt)"

echo "Waiting 10s to ensure victim survived"
sleep 10
- name: Verify failure report
run: |
if ./bin/Hauyne.Injector "$VICTIM_PID" --type Moonyware.NativeEntry 2>&1; then
echo "Injector should've failed"
exit 1
fi
echo "PASS: bad type correctly reported failure"

- name: Verify victim survived
run: |
sleep 10
if kill -0 $VICTIM_PID 2>/dev/null; then
echo "Victim still alive"
else
echo "Victim died"
exit 1
fi

kill $VICTIM_PID 2>/dev/null || true
- name: Cleanup
if: always()
run: kill $VICTIM_PID 2>/dev/null || true

- name: Backtrace
if: failure()
Expand Down
36 changes: 15 additions & 21 deletions Hauyne.Injector/injector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,26 @@ pub fn main(init: std.process.Init) u8 {
return 1;
};

if (is_windows) {
const payload_ok = if (is_windows) blk: {
const windows = @import("windows.zig");
const payload_ok = windows.inject(allocator, @intCast(pid), bootstrap_path, payload_path, type_name, method_name) catch |err| {
std.debug.print("Injection failed: {}\n", .{err});
return 1;
};
if (!payload_ok) {
std.debug.print("Injected into PID {d}, but payload failed to load\n", .{pid});
printLastLogLine(allocator, bootstrap_path);
return 1;
}
} else if (builtin.os.tag == .linux) {
break :blk windows.inject(allocator, @intCast(pid), bootstrap_path, payload_path, type_name, method_name);
} else if (builtin.os.tag == .linux) blk: {
const linux = @import("linux/linux.zig");
const payload_ok = linux.inject(io, allocator, @intCast(pid), bootstrap_path, payload_path, type_name, method_name) catch |err| {
std.debug.print("Injection failed: {}\n", .{err});
return 1;
};
if (!payload_ok) {
std.debug.print("Injected into PID {d}, but payload failed to load\n", .{pid});
printLastLogLine(allocator, bootstrap_path);
return 1;
}
break :blk linux.inject(io, allocator, @intCast(pid), bootstrap_path, payload_path, type_name, method_name);
} else {
std.debug.print("Unsupported platform\n", .{});
return 1;
};

const ok = payload_ok catch |err| {
std.debug.print("Injection failed: {}\n", .{err});
return 1;
};

if (!ok) {
std.debug.print("Injected into PID {d}, but payload failed to load\n", .{pid});
printLastLogLine(allocator, bootstrap_path);
return 1;
}

println(allocator, "Injected into PID {}\n", .{pid});
Expand Down Expand Up @@ -361,7 +356,6 @@ fn isDotNetProcessLinux(io: std.Io, allocator: std.mem.Allocator, pid: u32, inac
return false;
}


fn isDotNetProcessWindows(pid: u32) bool {
const windows = std.os.windows;

Expand Down
2 changes: 1 addition & 1 deletion Hauyne.Injector/linux/victim.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Mozilla Public License, v. 2.0.

const std = @import("std");
const procfs = @import("procfs.zig");

const arch = switch (@import("builtin").cpu.arch) {
.x86_64 => @import("arch/x86_64.zig"),
Expand All @@ -31,7 +32,6 @@ pub fn pickVictimThread(io: std.Io, allocator: std.mem.Allocator, tgid: i32) !i3
const syscall_path = std.fmt.allocPrint(allocator, "/proc/{d}/task/{d}/syscall", .{ tgid, tid }) catch continue;
defer allocator.free(syscall_path);

const procfs = @import("procfs.zig");
const syscall_text = procfs.readFileAlloc(allocator, syscall_path) catch continue;

const trimmed = std.mem.trimEnd(u8, syscall_text, "\n\r \t");
Expand Down
Loading