⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cresourceripper.cpp

📁 pe exe packer (must use vc2005 to compile)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Author:   Brandon LaCombe
// Date:     February 3, 2006
// License:  Public Domain
#include "CResourceRipper.h"
#include "..\..\FileTools.h"
#include "..\..\remem.h"

// user defined types

// Defines the nodes that make up the filter level linked list attachted to each
// RESOURCEFILTER structure.
typedef struct _FILTERLEVEL FILTERLEVEL, *PFILTERLEVEL;

struct _FILTERLEVEL
{
    PFILTERLEVEL pNext;

    DWORD dwLevel;      // level the filter applies to
    DWORD dwFlags;
    union
    {
        WORD  wId;
        PTSTR pString;
    };
};

// Defines the nodes that make up the filter linked list.
struct _RESOURCEFILTER
{
    PRESOURCEFILTER pNext;

    DWORD        dwId;
    PFILTERLEVEL pLevels;
};

// Defines the nodes that makeup the resource tree structure. The tree mirrors
// the information stored in the resource section of the pe file processed.
struct _RESOURCELEAF
{
    // LINKAGE VARIABLES (used to form the tree structure)
    PRESOURCELEAF pParent;
    PRESOURCELEAF pSibling;
    PRESOURCELEAF pChild;

    // COMMON VARIABLES (used in directory and data leaves)
    DWORD dwLevel;          // level of the leaf (total number of parents)
    BOOL bDirectory;

    BOOL     bNameIsString;
    union
    {
        WORD wId;
        WORD wNameLength;
    };
    PTSTR    pNameString;

    // DATA LEAF VARIABLES (only used if leaf is a data leaf)
    BOOL  bDeleteFlag;
    BOOL  bRetain;

    DWORD dwDataSize;
    union
    {
        DWORD dwDataRva; // if leaf is not retained then contains the rva
        PBYTE pbData;    // otherwise it is a memory pointer to the data
    };
};

// Combines the three different output pointers into one variable.
struct _RESOURCEPOINTERS
{
    PBYTE pbOutput;
    PBYTE pbHeaders;
    PBYTE pbStrings;
    PBYTE pbData;
};

// code start

// Class constructor.
CResourceRipper::CResourceRipper()
{
    m_hHeap = GetProcessHeap();
    m_pDeletionFilters = NULL;
    m_pRetentionFilters = NULL;
    m_pResourceTree = NULL;
    m_dwHeaderSize = 0;
    m_dwStringSize = 0;
    m_dwDataSize = 0;
    m_bMoveData = TRUE;
    m_bNullSource = FALSE;
    m_bStrip = FALSE;
}

// Class destructor.
CResourceRipper::~CResourceRipper()
{
    DeleteResources(m_pResourceTree, TRUE);
    DeleteFilters(&m_pRetentionFilters);
    DeleteFilters(&m_pDeletionFilters);
}

// Wrapper around the AddFilter function.
VOID CResourceRipper::AddDeletionFilter(DWORD dwId, DWORD dwLevel, DWORD dwFlags, PVOID pvName)
{
    AddFilter(&m_pDeletionFilters, dwId, dwLevel, dwFlags, pvName);
}

