pcrypt

Antivirus, forensics, intrusion detection, cryptography, etc.
Message
Author
User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#16 Post by rufwoof »

Virus scanners typically identify known virus and search for virus like patterns.

A breached system is a either knowingly or not infected system that could potentially be exploited by hackers. When knowingly infected typically a virus scanner will detect that. Unknown penetrations are a concern as they might be dormant or doing relatively light tasks perhaps to spread further, such as seeking out LAN ports that are open to spread through in a unobserved manner.

Often firewalls protect against inbound traffic but do little to monitor outbound. Once in a virus might request things from outside and its return traffic is more accepted as being valid traffic ... which could be a payload program that the internal program runs from the inside.

Many program providers conveniently publish security risks, typically after they've figured out a patch (but not always and some publish risks even before patches are available). Which are a good source for hackers as they are given pointers of where to look for potential exploits to be applied and on which versions of systems (that might not have been patched in a timely manner).

Having a firewall running on each PC on a LAN is better than not. More so if one or more are Puppy's as that provides potentially easier means to break out (such as firefox running as root with a known vulnerability). As a for-instance, when gcmartin was hereabouts he was shocked at how quickily/easily it was for a total stranger to ask why he was running as root and reveal gcmartin's personal address to him. IIRC scared the pants off him and g subsequently totally revised his setup/security practices.

User avatar
rcrsn51
Posts: 13096
Joined: Tue 05 Sep 2006, 13:50
Location: Stratford, Ontario

#17 Post by rcrsn51 »

Thanks. Can you give an example? How would a breached computer on my network attempt to attack my computer and how would a firewall on my computer stop it?

User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#18 Post by rufwoof »

