SANS Digital Forensics and Incident Response Blog

An anti-forensics dd primer

dd is the swiss army knife of file tools - with /dev/tcp it can also be a network tool (but nc is simpler).

First we need the basics for dd. For this we have the man page and some definitions. I have taken (blatantly paraphrased) the man file info for dd and included this below (which is simple to obtain - "man dd").

For the purpose of a task such as reversing files and swapping them, we need to concentrate on the following options:

  • bs - This is block size. Setting "bs=1" means that we can use dd as a bit level (instead of a block level tool). Although it does slow down the process from a block copy, we are not looking at how fast we can copy here.
  • skip - this tells us to skip "n" blocks. In our case, we want "n" bits.

What we are going to do is start at the value of "n" set to our last bit in the file. We will loop the dd function to next copy bit "n - 1", then "n - 2", ... to "n=1". This means n gets copied to bit 1, "n - 1" to bit 2, ..., bit 1 to bit n.

In other words we need to copy bit "n - i" in the source file to bit "i - n" in the destination file.

How to reverse a file with dd

Reversing a file is actually fairly simple, a small shell script code executed in with the length of the file (based on the sector size) is all that is required. You can either use a default block size (where the individual blocks will be moved into a reverse order), or set the block size to 1 in order to completely reverse the file. The flag, "bs=1" is added in order to copy the entire file in reverse - bit by bit.

If the size of the file and its name are known beforehand, the script is particularly simple (note that this script uses the 'count' command, which is not found on all systems, you may try seq instead):

$j = [file_size]
$F=[file to copy]
for i in `count 0 $j`; do
dd conv=noerror bs=1 count=1 skip=($i) if=$F > /($j).out


In the event that you do not know the size of the file, the following script can be used (or if you want to incorporate this in to a script that changes multiple files at once) you need to feed more information into the script (including a file descriptor). This script is a little messy (I have not made any effort to tidy it up), but does the trick.

#! /bin/bash
# This is a small utility script that will reverse the
# file that a user inputs
# It is not coded securely and presumes the directory for a
# number of command - change
# this to run it in a real environment. The main thing is
# a proof of concept anti-forensic tool.
# This script by reversing files will make the file
# undetectable as a type of file by commercial
# file checkers. Run it in reverse to get the original back.
# Author: Craig S Wright

#Set the file to reverse
echo "Enter the name (and path if necessary) of the file you want to reverse:"; read FILE

#i Work out the file size
SIZE_OF_FILE=`/bin/ls -l $FILE | awk '{print $5}'`

#The script - not pretty - but the idea was all I was
# aiming at

K=`expr $SIZE_OF_FILE - $i`

/bin/dd conv=noerror bs=1 skip=$K if=$FILE count=1 > $FILE.out
i=`expr $i + 1`

J_Plus=`expr $SIZE_OF_FILE + 1`

while [ "$i" != "$J_Plus" ] do
K=`expr $SIZE_OF_FILE - $i`
/bin/dd conv=noerror bs=1 skip=$K if=$FILE count=1 >> $FILE.out
i=`expr $i + 1`


To go a little further and add some options, I have included the following example. I have NOT added input checking or other NECESSARY security controls. This is a quick and nasty only. Please fix the paths and input checking if you want to run it.

The following script is called

#! /bin/bash
# Set the file to reverse - I DO NOT check if the file
# actually exists - you should!
echo "Enter the name (and path if necessary) of the file you want to reverse:"; read FILE

# Default File output = FILE.out

# Set the file where the reversed file is to be saved - I DO
# NOT check if the file actually exists - you should!

echo "Enter the name (and path if necessary) of the file you want the output saved as (must be different to the input):"; read $FILE_OUT

#Set the Block Size. This will default to BS=1 for dd
echo "Enter the Block Size (the default = 1 bit):"; read BS_SIZE

# Work out the file size
SIZE_OF_FILE=`/bin/ls -l $FILE | awk '{print $5}'`


#The script - not pretty - but the idea was all I was
# aiming at

K=`expr $SIZE_OF_FILE - $i`

/bin/dd conv=noerror bs=$BS_SIZE skip=$K if=$FILE count=1 > $FILE_OUT

i=`expr $i + 1`

J_Plus=`expr $SIZE_OF_FILE + 1`

while [ "$i" != "$J_Plus" ] do
K=`expr $SIZE_OF_FILE - $i`
/bin/dd conv=noerror bs=$BS_SIZE skip=$K if=$FILE count=1 >> $FILE_OUT
i=`expr $i + 1`

# The end...


To use the previous script enter:

$ ./

Enter the name of the file you want to reverse and the block size (best left at 1 bit). This will return the bitwise reversed file. If you want to verify it - run it twice and use "diff" to validate that the same file is returned. This will reverse the reverse and get the original back.