// Adds a resource filter to the specified filter linked list.
VOID CResourceRipper::AddFilter(PRESOURCEFILTER * pFilterList, DWORD dwId, DWORD dwLevel, DWORD dwFlags, PVOID pvName)
{
    BOOL            bRet;
    PRESOURCEFILTER pFilter;
    PFILTERLEVEL    pCurrentLevel,
                  * ppLink;
    DWORD           dwLength;


    bRet = FALSE;

    // get a pointer to a filter with the specified id or create a new filter
    // if no filter has that id
    pFilter = LocateFilter(*pFilterList, dwId);
    if(pFilter == NULL)
        pFilter = CreateFilter(pFilterList, dwId);

    // go to the end of the level list
    ppLink = &pFilter->pLevels;
    pCurrentLevel = pFilter->pLevels;
    while(pCurrentLevel)
    {
        // level already exists so edit it
        if(pCurrentLevel->dwLevel == dwLevel)
            break;

        ppLink = &pCurrentLevel->pNext;
        pCurrentLevel = pCurrentLevel->pNext;
    }

    // if the filter level doesn't already exist then create it
    if(pCurrentLevel == NULL)
        pCurrentLevel = (PFILTERLEVEL)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, sizeof(FILTERLEVEL));

    *ppLink = pCurrentLevel;

    // if FF_STRING is present in the flags then we must be modifying
    // an existing level, so we free the memory associated with pString
    if(pCurrentLevel->dwFlags & FF_STRING)
        HeapFree(m_hHeap, 0, pCurrentLevel->pString);

    pCurrentLevel->dwLevel = dwLevel;
    pCurrentLevel->dwFlags = dwFlags;
    if(dwFlags & FF_STRING)
    {
        dwLength = lstrlen((PTSTR)pvName);
        pCurrentLevel->pString = (PTSTR)HeapAlloc(m_hHeap, 0, (dwLength + 1) * sizeof(TCHAR));
        lstrcpy(pCurrentLevel->pString, (PTSTR)pvName);
    }
    else
    {
        pCurrentLevel->wId = (WORD)pvName;
    }
}

// Wrapper around the AddFilter function.
VOID CResourceRipper::AddRetentionFilter(DWORD dwId, DWORD dwLevel, DWORD dwFlags, PVOID pvName)
{
    AddFilter(&m_pRetentionFilters, dwId, dwLevel, dwFlags, pvName);
}

// Counts the number of siblings the specified leaf has.
DWORD CResourceRipper::CountSiblings(PRESOURCELEAF pLeaf)
{
    DWORD         dwCount;
    PRESOURCELEAF pCurrentLeaf;

    dwCount = 0;
    pCurrentLeaf = FindFirstLeaf(pLeaf, FALSE);
    while(pCurrentLeaf)
    {
        dwCount++;
        pCurrentLeaf = pCurrentLeaf->pSibling;
    }
    return dwCount;
}

// Creates a filter and adds it to the specified list.
PRESOURCEFILTER CResourceRipper::CreateFilter(PRESOURCEFILTER * pFilterList, DWORD dwId)
{
    PRESOURCEFILTER * ppLink,
                      pNewFilter;

    pNewFilter = (PRESOURCEFILTER)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, sizeof(RESOURCEFILTER));
    pNewFilter->dwId = dwId;

    ppLink = pFilterList;
    while(*ppLink)
        ppLink = &(*ppLink)->pNext;
    *ppLink = pNewFilter;

    return pNewFilter;
}

// Deletes a filter tree.
VOID CResourceRipper::DeleteFilters(PRESOURCEFILTER * pFilter)
{
    PRESOURCEFILTER pCurrentFilter,
                    pNextFilter;
    PFILTERLEVEL    pCurrentLevel,
                    pNextLevel;

    pCurrentFilter = *pFilter;
    while(pCurrentFilter)
    {
        pNextFilter = pCurrentFilter->pNext;

        pCurrentLevel = pCurrentFilter->pLevels;
        while(pCurrentLevel)
        {
            pNextLevel = pCurrentLevel->pNext;
            if(pCurrentLevel->dwFlags & FF_STRING)
                HeapFree(m_hHeap, 0, pCurrentLevel->pString);
            HeapFree(m_hHeap, 0, pCurrentLevel);
            pCurrentLevel = pNextLevel;
        }

        HeapFree(m_hHeap, 0, pCurrentFilter);
        pCurrentFilter = pNextFilter;
    }
    *pFilter = NULL;
}

