careless223 Posted July 6, 2008 Posted July 6, 2008 I'm sure this is nothing new but I found this neat trick on another forum where a user had uploaded an image that had hidden music in it. It was essentially music stenography. Here is the procedure. 1. Take your music file and rename it to a ".raw". 2. Open it in photoshop or paint shop pro. 3. If it asks you to specify a size, the X height must equal the exact byte size. (This varies though and in photoshop you can just use the guess function and it will most likely work.) 4. Save your creation as a ".png" with no compression. To listen to it you need to do the reverse. 1. Download the file to your desktop and open it with photoshop or paint shop pro. 2. Save the file as a ".raw". 3. Rename to ".mp3" or whatever the original extension was. Here is an example of what you get. Go ahead try to decode it. Quote
digip Posted July 6, 2008 Posted July 6, 2008 That's pretty cool. Although I haven't tried it, can this be done with any file? Quote
careless223 Posted July 6, 2008 Author Posted July 6, 2008 I think it could. There might be a maximum size limit though. Quote
iisonly Posted July 6, 2008 Posted July 6, 2008 For Gimp users!!1! :P You can use this command (in windows) and you can play your pictures in winamp copy /b my_picture.jpg + my_song.mp3 my_new_picture.jpg and in linux: cat picture.gif sound.mp3 > combined.gif Quote
Shaun Posted July 6, 2008 Posted July 6, 2008 PNG is non-lossy, there is no reason it disable compression. I made a utility a few years ago to use this method to use image shack as a file hosting system, with files split into multiple images to get around the image size limit. Quote
digip Posted July 6, 2008 Posted July 6, 2008 Ok. Tried this with executables, but no go. They just corrupt the files. So, I instead stuffed it in a rar file first, then renamed the rar to raw, then did the image import in PhotoShop and saved it as a PNG. Did the reverse and renamed back to rar, and then opened the exe just fine. This is nice, because you can now compress an exe file even smaller in the process without losing it in the converting process. Doing it in a rar, I didn't get prompted for a header size or dimensions. It did it automatically for me. When I tried it with renamed exe alone, they prompt you for all the info, which seemed to corrupt the final output. Quote
careless223 Posted July 6, 2008 Author Posted July 6, 2008 PNG is non-lossy, there is no reason it disable compression. Im soooooo sorry for the mistake. I only wrote this at 1 am. :P Quote
Shaun Posted July 6, 2008 Posted July 6, 2008 Ok. Tried this with executables, but no go. They just corrupt the files. So, I instead stuffed it in a rar file first, then renamed the rar to raw, then did the image import in PhotoShop and saved it as a PNG. Did the reverse and renamed back to rar, and then opened the exe just fine. This is nice, because you can now compress an exe file even smaller in the process without losing it in the converting process. Doing it in a rar, I didn't get prompted for a header size or dimensions. It did it automatically for me. When I tried it with renamed exe alone, they prompt you for all the info, which seemed to corrupt the final output. You can do it with an EXE, I don't know about this method but my utility I made which did the same thing worked with anything. The only reason I could think of might make it not work using this method is if the image dimensions meant that it had extra data on the end (would probably look like a line of black pixels) especially if the EXE length was prime maybe. If you add extraneous data to the end of an EXE it won't work, but a RAR will. My utility had a metafile with file length so it didn't read in extra data and MD5 hashes to make sure it wasn't corrupt. I might still have it somewhere. Quote
webjockey Posted July 6, 2008 Posted July 6, 2008 I think what this is doing (after listening to the gimp post) is that you are actually zipping two files into a new file. So, what you do in Windows it go into command prompt, take your Song, take your picture, and put them into a lossless compression format (0% compression) or make it lossless. then rename the file. This is how some viruses are put into exes as trojans. when the person starts the application, it will open up both executables inside the 'executable' you clicked. Quote
Shaun Posted July 7, 2008 Posted July 7, 2008 I think what this is doing (after listening to the gimp post) is that you are actually zipping two files into a new file. So, what you do in Windows it go into command prompt, take your Song, take your picture, and put them into a lossless compression format (0% compression) or make it lossless. then rename the file. This is how some viruses are put into exes as trojans. when the person starts the application, it will open up both executables inside the 'executable' you clicked. The method iisonly posted is nothing to do with zipping, it just concatenates two files and the software that opens them is quite tolerant of extra unnecessary data and ignores it. The actual method used to inject viruses into EXEs usually not how you described, it's quite a bit more complicated, generally either fitting the extra instructions into exist code caves in the original EXE or extending or adding a section by editing the PE header and section table and putting the extra code in that. You can't just concatenate two EXEs because the length won't match up with the data in the PE header and windows will just tell you it's not a valid win32 application. Quote
snakey Posted July 8, 2008 Posted July 8, 2008 ok i found you can only do up to 3mb files because the size cant be bigger then 300000 pixels Quote
digip Posted July 8, 2008 Posted July 8, 2008 just did one Well, I converted it back, but this file was corrupt for some reason and didn't open as an mp3. Were you able to successfully convert it back to an mp3 and play it? I opened it in an editor, and it looks like it tripled each character, so I don't think it was created properly. Quote
Razor512 Posted July 9, 2008 Posted July 9, 2008 ok i found you can only do up to 3mb files because the size cant be bigger then 300000 pixels I wonder if they will remove this limitation in photoshop cs4 which is suppose to support cuda or some other kind of gpu acceleration Quote
Razor512 Posted July 9, 2008 Posted July 9, 2008 Well, I converted it back, but this file was corrupt for some reason and didn't open as an mp3. Were you able to successfully convert it back to an mp3 and play it? I opened it in an editor, and it looks like it tripled each character, so I don't think it was created properly. yep, did you select this option when saving the raw file has to be non interleaved to retain the original code or it will be corrupt Quote
Shaun Posted July 9, 2008 Posted July 9, 2008 I couldn't find my old image shack file storage thing, but I felt like rewriting the image encoding part, the old one had input checking, split files into multiple images and handled all the uploading and downloading from imageshack too, but this is just an encoder/decoder. It uses 32bit PNGs unlike when you import files into photoshop as RAWs. This PNG is actually 25% smaller (400kB) than the MP3 file it was encoded from due to the PNG RLE compression, which just shows how shitty MP3 is as a codec. It seems that having a wide image results in better compression than a long image, but too wide seems to cause problems. The one improvement I made is storing the file length of the original file in the PNG metadata, so there is no need to have an extra file to store the file length in order to be able to strip off any padding necessary to make the data fit in the image. The only downside of this is some image host or utility which doesn't respect PNG metadata could strip the data necessary to turn it back into a file, but imageshack at least leaves your files alone. I considered putting the file length in the first pixel or something, but I like it this way. Here's the code if anyone wants it, it needs Python 2.5 with the Python Imaging Library 1.1.6. Also a Windows binary here if you can't be bothered to install those. #!/usr/bin/env python import Image, PngImagePlugin import random import sys, getopt class BinPng(): def __init__(self, png_path = None, bin_path = None, constraint = None, longest = None): self.bin_data = None self.png = None self.metadata = None self.constraint = constraint self.longest = longest if (png_path): self.load_png(png_path) if (bin_path): self.load_bin(bin_path) def load_bin(self, bin_path): f = open(bin_path, 'rb') data = f.read() f.close() self.bin_data = data def load_png(self, png_path): self.png = Image.open(png_path) def bin_to_png(self): if (not self.bin_data): return False data = self.bin_data #make a PNG metadata field to store the actual file length so we can strip off the padding later self.metadata = PngImagePlugin.PngInfo() self.metadata.add_text('length', str(len(data))) data = self.pad_data(data, self.constraint) size = self.get_dimensions(len(data), self.constraint, self.longest) self.png = Image.fromstring('RGBA', size, data) def png_to_bin(self): if (not self.png): return False self.bin_data = self.png.tostring()[:int(self.png.info['length'])] def write_bin(self, file_path, auto_convert = True): if (auto_convert == True): self.png_to_bin() f = open(file_path, 'wb') f.write(self.bin_data) f.close() def write_png(self, file_path, auto_convert = True): if (auto_convert == True): self.bin_to_png() self.png.save(file_path, 'PNG', pnginfo = self.metadata) def fermat_primality(self, n): checks = 0 #do 20 fermat checks, should be good enough for this porpoise while checks < 20: a = random.randint(1, n-1) if pow(a, n-1, n) != 1: return False checks += 1 return True def pad_data(self, data, dimension_constraint = None): length = len(data) #pad data to make it fit in 32bit pixels extra = '\x00' * (4 - length % 4) length += (4 - length % 4) if (dimension_constraint and dimension_constraint < length/4): extra += '\x00' * 4 * (dimension_constraint - length/4 % dimension_constraint) length += 4 * (dimension_constraint - length/4 % dimension_constraint) return data + extra while (self.fermat_primality(length/4)): #pad probable prime pixel lengths to get nicer dimensions extra += '\x00' * 4 length += 4 return data + extra def get_dimensions(self, length, dimension_constraint = None, longest = None): length /= 4 if (dimension_constraint and dimension_constraint < length): ceil = dimension_constraint else: ceil = int(length**0.5) while (ceil > 0): if (length % ceil == 0): if (length / ceil > ceil): size = (length / ceil, ceil) else: size = (ceil, length / ceil) if (longest == 'x' or not longest): return size else: return (size[1], size[0]) ceil -= 1 if __name__ == '__main__': usage = '-e <file>\tEncode this file to PNG\n' + \ '-d <file>\tDecode from this PNG\n' + \ '-o <file>\tFile to write to\n\n' + \ 'Optional options only used for encoding:\n' + \ '-c <number>\tConstrain one dimension to this length, defaults to 1024\n' + \ '-l <x or y>\tMake the X or Y dimension the longest, defaults to Y' try: opts, args = getopt.getopt(sys.argv[1:], 'he:d:o:l:c:') except getopt.GetoptError, e: print str(e) print usage sys.exit() operation = None in_file = None out_file = None l = 'y' c = 1024 for opt, arg in opts: if (opt == '-h'): print usage sys.exit() elif (opt == '-e'): operation = 'e' in_file = arg elif (opt == '-d'): operation = 'd' in_file = arg elif (opt == '-o'): out_file = arg elif (opt == '-l'): l = arg.lower() elif (opt == '-c'): c = int(arg) if (operation == 'e'): BinPng(bin_path = in_file, longest = l, constraint = c).write_png(out_file) elif (operation == 'd'): BinPng(png_path = in_file).write_bin(out_file) elif (not operation): print usage Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.