ORW

seccomp

参考:

用处

用于添加白/黑名单,允许/禁止某些系统调用,以达到保护系统的目的

Seccomp-BPF

比较原始的写法

把那些宏当做一个虚拟机的汇编来看就好理解了

例如以下这个C程序

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/prctl.h>
#include <seccomp.h>
#include <linux/seccomp.h>
#include <linux/filter.h>

int main()
{
    struct sock_filter filter[] = {
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 4),
        BPF_JUMP(BPF_JMP + BPF_JEQ, 0xc000003e, 0, 2),
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 0),
        BPF_JUMP(BPF_JMP + BPF_JEQ, 59, 0, 1),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
    };
    struct sock_fprog prog = {
        .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
    };
    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
    printf("start!n");
    system("id");
    return 0;
}

用seccomp-tools可以把那一堆结构体翻译成人话

$ seccomp-tools dump ./seccomp 
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x02 0xc000003e  if (A != ARCH_X86_64) goto 0004
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x15 0x00 0x01 0x0000003b  if (A != execve) goto 0005
 0004: 0x06 0x00 0x00 0x00000000  return KILL
 0005: 0x06 0x00 0x00 0x7fff0000  return ALLOW

进阶写法

用seccomp库函数

sudo apt install libseccomp-dev libseccomp2 seccomp
#include <unistd.h>
#include <seccomp.h>
#include <linux/seccomp.h>

int main(void){
    scmp_filter_ctx ctx;
    ctx = seccomp_init(SCMP_ACT_ALLOW);
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
    seccomp_load(ctx);
    char * str = "/bin/sh";
    write(1,"hello worldn",12);
    syscall(59,str,NULL,NULL);//execve
    return 0;
}
open(file,oflag)`,`read(fd,buf,n_bytes)`和`write(fd,buf,n_bytes)

如何构造函数

open(file,oflag),read(fd,buf,n_bytes)write(fd,buf,n_bytes)

open

file就是我们要读取的文件名,CTF中一般为flag,或者flag.txt。
而oflag则是我们以何种方式打开文件,如只读,只写,可读可写。一般来说我们都设置oflag=0,以默认方式打开文件,一般来说都是只读,我们并不需要对flag进行其它操作,所以只读的权限就够了

read和write

这两个是大同小异的。fd是文件描述符,通过设置它来决定函数的操作。在大多数时候,我们常常设置read的fd为0,代表标准输入,但在ORW中,我们需要设置read的fd为3,表示从文件中读取,buf就是我们读取出的flag值存放的地址,n_bytes就是能输入多少字节的数据。write的fd还是如常,依旧为1.

源码

img

打开第一个文件,它的描述符是2之后的数,由于是第一个打开的,所以文件描述符是3

栈可执行的ORW

用shellcreft模块构造ORW的shellcode

shellcraft.open('/flag')
shellcraft.read(3,buf,n_bytes)
shellcraft.write(1,buf,n_bytes)
posted @ 2024-12-09 00:03  r_0xy  阅读(29)  评论(0)    收藏  举报