Part of a malware analysis I wrote on included a payload hidden in a Graphics Interchange Format (GIF) file. A reverse shell backdoor embedded in a GIF image file was uploaded to a server and decoded to execute the malware. I found this immensely interesting that something malicious could be passed in undetected within an otherwise benign file. Steganography is the process of hiding information within a medium that is not hidden. There are a few properties of steganographic information that are vital for the process to be successful. First, the information must be embedded in a separate medium. The whole point of the steganographic process is to cloak the information in another medium so not to raise suspicion. Also, the process of encoding the hidden information must be known by both the sender and receiver of the information. In order for the receiver to make sense of the hidden message, they must know the process in which it was encoded so to reverse that process in order to decode. Finally, the hidden information must be identifiable by both sending and receiving parties. In order to begin the decoding process, the receiver must know which information to decode.
A popular and simple method for implementing digital image steganography is what is known as Least Significant Bit (LSB) Steganography. In this process, the least significant bit for every byte in a file is altered to resemble each bit in the hidden file. For example: the data stream 0xFFFF0000FFFF can be translated into the bits, 11111111 11111111 00000000 00000000 11111111 11111111. If we were to hide the data stream 0x2A or 101010 we would change the LSB of each of the bytes in the first data stream to the following: 11111111 11111110 00000001 00000000 1111111 11111110 or 0xFFFE0100FFFE. The data is minimally altered so that the digital image is still intact and is able to be opened without detection. Notice that the embedded information is significantly smaller than the host
A slightly more secure version of LSB is Selective Least Significant Bit (SLSB) steganography. This method alters the LSB of certain bytes. When dealing with a digital image, the SLSB is changed for a given color channel. For example, all bytes that correspond to the Blue channel in a given image would be altered while Red and Green are left unmodified. The open-source tool, Steganography Studio allows for different encryption algorithms including SLSB. During my test of the software the only noticeable difference in the original image and the steganographic one is the file size. The steganographic image is slightly smaller. There are no discernable visual differences between the two files.
I really wanted to write my own tool for accomplishing something similar to this using Python. I came up with a slightly different approach to embedding data. I started with the third principle of steganography; making the encoded data identifiable. I thought the easiest way to incorporate an identifier within a host file would be to have a unique set of bytes at the end of the file to signify that data following this signature would be the hidden information. My encode tool writes the signature, “FFFF0000FFFF0000FFFF” at the end of the host file followed by the hidden information. I followed the second property of steganography by encoding the hidden information in base64. My decode tool searches a given file for my “secret” signature, then proceeds to decode the rest of the file from base64 to hexadecimal and saves the file in whatever format the user designates. I modified my existing file signature finder tool I wrote earlier since the algorithm for finding a file signature could be used for this purpose as well. I used Pyinstaller to create standalone executable files so that the tools do not rely on Python 2.7 installed in order to run.
#!/bin/usr/python import binascii import base64 textFile = raw_input('Enter embeded file name: ') imgFile = raw_input('Enter host file name: ') secretSig = binascii.a2b_hex('FFFF0000FFFF0000FFFF') fileOut = raw_input('Enter output file name: ') with open(textFile, 'rb') as txt: content = txt.read() content = base64.b64encode(content) content = binascii.hexlify(content).upper() content = binascii.a2b_hex(content) #print content #print 'Secret signature',secretSig with open(imgFile, 'rb') as img: imageData = img.read() imageData = binascii.hexlify(imageData).upper() imageData = binascii.a2b_hex(imageData) #print imageData target = open(fileOut, 'wb') target.write(imageData) target.write(secretSig) target.write(content) target.close() ##content = binascii.unhexlify(content) ##content = base64.b64decode(content) ##print ('content decoded: '),content pause = raw_input('File done. Press enter.')
#!/bin/usr/python import binascii import base64 hexFile = raw_input('Enter the file name to decode: ') secretSig = 'FFFF0000FFFF0000FFFF' sigLen = len(secretSig) with open(hexFile, 'rb') as f:#'rb' for windows, read as binary content = f.read() hexDump = (binascii.hexlify(content)).upper() #create string 'hexDump' of entire file dumpLen = len(hexDump) #file length in nibbles progress = [10,20,30,40,50,60,70,80,90,100] print "Dump length: ",dumpLen print "Looking for secret signature: ",secretSig for i in range(0, dumpLen): if(i>0): percent = 100*i/dumpLen if(percent%10 == 0): # percent = percent+10 #account for starting at 0 for y in range(0, len(progress)): #check if percentage is included in progress list if(progress[y] == percent): #percentage found in progress list print percent,"%" progress[y] = 0 #MARK IT ZERO! Display a percentage once if(hexDump[i:i+sigLen] == 'FFFF0000FFFF0000FFFF'): print "Found secretSig at offset ",i startSecret = i+sigLen print "Secret starts at ",startSecret secretMsg = hexDump[startSecret:dumpLen] secretMsg = secretMsg.decode("hex") secretMsg = base64.b64decode(secretMsg) #print "The secret message is: ",secretMsg fileOut = raw_input('Enter the output file name: ') target = open(fileOut, 'wb') target.write(secretMsg) target.close() raw_input('Press enter to exit.')