Static analysis: file selection and encryption modes
Address: mode decided in 0x1400b5fb0 (folder parser) and 0x1400ae840 (per-file coroutine);
bodies 0x1400b23a0 (Full), 0x1400b3580 (Spot), 0x1400b4780 (Part)
Callers / callees: folder parser → FUN_140074480 enqueue → FUN_1400ae840 → mode body
Purpose
Each file that survives the exclusions gets one of three modes. Each mode encrypts some regions in place, in 0xFFFF-byte chunks.
Walkthrough
- Extension in the database set → mode 0, Full: the whole file.
- Otherwise, extension in the VM/disk-image set, or size > 2,000,000 bytes → mode 2, Part: striped regions.
- Otherwise → mode 1, Spot (the binary’s own log name): only the first
percent% of the file.
In every encrypted region, the first and last chunk use KCipher-2 and the middle chunks use ChaCha8. Both cipher states carry on across chunks and regions.
| Mode | Coroutine | Region(s) encrypted (S = size, p = percent) | Observed live |
|---|---|---|---|
| 0 Full | FUN_1400b23a0 |
[0, S) | zero_db.sqlite (0x30000 B) and e2e_db.sqlite (0x30123 B) → mode byte 0 |
| 1 Spot | FUN_1400b3580 |
[0, p·S/100) | zero_small.txt, e2e_small.txt, the sample’s .zip, stage2 files → mode byte 1 |
| 2 Part, p ≥ 50 | FUN_1400b4780 |
4 stripes of B = p·S/500 bytes, starting every (S − 4B)/5 bytes | zero_big.bin and e2e_big.bin (3,000,000 B): reads at 0, 360,000, 720,000, 1,080,000 |
| 2 Part, p < 50 | FUN_1400b4780 |
2 stripes of B = p·S/300 bytes, starting every (S − 2B)/3 bytes | not exercised live (round-trip tested only) |
At the default p = 50, Part mode covers only 40% of the file, in four 10% stripes; 60% stays plaintext. Spot mode on a small document leaves its second half untouched.
Key constants / structures
Full-mode extensions (153), decoded from obfuscated .rdata tables that FUN_140003680
builds into set 0x1400f5e60 (artifacts/decoded/db_extensions.txt):
.4dd .4dl .accdb .accdc .accde .accdr .accdt .accft .adb .ade .adf .adp .arc .ora .alf .ask .btr .bdf .cat .cdb .ckp .cma .cpd .dacpac .dad .dadiagrams .daschema .db .db-shm .db-wal .db3 .dbc .dbf .dbs .dbt .dbv .dbx .dcb .dct .dcx .ddl .dlis .dp1 .dqy .dsk .dsn .dtsx .dxl .eco .ecx .edb .epim .exb .fcd .fdb .fic .fmp .fmp12 .fmpsl .fol .fp3 .fp4 .fp5 .fp7 .fpt .frm .gdb .grdb .gwi .hdb .his .ib .idb .ihx .itdb .itw .jet .jtx .kdb .kexi .kexic .kexis .lgc .lwx .maf .maq .mar .mas .mav .mdb .mdf .mpd .mrg .mud .mwb .myd .ndf .nnt .nrmlib .ns2 .ns3 .ns4 .nsf .nv .nv2 .nwdb .nyf .odb .oqy .orx .owc .p96 .p97 .pan .pdb .pdm .pnz .qry .qvd .rbf .rctd .rod .rodx .rpd .rsd .sas7bdat .sbf .scx .sdb .sdc .sdf .sis .spq .sql .sqlite .sqlite3 .sqlitedb .te .temx .tmd .tps .trc .trm .udb .udl .usr .v12 .vis .vpd .vvv .wdb .wmdb .wrk
Forced-Part extensions (20), which FUN_140034500 builds into set 0x1400f5e38 from stack strings:
.vdi .vhd .vmdk .pvm .vmem .vmsn .vmsd .nvram .vmx .raw .qcow2 .subvol .bin .vsv .avhd .vmrs .vhdx .avdx .vmcx .iso
Findings
- Part and Spot leave large parts of files in plaintext, so VM disks, archives and databases over 2 MB can often be partly carved without any key.
- The mode, percent and size are stored in the RSA blob and the journal, and the decryptor infers them the same way when no key is available.
Cross-references
- Related:
05-cryptography.md,06-file-format-and-journal.md,07-string-obfuscation.md