[佛系更新……]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