Overview

This post documents a full analysis of LockBit 5.0 for Linux (internally labeled LINUX Locker v1.01, Linux amd64), a ransomware sample that demonstrates several sophisticated design choices: strace evasion, offline-capable encryption, ChaCha20 with Curve25519 key exchange, and aggressive free space wiping. All testing was conducted in an isolated VirtualBox VM with network access intentionally controlled.

Disclaimer: This analysis was conducted in a controlled, isolated environment for educational and defensive security research purposes only.


Lab Setup

  • Platform: VirtualBox VM running REMnux (Ubuntu-based malware analysis distro)
  • Network: Host-Only adapter (192.168.56.x) — internet unreachable, confirmed via ping 8.8.8.8
  • Sample: bitlock.elf (LockBit 5.0 Linux)
  • Tools: snoop-bfcc (eBPF), Ghidra, Wireshark, xxd, ss

Stage 1: Dynamic Analysis with eBPF (snoop-bfcc)

The first challenge: LockBit actively detects and blocks strace. Classic ptrace-based monitoring fails silently. The solution was snoop-bfcc, an eBPF-based file access tracer that operates entirely in kernel space, bypassing ptrace detection.

sudo /usr/share/bcc/tools/opensnoop -p $(pgrep bitlock)

The full captured file access trace (bitlock.elf entries only):

PID    COMM          FD   ERR PATH
2486   bitlock.elf    3   0   /etc/ld.so.cache
2486   bitlock.elf    3   0   /lib/x86_64-linux-gnu/libpthread.so.0
2486   bitlock.elf    3   0   /lib/x86_64-linux-gnu/libc.so.6
2486   bitlock.elf    3   0   /lib/x86_64-linux-gnu/libgcc_s.so.1
2486   bitlock.elf    3   0   /proc/self/status
2486   bitlock.elf    3   0   /proc/2192/comm
2486   bitlock.elf    3   0   /proc/2192/cmdline
2486   bitlock.elf    3   0   /proc/ioports
2486   bitlock.elf    3   0   /proc/self/maps
2486   bitlock.elf    3   0   /dev/urandom
2486   bitlock.elf    4   0   /sys/devices/system/cpu/online
2486   bitlock.elf    4   0   /home/remnux/Desktop/bait/ReadMeForDecrypt.txt
2486   bitlock.elf    4   0   /home/remnux/Desktop/bait/
2486   bitlock.elf    5   0   /home/remnux/Desktop/bait/password_bait.txt.840d22e34b8e1f9e
2486   bitlock.elf    4   0   /home/remnux/Desktop/bait/private_bait.txt.5c2a3df8b0bd0d8e
2486   bitlock.elf    4   0   /proc/mounts
2486   bitlock.elf   -1  13   /tmp.qrdmymsfzm                          (FAILED: EACCES)
2486   bitlock.elf   -1  30   /snap/bare/5/tmp.wqmkyxfjtf              (FAILED: EROFS)
2486   bitlock.elf   -1  30   /snap/core24/1587/tmp.hxncvjbhyr         (FAILED: EROFS)
2486   bitlock.elf   -1  30   /snap/firefox/8107/tmp.exorcezyms        (FAILED: EROFS)
2486   bitlock.elf   -1  30   /snap/mesa-2404/1165/tmp.xihvdzquht      (FAILED: EROFS)
2486   bitlock.elf   -1  30   /snap/snapd/26865/tmp.gyitwspvtj         (FAILED: EROFS)

Breaking this down into execution phases:

Phase 1 — Library Initialization

/etc/ld.so.cache
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libgcc_s.so.1

Standard C runtime loading. The presence of libpthread confirms multi-threaded execution — relevant for the parallel encryption later.

Phase 2 — Reconnaissance & Anti-Analysis

/proc/self/status      (TracerPid check — likely strace detection)
/proc/2192/comm        (process name enumeration)
/proc/2192/cmdline     (process command line inspection)
/proc/ioports          (hardware I/O mapping — VM detection)
/proc/self/maps        (own memory layout inspection)

This is deliberate anti-analysis behavior. Reading /proc/self/status is a known technique to check TracerPid — if non-zero, a debugger is attached. This is the most likely mechanism behind the observed strace blocking, though the exact code path was not directly confirmed in Ghidra. /proc/ioports is a classic VM fingerprinting method.

Phase 3 — Key Generation & CPU Profiling

/dev/urandom                          (entropy source)
/sys/devices/system/cpu/online        (CPU core count)

This is the transition point from reconnaissance to encryption. /dev/urandom supplies cryptographic entropy for the ChaCha20 key. The CPU core count directly determines the thread pool size for parallel file encryption.

Phase 4 — Encryption & Ransom Note

/home/remnux/Desktop/bait/ReadMeForDecrypt.txt  (ransom note written)
/home/remnux/Desktop/bait/
/home/remnux/Desktop/bait/password_bait.txt.840d22e34b8e1f9e
/home/remnux/Desktop/bait/private_bait.txt.5c2a3df8b0bd0d8e

