Rating:

## Special Device File (Reverse)

### Solution

This challenge is similar to [Special Instruction](./spins.md), but the binary is AArch64 ELF, thus we can use decompiler this time.

```c
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
unsigned int fd; // w21 MAPDST
char *flag_buf; // x0
__int64 seed; // [xsp+28h] [xbp-8h]

seed = 0x139408DCBBF7A44LL;
fd = _open("/dev/xorshift64", 1LL, 0LL);
_write();
_close(fd);
fd = _open("/dev/xorshift64", 0LL, 0LL);
flag_buf = decode(&flag, &randval, fd);
puts(1LL, flag_buf);
puts(1LL, "\n");
_close(fd);
exit(0LL);
}

char *__fastcall decode(char *flag, char *key, unsigned int rng)
{
char *p; // x21
__int64 i; // x3

if ( *flag )
{
p = flag;
i = 0LL;
do
{
*p ^= get_random_value(rng) ^ key[i];
++i;
++p
}
while ( flag[i] );
}
return flag;
}
```

It's pretty simple. In `main` it will open `/dev/xorshift64`, write something then close it, IDA didn't correctly infer the argument here, we can assume it writes `0x139408DCBBF7A44LL` to the device, which is the seed of the RNG.

And then, in the `decode` function, a global encrypted `flag`(`0x1800`) will perform XOR with `randval`(`0x1820`) and `get_random_value`. Simply extract these bytes and simulate the RNG, then we can decrypt the flag.

Again, I spent many time on finding the correct version of xorshift64, and finally found it on [Japanese Wikipedia](https://ja.wikipedia.org/wiki/Xorshift).

```python
#!/usr/bin/env python3

seed = 0x139408DCBBF7A44
mask = 0xFFFFFFFFFFFFFFFF

def get_rand():
global seed
seed ^= (seed << 13) & mask
seed ^= (seed >> 7) & mask
seed ^= (seed << 17) & mask
return seed

with open('runme', 'rb') as f:
f.seek(0x1800)
flag = f.read(0x20)
f.seek(0x1820)
randval = f.read(0x20)

for i in range(32):
r = get_rand()
print(chr((flag[i] ^ randval[i] ^ r) & 0xFF), end="")
```

The flag is `SECCON{UseTheSpecialDeviceFile}`

Original writeup (https://github.com/jaidTw/ctf-writeups/blob/master/seccon-2018/spdev.md).