Static analysis: Windows API calls behind each behaviour
Method: Ghidra cross-references to each imported function, 49 behaviour-relevant imports
(get_bulk_xrefs). Each call site was mapped to its containing function from the function list,
and the key ones were confirmed with get_function_callers and decompiles. Raw data:
artifacts/ghidra/api_callsites.json. All imports are called directly through the IAT; the binary
does not resolve APIs dynamically (the only GetProcAddress / LoadLibraryExW callers are CRT
and STL helpers).
Behaviour → API → call site
| Behaviour | API (DLL) | Call site → function | Notes |
|---|---|---|---|
| Read operator arguments | GetCommandLineW, CommandLineToArgvW (kernel32, shell32) |
0x14004cb62, 0x14004cb72 → main FUN_14004ca40 |
argv goes to the argh-style parser FUN_140053d70 |
| Size thread pools | GetSystemInfo |
0x14004d549 → main |
CPU count → 30% root parsers / 10% folder parsers / rest encryptors |
| Drive sweep | GetLogicalDriveStringsW |
0x140076786 → FUN_1400766e0 |
first five drive letters only |
GetDriveTypeW |
0x140076827 → FUN_1400766e0; 0x140042d07 → FUN_140042c50; 0x140042b14 → FUN_140042ae0 |
skip CD-ROM / no-root; classify each root | |
| Network share discovery | WNetGetConnectionW (mpr) |
0x140042a97 → FUN_1400429f0; 0x140042bb7 → FUN_140042ae0 |
mapped drive → “network disk” |
PathIsNetworkPathW (shlwapi) |
0x1400433a9 → FUN_140042c50 |
UNC → “network path” | |
| Folder walk | FindFirstFileExW, FindNextFileW, FindFirstFileW, GetFileInformationByHandleEx |
0x140078a1b / 0x14007899c / 0x140078b1a / 0x140078c11 → STL std::filesystem iterator helpers FUN_1400789d8, FUN_140078998, FUN_140078a4c |
used by the folder parser FUN_1400b81d0 (via FUN_14006e720) |
| Protected-process snapshot | WTSEnumerateProcessesW, WTSFreeMemory (wtsapi32) |
0x140070c79, 0x140070df5 → FUN_140070c30 |
PIDs of 20 system process names |
| Unlock files by killing their owners | RmStartSession (rstrtmgr) |
0x140070eb3 → FUN_140070e30 |
|
RmRegisterResources |
0x140070eef → FUN_140070e30 |
the locked file | |
RmGetList |
0x140070f2d, 0x140070f9a → FUN_140070e30 |
size query, then the list | |
RmShutdown |
0x140071024 → FUN_140070e30 |
RmForceShutdown, unless a holder is self or protected |
|
RmEndSession |
0x1400710be, 0x14007115f, 0x1400711c3 → FUN_140070e30 |
||
| Shadow-copy deletion via WMI | CoInitializeEx (ole32) |
0x140071d8d → FUN_140071d80 |
caller decodes the PowerShell command |
CoCreateInstance |
0x14007167d → FUN_140071620 |
CLSID/IID at 0x1400c7558 / 0x1400c7568, then ConnectServer("ROOT\CIMV2") (vtable +0x18) |
|
CoSetProxyBlanket |
0x140071704 → FUN_140071620 |
authn 10 (WINNT), level 3 (CALL), impersonation 3 (IMPERSONATE) | |
SysAllocString ×7, VariantInit ×6, VariantClear ×6 (oleaut32) |
0x140071692–0x140071c90 → FUN_140071620 |
GetObject("Win32_Process"), GetMethod("Create"), Win32_ProcessStartup instance with CreateFlags = 0 (VT_I4) and ShowWindow = 0 (VT_UI1, SW_HIDE); in-params CommandLine and ProcessStartupInformation; ExecMethod (vtable +0xC0); reads ReturnValue and ProcessId, the latter cast to short |
|
OpenProcess, WaitForSingleObject |
0x140071f50, 0x140071f66 → FUN_140071d80 |
SYNCHRONIZE on the returned PID, 15 s wait (PID truncated to 16 bits) | |
| Key-generation seed (the weakness) | QueryPerformanceCounter |
0x140078ddd → FUN_140078dd4 (steady-clock wrapper) |
callers: FUN_14007b1f0 (per-value Yarrow seed), FUN_14007bbe0 (RSA padding Yarrow), FUN_1400ae840, main (timing). The only other QPC call is the CRT’s __security_init_cookie |
QueryPerformanceFrequency |
0x140078e05 → FUN_140078df0 |
converts ticks to the ns string (QPC × 100 at 10 MHz) |
|
| Open target / clear read-only | GetFileAttributesW, SetFileAttributesW |
0x1400aeea7, 0x1400aeeca → FUN_1400ae840 |
if FILE_ATTRIBUTE_READONLY is set, writes back attrs ^ 1 (decompile lines 271–277) |
CreateFileW |
0x1400aef07, 0x1400aef5f → FUN_1400ae840 |
first: 0xC0010000 (GENERIC_READ|WRITE|DELETE), OPEN_EXISTING, FILE_FLAG_OVERLAPPED\|NORMAL. On error 0x20/0x21 (sharing/lock violation): FUN_140070e30 (Restart Manager), then a retry with GENERIC_READ|WRITE, share R/W |
|
GetFileSizeEx |
0x1400af41e → FUN_1400ae840 |
drives the mode choice (> 2,000,000 B = Part) | |
| Journal | CreateFileW |
0x1400adc3f → FUN_1400adb00 |
<name>.arika, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED |
| In-place encryption I/O | ReadFile / WriteFile (overlapped) |
0x140040993 → FUN_1400407e0; 0x14004075d → FUN_1400405b0 |
asio random-access-file wrappers, reached from the async helpers FUN_14003f880 / FUN_1400397a0 |
CreateIoCompletionPort, GetQueuedCompletionStatus, PostQueuedCompletionStatus |
0x140040471, 0x14003866f; 0x140038ac6, 0x1400390fc; 0x140038c3a… |
asio IOCP scheduler (FUN_1400385d0, FUN_140038900, FUN_140038e60) |
|
Rename to .akira |
SetFileInformationByHandle (FileRenameInfo) |
0x1400b1deb → FUN_1400ae840 |
breakpoint on this confirmed each finished file |
| Delete journal | DeleteFileW |
0x1400b1f02 → FUN_1400ae840 |
|
| Ransom note / log | CreateFileW, WriteFile via CRT _wsopen / std::ofstream |
0x1400aaa52… → FUN_1400aa94c (_sopen_nolock) |
note writer FUN_140042420; logger FUN_14004c6f0 |
Not malicious, but flagged by scanners
| API | Where | What it really is |
|—|—|—|
| TerminateThread | 0x1400365e0 → FUN_140036580 | asio win_thread::join: waits for the thread, then TerminateThread only when the global terminate flag is set, otherwise QueueUserAPC + wait. Library teardown, not process killing |
| IsDebuggerPresent | 0x140085c84, 0x14008c80d | CRT fail-fast / __acrt_call_reportfault; no anti-debug |
| WSAStartup | 5 static initializers (FUN_140001830 …) | asio’s winsock init object; no socket is ever created |
| GetCurrentProcessId | logger and CRT | log formatting; Restart Manager compares holders to the own PID |
Findings
- The destructive chain is short and fully direct-imported:
WTSEnumerateProcessesW;- the
CoCreateInstance→Win32_Process.Createsequence (shadow copies); RmShutdown(lock holders);CreateFileW/ overlappedReadFile/WriteFile;SetFileInformationByHandle(rename). These are good API-sequence hunting anchors.
QueryPerformanceCounterfeeding Yarrow is the single root cause of key recoverability.FUN_14007b1f0reaches it throughFUN_140078dd4with no other entropy source.
Cross-references
- Related:
08-function-map.md,05-cryptography.md,05-detections/01-detections.md