Files receive unique per-victim extension identifiers (840d22e34b8e1f9e, 5c2a3df8b0bd0d8e). These are not random — they encode victim identification data used for key retrieval after ransom payment.

Phase 5 — Filesystem Expansion & Wipe

/proc/mounts                         (discover all mount points)
/tmp.qrdmymsfzm                      (FAILED: EACCES)
/snap/*/tmp.*                        (FAILED: EROFS — read-only filesystem)

LockBit attempts to expand encryption to all mounted filesystems. The failures on /snap/* are due to read-only snap squashfs mounts. The randomized temp filenames (qrdmymsfzm, wqmkyxfjtf) are runtime-generated for forensic evasion.


Stage 2: Static Analysis with Ghidra

Entry Point

The binary’s entry() function follows the standard __libc_start_main pattern, confirming a C-compiled binary (not pure assembly). The actual main() is located at FUN_00401d50.

void entry() {
    thunk_FUN_00400ea6(FUN_00401d50, param_2, &stack0x...);
    do { /* WARNING: Do nothing block */ } while(true);
}

Argument Parsing (FUN_00401d50)

Running the binary with -h reveals the full CLI — a remarkably feature-complete ransomware interface:

LockBit 5.0 help menu showing full CLI options

The main function implements a full argument parser consistent with this CLI. Notable flags:

  • -r <10-90> — Partial encryption: only encrypts a percentage of each file. Speed optimization that still renders files unrecoverable.
  • -k — Disables self-destruct. Binary deletes itself by default after execution.
  • -w — Enables free space wiping to prevent forensic recovery of deleted files.
  • -q — Quiet mode: no extension changes, no ransom notes. Stealth deployment option.

ChaCha20 Identification

The most significant static finding is the ChaCha20 sigma constant at DAT_0065e2d0:

_DAT_0065e2d0 = 0x3320646e61707865;  // "expand 32-by"
_DAT_0065e2d8 = 0x6b20657479622d32;  // "te k"

Combined: "expand 32-byte k" — the canonical ChaCha20/Salsa20 initialization constant. This is a definitive identification marker.

Ghidra decompiler showing ChaCha20 sigma constant at DAT_0065e2d0

The function FUN_00452790 performs the ChaCha20 state initialization, byte-packing the constant via MOVZX + shift + OR sequences — the standard little-endian state setup.

Key Material Structure

At LAB_00405640, the encryption config struct is populated:

*(undefined8 *)pcVar20          = local_438;   // ChaCha20 key material
*(ulong *)(pcVar20 + 0x08)      = uStack_430;
*(undefined8 *)(pcVar20 + 0x10) = local_428;
*(undefined8 *)(pcVar20 + 0x18) = uStack_420;

This 32-byte structure is the ChaCha20 key, derived from /dev/urandom entropy.

Encrypted String Table

A large data region beginning at DAT_00459490 contains an encrypted string table — the ransom note template and configuration strings stored obfuscated in the binary. The runtime decryption routine (FUN_0043aad0) resolves these at execution time, making static string analysis unreliable.


Stage 3: Encrypted File Structure

xxd bait/password_bait.txt.840d22e34b8e1f9e | head -20

xxd output of encrypted file showing header structure

