[佛系更新……]prctl()
in CTF
赛题里经常见到
prctl()
,每次都查资料,每次都忘,这次决定把每次的见到的记录一下。
详细见prctl(2) — Linux manual page
函数声明
#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
描述
prctl - operations on a process or thread
prctl()
用来对进程就行操作。
prctl()
is called with a first argument describing what to do (with values defined in <linux/prctl.h>), and further arguments with a significance depending on the first one.
使用过的几个参数:
prctl()
函数的第一个参数就是来描述想要做的事情。在linux/prctl.h
里定义的很多可选参数。
这里选几个见过的来描述好了:
PR_SET_NO_NEW_PRIVS
PR_SET_NO_NEW_PRIVS (since Linux 3.5)
Set the calling thread's no_new_privs attribute to the value
in arg2. With no_new_privs set to 1, execve(2) promises not
to grant privileges to do anything that could not have been
done without the execve(2) call (for example, rendering the
set-user-ID and set-group-ID mode bits, and file capabilities
non-functional). Once set, the no_new_privs attribute cannot
be unset. The setting of this attribute is inherited by chil‐
dren created by fork(2) and clone(2), and preserved across
execve(2).
Since Linux 4.10, the value of a thread's no_new_privs
attribute can be viewed via the NoNewPrivs field in the
/proc/[pid]/status file.
For more information, see the kernel source file Documenta‐
tion/userspace-api/no_new_privs.rst (or Documenta‐
tion/prctl/no_new_privs.txt before Linux 4.13). See also
seccomp(2).
这个参数会很常见:prctl(38, 1LL, 0LL, 0LL, 0LL);
//[include/linux/prctl.h](https://code.woboq.org/userspace/include/linux/prctl.h.html)
#define PR_SET_NO_NEW_PRIVS 38
简单来说,就是当第一个参数是PR_SET_NO_NEW_PRIVS
的时候,第二个参数就是no_new_privs
,然后当其值为1
时,我们就没办法使用execve()
,这个设置还会继承到子进程。
PR_SET_SECCOMP
#define PR_SET_SECCOMP 22
PR_SET_SECCOMP (since Linux 2.6.23)
Set the secure computing (seccomp) mode for the calling thread,
to limit the available system calls. The more recent seccomp(2)
system call provides a superset of the functionality of
PR_SET_SECCOMP.
The seccomp mode is selected via arg2. (The seccomp constants
are defined in <linux/seccomp.h>.)
With arg2 set to SECCOMP_MODE_STRICT, the only system calls that
the thread is permitted to make are read(2), write(2), _exit(2)
(but not exit_group(2)), and sigreturn(2). Other system calls
result in the delivery of a SIGKILL signal. Strict secure
computing mode is useful for number-crunching applications that
may need to execute untrusted byte code, perhaps obtained by
reading from a pipe or socket. This operation is available only
if the kernel is configured with CONFIG_SECCOMP enabled.
With arg2 set to SECCOMP_MODE_FILTER (since Linux 3.5), the
system calls allowed are defined by a pointer to a Berkeley
Packet Filter passed in arg3. This argument is a pointer to
struct sock_fprog; it can be designed to filter arbitrary system
calls and system call arguments. This mode is available only if
the kernel is configured with CONFIG_SECCOMP_FILTER enabled.
If SECCOMP_MODE_FILTER filters permit fork(2), then the seccomp
mode is inherited by children created by fork(2); if execve(2)
is permitted, then the seccomp mode is preserved across
execve(2). If the filters permit prctl() calls, then additional
filters can be added; they are run in order until the first non-
allow result is seen.
For further information, see the kernel source file
Documentation/prctl/seccomp_filter.txt.
碰到了一道题里是这么写的:
prctl(22, 2LL, &unk_202070);
/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
补充一下:就是如果arg2
为SECCOMP_MODE_STRICT
,则只允许调用read
,write
,_exit
,sigreturn
这几个系统调用。如果arg2
为SECCOMP_MODE_FILTER
,就是BPF过滤,其中对syscall
的限制通过arg3
的BPF
(Berkeley Packet Filter)的相关结构体定义:
/*
* Try and keep these values and structures similar to BSD, especially
* the BPF code definitions which need to match so you can share filters
*/
struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
unsigned short len; /* Number of filter blocks */
struct sock_filter *filter;
};
struct sock_filter { /* Filter block */
__u16 code; /* Actual filter code */
__u8 jt; /* Jump true */
__u8 jf; /* Jump false */
__u32 k; /* Generic multiuse field */
};
至于这个结构体,在程序里也看不懂,直接export出来,使用seccomp-tools就可以了。
附上使用方法:
把filter
结构体的数据export出来然后:
seccomp-tools disasm export_result