corCTF2022 corjail
Problem
Environment
- linux version:
5.10.127- CONFIG_SLUB_DEBUG=y
- CONFIG_SLUB=y
- CONFIG_SLAB_FREELIST_RANDOM=y
- CONFIG_SLAB_FREELIST_HARDENED=y
Simple description
The goal of this challenge is escaping docker with seccomp-ed environment by using off-by-one in kmalloc-4k.
The seccomp prohibits us to use struct msg_msg and struct msg_msgseg.
So, we need to find new structure which makes us exploit off-by-one. And after making RIP control (ROP, or something…), we have to LPE and Escaping docker.
Module
The module is simple: just prints the count of each syscall called and makes us to filter which syscall’s call count will be counted.
It utilizes Syscall statistics patch based on https://lwn.net/Articles/896474/ (check out build/build_kernel.sh).
Create Simple Build VM Using Ubuntu Cloud
Overview
I had to build a kernel and an image for trying CorJail. But the building was not completed in my environment (WSL2 on Windows 11). I think I will be comfortable if I have a linux VM for a building linux kernel, file system image, and etc.
Step
- Select Ubuntu version and download its image on here
- Install
cloud-init,cloud-utilsandqemu-system- You can install them by
sudo apt install -y cloud-init cloud-utils qemu-systemon Debian/Ubuntu.
- You can install them by
- Generate a RSA key using
ssh-keygen -t rsa - Set up config file and create seed.img
- To create config files, see config files section
- Create seed.img via
cloud-localds seed.img user-data.yaml metadata.yaml
- Set shared foldder and run qemu
- In guest OS, add
shared /shared 9p trans=virtio,version=9p2000.L,access=any 0 0to/etc/fstab- After addition type
sudo systemctl daemon-reload && sudo systemctl restart local-fs.target && sudo mount -a.
- After addition type
Then if you need more space for a qemu drive, use qemu-img resize.
AsisCTF2020Qual shared_house
Problem
Enviroment
- linux version:
4.19.98- No SMAP
- No KPTI
Features
This challenge provide simple device (it has only one function: mod_ioctl). And the function is like following:
struct request_t
{
unsigned int size;
char __padding0[4];
void *data;
};
uint64_6 mod_ioctl(struct file *a1, unsigned int cmd, unsigned __int64 arg) {
struct request_t req;
if (copy_from_user(&req, arg, 0x10LL)) return -14LL;
if (req.size > 0x80) return -22LL;
mutex_lock(&_mutex);
if (cmd == 0xC12ED002) { // cmd == 0xC12ED002: delete_note
if (!note) {
goto ERROR;
}
kfree(note);
note = 0LL;
} else if (cmd == 0xC12ED001) { // cmd == 0xC12ED001: alloc_new_note
if (note) kfree(note);
size = req.size;
note = (char *)_kmalloc(req.size, 0x6080C0LL);
if (!note) goto ERROR;
} else if (cmd == 0xC12ED003) { // cmd == 0xC12ED003: write_note
if (!note || req.size > size || copy_from_user(note, req.data, req.size))
goto ERROR;
note[req.size] = 0; // off-by-one if req.size==size
} else if (cmd != 0xC12ED004 || !note || req.size > size ||
copy_to_user(req.data, note,
req.size)) { // cmd == 0xC12ED004: read_note
goto ERROR;
}
mutex_unlock(&_mutex);
return 0LL;
ERROR:
mutex_unlock(&_mutex);
return -22;
}
Vulnerability
The vulnerability is obvious. The off-by-one in write_note.
HITCON2020 spark
Problem
Environment
- linux version:
5.9.11- No SMAP
- No SMEP
- No KPTI
Module
The source code of module is not provided, but the challenge gives us the demo program using it.
/*
* This is a demo program to show how to interact with SPARK.
* Don't waste time on finding bugs here ;)
*
* Copyright (c) 2020 david942j
*/
#include <assert.h>
#include <fcntl.h>
#include <linux/spark.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#define DEV_PATH "/dev/node"
#define N 6
static int fd[N];
const char l[] = "ABCDEF";
/*
B -- 10 -- D -- 11 -- F
/ \ |
4 | |
/ | |
A 5 4
\ | |
2 | |
\ | |
C -- 3 - E
*/
static void link(int a, int b, unsigned int weight) {
printf("Creating link between '%c' and '%c' with weight %u\n", l[a], l[b],
weight);
assert(ioctl(fd[a], SPARK_LINK, fd[b] | ((unsigned long long)weight << 32)) ==
0);
}
static void query(int a, int b) {
struct spark_ioctl_query qry = {
.fd1 = fd[a],
.fd2 = fd[b],
};
assert(ioctl(fd[0], SPARK_QUERY, &qry) == 0);
printf("The length of shortest path between '%c' and '%c' is %lld\n", l[a],
l[b], qry.distance);
}
int main(int argc, char *argv[]) {
for (int i = 0; i < N; i++) {
fd[i] = open(DEV_PATH, O_RDONLY);
assert(fd[i] >= 0);
}
link(0, 1, 4);
link(0, 2, 2);
link(1, 2, 5);
link(1, 3, 10);
link(2, 4, 3);
link(3, 4, 4);
link(3, 5, 11);
assert(ioctl(fd[0], SPARK_FINALIZE) == 0);
query(0, 5);
query(3, 2);
query(2, 5);
for (int i = 0; i < N; i++) close(fd[i]);
return 0;
}
As we can see in demo.c, this module is for a shortest path search.
And each node can be allocated by open and two nodes can be linked by link. The searching path is done by query.