**Hacker handle**: 0xc3

## Instructions
To start the connector software, run the binary as follows:

```
CONNECTION_KEY=WMJMNJIYFZFLRUHNMCDY ./RoveConnectCTL.antianalysis
```

## General notes
_Apologies, these notes are probably not all in chronological order, and are quite chaotic, and probably incomplete. I'll try to do better for the second assignment._

Ghidra starts disassembling at 0x1000c0, but we want to skip two bytes.

The first call is a call to the sys_time syscall, which is contained in a section that contains
a whole bunch of system call wrappers.

The result of the call to `sys_time` plus something looking like the string BAMAPWNS are written to 0x3ffda8. Why? I have no idea.

Seems like this is at least somewhat packed or obfuscated, since strings are missing that are definitely printed.

It also seems to do some waiting (using cpuid, rdtsc, mfence, lfence, looping), perhaps to throw off sandboxing. It certainly caused `rr` to be very slow / not work. Removing the looping part made `rr` at least record an execution.

0x101aaa is probably something like puts.

`entry` contains some instructions which seem to do nothing, but code embedded within is jumped to later on (0x1000e0). That calls 0x1001ed.

There are pieces of code below what Ghidra detects as setup_main. Skipping two bytes (48 be) and disassembling reveals a piece of code which eventually gets to 0x101449, printing that the master connection key has been disabled and that this connection attempt is logged. In my executions I've never reached this piece of code. Skipping (48 be) again reveals a piece of code which eventually gets to 0x101476, which is reached when the anti-* techniques are disabled but authorization is not given.

Two snippets at `0x100169` and `0x10016e` manipulate `[rdi]`, adding 17 and subtracting 48, respectively. They are used throughout the binary.

There are a bunch of functions like at `0x1008e9` and `0x100265` and `0x100886` which do... things... I have no idea what the semantic meaning of them is.

As far as I can tell, `call_indirects` (`0x100848`) only ever gets called with `[rdi]-=48` and `[rdi]+=17`.
So it always does `[rdi] = [rdi] + 48`. I've patched it as follows:
`0x100848`: `push r13; mov r13,rdx` => `add qword ptr [rdi],48; ret` (encoded as the 5 bytes: 48 83 07 30 c3).

## Anti-debugging techniques
`ptrace(PTRACE_TRACEME)` is used. If it fails, starting the connector software fails, with an error message asking us to "insert disk 2".
It can be patched out by replacing code in the syscall subroutine at `0x10024c` (which I've dubbed `sys_ptrace`), replacing `mov r10, rcx` with
`mov rax, rcx` and replacing the jump with `nop; ret`.

Additionally, and I'm not sure whether I should call this an anti-debugging or an anti-sandbox technique, there are busy-waiting pieces of code at `0x1013f0` and `0x10095d` (those are the addresses of the loop labels). They can be 'patched out' (kept from looping) by modifying `0x10142a` and `0x100994`, changing the `JNZ` to a 2-byte NOP. Only the code at `0x1013f0` seems to trip up tools though (it was triggered for me when running the binary under rr, causing it to be very very slow); I haven't patched the one at `0x100994`.

## Anti-VM / Platform detection
In what I've dubbed `check_system` (the function starting at `0x100cd9`), there are checks for supported hardware and VM presence.
To perform these checks, paths in /sys/ are opened. The paths are stored encrypted within the binary, and this function led me to
the decryption functions.

`0x100310` is some kind of XOR-based decryption/deciphering with key `0xa9`.
`0x100332` seems to do some decrypt-compare operation, not storing the decrypted stuff anywhere.

`0x100780` contains pointers to strings containing "ExploreTeK" and such, so that probably has to do with the expected hardware.
`0x1007c0` contains pointers to strings containing VM software manufacturer names, so that probably has something to do with VM detection.

We can patch out both of these checks; we want what I've dubbed `hw_invalid` (`[RSP + 0xc]`) to be zero and what I've dubbed `in_vm` (`EBX`) to stay zeroed.
To do this, patch `0x100d06` to set `[RSP + 0xc]` to zero and patch `0x100dfb` to nop out the `setz bl` instruction.

Now, we get a STAGE 2 INACCESSIBLE: PERMISSION DENIED message. Interesting.
This string is stored (encrypted) at `0x10052d`, putting a read watchpoint on it reveals code that was not found by Ghidra from 0x101476 onwards. Poking around there also finds other code (probably) (I don't quite remember).

## Authorization
After finding the decryption functions described in the previous section, I xor'ed the whole binary with 0xa9 and ran `strings` on it, revealing a bunch of the strings that were printed (and a bunch that weren't). This led to the `CONNECTION_KEY` environment variable. Poking around further and looking at the callers of `getenv` led to two functions, at `0x100fb9` and `0x100a9e`. The function at `0x100a9e` contains a set of comparisons to letters, which revealed a possible value for `CONNECTION_KEY`; `CONNECTION_KEY=WMJMNJIYFZFLRUHNMCDY`. I don't know if this _is_ the master connection key; the presence of one implies other forms of authorization but I haven't found them.

In any case, running the binary with that environment variable set starts the connector software.

## Debug messages
There may be more debug messages than this; all I found was a piece of code starting at `0x10174b` which checks for the time and hostname of the system. Setting the hostname to "ingenuity" and the time between April 1st and April 6th, 2021 prints an additional message, noting that the "CONNECTION SYSTEM" is okay and adding a dev note to disable the master connection key.


## Overview of patches
### (for my personal sanity so I can easily check if I've done them all or reversed them all)
sys_ptrace:
mov r10, rcx => mov rax,rcx
jmp do_syscall => nop; ret

maybe_wait: 10142a: jnz maybe_wait_loop => nop (2 bytes)

check_system:
0x100d06: mov dword ptr [RSP + hw_invalid], 0x0 instead of 0x1. This bypasses the HW check.
0x100dfb: setz bl => nop; nop (3 bytes). This bypasses the VM check.
