Application Security Testing: An Integral Part of DevOps
Environment: VC6 SP4, NT4 SP3, Win95 and above, Win2k and above
After publishing my POP3 class in 2001, lots of e-mails reached me. Most people were not asking for a problem or reporting bugs but they asked me how to de- or encode Base64 data. I think at the beginning of 2002 a new virus spread around the world. It was using a bug in MS Outlook that executed attached files automatically. I wanted to know how it works to protect my computer properly. That was the day when I decided to write my own Base64 class for decoding and encoding data out and into the Base64 format because I wanted to write a mail filter tool.
My Base64 class can decode and encode data in and out of the Base64 format. You can decode Base64 data in two ways. You can decode a whole file containing Base64 data or you can pass a buffer to the class that contains the Base64 data. Encoding works the same. Per file or per buffer as wanted and needed. The class works no matter how much data you pass or how huge the files are. The only thing you need to take care of is to reserve enough memory.
Below I will explain all four cases of de- and encoding Base64 data with my class. You can download the source of this class and use it. The only thing I would like to ask you is to reference at this class in the Info screen of your app, maybe, but that's up to you.
If you have problems using the class or want to tell me of improvements and so forth, feel free to mail me. I am still improving the class and optimizing it, so there may be updates in the near future.
Case 1: You want to decode a Base64-encoded application with the file name "test.b64" and store the decoded application in "test.exe".
CBase64 B64; B64.DecodeFile ("test.b64", "test.exe");
Case 2: You want to decode a Base64-encoded buffer and store the decoded data in another buffer. This case is a bit more complicated. Base64-encoded data is around 30% larger in size than normal data. This means you do not need a buffer that is as large as the buffer containing the Base64 data. This is solved for you with the CreateMatchingDecodingBuffer function. The first Parameter of this function is the address of the buffer that holds the data that you want to decode. The second parameter is an address to a char* that will receive the adress of a matching decoding buffer. DO NOT FORGET to delete this buffer as soon as you do not need it any more. Here, pInput is the buffer that contains the Base64 data.
char* pDecodedDataBuffer; B64.CreateMatchingDecodingBuffer (pInput, &pDecodedDataBuffer); B64.DecodeBuffer (pInput, pDecodedDataBuffer); //...use the decoded data write it to a file etc. ... delete pDecodedDataBuffer;
Case 3: You want to encode a file into Base64 and store the decoded data in the file in "test.b64".
CBase64 B64; B64.EncodeFile ("test.exe", "test.b64");
Case 4: You want to encode a buffer and store the encoded data in another buffer. This case is a bit more complicated than just encoding a file. Encoding a buffer means that your encoded data will be around 30% larger than your source data. To create a buffer that is capable of holding all the encoded data, you can call CreateMatchingEncodingBuffer. The function takes two parameters. The first parameter tells the function how many bytes there are in your buffer that need to be encoded. The second parameter is is the address to a char* that will be filled by the function with the address of a matching buffer for the encoded data. DO NOT FORGET to delete pInput as soon as you do not need it any more. In this sample, pInput contains 114 bytes that I want to be encoded. At first, I create a matching buffer by calling CreateMatchingEncodingBuffer. Then, I pass pInput and pB64Output to EncodeBuffer and tell it that there are 114 bytes to encode in pInput. The function now converts the bytes from pInput to Base64 and stores the result in pB64Output.
char* pB64Output; B64.CreateMatchingEncodingBuffer (pInput, &pB64Output); B64.EncodeBuffer (pInput, 114, pB64Output); //... process the encoded data write it to a file, etc. delete pInput;