## Reversing - random_pitfalls
We are given the binary, which:
* `mmap`s 64 consecutive `PROT_NONE` pages.* Randomly selects 32 of them, and `mprotect`s them to `PROT_READ|PROT_WRITE`.* Places 40-byte random values into the first 31 of them.* Places `flag ^ value[0] ^ ... ^ value[30]` into the last one.* Disables all syscalls except `write(1, buf, 40)` and `exit`.* Reads shellcode from stdin.* Prepends a prologue, which clears all general purpose registers except `rdi`  and `rsi` (including `rsp`!).* Calls the shellcode, passing the address of the first page as `rdi` and the  address of the buffer as `rsi`.
The gist of the task is to find a way to determine whether a page is readablewithout relying on the OS. Indeed, we need to correctly determine which 32 pagesare mapped, and xor all the corresponding 40-byte values in order to get theflag. An incorrect guess would lead to a segfault, and on the next attempt we'llsee some completely new new values.
Still, the way pages are randomly chosen looks a bit weird, let's write asimilar loop in python and see if the distribution it produces is biased.. no,for all practical intents and purposes, it's not.
Second guess - Spectre-like approach, when we would try to provoke speculativeaccesses to those pages and measure differences in timings. Sounds complicated,let's leave this as a last resort.
Third guess - a specialized machine instruction. Let's check out Volume 2 ofIntel Manual. And let's start with Chapter 5 (V-Z) and move backwards, becauseis's fun (no, seriously, that was the solution process!). The first instructionwe encounter this way is: `XTEST - Test If In Transactional Execution`. Thisparticular one is irrelevant, but - What Happens To Page Faults If InTransactional Execution?
Quick test:
```#include <assert.h>#include <stddef.h>#include <stdio.h>#include <sys/mman.h>#include <unistd.h>
static inline int is_mapped(void *p) {    long long rax;    asm("mov $-1,%%rax\n"        "xbegin 0f\n"        "mov 0(%[p]),%%rbx\n"        "xend\n"        "0: mov %%rax,%[rax]\n"        : [rax] "=r" (rax) : [p] "r" (p) : "rax", "rbx");    return rax == -1;}
int main() {    assert(getpagesize() == 4096);    void *m0 = mmap(NULL, 4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);    assert(m0 != MAP_FAILED);    void *m1 = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);    assert(m1 != MAP_FAILED);    *(long long *)m1 = 1;    for (;;) {        assert(!is_mapped(m0));        assert(is_mapped(m1));    }}```
The code loads `-1` into `rax`, initiates a transaction, dereferences a pointer,and ends a transaction. When transaction is aborted for whatever reason, `rax`receives a reason code (`-1` is not a valid reason code), otherwise it stays asis. Turns out a page fault is a completely valid reason to abort a transactionwithout calling an interrupt handler! That's why, by the way, `*(long long *)m1= 1` is very important in this test, pages allocated by `mmap` are mapped onlyon first access, which, if it happens inside a transaction, never reaches the`#PF` handler.
With that knowledge, implementing shellcode is trivial, and we get the flag:`SECCON{7h1S_ch4L_Is_in5p1r3d_by_sgx-rop}`. The SGX ROP article turned out to befantastic, by the way - a very much recommended read.