This works on text and binary files and with a little tweeking, you can reverse headers but leave the body the same, reverse the body after skipping the file header and many more options.

I am yet to find a forensic tool that will find reversed text if you are not looking for it. Also, this is a simple way of passing tools when an IDS/IPS is in use. The reversed files are not found in default scans. This has been tested with several of the leading IDS products. In all cases, it was possible to sent tools without setting an alert.

With time and practice, you can create a loader script that will take the reversed file and execute it directly into memory. This leaves no copy of the original file to be uncovered with a Host based IDS.

The script example above has the file output written without checking if a file exists. The following is an example of how you can add a small amount of script to verify that you are not overwriting an existing file:

if [ -f $FILE ] then
echo "The file [$FILE] that you are seeking write already exists"
echo "Do you want to overwrite the existing file? ( y/n ) : \c"
if [ "$RESPONSE" = "n" ] || [ "$RESPONSE" = "N" ] then
echo "The file will not be overwritten and the process will abort!"


It is also a good idea to use the full path in a script. Users can change the path variables they are exposed to and unless you set these (either explicitly or by adding a profile for the script to use) an attacker could use a system script to run their own binary.

The key to successfully testing a system and validating the security state of that system is to think outside the box. For instance, there are several reasons why you would want to reverse a file for testing:

  1. Attackers could do this to bypass filters, controls and other protections
  2. Anti-forensics, finding the needle in a haystack is difficult - esp. when the tools do not help
  3. Pen Testing - just as in point 1 for attackers, the tester can use this to load tools without being detected by filters or through malware detection engines

Once a file has bypassed the perimeter controls, getting it to work inside an organization is simple. Hence a means to bypass controls is of interest to those on the attack side of the equation (both validly and less so).

Next, it is a concern to the forensic professional. Hiding files through reversing them makes the process of discovery a proverbial search for the needle in a haystack.

An interesting effect to try is to maintain the header on a bitmap file (i.e. skip the first portion of the file and reverse the later parts). What ends up occurring is that the image can be recreated upside down. All types of interesting effects can be found.

As always, the cards are stacked in favor of the attacker. When in a contest that pits rules against open morality, rules lose more than not. This does not mean that we give up, only that we have to understand the odds that are stacked against us and that it is also the case that people naturally err. This is when we (the "good" guys) win.

For security professionals to be successful, we need to think outside the box.

Craig Wright is a Director with Information Defense in Australia. He holds both the GSE-Malware and GSE-Compliance certifications from GIAC and completed the GSE as well. He is a perpetual student with numerous post graduate degrees including an LLM specializing in international commercial lawand ecommerce law, A Masters Degree in mathematical statistics from Newcastle as well as working on his 4th IT focused Masters degree (Masters in System Development) from Charles Stuart University where he lectures subjects in a Masters degree in digital forensics. He is writing his second doctorate, a PhD on the quantification of information system risk at CSU.


Posted April 14, 2010 at 1:46 PM | Permalink | Reply

David Kovar

Good morning,
You could also just do:
dd if=file1 of=file2 conv=swab
This gets you byte, not bit, swapped data but it would be a bit faster to do.
I had to use this while researching a bi-endian chip and what it might do to the file system.

Posted April 14, 2010 at 3:31 PM | Permalink | Reply


Nice way to evade signature detection.
I imagine that such content scrambling would probably also be done with using an XOR for example.
I noticed that reversing a file like this is a bit time consuming and just had to write a little script that speeds up by just reading the file in memory and then applying a reverse routine.

# reverse a file
use strict;
use warnings;
my $ifile = shift || "./data";
my $ofile = $ifile . ".reversed";
# slurp file
open(IFH,"< $ifile") or die "failed to read [$ifile] [$!]\
undef $/;
my $data = ;
# write file with reversed data
open(OFH,"> $ofile") or die "failed to create [$ofile] [$!]\
print OFH reverse($data);

user@shadowdragon:~/dev$ time ./ data
user@shadowdragon:~/dev$ time ./
0+0 records in
0+0 records out
0 bytes (0 B) copied, 9.018e-06 s, 0.0 kB/s

Posted April 15, 2010 at 7:32 AM | Permalink | Reply


I think bs=1 gives you blocksize of 1 byte, not 1 bit. At least the man page agrees with me on that.

Posted April 15, 2010 at 1:14 PM | Permalink | Reply

Anders Thulin

I got a bit confused by this ''" the reason for reversing the files is not very clear. Searching for reverse text was mentioned somewhere in the middle ''" is that it?
My immediate impression is that it seems quite an expensive operation to reverse the files that are to be searched. Reversing the search pattern seems simpler. And if searcher for further obfuscations (rotated bytes, say, or bit-shifted files) it seems less work to adjust the search pattern accordingly. What am I missing?

Posted April 15, 2010 at 9:57 PM | Permalink | Reply

