permissions
07/18/2023
By: unvariant
Tags: pwn AmateursCTF-2023Problem Description:
Every programmer should read the Intel Software Developer Manuals at least once.
Hints:
Reveal Hints
NoneProvided Files
- chal.c
- chal
- Dockerfile
chal.c
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/seccomp.h>
#include <seccomp.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
void setup_seccomp () {
return;
}
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_KILL);
int ret = 0;
ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
ret |= seccomp_load(ctx);
if (ret) {
errx(1, "seccomp failed");
}
}
int main () {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
alarm(6);
int fd = open("flag.txt", O_RDONLY);
if (0 > fd)
errx(1, "failed to open flag.txt");
char * flag = mmap(NULL, 0x1000, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (flag == MAP_FAILED)
errx(1, "failed to mmap memory");
if (0 > read(fd, flag, 0x1000))
errx(1, "failed to read flag");
// make flag write-only
if (0 > mprotect(flag, 0x1000, PROT_WRITE))
errx(1, "failed to change mmap permissions");
char * code = mmap(NULL, 0x100000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
if (code == MAP_FAILED)
errx(1, "failed to mmap shellcode buffer");
printf("> ");
if (0 > read(0, code, 0x100000))
errx(1, "failed to read shellcode");
setup_seccomp();
((void(*)(char *))code)(flag);
exit(0);
}
Intended
In the provided source file, the code does a few things
- writes the contents of
flag.txt
into a mmapped buffer - mprotects the flag memory to
PROT_WRITE
- mmaps shellcode
- setups up seccomp sandbox
- executes shellcode
The intended solution is to simply print out the contents of the flag. Even
though the memory is set to PROT_WRITE
, on x64 there is not concept of
write-only memory. On x64 write implies read, so even though the memory
protection is set to write-only we can still read the flag.
Unintendeds
flag.txt
fd is not closed
I forgot to close the flag.txt
fd before executing the shellcode, which
meants that you could simply read from the flag fd and get the flag.