Friday, November 14, 2008

Read Flash Shared Objects with C++

Hi everyone,

Recently we needed to read the flash shared objects with an external application.

The problem was this: We have a setup file. This file can be downloaded from a bunch of different download locations. We need to do some stuff in the installer according to the download location. Like this: We may download dynamic content within the installer if the setup.exe is downloaded from location A.

Anyways. My first try was to put cookies while downloading the setup.exe. However we can't know which browser the user uses. And also there is another potential danger which is that browsers may change their way of storing their cookies. So we decided to go with flash shared objects as long as almost everybody has flash installed.

So before initiating the download we put a flash shared object to users machine. It is a GUID string in between two '_'. Something like this: _AF2504E0-4F89-11D3-9A0C-0305E82C330A_

Flash is storing shared objects on binary files. (For XP: C:\Documents and Settings\[USERNAME]\Application Data\Macromedia\Flash Player\#SharedObjects\[RANDOMFOLDERNAME])

So my first plan of reading the shared objects with a batch file failed. So I decided to write a small c++ app which could read the shared object I have written just before the download. After a day of learning C++ my the source code looks like below:




#include "stdafx.h"
#include <fstream>
#include <windows.h>
#include <iostream>
#include <stdio.h>

using namespace std;

// Flash stores the files in a random folder under #SharedObjects folder.
// So I had to find the name of that folder and return it.
wstring FindRandomFolderName(LPCWSTR SharedObjectPath)
{
// first we need to find the shared objects folder.
HANDLE hFind;
WIN32_FIND_DATA DataStructure;

hFind = FindFirstFile(SharedObjectPath, &DataStructure);
wstring folderName = L"";

if(hFind == INVALID_HANDLE_VALUE)
{
// As long as the path in the first parameter is correct we shouldn't hit this line.
}
else
{
// Find the last folder in the list. The first is "." second is ".."
while(FindNextFile(hFind, &DataStructure)!=0)
{
folderName = DataStructure.cFileName;
}

if(hFind != INVALID_HANDLE_VALUE)
{
//cout<<DataStructure.cFileName<<endl;
}
else
{
printf ("Invalid file handle. Error is %u\n", GetLastError());
}

FindClose(hFind);
}
return folderName;
}

int _tmain(int argc, _TCHAR* argv[])
{
if(argc==1)
{
cout << "Invalid number of arguments!\n";
return 0;
}

wstring path = argv[1];
LPCWSTR star = L"*";
wstring pathWithStar = path;
LPCWSTR domainNameAndFileName = L"\\www.pagefish.com\\referrer.sol";

pathWithStar.append(star);

wstring folderName = FindRandomFolderName((LPCWSTR)pathWithStar.c_str());

path.append(folderName);
path.append(domainNameAndFileName);

long begin, end, byteCount;

ifstream myFile;

myFile.open((wchar_t*)path.c_str(), ios::in | ios::binary);
//myFile.open(argv[1], ios::in | ios::binary);

begin = myFile.tellg();
myFile.seekg (0, ios::end);
end = myFile.tellg();
myFile.seekg(0, 0);
byteCount = end - begin;

char *buffer;
char referrerId[36]; // this is a guid saved in the shared object file
buffer = new char [byteCount];

myFile.read (buffer, byteCount);

if (!myFile)
{
// An error occurred!
}

myFile.close();

bool readReferrer = false;
int targetIndex = 0;

ofstream outFile;
outFile.open("referrerid.txt");

for (int i=0; i<byteCount; i++)
{
if(buffer[i]=='_' && readReferrer==false)
{
readReferrer=true;
}
else if(buffer[i]=='_' && readReferrer==true)
{
readReferrer=false;
}
if(readReferrer && buffer[i]!='_')
{
referrerId[targetIndex++] = buffer[i];
outFile << buffer[i];
}
}

outFile.close();

return 0;

}

No comments: