cresourceripper.cpp
来自「pe exe packer (must use vc2005 to compil」· C++ 代码 · 共 895 行 · 第 1/2 页
CPP
895 行
// allocate a dummy node
m_pResourceTree = (PRESOURCELEAF)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, sizeof(RESOURCELEAF));
ProcessDirectory((PIMAGE_RESOURCE_DIRECTORY)m_pbRsrc, m_pResourceTree);
}
// Performs the retention and deletion processes and cleans up deleted leaves.
VOID CResourceRipper::FilterResources()
{
ProcessLeaf(m_pResourceTree, m_pRetentionFilters, &CResourceRipper::RetentionCallback);
ProcessLeaf(m_pResourceTree, m_pDeletionFilters, &CResourceRipper::DeletionCallback);
DeleteResources(m_pResourceTree, m_bStrip);
}
// Returns the first or the last sibling of the supplied leaf alphabetically
// sorted. Note that strings are considered greater than ids.
PRESOURCELEAF CResourceRipper::FindAlphaLeaf(PRESOURCELEAF pLeaf, BOOL bNot)
{
PRESOURCELEAF pAlphaLeaf,
pCurrentLeaf;
BOOL bNewAlpha;
pAlphaLeaf = FindFirstLeaf(pLeaf, FALSE);
pCurrentLeaf = pAlphaLeaf->pSibling;
while(pCurrentLeaf)
{
bNewAlpha = FALSE;
if(pAlphaLeaf->bNameIsString = pCurrentLeaf->bNameIsString)
{
if(pAlphaLeaf->bNameIsString) // both leaves are strings
{
if(lstrcmp(pAlphaLeaf->pNameString, pCurrentLeaf->pNameString) > 0)
bNewAlpha = TRUE;
}
else // both leaves are ids
{
if(pAlphaLeaf->wId > pCurrentLeaf->wId)
bNewAlpha = TRUE;
}
}
else if(pAlphaLeaf->bNameIsString)
bNewAlpha = TRUE;
if(bNot)
bNewAlpha ^= TRUE;
if(bNewAlpha)
pAlphaLeaf = pCurrentLeaf;
pCurrentLeaf = pCurrentLeaf->pSibling;
}
return pAlphaLeaf;
}
// Returns the first or the last sibling of the supplied leaf.
PRESOURCELEAF CResourceRipper::FindFirstLeaf(PRESOURCELEAF pLeaf, BOOL bNot)
{
PRESOURCELEAF pFirstLeaf;
pFirstLeaf = pLeaf->pParent->pChild;
if(bNot)
{
while(pFirstLeaf->pSibling)
pFirstLeaf = pFirstLeaf->pSibling;
}
return pFirstLeaf;
}
// Returns the parent of the specified data leaf that is at the specified level.
PRESOURCELEAF CResourceRipper::FindLeafByLevel(PRESOURCELEAF pDataLeaf, DWORD dwLevel)
{
PRESOURCELEAF pLeaf;
pLeaf = NULL;
if(dwLevel <= pDataLeaf->dwLevel)
{
pLeaf = pDataLeaf;
while(pLeaf->dwLevel != dwLevel)
pLeaf = pLeaf->pParent;
}
return pLeaf;
}
// Calculates the size of the resource section upon export.
DWORD CResourceRipper::GetSize()
{
return m_dwHeaderSize + m_dwStringSize + m_dwDataSize;
}
// Checks if a supplied data leaf is a GROUP_ICON or GROUP_CURSOR data item.
BOOL CResourceRipper::IsGroupIconOrCursor(PRESOURCELEAF pDataLeaf)
{
BOOL bRet;
PRESOURCELEAF pTypeLeaf;
bRet = FALSE;
if(pDataLeaf->bDirectory == FALSE)
{
if(pDataLeaf->dwLevel == 3 && pDataLeaf->bNameIsString == FALSE)
{
pTypeLeaf = FindLeafByLevel(pDataLeaf, 1);
if(pTypeLeaf)
{
if(pTypeLeaf->bNameIsString == FALSE)
{
if(pTypeLeaf->wId == (WORD)RT_GROUP_ICON || pTypeLeaf->wId == (WORD)RT_GROUP_CURSOR)
{
bRet = TRUE;
}
}
}
}
}
return bRet;
}
// Sets up input file pointers. Returns TRUE if the input has a resource section.
BOOL CResourceRipper::LoadFile(PBYTE pbFile)
{
BOOL bRet;
DWORD dwRsrcRva;
PIMAGE_NT_HEADERS pNt;
bRet = FALSE;
m_pbFile = pbFile;
pNt = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew);
dwRsrcRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
m_pbRsrc = RvaToPointer(pbFile, dwRsrcRva);
if(m_pbRsrc) bRet = TRUE;
return bRet;
}
// Locates a filter in the linked list with the specified uid.
PRESOURCEFILTER CResourceRipper::LocateFilter(PRESOURCEFILTER pFilterList, DWORD dwId)
{
PRESOURCEFILTER pCurrentFilter;
pCurrentFilter = pFilterList;
while(pCurrentFilter)
{
if(pCurrentFilter->dwId == dwId)
return pCurrentFilter;
pCurrentFilter = pCurrentFilter->pNext;
}
return NULL;
}
// Tells the ripper whether or not it should null out the original resources.
VOID CResourceRipper::MoveData(BOOL bMoveData)
{
m_bMoveData = bMoveData;
}
// Parses the RT_GROUP_ICON or RT_GROUP_CURSOR data to determine which icons or
// cursors it refers to. Next, it searches the resource tree for the icons or
// cursors and calls the specified callback.
VOID CResourceRipper::ParseGroupIconOrCursor(PRESOURCELEAF pGroupLeaf, FILTERCALLBACK pfCallback)
{
PGRPDIR pHeader;
PGRPDIRENTRY pEntries;
DWORD x;
WORD wTypeId;
PRESOURCELEAF pTypeLeaf,
pIdLeaf,
pLangLeaf;
if(pGroupLeaf->bRetain)
pHeader = (PGRPDIR)pGroupLeaf->pbData;
else
pHeader = (PGRPDIR)RvaToPointer(m_pbFile, pGroupLeaf->dwDataRva);
if(pHeader)
{
pEntries = PGRPDIRENTRY(pHeader + 1);
// Convert directory type id to resource type id
wTypeId = 0;
if(pHeader->idType == 1) wTypeId = (WORD)RT_ICON;
else if(pHeader->idType == 2) wTypeId = (WORD)RT_CURSOR;
if(wTypeId)
{
// we start searching the level 1 leaves looking for RT_ICON or RT_CURSOR
pTypeLeaf = m_pResourceTree->pChild;
while(pTypeLeaf)
{
if(pTypeLeaf->bNameIsString == FALSE && pTypeLeaf->wId == wTypeId)
{
// now loop through each group entry
for(x = 0; x < pHeader->idCount; x++)
{
// search level 2 leaves for id in the group entry
pIdLeaf = pTypeLeaf->pChild;
while(pIdLeaf)
{
if(pIdLeaf->bNameIsString == FALSE && pIdLeaf->wId == pEntries[x].nID)
{
pLangLeaf = pIdLeaf->pChild;
while(pLangLeaf)
{
// ensure the level 3 leaf is a data leaf
if(pLangLeaf->bDirectory == FALSE)
{
// only process icons with same language id as group entry
if(pLangLeaf->wId == pGroupLeaf->wId)
{
(this->*pfCallback)(pLangLeaf);
}
}
pLangLeaf = pLangLeaf->pSibling;
}
}
pIdLeaf = pIdLeaf->pSibling;
}
}
}
pTypeLeaf = pTypeLeaf->pSibling;
}
}
}
}
// Does the actual ripping of the resources from the input file.
VOID CResourceRipper::ProcessDirectory(PIMAGE_RESOURCE_DIRECTORY pDir, PRESOURCELEAF pParentLeaf)
{
DWORD dwEntryCount,
x,
y;
PIMAGE_RESOURCE_DIRECTORY pChildDirectory;
PRESOURCELEAF pCurrentLeaf,
* ppLink;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pEntries;
PIMAGE_RESOURCE_DATA_ENTRY pResourceDataEntry;
PIMAGE_RESOURCE_DIRECTORY_STRING pResourceString;
PTSTR pNameMemory;
ppLink = &pParentLeaf->pChild;
dwEntryCount = pDir->NumberOfIdEntries + pDir->NumberOfNamedEntries;
pEntries = PIMAGE_RESOURCE_DIRECTORY_ENTRY(pDir + 1);
for(x = 0; x < dwEntryCount; x++)
{
// create an empty leaf
pCurrentLeaf = (PRESOURCELEAF)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, sizeof(RESOURCELEAF));
*ppLink = pCurrentLeaf;
pCurrentLeaf->pParent = pParentLeaf;
pCurrentLeaf->dwLevel = pParentLeaf->dwLevel + 1;
// copy the name/id from the resource section to the leaf
if(pEntries[x].NameIsString)
{
pResourceString = PIMAGE_RESOURCE_DIRECTORY_STRING(m_pbRsrc + pEntries[x].NameOffset);
pNameMemory = (PTSTR)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, (pResourceString->Length + 1) * sizeof(TCHAR));
// it's important that we copy the string character by character so
// that ansi compilations will work
for(y = 0; y < pResourceString->Length; y++)
pNameMemory[y] = (TCHAR)PWSTR(pResourceString->NameString)[y];
pCurrentLeaf->bNameIsString = TRUE;
pCurrentLeaf->wNameLength = pResourceString->Length;
pCurrentLeaf->pNameString = pNameMemory;
m_dwStringSize += (pResourceString->Length * sizeof(WCHAR) + sizeof(pResourceString->Length));
if(m_bNullSource)
ZeroMemory(pResourceString, pResourceString->Length * sizeof(WCHAR) + sizeof(pResourceString->Length));
}
else
pCurrentLeaf->wId = pEntries[x].Id;
// continue based on whether the entry points to another directory
if(pEntries[x].DataIsDirectory)
{
pCurrentLeaf->bDirectory = TRUE;
pChildDirectory = PIMAGE_RESOURCE_DIRECTORY(m_pbRsrc + pEntries[x].OffsetToDirectory);
ProcessDirectory(pChildDirectory, pCurrentLeaf);
}
else
{
pResourceDataEntry = PIMAGE_RESOURCE_DATA_ENTRY(m_pbRsrc + pEntries[x].OffsetToData);
pCurrentLeaf->dwDataSize = pResourceDataEntry->Size;
pCurrentLeaf->dwDataRva = pResourceDataEntry->OffsetToData;
if(m_bNullSource)
ZeroMemory(pResourceDataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
m_dwHeaderSize += sizeof(IMAGE_RESOURCE_DATA_ENTRY);
}
if(m_bNullSource)
ZeroMemory(&pEntries[x], sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
m_dwHeaderSize += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY);
ppLink = &pCurrentLeaf->pSibling;
}
if(m_bNullSource)
ZeroMemory(pDir, sizeof(IMAGE_RESOURCE_DIRECTORY));
m_dwHeaderSize += sizeof(IMAGE_RESOURCE_DIRECTORY);
}
// Searches a resource tree structure for data leaves. When it finds a data leaf
// that is filtered by the specified filters, it calls the callback function.
VOID CResourceRipper::ProcessLeaf(PRESOURCELEAF pLeaf, PRESOURCEFILTER pFilters, FILTERCALLBACK pfCallback)
{
PRESOURCELEAF pCurrentLeaf;
pCurrentLeaf = pLeaf;
while(pCurrentLeaf)
{
ProcessLeaf(pCurrentLeaf->pChild, pFilters, pfCallback);
if(pCurrentLeaf->bDirectory == FALSE)
{
if(TestDataLeaf(pCurrentLeaf, pFilters))
{
(this->*pfCallback)(pCurrentLeaf);
if(IsGroupIconOrCursor(pCurrentLeaf))
{
ParseGroupIconOrCursor(pCurrentLeaf, pfCallback);
}
}
}
pCurrentLeaf = pCurrentLeaf->pSibling;
}
}
// Callback used to retain filtered resources.
VOID CResourceRipper::RetentionCallback(PRESOURCELEAF pDataLeaf)
{
PBYTE pbDataMemory,
pbDataPointer;
if(pDataLeaf->bRetain == FALSE)
{
pbDataMemory = (PBYTE)VirtualAlloc(0, pDataLeaf->dwDataSize, MEM_COMMIT, PAGE_READWRITE);
pbDataPointer = RvaToPointer(m_pbFile, pDataLeaf->dwDataRva);
if(pbDataPointer)
{
CopyMemory(pbDataMemory, pbDataPointer, pDataLeaf->dwDataSize);
pDataLeaf->pbData = pbDataMemory;
pDataLeaf->bRetain = TRUE;
if(m_bNullSource)
ZeroMemory(pbDataPointer, pDataLeaf->dwDataSize);
m_dwDataSize += pDataLeaf->dwDataSize;
}
else
VirtualFree(pbDataMemory, 0, MEM_RELEASE);
}
}
// Driver for ripping resources.
VOID CResourceRipper::Rip(PVOID pvFile)
{
DeleteResources(m_pResourceTree, TRUE);
m_bNullSource = m_bMoveData;
if(LoadFile((PBYTE)pvFile))
{
ExtractResources();
FilterResources();
}
// resource data can only be nulled out during ripping
m_bNullSource = FALSE;
}
// Sets the strip flag.
VOID CResourceRipper::Strip(BOOL bStrip)
{
m_bStrip = bStrip;
}
// Loops through each filter and determines if any of them filter out the
// specified data leaf.
BOOL CResourceRipper::TestDataLeaf(PRESOURCELEAF pDataLeaf, PRESOURCEFILTER pFilters)
{
PRESOURCEFILTER pCurrentFilter;
pCurrentFilter = pFilters;
while(pCurrentFilter)
{
if(TestFilter(pCurrentFilter, pDataLeaf))
return TRUE;
pCurrentFilter = pCurrentFilter->pNext;
}
return FALSE;
}
// Determines whether or not the specified filter matches the supplied data leaf.
BOOL CResourceRipper::TestFilter(PRESOURCEFILTER pFilter, PRESOURCELEAF pDataLeaf)
{
PFILTERLEVEL pCurrentLevel;
PRESOURCELEAF pCurrentLeaf;
BOOL bPass;
pCurrentLevel = pFilter->pLevels;
while(pCurrentLevel)
{
bPass = FALSE;
// get the leaf that corresponds to the level specified by the filter
pCurrentLeaf = FindLeafByLevel(pDataLeaf, pCurrentLevel->dwLevel);
if(pCurrentLeaf)
{
// if level flag is FF_ID
if(pCurrentLevel->dwFlags & FF_ID)
{
if(pCurrentLeaf->bNameIsString == FALSE)
{
if(pCurrentLevel->wId == pCurrentLeaf->wId)
bPass = TRUE;
}
if(pCurrentLevel->dwFlags & FF_NOT)
bPass ^= TRUE;
}
// if level flag is FF_STRING
else if(pCurrentLevel->dwFlags & FF_STRING)
{
if(pCurrentLeaf->bNameIsString)
{
if(lstrcmpi(pCurrentLeaf->pNameString, pCurrentLevel->pString) == 0)
bPass = TRUE;
}
if(pCurrentLevel->dwFlags & FF_NOT)
bPass ^= TRUE;
}
// if level flag is FF_ALL
else if(pCurrentLevel->dwFlags & FF_ALL)
bPass = TRUE;
// if level flag is FF_ALPHA
else if(pCurrentLevel->dwFlags & FF_ALPHA)
{
if(FindAlphaLeaf(pCurrentLeaf, pCurrentLevel->dwFlags & FF_NOT) == pCurrentLeaf)
bPass = TRUE;
}
else if(pCurrentLevel->dwFlags & FF_FIRST)
{
if(FindFirstLeaf(pCurrentLeaf, pCurrentLevel->dwFlags & FF_NOT) == pCurrentLeaf)
bPass = TRUE;
}
}
// if any level doesn't match then the filter doesn't match so return failure
if(bPass == FALSE)
return FALSE;
pCurrentLevel = pCurrentLevel->pNext;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?