This is the main code, resize.c, reverse.c, xor.c, swap.c, rswap.c will be posted you want to see them. Hope you like... #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h>
Table of Contents ================= 1 Where did the name come from? 2 I want to compile this! 3 HOWTO use fmask 4 principles of the mask programs (HOWTO add your own) 5 How powerful is this?
1 Where did the name come from? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 I want to compile this! ~~~~~~~~~~~~~~~~~~~~~~~~~~
!UNIX ONLY! Just chmod and run compile.sh dummy !UNIX ONLY!
3 HOWTO use fmask ~~~~~~~~~~~~~~~~~~
fmask is simple. You specify the operations you want to perform to the file, in the arguments, and the file itself in the last argument. I've implemented three operations: reverse, swap and xor. The last one is just xor'ing the file with a byte or a passphrase. If it's a three or less digit number, it xors with the bytes value, else it treats it as a string. To pass arguments to those operations you use the : character to separate their name from their arguments. Example use:
./fmask xor:15 example-file
will xor example-file with the byte 0x0F. The output of fmask will be the arguments you need to pass to fmask in order to get the original file back from the new file (fmask will modify example-file, it won't create a new file with the result). In this example, fmask will output:
xor:15 example-file
since xor is an inverse operation of itself. I've written two more programs, reverse and swap, which are generalizations of simpler operations. For reverse, with no arguments it simply reverses a file. If the content of example-file is 123456, with
./fmask reverse example-file
example-file will contain 654321. How can this be generalized? By adding an argument, say x, which shows how many bytes will be treated as a single block. In case of no arguments, x is 1 (note reverse is also an inverse operation of itself). Here's how to visualize this
block 1 block 2 block 2 block 1 +--------+--------+ +--------+--------+ +---+---+---+---+ reverse:2 +---+---+---+---+ | A | B | C | D | =========> | C | D | A | B | +---+---+---+---+ +---+---+---+---+
The last operation, swap, is merely exchanging odd-offset blocks with even blocks for a block of size 1:
ABCDEF becomes BADCFE
for blocks of larger size, it joins them. Suppose the block size is 3:
ABCDEF becomes DAEBFC
Here's a way to visualize this:
block 1 block 2 +------------|------------+ +---+---+---+---+---+---+ | A | B | C | D | E | F | +---+---+---+---+---+---+
block 1 +---+---+---+ | A | B | C | +---+---+---+ \ block 2 join these DA - EB - FC +---+---+---+ / | D | E | F | +---+---+---+
D is picked first (first from block 2). Then A is picked second (first from block 1). E is picked third, and B is picked fourth, et cetera (this is a generalization of the odd/even exchange).
This operation is not the inverse of itself. I have written another program, called rswap (which you don't need to use by yourself; it's useful only for fmask), which is the inverse of swap. Here's an example:
output is rswap:3 example-file. That tells you with the argument 'rswap:3 example-file', fmask will create the original file back from the new file just created.
There's one thing to mention left: padding. Because reverse and swap operate on blocks of arbitrary size, sometimes the block size does not perfectly divide the file size into blocks; when this occurs, fmask will add padding bytes of random values to the end of the file before it calls the operations. As such, you'll also need to crop these random bytes out. That is why fmask also provides the 'resize' operation, which you should not use by yourself because you will lose your data. Here's an illustration of what I'm talking about
Since example-file is only 6 bytes long, 2 bytes must be added in order for 4 to perfectly divide the size of the file. These two random bytes are added. Then reverse is performed. Then comes the time of swap, which has a block size of 5. The file is 8 bytes long, and 2 bytes must be added in order for 5 to perfectly divide the file size. These bytes are added, then swap is performed. Clearly, the reverse operations will have to remove those bytes in every step. The return string of fmask demonstrates this:
rswap:5 resize:8 reverse:4 resize:6 foo
notice the file is resized twice.
4 principles of the mask programs (HOWTO add your own) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1) must have an inverse program 2) must print the number of bytes added to the file in case of padding -- the inverse program must get those bytes to be the last in the file (this will be fixed in the next version of fmask and the program won't have to do this dirty job -- fmask will do it). 3) the last argument argv[argc-1] is the file operating on, passed by fmask. It's handy because of 'file = argv[--argc];'
Here's an example, the simple_xor.c program:
int main(int argc, char **argv) { FILE *fp; fpos_t fpos; int c; // we want 2 arguments, byte to xor and the filename if(argc != 3) return 0; if((fp = fopen(argv[argc - 1], "r+b")) == NULL) return 0; fgetpos(fp, &pos); while((c = getc(fp)) != EOF) { fsetpos(fp, &pos); // go back 1 byte to write the new byte putc(c ^ argv[1][0], fp); fgetpos(fp, &pos); } fclose(fp) puts("0"); // we did not modify the file size; print 0 to indicate // 0 bytes were added to the file. return 0; }
Compile and put the binary in the fmask directory. Run
./fmask simple_xor:A example-file
to XOR example-file bytes with the byte A. If your operation has an inverse different than itself, you must add the alias to the cmds[] struct in fmask.c. swap is one such operation; rswap is its inverse (and swap is the inverse of rswap -- struct works both ways).
5 How powerful is this? ~~~~~~~~~~~~~~~~~~~~~~~~
Really powerful! Or at least the author thinks so. The operations reverse and swap are the only operations you'll probably ever need, but you can add your own, and they don't have to operate on same-sized blocks (for example, their size might be an arithmetic progression or really anything that you have in mind). Here's an example of how well it hides the original content of the file. example-file contains the alphabet and a newline.
Recognize anything? If you run the decryption string returned by fmask you get the original file back again, with the alphabet
Here's another example of adding rc4 functionality using OpenSSLs tools. In this example, I'll show you how to add OpenSSL's blowfish encryption to fmask, without writing any C code. First how to use the openssl(1) utility for blowfish encryption and decryption:
-in (the source file) -out (the encrypted file) -k (password) -d (decrypt)
first argument should be the algorithm we want to use, which is bf (sort for blowfish). There'll be two shell scripts, for encryption and decryption. Here is rc4_enc.sh:
if [ $# -eq 2 ]; then openssl rc4 -in $2 -out "$2.temp" -k $1 mv "$2.temp" $2 echo 0 fi
Notice I print 0 since the algorithm doesn't add any padding to the filesize; after decryption, it'll be back to its original size, and not some padded one. rc4_dec.sh is similar except there's a -d added in the argument list to denote decryption. If you don't want to type the .sh part when you invoke fmask, use symbolic links like so:
ln -s rc4_enc.sh rc4 ln -s rc4_dec.sh rc4_dec
and don't forget to add "rc4" and "rc4_dec" in the cmds struct in fmask.c
Name:
Anonymous2014-05-08 22:15
No comments? This is depressing. Please come down from the heavens and say something about my code Gods of prog.