写在正文之前
本文用于记录Pwn题里有关seccomp和prctl函数的知识点,其中很大一部分归纳于Linux下使用man seccomp
和man prctl
命令获得的帮助文档,有部分是个人的理解,翻译(渣翻,英语水平不好,会结合谷歌翻译),还有部分是参考许多大佬的文章。
部分参考文章:Seccomp从0到1
(博主还是菜鸟,有些知识可能理解不够透彻,有些表述可能不够严谨,欢迎大家指正,望大家多多包涵)
seccomp函数
这个函数在man上解释是:
The seccomp() system call operates on the Secure Computing (seccomp)state of the calling process.
(seccomp()系统调用在调用进程的安全计算(seccomp)状态下运行)
从它的功能上看,说白了其实就是限制了程序对系统调用的使用,而在Pwn题中,某些情况(比如栈溢出的ret2syscall
和某些ret2shellcode
方法)是需要使用系统调用的,所以某些禁用了execve
系统调用的程序就不能使用system
函数,也就不能直接打开一个shell。
seccomp函数原型:
int seccomp(unsigned int operation, unsigned int flags, void *args);
常用operation参数:
SECCOMP_SET_MODE_STRICT: (1)
只允许当前线程使用read
,write
,_exit
,sigreturn
几个系统调用,其他的会抛出SIGKILL
错误。
相当于prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT)
即prctl(22,1)
这个语句的作用。
SECCOMP_SET_MODE_FILTER: (2)
可以使用BPF(Berkeley Packet Filter)
来自定义规则来限制系统调用。
要使用这个参数,必须先设置好这个prctl(PR_SET_NO_NEW_PRIVS, 1)
即prctl(38,1)
。
这时当flags为0时相当于prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, args)
即prctl(22,2,args)
常用的flags参数
SECCOMP_FILTER_FLAG_TSYNC: (1)
When adding a new filter, synchronize all other threads of the calling process to the same seccomp filter tree.
(个人认为就是将规则应用到程序的所有线程中,但是我没有做过实验)
SECCOMP_FILTER_FLAG_LOG (2)
SECCOMP_FILTER_FLAG_SPEC_ALLOW (4)
其他
BPF
就不详细介绍了,可以利用seccomp-tools来写。
seccomp库函数
Ubuntu下可以使用命令先下载sudo apt install libseccomp-dev libseccomp2 seccomp
,然后文件在/usr/include/seccomp.h
。
使用这个库就可以在不了解BPF
的情况下设计规则。
这里介绍一下我曾经遇到过的几个函数
seccomp_init函数
scmp_filter_ctx seccomp_init(uint32_t def_action);//原型
/*
功能:初始化过滤器状态
参数:def_action为默认过滤器动作
返回:scmp_filter_ctx是一个void指针
*/
def_action参数
#define SCMP_ACT_KILL_PROCESS 0x80000000U
/*
大致与SCMP_ACT_KILL相同,区别是这一个是全部线程结束。
*/
#define SCMP_ACT_KILL_THREAD 0x00000000U
/*
同SCMP_ACT_KILL
*/
#define SCMP_ACT_KILL SCMP_ACT_KILL_THREAD
/*
“白名单”模式,使用系统调用且没匹配到规则时抛出SIGSYS,并终止线程,线程不会收到信号。
*/
#define SCMP_ACT_TRAP 0x00030000U
/*
没太看懂……,其中也是“白名单”模式,未匹配到规则时抛出SIGSYS并执行一些操作
*/
#define SCMP_ACT_ERRNO(x) (0x00050000U | ((x) & 0x0000ffffU))
/*
“白名单”模式,未匹配到规则时返回errno的值
*/
#define SCMP_ACT_TRACE(x) (0x7ff00000U | ((x) & 0x0000ffffU))
/*
……
*/
#define SCMP_ACT_LOG 0x7ffc0000U
/*
“白名单”模式,未匹配到规则时会被记录,其他情况无影响
*/
#define SCMP_ACT_ALLOW 0x7fff0000U
/*
“黑名单”模式,匹配到规则会有影响
*/
seccomp_rule_add函数
添加规则用的函数。
原型:
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action,
int syscall, unsigned int arg_cnt, ...);
action参数
基本与seccomp_init的参数一样。
syscall参数
指的是对应系统调用的编号。
arg_cnt参数
arg_array参数中的元素数
arg_array(...)参数
scmp_arg_cmp结构的数组
seccomp_load函数
这个函数是将之前设置好的seccomp规则导入到内核中真正的执行。
函数原型:
int seccomp_load(scmp_filter_ctx ctx)
prctl函数
进程控制函数
函数原型:
int prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
参数比较复杂,这里我就把/usr/include/linux/prctl.h
文件贴出来了:
#ifndef _LINUX_PRCTL_H #define _LINUX_PRCTL_H #include <linux/types.h> /* Values to pass as first argument to prctl() */ #define PR_SET_PDEATHSIG 1 /* Second arg is a signal */ #define PR_GET_PDEATHSIG 2 /* Second arg is a ptr to return the signal */ /* Get/set current->mm->dumpable */ #define PR_GET_DUMPABLE 3 #define PR_SET_DUMPABLE 4 /* Get/set unaligned access control bits (if meaningful) */ #define PR_GET_UNALIGN 5 #define PR_SET_UNALIGN 6 # define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */ # define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */ /* Get/set whether or not to drop capabilities on setuid() away from * uid 0 (as per security/commoncap.c) */ #define PR_GET_KEEPCAPS 7 #define PR_SET_KEEPCAPS 8 /* Get/set floating-point emulation control bits (if meaningful) */ #define PR_GET_FPEMU 9 #define PR_SET_FPEMU 10 # define PR_FPEMU_NOPRINT 1 /* silently emulate fp operations accesses */ # define PR_FPEMU_SIGFPE 2 /* don't emulate fp operations, send SIGFPE instead */ /* Get/set floating-point exception mode (if meaningful) */ #define PR_GET_FPEXC 11 #define PR_SET_FPEXC 12 # define PR_FP_EXC_SW_ENABLE 0x80 /* Use FPEXC for FP exception enables */ # define PR_FP_EXC_DIV 0x010000 /* floating point divide by zero */ # define PR_FP_EXC_OVF 0x020000 /* floating point overflow */ # define PR_FP_EXC_UND 0x040000 /* floating point underflow */ # define PR_FP_EXC_RES 0x080000 /* floating point inexact result */ # define PR_FP_EXC_INV 0x100000 /* floating point invalid operation */ # define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */ # define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */ # define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */ # define PR_FP_EXC_PRECISE 3 /* precise exception mode */ /* Get/set whether we use statistical process timing or accurate timestamp * based process timing */ #define PR_GET_TIMING 13 #define PR_SET_TIMING 14 # define PR_TIMING_STATISTICAL 0 /* Normal, traditional, statistical process timing */ # define PR_TIMING_TIMESTAMP 1 /* Accurate timestamp based process timing */ #define PR_SET_NAME 15 /* Set process name */ #define PR_GET_NAME 16 /* Get process name */ /* Get/set process endian */ #define PR_GET_ENDIAN 19 #define PR_SET_ENDIAN 20 # define PR_ENDIAN_BIG 0 # define PR_ENDIAN_LITTLE 1 /* True little endian mode */ # define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */ /* Get/set process seccomp mode */ #define PR_GET_SECCOMP 21 #define PR_SET_SECCOMP 22 /* Get/set the capability bounding set (as per security/commoncap.c) */ #define PR_CAPBSET_READ 23 #define PR_CAPBSET_DROP 24 /* Get/set the process' ability to use the timestamp counter instruction */ #define PR_GET_TSC 25 #define PR_SET_TSC 26 # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ /* Get/set securebits (as per security/commoncap.c) */ #define PR_GET_SECUREBITS 27 #define PR_SET_SECUREBITS 28 /* * Get/set the timerslack as used by poll/select/nanosleep * A value of 0 means "use default" */ #define PR_SET_TIMERSLACK 29 #define PR_GET_TIMERSLACK 30 #define PR_TASK_PERF_EVENTS_DISABLE 31 #define PR_TASK_PERF_EVENTS_ENABLE 32 /* * Set early/late kill mode for hwpoison memory corruption. * This influences when the process gets killed on a memory corruption. */ #define PR_MCE_KILL 33 # define PR_MCE_KILL_CLEAR 0 # define PR_MCE_KILL_SET 1 # define PR_MCE_KILL_LATE 0 # define PR_MCE_KILL_EARLY 1 # define PR_MCE_KILL_DEFAULT 2 #define PR_MCE_KILL_GET 34 /* * Tune up process memory map specifics. */ #define PR_SET_MM 35 # define PR_SET_MM_START_CODE 1 # define PR_SET_MM_END_CODE 2 # define PR_SET_MM_START_DATA 3 # define PR_SET_MM_END_DATA 4 # define PR_SET_MM_START_STACK 5 # define PR_SET_MM_START_BRK 6 # define PR_SET_MM_BRK 7 # define PR_SET_MM_ARG_START 8 # define PR_SET_MM_ARG_END 9 # define PR_SET_MM_ENV_START 10 # define PR_SET_MM_ENV_END 11 # define PR_SET_MM_AUXV 12 # define PR_SET_MM_EXE_FILE 13 # define PR_SET_MM_MAP 14 # define PR_SET_MM_MAP_SIZE 15 /* * This structure provides new memory descriptor * map which mostly modifies /proc/pid/stat[m] * output for a task. This mostly done in a * sake of checkpoint/restore functionality. */ struct prctl_mm_map { __u64 start_code; /* code section bounds */ __u64 end_code; __u64 start_data; /* data section bounds */ __u64 end_data; __u64 start_brk; /* heap for brk() syscall */ __u64 brk; __u64 start_stack; /* stack starts at */ __u64 arg_start; /* command line arguments bounds */ __u64 arg_end; __u64 env_start; /* environment variables bounds */ __u64 env_end; __u64 *auxv; /* auxiliary vector */ __u32 auxv_size; /* vector size */ __u32 exe_fd; /* /proc/$pid/exe link file */ }; /* * Set specific pid that is allowed to ptrace the current task. * A value of 0 mean "no process". */ #define PR_SET_PTRACER 0x59616d61 # define PR_SET_PTRACER_ANY ((unsigned long)-1) #define PR_SET_CHILD_SUBREAPER 36 #define PR_GET_CHILD_SUBREAPER 37 /* * If no_new_privs is set, then operations that grant new privileges (i.e. * execve) will either fail or not grant them. This affects suid/sgid, * file capabilities, and LSMs. * * Operations that merely manipulate or drop existing privileges (setresuid, * capset, etc.) will still work. Drop those privileges if you want them gone. * * Changing LSM security domain is considered a new privilege. So, for example, * asking selinux for a specific new context (e.g. with runcon) will result * in execve returning -EPERM. * * See Documentation/prctl/no_new_privs.txt for more details. */ #define PR_SET_NO_NEW_PRIVS 38 #define PR_GET_NO_NEW_PRIVS 39 #define PR_GET_TID_ADDRESS 40 #define PR_SET_THP_DISABLE 41 #define PR_GET_THP_DISABLE 42 /* * Tell the kernel to start/stop helping userspace manage bounds tables. */ #define PR_MPX_ENABLE_MANAGEMENT 43 #define PR_MPX_DISABLE_MANAGEMENT 44 #define PR_SET_FP_MODE 45 #define PR_GET_FP_MODE 46 # define PR_FP_MODE_FR (1 << 0) /* 64b FP registers */ # define PR_FP_MODE_FRE (1 << 1) /* 32b compatibility */ /* Control the ambient capability set */ #define PR_CAP_AMBIENT 47 # define PR_CAP_AMBIENT_IS_SET 1 # define PR_CAP_AMBIENT_RAISE 2 # define PR_CAP_AMBIENT_LOWER 3 # define PR_CAP_AMBIENT_CLEAR_ALL 4 /* Per task speculation control */ #define PR_GET_SPECULATION_CTRL 52 #define PR_SET_SPECULATION_CTRL 53 /* Speculation control variants */ # define PR_SPEC_STORE_BYPASS 0 # define PR_SPEC_INDIRECT_BRANCH 1 /* Return and control values for PR_SET/GET_SPECULATION_CTRL */ # define PR_SPEC_NOT_AFFECTED 0 # define PR_SPEC_PRCTL (1UL << 0) # define PR_SPEC_ENABLE (1UL << 1) # define PR_SPEC_DISABLE (1UL << 2) # define PR_SPEC_FORCE_DISABLE (1UL << 3) #endif /* _LINUX_PRCTL_H */
来源:Ubuntu16.04的
/usr/include/linux/prctl.h
文件