// Deletes a resource leaf.
// Returns TRUE if the leaf deleted was the last leaf at that level.
BOOL CResourceRipper::DeleteLeaf(PRESOURCELEAF pLeaf)
{
    BOOL            bRet;
    PBYTE           pbData;
    PRESOURCELEAF * ppLink;

    // assume there are no sibling leaves
    bRet = TRUE;

    // here we determine where the specified leaf is linked from
    if(pLeaf->pParent)
    {
        // start with the child of the parent
        ppLink = &pLeaf->pParent->pChild;

        // keep looping till we find the specified leaf
        while(*ppLink != pLeaf)
        {
            bRet = FALSE;
            ppLink = &(*ppLink)->pSibling;
        }
    }
    else
        // dummy node, so it's linked from the class member variable
        ppLink = &m_pResourceTree;

    // unlink the to be deleted leaf
    *ppLink = pLeaf->pSibling;

    // handle string
    if(pLeaf->bNameIsString)
    {
        HeapFree(m_hHeap, 0, pLeaf->pNameString);
        m_dwStringSize -= (pLeaf->wNameLength * sizeof(WCHAR) + sizeof(((PIMAGE_RESOURCE_DIRECTORY_STRING)0)->Length));
    }

    // handle data
    if(pLeaf->bDirectory == FALSE)
    {
        if(pLeaf->bRetain)
        {
            VirtualFree(pLeaf->pbData, 0, MEM_RELEASE);
            m_dwDataSize -= pLeaf->dwDataSize;
        }
        else
        {
            if(m_bNullSource)
            {
                pbData = RvaToPointer(m_pbFile, pLeaf->dwDataRva);
                ZeroMemory(pbData, pLeaf->dwDataSize);
            }
        }
    }

    if(pLeaf->pSibling)
        bRet = FALSE;

    // update header size
    if(pLeaf->pParent)
    {
        m_dwHeaderSize -= sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY);

        if(pLeaf->bDirectory == FALSE)
            m_dwHeaderSize -= sizeof(IMAGE_RESOURCE_DATA_ENTRY);

        if(bRet)
            m_dwHeaderSize -= sizeof(IMAGE_RESOURCE_DIRECTORY);
    }

    HeapFree(m_hHeap, 0, pLeaf);
    return bRet;
}

// Deletes all leaves that are flagged for deletion. Also cleans up empty
// directories. Returns TRUE if the entire tree was deleted.
BOOL CResourceRipper::DeleteResources(PRESOURCELEAF pLeaf, BOOL bDeleteAll)
{
    PRESOURCELEAF pCurrentLeaf,
                  pNextLeaf;

    // loop through all siblings
    pCurrentLeaf = pLeaf;
    while(pCurrentLeaf)
    {
        pNextLeaf = pCurrentLeaf->pSibling;

        // recusively search the tree
        if(DeleteResources(pCurrentLeaf->pChild, bDeleteAll))
        {
            // if all children were delted then delete this one also
            if(DeleteLeaf(pCurrentLeaf))
                return TRUE; // i have no siblings now
        }
        else if(pCurrentLeaf->bDirectory == FALSE) // found a data leaf
        {
            if(pCurrentLeaf->bDeleteFlag || bDeleteAll)
            {
                if(DeleteLeaf(pCurrentLeaf))
                    return TRUE; // i have no siblings now
            }
        }
        pCurrentLeaf = pNextLeaf;
    }
    return FALSE;
}

// Callback used to set deletion flag on filtered resources.
VOID CResourceRipper::DeletionCallback(PRESOURCELEAF pDataLeaf)
{
    if(pDataLeaf->bRetain == FALSE)
        pDataLeaf->bDeleteFlag = TRUE;
}

// Driver for exporting a resource section.
VOID CResourceRipper::Export(PVOID pvOutput, DWORD dwBaseRva)
{
    RESOURCEPOINTERS OutputPointers;

    if(pvOutput && m_pResourceTree)
    {
        OutputPointers.pbOutput = (PBYTE)pvOutput;
        OutputPointers.pbHeaders = OutputPointers.pbOutput;
        OutputPointers.pbStrings = OutputPointers.pbHeaders + m_dwHeaderSize;
        OutputPointers.pbData = OutputPointers.pbStrings + m_dwStringSize;
        ExportLeaf(m_pResourceTree, &OutputPointers, dwBaseRva);
    }
}