00000000: 2241 f5e6 562e 3b72 7712 69af 98ad 307e  "A..V.;rw.i...0~
00000010: 7cb8 d328 1baa d817 0000 0000 0000 00e8  |..(............
00000020: 4d32 185f ab67 9a00 0000 0000 0000 0000  M2._.g..........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
[zeros...]
00000080: bc49 7a64 ee0f b9f3 bd99 f3c4 c3a2 f9f2  .Izd............

Inferred header structure:

[0x00 - 0x17]  24 bytes  → Nonce / IV
[0x18 - 0x2F]  24 bytes  → Curve25519-encrypted key blob
[0x30 - 0x7F]  Padding / metadata (mostly zeros)
[0x80+]        Encrypted file content

Note: Header structure is inferred from known LockBit behavior and file layout analysis. The 24-byte nonce field suggests XChaCha20 rather than standard ChaCha20 (which uses a 12-byte nonce). Full cryptographic confirmation would require memory forensics or source-level analysis.

The Curve25519 public key is hardcoded in the binary, enabling offline encryption — the per-file key is wrapped with the attacker’s Curve25519 public key and embedded in the file header. Decryption requires the Curve25519 private key held exclusively by LockBit operators.


Stage 4: Network Behavior Analysis

This is the most operationally significant finding of the analysis.

Test Configuration

  • Network adapter: VirtualBox Host-Only (192.168.56.101/24)
  • Internet connectivity: None (ping 8.8.8.8Network is unreachable)
  • Monitoring: Wireshark (all interfaces), watch -n 0.1 'ss -tnp', ifconfig counters

Results

Monitor Result
Wireshark 0 packets captured
ss socket monitor 0 connections established
ifconfig TX delta 0 bytes from bitlock.elf

LockBit 5.0 generated zero network traffic during the entire encryption process.

Implications

This confirms a fully offline-first design:

  1. Curve25519 public key is hardcoded in the binary — no network key exchange required
  2. ChaCha20 key generated locally via /dev/urandom
  3. Wrapped key stored in encrypted file header
  4. C2 communication, if any, occurs via a separate dropper component

Defensive implication: Network-based detection is ineffective against this variant. Encryption completes entirely offline before any C2 contact would occur.


Stage 5: Ransom Note

~~~ You have been attacked by LockBit 5.0 - the fastest, most stable
and immortal ransomware since 2019 ~~~~

>>>>> You must pay us.

Tor Browser link where the stolen information will be published:
http://lockbitapt67g6rwzjbcxnww5efpg4qok6vpfet[...].onion

The note claims double extortion — data exfiltration in addition to encryption. In our isolated test environment, no exfiltration was possible. This capability likely requires a separate dropper or network-connected deployment.


Sample Information

Field Value
SHA256 4dc06ecee904b9165fa699b026045c1b6408cc7061df3d2a7bc2b7b4f0879f4d
MD5 ca93d47bcc55e2e1bd4a679afc8e2e25
File name LockBit_LINUX_AMD64
File size 385,634 bytes
First seen 2025-09-20
Vendor detections 6/13 (MalwareBazaar)
Source MalwareBazaar

IOCs

Type Value
SHA256 4dc06ecee904b9165fa699b026045c1b6408cc7061df3d2a7bc2b7b4f0879f4d
MD5 ca93d47bcc55e2e1bd4a679afc8e2e25
File extension pattern .{16-char hex} (e.g. .840d22e34b8e1f9e)
Ransom note filename ReadMeForDecrypt.txt
Tor domain lockbitapt67g6rwzjbcxnww5efpg4qok6vpfet[...].onion
ChaCha20 constant 0x3320646e61707865 / 0x6b20657479622d32
Encryption algorithm ChaCha20/XChaCha20 + Curve25519 key exchange
Anti-analysis (empirical) strace blocking — mechanism inferred via /proc/self/status TracerPid
VM detection /proc/ioports enumeration

Key Findings Summary

Finding Detail
Malware family LockBit 5.0, LINUX Locker v1.01
Architecture x86-64 ELF, C-compiled, multi-threaded
Encryption ChaCha20/XChaCha20 + Curve25519 key exchange
Key storage Per-file key embedded in encrypted file header
Anti-analysis strace detection, VM fingerprinting via /proc/ioports
Network activity Zero — fully offline capable
Partial encryption Configurable via -r flag (10-90% per file)
Self-destruct Enabled by default, disabled with -k
Free space wipe -w flag — prevents forensic file recovery
Double extortion Claimed in ransom note
Decryptability Impossible without LockBit operator Curve25519 private key

Detection Opportunities

Since network detection is ineffective, defenders should focus on endpoint-level signals:

  1. File rename bursts — Rapid file renames with 16-char hex extensions in short timeframes
  2. /proc enumeration pattern — Sequential reads of /proc/[pid]/comm across multiple PIDs
  3. /dev/urandom + /sys/.../cpu/online sequence — This specific combination is a strong behavioral indicator
  4. ReadMeForDecrypt.txt creation — Filesystem IOC, straightforward to alert on
  5. Temp file writes to mount roots — Large sequential writes to /, /snap/* with random filenames

Tools Used

Tool Purpose
snoop-bfcc (eBPF) File access tracing — bypasses strace detection
Ghidra Static reverse engineering
Wireshark Network traffic capture
xxd Binary file inspection
ss / ifconfig Socket and interface monitoring
MalwareBazaar Sample identification and vendor intelligence

Conclusion

LockBit 5.0 Linux is a mature, operationally-focused ransomware. Its most defining characteristic is a zero-dependency encryption model: no network connectivity, no C2 handshake, no external key material required. The Curve25519 public key is embedded in the binary, ChaCha20 keys are generated and wrapped locally, and the entire encryption pipeline completes before any external communication would occur.

The strace evasion required a pivot to eBPF-based monitoring, which proved significantly more effective. The combination of behavioral tracing, ChaCha20 constant identification in Ghidra, and triple-confirmed zero network activity provides a complete picture of the malware’s operation.

For defenders, the conclusion is clear: endpoint-level behavioral detection is the only reliable layer against a ransomware engineered to operate entirely offline.


Open Questions

The following findings warrant further investigation:

  • IPv6 string presence: MalwareBazaar YARA matched linux_generic_ipv6_catcher, indicating an IPv6-format string in the binary. No corresponding network activity was observed. This likely references a hardcoded Tor relay or C2 endpoint within the encrypted string table at DAT_00459490. Decoding this table would be the natural next step.
  • XChaCha20 vs ChaCha20: The 24-byte nonce field in the encrypted header suggests XChaCha20. Confirming this via memory forensics during active encryption would close this open question.
  • Exfiltration component: The ransom note claims data theft. No exfiltration was observed in this isolated test. A networked execution with full traffic capture would determine whether this is a genuine capability or a bluff.