Poor man's bitmap encryption [Archive] - C Board

PDA

View Full Version : Poor man's bitmap encryption


jdinger
05-13-2002, 09:19 AM
There have been a handful of posts in the past that asked for ways to create your own file format, etc. in order to protect you game's bitmaps from tampering.

What I'm providing here is a very simple way to make an image unreadable and therefore uneditable. Granted ( as it's been stated before ) no method is absolute. If someone knows enough and REALLY wants to screw with your game they will find a way.

Also, these code snippet's use the Window's API ( CreateFile, WriteFile, ReadFile, etc.)


//global declares
HANDLE hFile=NULL;
BITMAPFILEHEADER bmfh;
BYTE Remain[65535];
DWORD dwSize=0, dwRead=0;

//Read the bitmap in
hFile=CreateFile("t1.bmp",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ NORMAL,NULL);
ReadFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwRead,NULL);
dwSize=GetFileSize(hFile,NULL);
dwSize-=sizeof(BITMAPFILEHEADER);
ReadFile(hFile,&Remain,dwSize,&dwRead,NULL);
CloseHandle(hFile);


This first snippet just reads the bitmap into memory in 2 parts:
1 - The BITMAPFILEHEADER structure that'll we'll alter
2 - Everything else

It also sets our dwSize variable ( which is the 2nd part of our "encryption" ).


//this is our "encryption" part 1
bmfh.bfType=19777;

dwRead=0;
hFile=CreateFile("t2.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE _NORMAL,NULL);
WriteFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwRead,NULL);

//this is our "encryption" part 2
WriteFile(hFile,&dwSize,sizeof(DWORD),&dwRead,NULL);

for(i=0;i<dwSize;i++)
{
WriteFile(hFile,&Remain[i],sizeof(BYTE),&dwRead,NULL);
}
CloseHandle(hFile);


This 2nd part creates a new file that has 2 changes made to it.
1 - The BITMAPFILEHEADER's bfType is changed to 19777
(normally it's 19778, or "BM")
2 - The size of our remaining bytes is written in between our header and our remaining bytes.


HANDLE hFile=CreateFile("t2.bmp",GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NO RMAL,NULL);
ReadFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwRead,NULL);
ReadFile(hFile,&dwSize,sizeof(DWORD),&dwRead,NULL);
ReadFile(hFile,&Remain,dwSize,&dwRead,NULL);
CloseHandle(hFile);


This 3rd part is the first part of our "decryption". We read the file back in, in it's 3 parts: header, size and remaining bytes.


bmfh.bfType=19778;
dwRead=0;
hFile=CreateFile("t3.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE _NORMAL,NULL);
WriteFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwRead,NULL);
for(i=0;i<dwSize;i++)
{
WriteFile(hFile,&Remain[i],sizeof(BYTE),&dwRead,NULL);
}
CloseHandle(hFile);


This last part just rewrites the bitmap in it's original form.

Of course, you would want to delete the temporary bitmap ( in our case, "t3.bmp" ) when the game exits. And you could change your bfType to whatever number (WORD) you choose, I just used 19777 for simplicities sake here.

Let me know what you think. :)

mickey
05-13-2002, 10:10 AM
i don't know if this is okey, since the point here is not allowing other people to see and tamper with your graphic files, so what i did is, since the first 2? (or was it 3 bytes?) of a BMP is supposed to be 'BM' right? well i changed those values and turned it into soemthing else like XX, this way, no viewer would open the bmp anymore.

thought it's just that plain and simple, well i guess it's not that easy to decipher it too, is it?

:)

jdinger
05-13-2002, 10:12 AM
I haven't tried it your way, mickey, but it sounds like it would work ok. Have you tried it or are you just suggesting it? From the sounds of things we're using the same method, just different avenues of making the change.

mickey
05-13-2002, 10:14 AM
oh hey i think we did the same thing, anyway to change it back to it's orginal state, i would just change back again the two (or 3) bytes that i changed back to 'BM'

btw, i used the ifstream class, :)

:)

jdinger
05-13-2002, 10:21 AM
Originally posted by mickey
btw, i used the ifstream class, :)

I agree, using fstream would have been a better example ( for portability ). I've really gotten spoiled with the WinAPI so that's why I used it here. I learned fstream basics but when I learned the WinAPI file functions I got so used to them I don't even use fstream anymore.

tyouk
05-13-2002, 08:19 PM
Both of you have come up with some very simple methods to "encrypt" a bitmap file so others could not read it using a normal bitmap reader. However, long ago I created a bitmap file reader that would ignore the first few bytes (supposed to BM) and simply read in the image itself. Thus my reader would ignore whatever you change your first three bytes to and simply load the image anyways.

If you want to get serious about encrypting a bitmap file, thats not the way to go. You almost need to create a different way of storing the same information (like for instance have your "bitmap creator" place false bitmap information on the first line, then have the REAL bitmap first line on the second line, and then another false line, then the second line of the real thing, etc. until you have all the bitmap information there). This isn't really storing the information in a different way, but what it does allow you to do is so then when people see your bitmaps in a bitmap reader of some kind they don't see what your program uses. You would have to of course create a function that loads the bitmap by reading every second line starting with the second line of the file. (Well "image line" that is.) Now through this method they could still mess with your images, but this way hides what is truly there.

To truly encrypt your file, what I would suggest is creating a file that stores data in a much different way. Such as replacing numbers with letters or ASCII characters (non-alphabetical) and simply store the information like you would normally a bitmap (without the BM at the beginning). This way, you would need a "deciphering" program to actually read it because there wouldn't be a chance in hell any bitmap reader could ever read a file and get the proper RGB values when you have everything in this manner.

jdinger
05-14-2002, 06:41 AM
tyouk, re-read my first post.

As I said you this isn't a solid encryption. It's just a simple way to hide your images from the average game player. Consider it one step above renaming them to *.dat.

Also, I didn't just change the first two bytes, I also added a DWORD between the BITMAPFILEHEADER and the rest of the bitmap (BITMAPINFOHEADER, RGBQUAD table and image data).

I use a virtual file system for my games, this was just a general example for people who had no experience with manipulating bitmap data.

tyouk
05-14-2002, 07:10 PM
Ahhh, I guess I skimmed a little too quickly. ;) I guess I have to slow down when reading!

In that case, its a pretty good method.

mickey
06-01-2002, 10:23 PM
ei sorry for replying long i lost this thread i just remembered it hehe, anyway,

yup i tried it already and it does really work, i made a dos program for this that contains two functions,

one fucntion is to encrypt(that is, put xx on the BM thingy) of any bitmap that i'd like, (i used the argv argc command line from main) then another function to decrypt, that is to change the xx to BM again,

try it, no ordinary viewer could open any bitmap file anymore, :)

well i guess these ordianry viewer rely on the BM to work, i mean, they would always check this and if it's not BM, probably it would return false immedietly,

well, to encrypt it truly, i think a reserach on variou encryption method is a must to konw the most effective ways to encrypt it, :)