Static analysis: entry point and main flow
Address: 0x14004ca40
Symbol: main (Ghidra FUN_14004ca40), reached from CRT entry @ 0x1400855b8
Callers / callees: CRT start-up → main → logger, CLI parser, drive sweep, pre-encryption steps, crypto init, thread pools
Purpose
main does all one-time set-up, then hands files to encryptor threads. Everything after
the thread pools start is asynchronous C++20 coroutines on an asio IOCP pool. A flow
diagram is in artifacts/diagrams/execution-flow.png.
Walkthrough
- Logging (
FUN_14004c6f0): spdlog-stylefile_loggerwritingLog-%d-%m-%Y-%H-%M-%S.txtin the working directory. -
Command line (
FUN_140053d70): an argh-style parser with no registered parameters. A value has to be attached with=. | Argument | Effect | Default | |—|—|—| |--encryption_path=<path>/-p=<path>| encrypt only this tree | none | |--share_file=<file>/-s=<file>| text file of UNC paths or drives, one per line; replaces the drive sweep | none | |--encryption_percent=<n>/-n=<n>| percent used by Spot and Part modes | 50 | |-localonly| skip network disks and paths | off | |-l| log the drive list and exit | off |Gotcha, confirmed live in run 1:
-p C:\x(with a space) is parsed as a bare flag. The path comes out empty and the sample sweeps every drive. - Targets, from exactly one source in priority order: the explicit path, then the share
file (
FUN_140041fc0), then the drive sweep (FUN_1400766e0). Classification and the five-drive limit are covered in02-targeting-and-exclusions.md. - Pre-encryption steps, run once and skipped in
-lmode: update the skip list (FUN_14006ecf0), take the protected-PID snapshot (FUN_140070c30), delete shadow copies (FUN_140071d80→FUN_140071620). See03-pre-encryption-actions.md. - Crypto init: import the RSA-4096 public key DER from
0x1400ee010(FUN_14007ba90/FUN_140081ac0). The RSA context gets its own QPC-seeded Yarrow instance for padding (FUN_14007bbe0). - Thread pools (
FUN_1400737d0): logical CPU count N, doubled when N < 5 (and treated as 2 when N = 1). 30% of N become root-folder parsers, 10% (at least one) folder parsers, and the rest encryptors. A 2-vCPU VM gets 1 / 1 / 2. - Root-folder queue (
FUN_140073950): roots are queued here. This was the dynamic “gate” breakpoint, wherer8holds the root path as astd::wstring. - Folder parsers (
FUN_1400b5fb0,FUN_1400b81d0):- apply the exclusions;
- drop
akira_readme.txt(FUN_140042420); - set the force-Full / force-Part flags;
- enqueue each file with
FUN_140074480(queue, path, fullFlag, partFlag, ctx, percent, …). The flags land in task fields+0x49and+0x4a.
- Per-file coroutine (
FUN_1400ae840): see05-cryptography.mdand06-file-format-and-journal.md. Raw decompile:artifacts/ghidra/FUN_1400ae840_per_file_coroutine.decompile.c. mainwaits for the pools, logs timing and exits. There is no self-deletion and no persistence.
Findings
- There is no C2, persistence or exfiltration code in this binary. The data theft that the note claims is not done by this file.
- In
-lmode the run stops after step 3 and only logs the drive list. - A file that still cannot be opened after Restart Manager is logged and skipped.
Cross-references
- Related:
02-targeting-and-exclusions.md,03-pre-encryption-actions.md,08-function-map.md