// Exports a leaf and all it's siblings.
VOID CResourceRipper::ExportLeaf(PRESOURCELEAF pParentLeaf, PRESOURCEPOINTERS pOutputPointers, DWORD dwBaseRva)
{
    DWORD                            dwDirSize,
                                     dwEntryCount,
                                     x,
                                     y;
    PRESOURCELEAF                    pCurrentLeaf;
    PIMAGE_RESOURCE_DATA_ENTRY       pDataEntry;
    PIMAGE_RESOURCE_DIRECTORY        pDir;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY  pEntries;
    PIMAGE_RESOURCE_DIRECTORY_STRING pString;

    pCurrentLeaf = pParentLeaf->pChild;
    if(pCurrentLeaf)
    {
        // reserve memory for directories and entries
        pDir = (PIMAGE_RESOURCE_DIRECTORY)pOutputPointers->pbHeaders;
        pEntries = PIMAGE_RESOURCE_DIRECTORY_ENTRY(pDir + 1);
        dwEntryCount = CountSiblings(pCurrentLeaf);
        dwDirSize = sizeof(IMAGE_RESOURCE_DIRECTORY) + sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) * dwEntryCount;
        ZeroMemory(pOutputPointers->pbHeaders, dwDirSize);
        pOutputPointers->pbHeaders += dwDirSize;

        // loop through each leaf
        for(x = 0; x < dwEntryCount; x++)
        {
            // handle naming
            if(pCurrentLeaf->bNameIsString)
            {
                pDir->NumberOfNamedEntries++;
                pEntries[x].NameIsString = TRUE;
                pEntries[x].NameOffset = pOutputPointers->pbStrings - pOutputPointers->pbOutput;
                pString = (PIMAGE_RESOURCE_DIRECTORY_STRING)pOutputPointers->pbStrings;
                pString->Length = pCurrentLeaf->wNameLength;

                // need to copy char by char for ansi compilations
                for(y = 0; y < pString->Length; y++)
                    PWSTR(pString->NameString)[y] = (WCHAR)pCurrentLeaf->pNameString[y];
                pOutputPointers->pbStrings += (pCurrentLeaf->wNameLength * sizeof(WCHAR) + sizeof(pString->Length));
            }
            else
            {
                pDir->NumberOfIdEntries++;
                pEntries[x].Id = pCurrentLeaf->wId;
            }

            // handle directory/data pointer
            if(pCurrentLeaf->bDirectory)
            {
                pEntries[x].DataIsDirectory = TRUE;
                pEntries[x].OffsetToDirectory = pOutputPointers->pbHeaders - pOutputPointers->pbOutput;

                // recursively handle the directory
                ExportLeaf(pCurrentLeaf, pOutputPointers, dwBaseRva);
            }
            else
            {
                pEntries[x].OffsetToData = DWORD(pOutputPointers->pbHeaders - pOutputPointers->pbOutput);
                pDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)pOutputPointers->pbHeaders;
                ZeroMemory(pDataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
                pOutputPointers->pbHeaders += sizeof(IMAGE_RESOURCE_DATA_ENTRY);
                pDataEntry->Size = pCurrentLeaf->dwDataSize;

                // do we need to use the old data rva or write new data?
                if(pCurrentLeaf->bRetain)
                {
                    CopyMemory(pOutputPointers->pbData, pCurrentLeaf->pbData, pCurrentLeaf->dwDataSize);
                    pDataEntry->OffsetToData = dwBaseRva + (pOutputPointers->pbData - pOutputPointers->pbOutput);
                    pOutputPointers->pbData += pCurrentLeaf->dwDataSize;
                }
                else
                    pDataEntry->OffsetToData = pCurrentLeaf->dwDataRva;
            }
            pCurrentLeaf = pCurrentLeaf->pSibling;
        }
    }
}

// Wraps the recursive function ProcessDirectory to encapsulate its operation.
VOID CResourceRipper::ExtractResources()
{
    m_dwHeaderSize = 0;
    m_dwStringSize = 0;
    m_dwDataSize = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -