Flash SWF 파일 추출하기
오후 10:08 99-12-02 조경민
-------------------------------------------------------------
상황 : SWF 플래쉬 파일을 Flash ActiveX컨트롤로 VC 프로그램에
붙여서 컴파일 하면 SWF파일은 VC프로그램안에 포함된다.
이때 Test.exe안에 포함된 어떤 SWF파일을 추출하여야 한다.
과정 :
먼저 나는 Test.exe파일을 바이너리로 열어 기존의 포함되었던 swf파일
도 바이너리로 열어서 비교해 보았다. 일딴 swf파일은 FWS라는 세바이트
로 시작하는것 같았다. 역시 Test.exe파일의 중하단 부분에 FWS로 시작
하는 부분이 있었다. 그 뒤는 swf파일과 동일하여 여기서 부터 추출을
하면 될거라 생각했다.
swf파일의 크기를 짐작하기
먼저 test.swf파일의 크기를 보았다. 0x082e로 2094 바이트였다.
이를 바이트로 나누니 2e 08로 들어갈것이므로 FWS부터 이 2e 08을 찾아
보았다.
F W S 2e 08 00 00 .... 이런식의 나열이었다. 플래쉬파일이 몇메가도
되므로~~~~~~~~~~~ 이부분이 파일의 크기라고 짐작을 하여 코딩을 하였다.
나중에 알게 되었다. 다음은 플래쉬 파일의 포맷 백서(white paper)이다.
http://www.macromedia.com/software/flash/open/spec/SWFfileformat.html
SWF파일 포맷
----------------
F UI8 기호 1byte
W UI8 기호 1byte
S UI8 기호 1byte
UI8 single byte file version 1byte
UI32 파일 크기 4byte (Unsigned Int in 32bit Compiler)
:
이런 식이었다.
그런데 문제는 Exe파일 도중에 어느 부분에서 절대적으로 나온다는 것은
정해지지 않았다. 나는 간단한 최소의 소스코드에 swf파일을 붙인 간단한
플래쉬 exe프로그램을 만들었다. 이때 FWS가 시작한 위치는0x2cf20 였다.
따라서 적어도 이 위치에서 부터 시작해서 보는 것이 좋을거라는 생각을했다.
이 위치서 부터 하나씩 읽어오면서 FWS가 나오면 SWF파일을 추출하는것이다.
다음은 FlashExtractor의 처음 버전인 Console 버전이다.
void Save_To_SWF( char* pStore, unsigned long size )
{
FILE* fp;
fp = fopen("sample.swf","wb");
if( fp == NULL)
{
printf(" Can't Write to SWF!!! \n");
return;
}
fwrite( (const void*)buf, sizeof(char), (long)size, fp);
fclose(fp);
}
unsigned long Extract_SWF_From_EXE( const char *pfname, char* pStore )
{
FILE* fp;
char size[4];
unsigned long wSize = 0;
memset( size, 0, sizeof(size) );
fp = fopen(pfname,"rb");
if( fp == NULL)
{
printf("[Error] : Can't Open %s !!!\n",pfname );
}
fseek( fp, (long)SKIP_EXE, 0 );
while( !feof( fp ))
{
if( fgetc(fp) == 'F' )
if( fgetc(fp) == 'W' )
if( fgetc(fp) == 'S' )
{ // then I found it!
printf("I Found it SWF .....\n");
fgetc(fp); // ignore one byte
memcpy( (void*)&wSize, 4, sizeof(char));
printf("Size : %ld\n",wSize);
fseek( fp, -8, SEEK_CUR);
pStore = new char[wSize];
fread( (void*)pStore, sizeof(char), (long)wSize, fp);
break;
}
}
}
fclose(fp);
return wSize;
}
============================================================================
다음은 MFC 버전이다.
// Extract to get SWF in EXE Resource
long CFlashExtractorDlg::ExtractSWF( char* sExeName, char*& pSwfBuf )
{
// Well I don't know where start resource address in Exe File
// But There exist After below address cos it was counted by small
// Dialog based application binary EXE.
// any app has a SWF after that address...
#define SKIP_EXE 0x2cf20L
CFile file;
long wSize = 0;
pSwfBuf = NULL;
file.Open( sExeName, CFile::modeRead | CFile::typeBinary );
if( file.m_hFile == NULL )
{
MessageBox("Can't Open Exe File","Error");
return 0;
}
// Set pos to find in exe fastly.
file.Seek( (LONG) SKIP_EXE, CFile::begin );
// blind finding will be start.
while( file.GetPosition() < file.GetLength() )
{
if( FGetC(file) == 'F' )
if( FGetC(file) == 'W' )
if( FGetC(file) == 'S' )
{ // then I found SWF in EXE
TRACE(" I Found SWF Resource \n");
FGetC(file); // ignore one byte header
// Read SWF Size in SWF Header
file.Read( (void*)&wSize, 4); // Maybe 4 byte . I guess --;
TRACE(" SWF Size : %ld\n",wSize );
// Return the pos to get entire SWF to SWFBUF
file.Seek( -8, CFile::current);
// and prepare BUF
// **CAUTION** I'll allocate pSwfBuf, Don't Alloc or Realloc
pSwfBuf = new char[wSize];
// And Read it!
file.Read( pSwfBuf, wSize);
TRACE(" SWF Readed\n");
break; // blah, now I have to relax , break break..
}
}
// File Close
file.Close();
return wSize; // Readed SWF File Size
}
void CFlashExtractorDlg::SaveToSWF( char*& pSwfBuf, long wSize, char* sSwfName )
{
CFile file(CFile::modeCreate | CFile::shareDenyNone );
file.Open( sSwfName, CFile::modeCreate |CFile::modeWrite| CFile::typeBinary );
file.Write( (void*)pSwfBuf, wSize );
file.Close();
delete [] pSwfBuf; // I'll delete pSwfBuf!
TRACE(" Saved SWF File To ; %s",sSwfName);
}
// Cute routine :) for emulate dos::fgetc, I love it.
char CFlashExtractorDlg::FGetC(CFile& file)
{
char buf;
file.Read(&buf, 1);
return buf;
}
===========================================================================
그리고 마지막으로 ATL COM 부분으로 만들었으며
STDMETHODIMP CSWFExtractor::get_ExeFileName(BSTR *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*pVal = (BSTR)(LPCTSTR)m_sExeFileName;
return S_OK;
}
STDMETHODIMP CSWFExtractor::put_ExeFileName(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
m_sExeFileName = newVal;
return S_OK;
}
STDMETHODIMP CSWFExtractor::get_SwfFileName(BSTR *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*pVal = (BSTR)(LPCTSTR)m_sSwfFileName;
return S_OK;
}
STDMETHODIMP CSWFExtractor::put_SwfFileName(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
m_sSwfFileName = newVal;
return S_OK;
}
// Extract to get SWF in EXE Resource
STDMETHODIMP CSWFExtractor::ExtractSWF()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
// Well I don't know where start resource address in Exe File
// But There exist After below address cos it was counted by small
// Dialog based application binary EXE.
// any app has a SWF after that address...
#define SKIP_EXE 0x2cf20L
CFile file;
UINT wSize = 0;
if( m_pSwfBuf != NULL)
delete [] m_pSwfBuf;
m_pSwfBuf = NULL;
if( file.Open( m_sExeFileName, CFile::modeRead | CFile::typeBinary ) == FALSE )
{
MessageBox(NULL,"Can't Open Exe File","Error",MB_OK);
return S_OK;
}
// Set pos to find in exe fastly.
file.Seek( (LONG) SKIP_EXE, CFile::begin );
// blind finding will be start.
while( file.GetPosition() < file.GetLength() )
{
if( FGetC(file) == 'F' )
if( FGetC(file) == 'W' )
if( FGetC(file) == 'S' )
{ // then I found SWF in EXE
TRACE(" I Found SWF Resource \n");
FGetC(file); // ignore one byte header ( File Version )
// Read SWF Size in SWF Header
file.Read( (void*)&wSize, 4); // Maybe 4 byte . I guess --; <- great! UI32 Type!
TRACE(" SWF Size : %ld\n",wSize );
// Return the pos to get entire SWF to SWFBUF
file.Seek( -8, CFile::current); // Back to the home!
// and prepare BUF
// **CAUTION** I'll allocate pSwfBuf, Don't Alloc or Realloc
m_pSwfBuf = new char[wSize];
// And Read it!
file.Read( m_pSwfBuf, wSize);
TRACE(" SWF Readed\n");
m_nSwfSize = wSize;
MessageBox(NULL,"Extract Finished ","Message",MB_OK);
CString buf;
buf.Format("%s %ld worked",(LPCTSTR)m_sExeFileName, m_nSwfSize);
MessageBox(NULL,(LPCTSTR)buf,"Message",MB_OK);
break; // blah, now I have to relax , break break..
}
}
// File Close
file.Close();
return S_OK;
}
STDMETHODIMP CSWFExtractor::SaveSWF()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
if( m_pSwfBuf == NULL)
{
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
CString sSwfName;
if( m_sSwfFileName.IsEmpty() == TRUE )
sSwfName = _T("sample.swf");
else
sSwfName = m_sSwfFileName;
CFile file(CFile::modeCreate | CFile::shareDenyNone );
file.Open( sSwfName, CFile::modeCreate |CFile::modeWrite| CFile::typeBinary );
file.Write( (void*)m_pSwfBuf, m_nSwfSize );
file.Close();
TRACE(" Saved SWF File To ; %s",sSwfName);
MessageBox(NULL,"Saved SWF ","Message",MB_OK);
return S_OK;
}
// Cute routine :) for emulate dos::fgetc, I love it.
char CSWFExtractor::FGetC(CFile& file)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
char buf;
file.Read(&buf, 1);
return buf;
}
STDMETHODIMP CSWFExtractor::GetSWFSize(long *RetVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*RetVal = 0;
if( m_pSwfBuf != NULL )
{
*RetVal = m_nSwfSize;
}
else
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
STDMETHODIMP CSWFExtractor::GetSWFData(BSTR *RetVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*RetVal = NULL;
if( m_pSwfBuf != NULL )
{
*RetVal = (BSTR)m_pSwfBuf;
}
else
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
==============================================================================
아래는 그것을 쓰는 예제이다.
Dim obj As New FLASHEXTRACTORLib.SWFExtractor
obj.ExeFileName = "c:\\Test.exe"
obj.SwfFileName = "c:\\my.swf"
obj.ExtractSWF
obj.SaveSWF
오후 10:08 99-12-02 조경민
-------------------------------------------------------------
상황 : SWF 플래쉬 파일을 Flash ActiveX컨트롤로 VC 프로그램에
붙여서 컴파일 하면 SWF파일은 VC프로그램안에 포함된다.
이때 Test.exe안에 포함된 어떤 SWF파일을 추출하여야 한다.
과정 :
먼저 나는 Test.exe파일을 바이너리로 열어 기존의 포함되었던 swf파일
도 바이너리로 열어서 비교해 보았다. 일딴 swf파일은 FWS라는 세바이트
로 시작하는것 같았다. 역시 Test.exe파일의 중하단 부분에 FWS로 시작
하는 부분이 있었다. 그 뒤는 swf파일과 동일하여 여기서 부터 추출을
하면 될거라 생각했다.
swf파일의 크기를 짐작하기
먼저 test.swf파일의 크기를 보았다. 0x082e로 2094 바이트였다.
이를 바이트로 나누니 2e 08로 들어갈것이므로 FWS부터 이 2e 08을 찾아
보았다.
F W S 2e 08 00 00 .... 이런식의 나열이었다. 플래쉬파일이 몇메가도
되므로~~~~~~~~~~~ 이부분이 파일의 크기라고 짐작을 하여 코딩을 하였다.
나중에 알게 되었다. 다음은 플래쉬 파일의 포맷 백서(white paper)이다.
http://www.macromedia.com/software/flash/open/spec/SWFfileformat.html
SWF파일 포맷
----------------
F UI8 기호 1byte
W UI8 기호 1byte
S UI8 기호 1byte
UI8 single byte file version 1byte
UI32 파일 크기 4byte (Unsigned Int in 32bit Compiler)
:
이런 식이었다.
그런데 문제는 Exe파일 도중에 어느 부분에서 절대적으로 나온다는 것은
정해지지 않았다. 나는 간단한 최소의 소스코드에 swf파일을 붙인 간단한
플래쉬 exe프로그램을 만들었다. 이때 FWS가 시작한 위치는0x2cf20 였다.
따라서 적어도 이 위치에서 부터 시작해서 보는 것이 좋을거라는 생각을했다.
이 위치서 부터 하나씩 읽어오면서 FWS가 나오면 SWF파일을 추출하는것이다.
다음은 FlashExtractor의 처음 버전인 Console 버전이다.
void Save_To_SWF( char* pStore, unsigned long size )
{
FILE* fp;
fp = fopen("sample.swf","wb");
if( fp == NULL)
{
printf(" Can't Write to SWF!!! \n");
return;
}
fwrite( (const void*)buf, sizeof(char), (long)size, fp);
fclose(fp);
}
unsigned long Extract_SWF_From_EXE( const char *pfname, char* pStore )
{
FILE* fp;
char size[4];
unsigned long wSize = 0;
memset( size, 0, sizeof(size) );
fp = fopen(pfname,"rb");
if( fp == NULL)
{
printf("[Error] : Can't Open %s !!!\n",pfname );
}
fseek( fp, (long)SKIP_EXE, 0 );
while( !feof( fp ))
{
if( fgetc(fp) == 'F' )
if( fgetc(fp) == 'W' )
if( fgetc(fp) == 'S' )
{ // then I found it!
printf("I Found it SWF .....\n");
fgetc(fp); // ignore one byte
memcpy( (void*)&wSize, 4, sizeof(char));
printf("Size : %ld\n",wSize);
fseek( fp, -8, SEEK_CUR);
pStore = new char[wSize];
fread( (void*)pStore, sizeof(char), (long)wSize, fp);
break;
}
}
}
fclose(fp);
return wSize;
}
============================================================================
다음은 MFC 버전이다.
// Extract to get SWF in EXE Resource
long CFlashExtractorDlg::ExtractSWF( char* sExeName, char*& pSwfBuf )
{
// Well I don't know where start resource address in Exe File
// But There exist After below address cos it was counted by small
// Dialog based application binary EXE.
// any app has a SWF after that address...
#define SKIP_EXE 0x2cf20L
CFile file;
long wSize = 0;
pSwfBuf = NULL;
file.Open( sExeName, CFile::modeRead | CFile::typeBinary );
if( file.m_hFile == NULL )
{
MessageBox("Can't Open Exe File","Error");
return 0;
}
// Set pos to find in exe fastly.
file.Seek( (LONG) SKIP_EXE, CFile::begin );
// blind finding will be start.
while( file.GetPosition() < file.GetLength() )
{
if( FGetC(file) == 'F' )
if( FGetC(file) == 'W' )
if( FGetC(file) == 'S' )
{ // then I found SWF in EXE
TRACE(" I Found SWF Resource \n");
FGetC(file); // ignore one byte header
// Read SWF Size in SWF Header
file.Read( (void*)&wSize, 4); // Maybe 4 byte . I guess --;
TRACE(" SWF Size : %ld\n",wSize );
// Return the pos to get entire SWF to SWFBUF
file.Seek( -8, CFile::current);
// and prepare BUF
// **CAUTION** I'll allocate pSwfBuf, Don't Alloc or Realloc
pSwfBuf = new char[wSize];
// And Read it!
file.Read( pSwfBuf, wSize);
TRACE(" SWF Readed\n");
break; // blah, now I have to relax , break break..
}
}
// File Close
file.Close();
return wSize; // Readed SWF File Size
}
void CFlashExtractorDlg::SaveToSWF( char*& pSwfBuf, long wSize, char* sSwfName )
{
CFile file(CFile::modeCreate | CFile::shareDenyNone );
file.Open( sSwfName, CFile::modeCreate |CFile::modeWrite| CFile::typeBinary );
file.Write( (void*)pSwfBuf, wSize );
file.Close();
delete [] pSwfBuf; // I'll delete pSwfBuf!
TRACE(" Saved SWF File To ; %s",sSwfName);
}
// Cute routine :) for emulate dos::fgetc, I love it.
char CFlashExtractorDlg::FGetC(CFile& file)
{
char buf;
file.Read(&buf, 1);
return buf;
}
===========================================================================
그리고 마지막으로 ATL COM 부분으로 만들었으며
STDMETHODIMP CSWFExtractor::get_ExeFileName(BSTR *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*pVal = (BSTR)(LPCTSTR)m_sExeFileName;
return S_OK;
}
STDMETHODIMP CSWFExtractor::put_ExeFileName(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
m_sExeFileName = newVal;
return S_OK;
}
STDMETHODIMP CSWFExtractor::get_SwfFileName(BSTR *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*pVal = (BSTR)(LPCTSTR)m_sSwfFileName;
return S_OK;
}
STDMETHODIMP CSWFExtractor::put_SwfFileName(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
m_sSwfFileName = newVal;
return S_OK;
}
// Extract to get SWF in EXE Resource
STDMETHODIMP CSWFExtractor::ExtractSWF()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
// Well I don't know where start resource address in Exe File
// But There exist After below address cos it was counted by small
// Dialog based application binary EXE.
// any app has a SWF after that address...
#define SKIP_EXE 0x2cf20L
CFile file;
UINT wSize = 0;
if( m_pSwfBuf != NULL)
delete [] m_pSwfBuf;
m_pSwfBuf = NULL;
if( file.Open( m_sExeFileName, CFile::modeRead | CFile::typeBinary ) == FALSE )
{
MessageBox(NULL,"Can't Open Exe File","Error",MB_OK);
return S_OK;
}
// Set pos to find in exe fastly.
file.Seek( (LONG) SKIP_EXE, CFile::begin );
// blind finding will be start.
while( file.GetPosition() < file.GetLength() )
{
if( FGetC(file) == 'F' )
if( FGetC(file) == 'W' )
if( FGetC(file) == 'S' )
{ // then I found SWF in EXE
TRACE(" I Found SWF Resource \n");
FGetC(file); // ignore one byte header ( File Version )
// Read SWF Size in SWF Header
file.Read( (void*)&wSize, 4); // Maybe 4 byte . I guess --; <- great! UI32 Type!
TRACE(" SWF Size : %ld\n",wSize );
// Return the pos to get entire SWF to SWFBUF
file.Seek( -8, CFile::current); // Back to the home!
// and prepare BUF
// **CAUTION** I'll allocate pSwfBuf, Don't Alloc or Realloc
m_pSwfBuf = new char[wSize];
// And Read it!
file.Read( m_pSwfBuf, wSize);
TRACE(" SWF Readed\n");
m_nSwfSize = wSize;
MessageBox(NULL,"Extract Finished ","Message",MB_OK);
CString buf;
buf.Format("%s %ld worked",(LPCTSTR)m_sExeFileName, m_nSwfSize);
MessageBox(NULL,(LPCTSTR)buf,"Message",MB_OK);
break; // blah, now I have to relax , break break..
}
}
// File Close
file.Close();
return S_OK;
}
STDMETHODIMP CSWFExtractor::SaveSWF()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
if( m_pSwfBuf == NULL)
{
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
CString sSwfName;
if( m_sSwfFileName.IsEmpty() == TRUE )
sSwfName = _T("sample.swf");
else
sSwfName = m_sSwfFileName;
CFile file(CFile::modeCreate | CFile::shareDenyNone );
file.Open( sSwfName, CFile::modeCreate |CFile::modeWrite| CFile::typeBinary );
file.Write( (void*)m_pSwfBuf, m_nSwfSize );
file.Close();
TRACE(" Saved SWF File To ; %s",sSwfName);
MessageBox(NULL,"Saved SWF ","Message",MB_OK);
return S_OK;
}
// Cute routine :) for emulate dos::fgetc, I love it.
char CSWFExtractor::FGetC(CFile& file)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
char buf;
file.Read(&buf, 1);
return buf;
}
STDMETHODIMP CSWFExtractor::GetSWFSize(long *RetVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*RetVal = 0;
if( m_pSwfBuf != NULL )
{
*RetVal = m_nSwfSize;
}
else
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
STDMETHODIMP CSWFExtractor::GetSWFData(BSTR *RetVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*RetVal = NULL;
if( m_pSwfBuf != NULL )
{
*RetVal = (BSTR)m_pSwfBuf;
}
else
MessageBox(NULL,"Sorry but u have to ExtractSWF to do this before ","Message",MB_OK);
return S_OK;
}
==============================================================================
아래는 그것을 쓰는 예제이다.
Dim obj As New FLASHEXTRACTORLib.SWFExtractor
obj.ExeFileName = "c:\\Test.exe"
obj.SwfFileName = "c:\\my.swf"
obj.ExtractSWF
obj.SaveSWF
'KB > MFC/Win32' 카테고리의 다른 글
C++로 간단한 윈도우NT 서비스 만들기 (0) | 2004.03.19 |
---|---|
8255, RS232 , IO 포트 , 시리얼 포트 제어 정리 (0) | 2004.03.19 |
[mfc] 소켓 서포트 안하고 쓰기 (0) | 2004.03.19 |
DLL을 사용하자 (0) | 2004.03.19 |
다이얼로그 베이스 DB프로그램 짜기 (0) | 2004.03.19 |