Skip to content

Commit

Permalink
buffer-overflow-control-flow: Add the first focused adversarial mission
Browse files Browse the repository at this point in the history
  • Loading branch information
jrtc27 authored and brooksdavis committed Sep 3, 2020
1 parent 202aa3d commit 7ddac3b
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/missions/buffer-overflow-control-flow/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,50 @@
# Exploiting a buffer overflow to manipulate control flow

The objective of this mission is to demonstrate arbitrary code execution
through a control-flow attack, despite CHERI protections. You will attack three
different versions of the program:

1. A baseline RISC-V compilation, to establish that the vulnerability is
exploitable without any CHERI protections.

2. A baseline CHERI-RISC-V compilation, offering strong spacial safety between
heap allocations, including accounting for imprecision in the bounds of large
capabilities.

3. A weakened CHERI-RISC-V compilation, reflecting what would occur if a memory
allocator failed to pad allocations to account for capability bounds
imprecision.

The success condition for an exploit, given attacker-provided input overflowing
a buffer, is to modify control flow in the program such that the `success`
function is executed.

1. Compile `buffer-overflow.c` and `btpalloc.c` together with a RISC-V target
and exploit the binary to execute the `success` function.

**buffer-overflow.c**
```C
{{#include buffer-overflow.c}}
```
2. Recompile with a CHERI-RISC-V target, attempt to exploit the binary and, if
it cannot be exploited, explain why.
3. Recompile with a CHERI-RISC-V target but this time adding
`-DCHERI_NO_ALIGN_PAD`, attempt to exploit the binary and, if it cannot be
exploited, explain why.
**btpalloc.c**
```C
{{#include btpalloc.c}}
```

## Support code

**btpalloc.h**
```C
{{#include btpalloc.h}}
```
**main-asserts.inc**
```C
{{#include main-asserts.inc}}
```
63 changes: 63 additions & 0 deletions src/missions/buffer-overflow-control-flow/btpalloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
* Copyright (c) 2020 Jessica Clarke
*/
#include "btpalloc.h"

#include <assert.h>
#include <stddef.h>

#include <sys/mman.h>

#ifdef __CHERI_PURE_CAPABILITY__
#include <cheriintrin.h>
#endif

static void *btpmem;
static size_t btpsize;

static void
btpinit(void)
{
btpsize = 0x100000;
btpmem = mmap(NULL, btpsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
assert(btpmem != MAP_FAILED);
}

void *
btpmalloc(size_t size)
{
void *alloc;
size_t allocsize;

if (btpmem == NULL)
btpinit();

alloc = btpmem;
/* RISC-V ABIs require 16-byte alignment */
allocsize = __builtin_align_up(size, 16);

#if defined(__CHERI_PURE_CAPABILITY__) && !defined(CHERI_NO_ALIGN_PAD)
allocsize = cheri_representable_length(allocsize);
alloc = __builtin_align_up(alloc,
~cheri_representable_alignment_mask(allocsize) + 1);
allocsize += (char *)alloc - (char *)btpmem;
#endif

if (allocsize > btpsize)
return (NULL);

btpmem = (char *)btpmem + allocsize;
btpsize -= allocsize;
#ifdef __CHERI_PURE_CAPABILITY__
alloc = cheri_bounds_set(alloc, size);
#endif
return (alloc);
}

void
btpfree(void *ptr)
{
(void)ptr;
}
8 changes: 8 additions & 0 deletions src/missions/buffer-overflow-control-flow/btpalloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
* Copyright (c) 2020 Jessica Clarke
*/
#include <stddef.h>

void *btpmalloc(size_t size);
void btpfree(void *ptr);
73 changes: 73 additions & 0 deletions src/missions/buffer-overflow-control-flow/buffer-overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
* Copyright (c) 2020 Jessica Clarke
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "btpalloc.h"

void
success(void)
{
puts("Exploit successful!");
}

void
failure(void)
{
puts("Exploit unsuccessful!");
}

static uint16_t
ipv4_checksum(uint16_t *buf, size_t words)
{
uint16_t *p;
uint_fast32_t sum;

sum = 0;
for (p = buf; words > 0; --words, ++p) {
sum += *p;
if (sum > 0xffff)
sum -= 0xffff;
}

return (~sum & 0xffff);
}

#include "main-asserts.inc"

int
main(void)
{
int ch;
char *buf, *p;
uint16_t sum;
void (**fptr)(void);

buf = btpmalloc(25000);
fptr = btpmalloc(sizeof(*fptr));

main_asserts(buf, fptr);

*fptr = &failure;

p = buf;
while ((ch = getchar()) != EOF)
*p++ = (char)ch;

if ((uintptr_t)p & 1)
*p++ = '\0';

sum = ipv4_checksum((uint16_t *)buf, (p - buf) / 2);
printf("Checksum: 0x%04x\n", sum);

btpfree(buf);

(**fptr)();

btpfree(fptr);

return (0);
}
45 changes: 45 additions & 0 deletions src/missions/buffer-overflow-control-flow/main-asserts.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
* Copyright (c) 2020 Jessica Clarke
*/
#include <assert.h>
#include <stdint.h>
#ifdef __CHERI_PURE_CAPABILITY__
#include <cheriintrin.h>
#endif

static void
main_asserts(void *buf, void *fptr)
{
uintptr_t ubuf = (uintptr_t)buf;
uintptr_t ufptr = (uintptr_t)fptr;
#ifdef __CHERI_PURE_CAPABILITY__
ptraddr_t ubuf_top;
#endif

#ifdef __CHERI_PURE_CAPABILITY__
ubuf_top = cheri_base_get(ubuf) + cheri_length_get(ubuf);
#endif

#if defined(__CHERI_PURE_CAPABILITY__) && !defined(CHERI_NO_ALIGN_PAD)
/*
* For the normal pure-capability case, `buf`'s allocation should be
* adequately padded to ensure precise capability bounds and `fptr`
* should be adjacent.
*/
assert(ubuf_top == ufptr);
#else
/*
* Otherwise `fptr` should be 8 bytes (not 0 due to malloc's alignment
* requirements) after the end of `buf`.
*/
assert(ubuf + 25008 == ufptr);
#ifdef __CHERI_PURE_CAPABILITY__
/*
* For pure-capability code this should result in the bounds of the
* large `buf` allocation including all of `fptr`.
*/
assert(ubuf_top >= ufptr + sizeof(void *));
#endif
#endif
}

0 comments on commit 7ddac3b

Please sign in to comment.