First post updated for a more recent version and a minor (cosmetic) bug fix.
[size=75]( ͡° ͜ʖ ͡°) :wq[/size]
[url=http://murga-linux.com/puppy/viewtopic.php?p=1028256#1028256][size=75]Fatdog multi-session usb[/url][/size]
[size=75][url=https://hashbang.sh]echo url|sed -e 's/^/(c/' -e 's/$/ hashbang.sh)/'|sh[/url][/size]

User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#19 Post by rufwoof »

As a alternative to using /dev/urandom to source random data, I quite like this ... (set C= ... number of 65535 bytes blocks)

Code: Select all

dd status=none if=/dev/urandom bs=65535 count=$C | pv --bytes | \
 openssl enc -aes-256-ctr \
 -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" \
 -nosalt > randomfile.bin 2>/dev/null
random key encrypted /dev/urandom data :)

Using -nosalt as otherwise (default) the output can contain predictable content (such as 'Salted').

dd using 65536 byte blocks is appropriate when using pipes as the default linux pipe block size is 65536.

Unlike /dev/random, /dev/urandom will not block when it has no more entropy, but instead continues to output pseudo-random data. By combining urandom with encoding of that urandom data using a aes-256 random key, that's close to continuing to be random.
[size=75]( ͡° ͜ʖ ͡°) :wq[/size]
[url=http://murga-linux.com/puppy/viewtopic.php?p=1028256#1028256][size=75]Fatdog multi-session usb[/url][/size]
[size=75][url=https://hashbang.sh]echo url|sed -e 's/^/(c/' -e 's/$/ hashbang.sh)/'|sh[/url][/size]

User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#20 Post by rufwoof »

Here are more recent versions of pcrypt.c, and a wrapper script that prepares the randomfile.bin that contains the random data

pcrypt.c

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

/************************************************************/
/* Rufwoof Jan 2016                                         */
/* 2019 revised to use randomfile.bin as source of random data */

/************************************************************/

int main(int argc,char **argv) {

  struct stat statbuf;
  struct stat statbufkeyfile;
  int key, data, output, ret, percent;
  double count=0, ccnt, pcnt;
  char keyfile[1024], outfile[1024], *point, DOING;
  FILE * mykeyfile, * sourcefile, * destfile, * f;

  if(argc<2) {
     printf("File encrypt/de-encrypt using a key size equal to message (file) size\n");
     printf("For encryption\n");
     printf("  pcrypt non-encrypted-file\n");
     printf("  creates a encrypted file with the same name and a .fck suffix\n");
     printf("  and a associated .key suffix keyfile - that should be kept safe\n\n");
     printf("\nFor de-encryption\n");
     printf("  pcrypt encrypted-file.fck\n");
     printf("  the .key keyfile that was used to encrypt must be in the same directory\n");
     return(0);
  }

  /* Bail out if the wrong number of arguments are used. */
  if(argc>2) {
     printf("Too many arguments.");
     sleep(3);
     return(1);
  }

  /* get the size of the source file */
  if ((sourcefile = fopen(argv[1], "rb")) == NULL) {
      printf("Can't open source file.\n");
      return(4);
  }
  fflush(sourcefile);
  fstat(fileno(sourcefile), &statbuf);
  fclose(sourcefile);

  if ( ! S_ISREG(statbuf.st_mode) ) {
      printf("Not a regular file pcrypt only works on files\n");
      return(6);
  }

  sourcefile=fopen(argv[1],"rb");

  DOING='e'; /* default is to encrypt */
  if ((point = strrchr(argv[1],'.')) != NULL ) {
     if (strcmp(point,".fck") == 0) {
         DOING='d'; /* de-encrypting */
     }
  }
  if ( DOING == 'e' ) {
   if ((f = fopen("randomfile.bin","rb")) == NULL ) { 
      printf("Can't open randomfile.bin\n");
      return(6);
   }
   snprintf(outfile, sizeof outfile, "%s.fck", argv[1]);
   snprintf(keyfile, sizeof keyfile, "%s.key", argv[1]);
   mykeyfile = fopen(keyfile,"wb");
  } else {
   snprintf(outfile, sizeof outfile, "%s", argv[1]);
   outfile[strlen(outfile)-4] = 0;  /* strip of .fck suffix */
   snprintf(keyfile, sizeof keyfile, "%s.key", outfile);
   if ((mykeyfile = fopen(keyfile,"rb")) == NULL ) {
      printf("Can't open key file.\n");
      return(5);
   }
   /* check keyfile and .fck file sizes are the same i.e. look like valid partners */
   fflush(mykeyfile);
   fstat(fileno(mykeyfile), &statbufkeyfile);
   fclose(mykeyfile);
   if ( statbufkeyfile.st_size != statbuf.st_size ) {
      printf("key file and .fck filesize differ\nperhaps corrupt or incorrect pairing\nprogram halting\n");
      return(5);
   }
   mykeyfile=fopen(keyfile,"rb");
  }
  destfile=fopen(outfile,"wb");
  /* f = fopen("/dev/urandom", "rb"); Dec 2019 */
  pcnt=statbuf.st_size/100;
  ccnt=1;
  percent=0;
  printf("0%%");
  fflush(stdout);
  /* Use the key to encrypt/decrypt the source file. */
  while (count < (statbuf.st_size)) {
     if ( DOING == 'd' ) {
         key=fgetc(mykeyfile);         /* decrypting */
     } else {
        key=fgetc(f);
        fprintf(mykeyfile,"%c",key);  /* store to .KEY file */
     }
     /* progress indicator */
     ccnt++;
     if ( ccnt > pcnt ) {
        ccnt=1;
        percent++;
        if ( percent > 100 ) {
           percent=100;
        }
        printf("\r%i%%",percent);
        fflush(stdout); /* have to flush otherwise not shown (unless a \n included) */
     }
     data=fgetc(sourcefile);
     output=(key^data);
     /* XOR the data byte once with a byte from a key and it encrypts. */
     /* XOR the resultant byte again with the same byte from the same key, and it decrypts. */
     fputc(output,destfile);
     count++;
  }
  printf("\rDone\n");
  /* update to the same uid/gid as the source file */
  fchown(fileno(destfile),statbuf.st_uid,statbuf.st_gid);
  /* update the permissions */
  fchmod(fileno(destfile),statbuf.st_mode);
  if ( DOING == 'e' ) {
     fclose(f);
  }
  fclose(mykeyfile);
  fclose(sourcefile);
  fclose(destfile);
  if ( DOING == 'd' ) {  /* remove input file(s) */
   ret=remove(keyfile);
  }
  ret=remove(argv[1]);
}
Wrapper script

Code: Select all

#!/bin/ash

# Rufwoof Dec 2019

# crypt shell script, encrypts (and decrypts when a .fck file suffix)
# Intended to be run in ram+encrypted swap (so no hdd footprints left)
# Master/Main (wrapper) script that calls pcrypt C program binary.
# On encryption creates a .fck and a .key files. No password needs to
# be remembered, simply bringing the two files back together again and
# running crypt against the .fck file - restores the clear text file.
# Individually both .fck and .key files are useless without the other
# so when stored separately they are secure (cannot be cracked).


if [ -z $1 ]; then
	echo " "
	echo "Usage : $0 <filename>"
	echo "if filename has a .fck suffix then decrypts"
	echo " "
	echo "Future proof One-Time-Pad style encryption"
	echo " "
	echo "We use /dev/urandom for random data which unlike /dev/random will not block"
	echo "if entropy is exhausted, but instead fall back to strong pseudo-random data"
	echo "when real random data is exhausted. As one-time-pad encryption requires a"
	echo "'key' the same size or larger than the file being encrypted, and hence"
	echo "entropy may be being exhausted (pseudo random data being produced by"
	echo "urandom) we further encrypt the urandom data using a aes-256-ctr random key."
	echo " "
	echo "Encryption should be performed totally in ram (or ram + encrypted swap) so"
	echo "not to leave any remnants (such as might be recovered from hdd). Even with"
	echo "unlimited resources, brute forcing one-time-pads will yield multiple"
	echo "potential solutions, but where the precise solution cannot be identified"
	echo "(mathematically impossible to crack/remains unknown)."
	echo " "
	exit
fi

if [ ! -f $1 ]; then
	echo "File $1 not found"
	exit
fi

# Inspect file extension
filename=$(basename "$1")
ext="${filename##*.}"

if [ "$ext" = "fck" ]; then
	# decrypt
	pcrypt $1
else
	# encrypt
	
	# generate random byte stream equal or longer than the file to be encrypted
	
	FILESIZE=$(stat -c%s "$1")
	C=`expr $FILESIZE / 65536` # we use a 65535 byte blocksize for dd (faster and matches linux pipe 65536 byte blocksize)
	C=`expr $C + 1`            # pad out (otherwise rounding will make it too short)
	O=`expr $C \* 65536`
	echo "Generating ${O} bytes of random key encrypted /dev/urandom data ..."
	# What we're doing next is using /dev/urandom as a source of random
	# bytes, writing those to randomfile.bin, but where we aes-256-ctr
	# encrypt those bytes using a random generated key, so even
	# if the /dev/urandom source of bytes was /dev/zero instead, it would
	# still be 'random' data being written to randomfile.bin.
	# dd with status=none is used to supress output of information
	# We size randomfile.bin content to be marginally larger than the
	# number of bytes required to one-time-pad. We use a 65536 byte block
	# size for the dd as that matches Linux pipe buffer size (faster).
	dd status=none if=/dev/urandom bs=65536 count=$C | pv --bytes | \
	openssl enc -aes-256-ctr \
	-pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" \
	-nosalt > randomfile.bin 2>/dev/null
	# -nosalt is used as otherwise 'salted' occurs in the random sequence
	echo "Encrypting ..."
	pcrypt $1
	rm randomfile.bin	# being (or rather should be running) in ram,
				# simple removal suffices (hdd would require shred)
fi
Note that I'm running OpenSSL 1.1.1d
[size=75]( ͡° ͜ʖ ͡°) :wq[/size]
[url=http://murga-linux.com/puppy/viewtopic.php?p=1028256#1028256][size=75]Fatdog multi-session usb[/url][/size]
[size=75][url=https://hashbang.sh]echo url|sed -e 's/^/(c/' -e 's/$/ hashbang.sh)/'|sh[/url][/size]

User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#21 Post by rufwoof »

Here's a newer script that I name 'vc' (One Time Pad is another name for Vernam Cipher).

The script produces .vc and .vk files, and you decrypt again by running the vc script against the .vc file. No matter what the clear text file, both .vc and .vk are random (high entropy/cannot be compressed), such that the clear text remains hidden (frequency and/or shift xoring analysis wont reveal any detail).

Handy in that no passwords have to be remembered, when separated the content is secure, only by bringing both the .vc and .vk files back together again can the clear text content to revealed. Store one on a server, another on your laptop, and if either the laptop or server are cracked then the content is safe. Nor will faster/more powerful systems in the future be able to brute force the content either (future proof).

Note that both .vc and .vk are interchangeable, both are in effect the key to the other, so it doesn't matter which you might store on a server/elsewhere. Storing say the key file .vk on a remote ssh server, and storing the .vc locally, you might boot, sshfs mount the ssh server (where the .vk file(s) is (are) stored) and then drag/drop (or whatever) move the .vk file to be alongside (same folder) as the .vk file, and then open the content (run the vc script). Moving the .vk file will remove it off the server. Later you might encrypt the file again, and move the (newer) .vk file back to the server.

Code: Select all

#!/bin/ash

# Rufwoof Dec 2019
#
# Requires xor (C program binary)


if [ -z $1 ]; then
	echo
	echo "Usage : $0 <filename>"
	echo
	echo "If filename has a .vc suffix then decrypts"
	echo
	echo "One-Time-Pad (Vernam Cipher) style encryption"
	echo
	exit
fi


if [ ! -f $1 ]; then
	if [ ! -L $1 ]; then
	    echo "File $1 not found"
	    exit
	fi
fi


xor >/dev/null 2>&1
RC=$?
if [ $RC -ne 2 ]; then
	echo "xor program as required by this script not found"
	exit
fi


if [ -L $1 ]; then # if a sym link read filesize of actual
	FILESIZE=$(stat -c%s "$(readlink -f $1)")
else
	FILESIZE=$(stat -c%s "$1")
fi
filename=$(basename "$1")
ext="${filename##*.}"


if [ "$ext" = "vk" ]; then
	B="${filename%.*}"
	if [ -f ${B}.vc ]; then
	    if [ -L ${B}.vc ]; then
		FS=$(stat -c%s "$(readlink -f ${B}.vc)")
	    else
		FS=$(stat -c%s "${B}.vc")
	    fi
	    if [ $FILESIZE -eq $FS ]; then
		echo "Hmm! Are you sure you want to encrypt a .vk file"
		echo "Suspect you actually want to decrypt ${B}.vc"
		C=1
		while [ $C -ne 0 ]; do
		    echo -n "decrypt (d) or continue and encrypt (e) d/e : "
		    read -n1 ans; echo
		    case $ans in
			d|D) filename="${B}.vc"; ext="vc"; C=0 ;;
			e|E) C=0 ;;
			*) echo "Answer should be d or e ... try again" ;;
		    esac
		done
	    fi
	fi
fi


if [ "$ext" = "vc" ]; then # decrypt

	echo Decrypting
	B="${filename%.*}"

	if [ -f $B ]; then
	    echo -n "Output file $B already exists, overwrite y/n : "
	    read -n1 ans; echo
	    if [ "$ans" = "y" ] || [ $ans = "Y" ]; then
		rm $B
	    else
	        echo exiting
	        exit
	    fi
	fi

	xor $B.vc $B.vk
	RC=$?
	if [ $RC -ne 0 ]; then
	    echo "Error occurred whilst running xor"
	    exit
	fi

	# if a sym link then we also remove the source file
	if [ -L $B.vk ]; then
	    rm "$(readlink -f $B.vk)"
	fi
	rm $B.vk
	if [ -L $B.vc ]; then
	    mv $(readlink -f ${B}.vc) ${B}
	    rm ${B}.vc
	else
	    mv $B.vc $B
	fi


else # encrypt


	if [ -f ${filename}.vk ] || [ -f ${filename}.vc ]; then
	    echo "Output file(s) ${filename}.vc"
	    echo "and/or ${filename}.vk"
	    echo -n "already exist, overwrite y/n : "
	    read -n1 ans; echo
	    if [ "$ans" = "y" ] || [ $ans = "Y" ]; then
		if [ -f ${filename}.vk ]; then
		    rm ${filename}.vk
		fi
		if [ -f ${filename}.vc ]; then
		    rm ${filename}.vc
		fi
	    else
	        echo exiting
	        exit
	    fi
	fi

	echo "Generating high entropy random bytes keyfile"
	dd if=/dev/random bs=32 iflag=fullblock | pv --bytes | head -c $FILESIZE >${filename}.vk

	KEYFILESIZE=$(stat -c%s "${filename}.vk")
	if [ $FILESIZE -gt $KEYFILESIZE ]; then # error in random file generation
		echo "Mis-match between generated random key filesize and clear-text filesize"
		echo "exiting"
		rm ${filename}.vk
		exit
	fi	

	echo "Encrypting ..."
	xor ${filename} ${filename}.vk
	RC=$?
	if [ $RC -ne 0 ]; then
	    echo "Error occurred whilst running xor"
	    exit
	fi

	if [ -L ${filename} ]; then
	    mv $(readlink -f ${filename}) ${filename}.vc
	    rm ${filename}
	else
	    mv ${filename} ${filename}.vc
	fi

fi

sync
For faster xor'ing I'm using the following xor.c program (load devx and gcc xor.c -o xor). Where that uses a trick of writing the output to the input file, which avoids having to use a third transitional file. i.e. xor file1 file2 where file2 has the random data will result in file1 original content being replaced with the xor'd output. Run a second time to restore it back as before.

Code: Select all

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <err.h>

/*
   No error checking etc. intended to be called/run from
   a wrapper shell script that does all the checks

   Fast (buffers 32K blocks) XOR'ing of two files, where
   the output file is the input file i.e. overwrites it
   (saves on having to use a transitory file).

   Rufwoof 2019
*/

int main(int argc, char *argv[]) {

	char *in_n, *key_n, *out_n;
	FILE *in_fp, *key_fp, *out_fp;
	unsigned char data[32768], key[32768];
	size_t in_l, key_l = 0, key_i = 0, data_i;
	
	if (argc == 1) { 
	    fprintf(stdout, "For usage see vc shell wrapper script\n");
	    return 2; 
	}
	
	in_fp  = fopen(argv[1],"rb");
	key_fp = fopen(argv[2],"rb");
	out_fp = fopen(argv[1],"rb+");
	
	while (1)
	{
	    data_i = 0;
	    in_l = fread(data, sizeof(unsigned char), sizeof(data), in_fp);
	    if (ferror(in_fp)) { return 1; }
	    if (in_l) {
		while (data_i < in_l)
		{
		    if (key_i >= key_l) {
			key_i = 0;
			key_l = fread(key,
				sizeof(unsigned char),sizeof(key), key_fp);
			if (ferror(key_fp)) { return 1; }
		    }
		    data[data_i] ^= key[key_i];data_i++;key_i++;
		}
		fwrite(data, sizeof(unsigned char), in_l, out_fp);
		if (ferror(out_fp)) { return 1; }
	    }
	    else if (!in_l && feof(in_fp)) { return 0; }
	                     /* End of in_fp, exit OK */
	}
	fclose(in_fp);
	fclose(out_fp);
	fclose(key_fp);
}
Little/no error checking in that as its solely intended to be called by the vc script - that does all the checking.

Fundamentally in Linux based systems the CSPRNG (Crytographically Secure Pseudo Random Number Generator) that derives its pool of random bytes from the likes of /dev/hwrng and the least significant bits of interrupts timestamps (hardware activity) sources both /dev/random and /dev/urandom. A difference however is that /dev/random will block if the kernels estimate of entropy is too low.

Large seemingly random sequences of numbers do not always have high entropy. You can take a small random number and turn it into a large random number and the entropy remains the same. For example, take a random number from 1 to 16 and compute its cryptographic hash with an algorithm like SHA-1 - the resulting 160 bit number looks very random, but it is one of only 16 possible such numbers. Guessing the number is just as easy as guessing a random number from 1 to 16. urandom will output low entropy (more predictable) data when the approximated entropy is low, and when removing (reading) long sequences of random bytes quickly entropy will tend to be low - and as such urandom random data tends to be significantly more predictable than /dev/random random data. One time pad (Vernam Cipher) requires that even if all possible valid ineligible clear text solutions are derived then the actual/correct solution remains obscure - cannot be differentiated. With /dev/urandom sourced random data that is much less assured than when using /dev/random random data.

It is important to use cryptographically secure random data as pure random could for instance yield all zeros as being a 'valid' random data sequence, that in turn would result in OTP yielding the same 'encrypted' output as the clear-text input. Our random data must exhibit the qualities of appearing random, and in the case of OTP the random data must also have relatively high entropy (otherwise even just cracking one/few bytes of clear text could highlight one overall most probable (or actual) solution.

A downside of using high entropy CSPRNG random data (/dev/random) is that it is much much slower to be produced compared to /dev/urandom. That is the price paid for higher security.
[size=75]( ͡° ͜ʖ ͡°) :wq[/size]
[url=http://murga-linux.com/puppy/viewtopic.php?p=1028256#1028256][size=75]Fatdog multi-session usb[/url][/size]
[size=75][url=https://hashbang.sh]echo url|sed -e 's/^/(c/' -e 's/$/ hashbang.sh)/'|sh[/url][/size]

User avatar
rufwoof
Posts: 3690
Joined: Mon 24 Feb 2014, 17:47

#22 Post by rufwoof »

For cross reference purposes, there's another post here http://www.murga-linux.com/puppy/viewto ... 50#1045950 that may be of interest. Based on Deniable Encryption. Basically it creates a apparently valid One Time Pad style pair of Crypted file and Key file, where when de-crypted reveals a valid clear text content ... however that's just a disguise and another entirely different clear text content is also hidden within that and can be de-crypted using another Key.

So if a adversary sees a encrypted file and one way or another pressures you to release the key ... then you can comply and they will see the 'fake' apparently valid content, not the real content (which is only accessible via another key, and without that key there is no indication of that hidden content).
[size=75]( ͡° ͜ʖ ͡°) :wq[/size]
[url=http://murga-linux.com/puppy/viewtopic.php?p=1028256#1028256][size=75]Fatdog multi-session usb[/url][/size]
[size=75][url=https://hashbang.sh]echo url|sed -e 's/^/(c/' -e 's/$/ hashbang.sh)/'|sh[/url][/size]

Post Reply