Craig S Wright

The reason is anti-forensic. The point is that it is simple to change the search item and store this in a manner that will not be detected.
This can be an attacker program or CP. A simple script can be used to run or view the file with no way to use hashes to determine this.
The selection of POSSIBLE obfuscations is an NP problem.
The tools we have are P. This means that it is always possible to hide a file and not be caught if the forensic analyst simply places reliance on his/her tools.
Reversing will also not change the mean entropy on a drive, so many normal stego techniques also fail.

Posted April 20, 2010 at 2:08 PM | Permalink | Reply

John Crout

The script reverses the byte order of a file without considering word size. Perhaps this is consdiered by the dd binary, and the dd binary differs depending on the architecture where it is built. Since the units of "block size" are bytes and files are stored in words, double words, quadruple words and double quadruple words this script doesn't inspire confidence. (This is based on Wikipedia definitions, as common ground:
The man page for dd defines -bs as "block size in bytes". (A disk editor is required to edit data at the bit level). Doesn't the misinterpretation applied here made the subsequent invalid? Even if a subsequent error allows accurate conclusions it seems as though the two errors may nullify any forensic testimony.
dd's ability to control block size allows the tool to be used to change between little endian and big endian file formats, or to fine-tune the process of creating the transferred file as fast as it can copied, by optimizing the amount of data read, before writing that data. When using bs to change the order of data written, form the data read, the order is changed only within the words, not within the entire file. To change the order of the file you'd need to buffer the input stream in order to delay writing the new file until the entire input file was read.
I'd like to hear other comments on this.

Posted April 21, 2010 at 10:07 PM | Permalink | Reply

Craig S Wright

Try running it on a bitmap file. Colors are mixed, but the file remains visible. Now think of the options for block size, ordering etc. The possible ways to rearrange the file is an NP problem.
On-the-fly byte order conversions can be done using conv=swab;
"dd conv=swab if= of="
As a crypto problem, the file is not to hard to reverse engineer to the original if you know what file you need to reverse.
An issue is that you can mix the file up in any combination and redisplay it. With some effort, you could make a relatively fast script to do this in memory.
now think of a binary executable.
This can be rearranged such that the file seems to be a bitmap or other innocuous file. It will not meet NSRL and other bad lists. It can even be stored mixed. A simple script can be run from a shell. This could extract and run the binary data. This would allow an attacker to bypass IDS etc. The file would not even require execute perms.
On top of that you have a poor-mans stego. You can rearrange the data such that it will not be uncovered but yet in an manner that does not change the entropy of the file at all.
If you think about it, using a series of bitmasks, you can also pad and extend a file with dd. Using the swab option you could (with time) swap the first half of the byte in reverse and add the un-reversed second part. Bit-masking the file and using a number of joined operations will allow this.
with bs options:
w ''" 2
b ''" 512 ''
and the conv changes, complete reversing is simple, and more complex operations come as a factor of number theory.
Buffer a bitmask of 01010101 and then 10101010 or whatever you like and you can mix the file more.
Use a series of bitmasks such as:
And you can mix the bytes further.Slower of course as you now have 4 more operations. Mask this with a logical ''AND' and you can select bits at a time.

Posted April 21, 2010 at 10:10 PM | Permalink | Reply

Craig S Wright

As with this being expensive, it is.
The thing is that it is more expensive for the forensic analyst. The person hiding the file need only care about a single file. The analyst needs to test many files.

Posted April 21, 2010 at 10:28 PM | Permalink | Reply

Craig S Wright

Further, change the script as such:
/bin/dd conv=noerror,swab bs=$BS_SIZE skip=$K if=$FILE count=1 > $FILE_OUT
Now you also reverse the byte order and the file.
My point is not to create a fast effective script to do this, but to have people think about the ways that data can be hidden.
If you leave bytes as they are, the character mix in a file and distribution stays the same. That is, statistical analysis of the file does not provide much information as to if there is a hidden message etc.

Posted April 21, 2010 at 10:50 PM | Permalink | Reply

Craig S Wright

Input against a byte:
Output to:
Use a logical AND operator. Add some XORs and you can make a cheap nasty mixer.
Bit mixing

Posted April 21, 2010 at 10:55 PM | Permalink | Reply

Craig S Wright

As for forensic testimony, this is not the point. It is NOT the analyst that is going to be mixing files and reblending them. The attacker/badguy will be the one doing this.
The aim here is not the creation of a better bit mixer, but to get people thinking about what can be done. I have already seen this from one Brazillian group and it is only a matter of time before something such as metasploit starts blending packets it sends..

Posted April 25, 2010 at 4:00 AM | Permalink | Reply

John Smith

I don't see the benefits of this from an anti forensics perspective. If you need to hide a file encrypt it. If you want to hide from simple keyword searching then compress it.