首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 將 EXE 內嵌 SWF 提取轉換為獨立 SWF 檔案

     編輯:VC 教學

前言

某些應用程式將 SWF (Flash) 檔案內嵌於 EXE 資源中,或以特定格式附加於 EXE 尾端。本文提供一個實用函式 exe2swf,掃描 EXE 檔案尋找 FWS (SWF 標誌) 簽名,提取後續資料並存為獨立 .swf 檔案,支援 Flash 6 格式。

完整轉換函式


AnsiString exe2swf(AnsiString FileName)
{
    int iFileHandle;
    unsigned long iFileLength;
    unsigned long iBytesRead;
    AnsiString dFileName;
    unsigned char* pszBuffer;

    // 1. 開啟來源 EXE
    iFileHandle = FileOpen(FileName.c_str(), fmOpenRead);
    if (iFileHandle < 0) return NULL;

    // 2. 取得檔案長度
    iFileLength = FileSeek(iFileHandle, 0, 2); // 從末尾偏移 0
    FileSeek(iFileHandle, 0, 0);               // 回到開頭

    // 3. 分配緩衝區讀入整個檔案
    pszBuffer = new unsigned char[iFileLength + 1];
    if (!pszBuffer)
    {
        FileClose(iFileHandle);
        return NULL;
    }

    iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
    FileClose(iFileHandle);

    // 4. 產生目標 SWF 檔名 (同目錄、同主檔名、副檔名 .SWF)
    dFileName = FileName.UpperCase().SubString(1, FileName.Length() - 4) + ".SWF";

    // 5. 掃描尋找 "FWS" 簽名 (0x46 0x57 0x53)
    // 注意:原碼邏輯為尋找前兩字節為 0, 0, 第三字節為 'F'...
    // 這暗示 SWF 前有特定填充或標記,實際 SWF 檔案開頭即為 "FWS" 或 "CWS"
    int i = 0, ii = 0;
    for (i = 0; i < (int)iFileLength - 2; i++)
    {
        // 原碼條件:pszBuffer[i-2]==0 && pszBuffer[i-1]==0 && pszBuffer[i]=='F'...
        // 這裡修正為標準 SWF 簽名搜尋:直接找 "FWS" 或 "CWS"
        if (i + 2 < (int)iFileLength &&
            pszBuffer[i] == 'F' && pszBuffer[i+1] == 'W' && pszBuffer[i+2] == 'S')
        {
            ii = i;
            break; // 找到第一個即可
        }
        // 兼容壓縮 SWF (CWS)
        if (i + 2 < (int)iFileLength &&
            pszBuffer[i] == 'C' && pszBuffer[i+1] == 'W' && pszBuffer[i+2] == 'S')
        {
            ii = i;
            break;
        }
    }

    if (ii == 0 && !(pszBuffer[0]=='F' && pszBuffer[1]=='W' && pszBuffer[2]=='S'))
    {
        // 未找到簽名
        delete[] pszBuffer;
        return NULL;
    }

    // 6. 移動緩衝區指標至簽名位置
    pszBuffer += ii;
    unsigned long swfLength = iFileLength - ii;

    // 7. 版本檢查 (原碼針對特定偏移值判斷 Flash 4/5/6)
    // 這裡簡化:直接寫入,播放器自行處理版本相容
    // if (ii != 376831 && ii != 286719 && ii != 811008) { ... }

    // 8. 建立並寫入 SWF 檔案
    iFileHandle = FileCreate(dFileName.c_str());
    if (iFileHandle >= 0)
    {
        FileWrite(iFileHandle, pszBuffer, swfLength);
        FileClose(iFileHandle);
    }

    // 9. 釋放原始緩衝區 (注意:pszBuffer 已偏移,需回推)
    pszBuffer -= ii;
    delete[] pszBuffer;

    return dFileName;
}

關鍵技術點解析

SWF 檔案格式簽名

標準 SWF 檔案開頭即為簽名,無額外填充。原碼搜尋 00 00 FWS 暗示該 EXE 將 SWF 以特定方式內嵌(如前綴兩個零字節)。

VCL 檔案操作函式

簽名十六進位含義
FWS46 57 53未壓縮 SWF (Flash 6+)
CWS43 57 53Zlib 壓縮 SWF (Flash 6+)
ZWS5A 57 53LZMA 壓縮 SWF (Flash 11+)
函式對應 API說明
FileOpenCreateFilefmOpenRead=0, fmOpenWrite=1, fmOpenReadWrite=2
FileCreateCreateFile (CREATE_ALWAYS)
FileSeekSetFilePointerorigin: 0=始, 1=當前, 2=末
FileReadReadFile
FileWriteWriteFile
FileCloseCloseHandle

記憶體管理細節

  • new unsigned char[size] 分配陣列,必須配對 delete[]。
  • 指標偏移 pszBuffer += ii 後寫入,寫入完成前必須回推 pszBuffer -= ii 才能正確 delete[]。
  • 現代 C++ 建議用 std::vector 或 std::unique_ptr 避免手動管理錯誤。

改良版:支援多 SWF 提取、資源表掃描、錯誤處理


std::vector ExtractAllSwfFromExe(AnsiString exePath)
{
    std::vector results;
    int hFile = FileOpen(exePath.c_str(), fmOpenRead);
    if (hFile < 0) return results;

    unsigned long len = FileSeek(hFile, 0, 2);
    FileSeek(hFile, 0, 0);

    std::vector buf(len);
    FileRead(hFile, buf.data(), len);
    FileClose(hFile);

    const char* sigs[] = {"FWS", "CWS", "ZWS"};
    for (unsigned long i = 0; i + 3 < len; ++i)
    {
        for (const char* sig : sigs)
        {
            if (buf[i] == sig[0] && buf[i+1] == sig[1] && buf[i+2] == sig[2])
            {
                // 找到 SWF 簽名,嘗試解析長度 (SWF Header 第 4-7 字節為檔案長度)
                if (i + 8 <= len)
                {
                    DWORD swfLen = *(DWORD*)(buf.data() + i + 4); // Little-endian
                    if (swfLen > 0 && swfLen <= len - i)
                    {
                        AnsiString outName = exePath + "_swf_" + IntToStr(results.size()) + ".swf";
                        int hOut = FileCreate(outName.c_str());
                        if (hOut >= 0)
                        {
                            FileWrite(hOut, buf.data() + i, swfLen);
                            FileClose(hOut);
                            results.push_back(outName);
                        }
                        i += swfLen - 1; // 跳過此 SWF
                        break;
                    }
                }
            }
        }
    }
    return results;
}

應用場景

  • 逆向分析:提取惡意軟體/廣告軟體內嵌的 SWF 載入器分析行為。
  • 資源回收:從舊專案 EXE 中回收遺失原始碼的 SWF 動畫/遊戲素材。
  • 格式轉換:批次將目錄下所有含 SWF 的 EXE 轉為獨立 SWF 供播放器播放。
  • 安全審計:檢查 EXE 是否攜帶未授權/惡意 SWF 內容。

法律提醒

提取內嵌 SWF 可能涉及:

  • 軟體授權條款:禁止反組譯、提取資源。
  • 著作權法:SWF 內容受著作權保護。
  • 數位千禧年版權法 (DMCA) / 相應法規:繞過保護措施提取可能違法。

僅在合法授權、安全研究、個人合理使用範圍內使用此技術。

掌握二進位檔案掃描與格式簽名識別技巧,不僅能提取 SWF,同樣適用於 PNG、JPG、ZIP、PE 等任何已知魔數的檔案格式提取與分析。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved