spot the bug: stream ciphers

Epic Technologies™ (no relation to any games companies) is happy to announce the release of Epic DRM™ the new DRM system that allows you to protect your shell commands from unauthorized viewing and modification, even in the hands of untrusted third parties! we have utilized the latest cryptographic algorithms like chacha20 and poly1305 for guaranteed maximum security

we have released a demo (https://git.lain.faith/haskal/spot-the-bug/src/branch/develop/stream-ciphers) containing an implementation of Epic DRM™ including a server program that sends Epic DRM™ protected shell commands to an untrusted client process, and receives protected commands back to execute. Epic DRM™ protects the authenticity and integrity of each command, making it completely safe to execute anything received by the client that can be successfully unprotected

getting started with Epic DRM™:

git clone https://git.lain.faith/haskal/spot-the-bug/
cd spot-the-bug/stream-ciphers
make

now, run ./epic_drm to start the DRM server, and ./client to execute an interaction with the server

scope

i'm not going to bother to set up an Official Online Environment for this or anything, so you'll have to run it on your own machine, but imagine that epic_drm is running as some privileged user with access to juicy data and magic buses and you are an unprivileged user running client. the goal is to pwn epic_drm by sending it some data over the communication channel. the goal does not involve dumping, ptracing, or otherwise committing privileged screwing with epic_drm through boring means

so basically, take a look at the code (it's not a lot uwu) and Spot The Bug!™
feel free to send me questions on mastodon or something

how it works

our technology is way too complicated for anyone but our top level COMPTIA Security+ certified engineers to understand, but we have provided the source code for your consideration (it's also in the repo)

epic_drm communicates using shared memory. it uses the following structure to organize communications:

struct command_channel {
    sem_t sem_c2s;
    sem_t sem_s2c;

    enum { GET_CMD, EXECUTE_CMD, SUCCESS, ERROR } command;

    struct {
        uint8_t nonce[24];
        uint8_t exec_cmd[CMD_SIZE];
        uint8_t mac[16];
    } data;
};

and here is the code for epic_drm.c - the demo implementation of Epic DRM™

/**
 * sends a protected command to the client
 */
void get_cmd(struct command_channel* chan, const uint8_t* key) {
    log("sending encrypted DRM command");
    uint8_t cmd[CMD_SIZE] = "echo 'this shell command has been protected with Epic DRM(tm)'";
    getrandom(chan->data.nonce, 24, 0);
    crypto_lock(chan->data.mac, chan->data.exec_cmd, key, chan->data.nonce, cmd, CMD_SIZE);
    chan->command = SUCCESS;
}

/**
 * unprotects and executes data from the client
 */
void execute_cmd(struct command_channel* chan, const uint8_t* key) {
    log("decrypting command");
    uint8_t cmd[CMD_SIZE];
    int res = crypto_unlock(cmd, key, chan->data.nonce, chan->data.mac, chan->data.exec_cmd, CMD_SIZE);
    if (res != 0) {
        log("decryption error");
        chan->command = ERROR;
    } else {
        log("executing command");
        system((const char*)cmd);
        chan->command = SUCCESS;
    }
}

int main() {
    // create random key
    uint8_t key[16];
    log("generating random key");
    getrandom(key, sizeof(key), 0);

    // initialize memory
    log("opening shm");
    shm_unlink(SHM_NAME);
    int shm = shm_open(SHM_NAME, O_RDWR | O_CREAT | O_EXCL, 0644);
    ftruncate(shm, SHM_SIZE);
    struct command_channel* chan = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);

    sem_init(&chan->sem_c2s, 1, 0);
    sem_init(&chan->sem_s2c, 1, 0);

    // process commands
    log("ready");
    while (true) {
        sem_wait(&chan->sem_c2s);

        switch (chan->command) {
            case GET_CMD:
                get_cmd(chan, key);
                break;
            case EXECUTE_CMD:
                execute_cmd(chan, key);
                break;
            default:
                log("unexpected command");
        }

        sem_post(&chan->sem_s2c);
    }
}

and finally, client.c - the untrusted client

// this code is untrusted
// but don't worry, Epic DRM(tm) protections are unbreakable

void* get_cmd(struct command_channel* chan) {
    // get the protected shell command from the DRM server
    void* dst = malloc(sizeof(chan->data));

    log("sending get_cmd");
    chan->command = GET_CMD;
    sem_post(&chan->sem_c2s);
    sem_wait(&chan->sem_s2c);
    logf("result: %s", chan->command == SUCCESS ? "success" : "error");
    if (chan->command == SUCCESS) {
        memcpy(dst, &chan->data, sizeof(chan->data));
        return dst;
    } else {
        return NULL;
    }
}

void send_cmd(struct command_channel* chan, void* data) {
    // send a protected shell command back to the server
    log("sending execute_cmd");
    memcpy(&chan->data, data, sizeof(chan->data));

    chan->command = EXECUTE_CMD;
    sem_post(&chan->sem_c2s);
    sem_wait(&chan->sem_s2c);
    logf("result: %s", chan->command == SUCCESS ? "success" : "error");
}

int main() {
    // perform a basic interaction with epic_drm
    log("opening drm");
    int shm = shm_open(SHM_NAME, O_RDWR, 0);
    struct command_channel* chan = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);

    // get protected shell command
    void* data = get_cmd(chan);
    log("data");
    for (size_t i = 0; i < 64; i++) {
        uint8_t b = ((uint8_t*)data)[i];
        printf("%02x ", b);
        if (i % 16 == 15) {
            printf("\n");
        }
    }
    printf("...\n");

    // send back
    send_cmd(chan, data);

    log("done");
}

this is based on a mistake someone has made that i had some fun exploiting in the past :P