Aller au contenu principal

Command Execution

Once authenticated through the C2 connection, the attacker can send arbitrary shell commands to the target machine. The rootkit executes them and relays the output back over the encrypted connection.

Execution Flow

  1. The authenticated C2 session sends a command (e.g., ls -la /root).
  2. The rootkit decrypts the message (ROT64) and passes it to execute_command().
  3. The command is wrapped as: <command> > /tmp/.wlkom_out 2>&1
  4. It is executed in user-space via call_usermodehelper() with /bin/sh -c.
  5. The rootkit reads the output file /tmp/.wlkom_out from kernel-space.
  6. The output is encrypted with ROT64 and sent back to the C2 server.
C2 Server Kernel Module User Space
│ │ │
│ "ls -la" (encrypted) │ │
├────────────────────────────►│ │
│ │ call_usermodehelper() │
│ ├─────────────────────────────►│
│ │ │
│ │ /bin/sh -c "ls -la │
│ │ > /tmp/.wlkom_out 2>&1" │
│ │ │
│ │ Read /tmp/.wlkom_out │
│ │◄─────────────────────────────┤
│ │ │
│ output (encrypted) │ │
│◄────────────────────────────┤ │

Why call_usermodehelper?

Kernel modules cannot directly execute shell commands or use standard library functions like system(). Instead, call_usermodehelper() is a kernel API that spawns a user-space process from kernel context. The module uses UMH_WAIT_PROC to wait for the command to finish before reading the output.

Output Handling

  • stdout and stderr are both redirected to /tmp/.wlkom_out using > file 2>&1.
  • The kernel reads the output file using filp_open() and kernel_read().
  • The output is capped at 4095 bytes per command.
  • If the command produces no output (e.g., sleep 5, rm file), a generic confirmation message is sent back instead.

Environment

Commands run with a minimal environment:

PATH=/sbin:/bin:/usr/sbin:/usr/bin

This ensures common system binaries are accessible without requiring absolute paths.

Return Code

The raw return value from call_usermodehelper() encodes the exit status in the upper bits. The module extracts the actual exit code by right-shifting by 8: status >> 8. This value is logged but not sent back to the C2 server.