Ever wondered how to extract a SWF file from Adobe's Flash Projector? There is already both free and paid (LOL!) programs which should do the trick, but it's so easy that it doesn't worth the effort of downloading or paying (again, LOL!) for them.
Flash projected SWF's are actually a standalone flash player, bundled with the original SWF. The projector contains only the needed flash runtime library, which is... what "bundling" mean.
The structure of a Projector file looks like this:
Standard MZ-PE executable Projector |
Original SWF file |
DWORD, 0xFA123456Flash Projector "check" value |
DWORD, Size of the original SWF file |
The executable is designed that way, so it reads his own last 8 bytes, which are the projector check DWORD and the SWF size.
If the "check" DWORD is equal to 0xFA123456, it reads <size of the original SWF> bytes back (excluding the last 8 bytes), and process the data as standard SWF.
So, long story short, here's a small code that will extract SWF file from Projector bundle:
dump_projector.c, poorly written in C#include <stdio.h>
#include <windows.h>
int main() {
int szFile;
char dataEnd[8];
DWORD lpNumberOfBytesRW;
HANDLE hfInput,
hfOutput,
hMemHeap,
hHeap;
hfInput = CreateFile("input_projector.exe", GENERIC_READ, 0, NULL,\
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfInput == INVALID_HANDLE_VALUE) {
printf("Cannot open input file for reading!\r\n");
} else {
szFile = GetFileSize(hfInput, NULL);
SetFilePointer(hfInput, szFile-8, NULL, FILE_BEGIN);
ReadFile(hfInput, dataEnd, 8, &lpNumberOfBytesRW, NULL);
if (*(DWORD*)&dataEnd == 0xFA123456) { // Check the signature
hHeap = GetProcessHeap();
if (hHeap) {
hMemHeap = (PHANDLE)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, *(DWORD*)&dataEnd[4]);
SetFilePointer(hfInput, szFile-8-*(DWORD*)&dataEnd[4], NULL, FILE_BEGIN);
ReadFile(hfInput, hMemHeap, *(DWORD*)&dataEnd[4], &lpNumberOfBytesRW, NULL);
hfOutput = CreateFile("dumped.swf", GENERIC_WRITE, 0, NULL,\
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfOutput == INVALID_HANDLE_VALUE) {
printf("Cannot create output file for writing!\r\n");
} else {
WriteFile(hfOutput, hMemHeap, *(DWORD*)&dataEnd[4], &lpNumberOfBytesRW, NULL);
CloseHandle(hfOutput);
printf("Done, check your shiny new dumped.swf! =)\r\n");
}
HeapFree(hHeap, 0, hMemHeap);
} else {
printf("Can't fetch the process heap!\r\n");
}
} else {
printf("This doesn't seems to be a projector bundle.\r\n");
}
CloseHandle(hfInput);
}
return 0;
}
Well, that's all. ;)
Comments
* You have an opinion? Let us all hear it!#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#if (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
#endif
char *repl_str(const char *str, const char *from, const char *to) {
/* Adjust each of the below values to suit your needs. */
/* Increment positions cache size initially by this number. */
size_t cache_sz_inc = 16;
/* Thereafter, each time capacity needs to be increased,
* multiply the increment by this factor. */
const size_t cache_sz_inc_factor = 3;
/* But never increment capacity by more than this number. */
const size_t cache_sz_inc_max = 1048576;
char *pret, *ret = NULL;
const char *pstr2, *pstr = str;
size_t i, count = 0;
#if (__STDC_VERSION__ >= 199901L)
uintptr_t *pos_cache_tmp, *pos_cache = NULL;
#else
ptrdiff_t *pos_cache_tmp, *pos_cache = NULL;
#endif
size_t cache_sz = 0;
size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from);
/* Find all matches and cache their positions. */
while ((pstr2 = strstr(pstr, from)) != NULL) {
count++;
/* Increase the cache size when necessary. */
if (cache_sz < count) {
cache_sz += cache_sz_inc;
pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz);
if (pos_cache_tmp == NULL) {
goto end_repl_str;
} else pos_cache = pos_cache_tmp;
cache_sz_inc *= cache_sz_inc_factor;
if (cache_sz_inc > cache_sz_inc_max) {
cache_sz_inc = cache_sz_inc_max;
}
}
pos_cache[count-1] = pstr2 - str;
pstr = pstr2 + fromlen;
}
orglen = pstr - str + strlen(pstr);
/* Allocate memory for the post-replacement string. */
if (count > 0) {
tolen = strlen(to);
retlen = orglen + (tolen - fromlen) * count;
} else retlen = orglen;
ret = malloc(retlen + 1);
if (ret == NULL) {
goto end_repl_str;
}
if (count == 0) {
/* If no matches, then just duplicate the string. */
strcpy(ret, str);
} else {
/* Otherwise, duplicate the string whilst performing
* the replacements using the position cache. */
pret = ret;
memcpy(pret, str, pos_cache[0]);
pret += pos_cache[0];
for (i = 0; i < count; i++) {
memcpy(pret, to, tolen);
pret += tolen;
pstr = str + pos_cache[i] + fromlen;
cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen;
memcpy(pret, pstr, cpylen);
pret += cpylen;
}
ret[retlen] = '