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

📄 cimportripper.cpp

📁 pe exe packer (must use vc2005 to compile)
💻 CPP
字号:
// Author:   Brandon LaCombe
// Date:     February 3, 2006
// License:  Public Domain
#include "CImportRipper.h"
#include "..\Loader\loaderstructs.h"
#include "..\..\FileTools.h"
#include "..\..\remem.h"

// user defined types

// Defines a structure that details information about an imported dll.
struct _IMPORTED_DLL
{
    PIMPORTED_DLL pLink;

    PSTR pDllName;
    BOOL bImportIsString;
    union
    {
        WORD wOrdinal;
        PSTR pFunctionName;
    };
};

// code start

// Class constructor.
CImportRipper::CImportRipper()
{
    m_hHeap = GetProcessHeap();
    m_pImportedDlls = NULL;
    m_dwHeaderSize = sizeof(KERNEL_IAT) + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2);
    m_dwStringSize = sizeof("KERNEL32.DLL") +
                     sizeof("GetModuleHandleA") +
                     sizeof("GetProcAddress") +
                     sizeof("VirtualAlloc") +
                     sizeof("VirtualFree") +
                     sizeof("VirtualProtect");
}

// Class destructor
CImportRipper::~CImportRipper()
{
    DeleteImportedDlls();
}

// Calculates the rva where the import descriptor array starts
DWORD CImportRipper::CalculateDescriptorRva(DWORD dwBaseRva)
{
    return dwBaseRva + sizeof(KERNEL_IAT);
}

// Creates a new dll structure and adds it to the end of the dll list.
PIMPORTED_DLL CImportRipper::CreateImportedDll()
{
    PIMPORTED_DLL   pNewDll,
                  * ppLink;

    pNewDll = (PIMPORTED_DLL)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, sizeof(IMPORTED_DLL));
    ppLink = &m_pImportedDlls;
    while(*ppLink)
        ppLink = &(*ppLink)->pLink;
    *ppLink = pNewDll;
    return pNewDll;
}

// Frees all the imported dll structures.
VOID CImportRipper::DeleteImportedDlls()
{
    PIMPORTED_DLL pCurrentDll,
                  pNextDll;

    pCurrentDll = m_pImportedDlls;
    while(pCurrentDll)
    {
        pNextDll = pCurrentDll->pLink;
        HeapFree(m_hHeap, 0, pCurrentDll->pDllName);
        if(pCurrentDll->bImportIsString)
            HeapFree(m_hHeap, 0, pCurrentDll->pFunctionName);
        HeapFree(m_hHeap, 0, pCurrentDll);
        pCurrentDll = pNextDll;
    }
    m_pImportedDlls = NULL;
    m_dwHeaderSize = sizeof(KERNEL_IAT) + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2);
    m_dwStringSize = sizeof("KERNEL32.DLL") +
                     sizeof("GetModuleHandleA") +
                     sizeof("GetProcAddress") +
                     sizeof("VirtualAlloc") +
                     sizeof("VirtualFree") +
                     sizeof("VirtualProtect");
}

// Exports an import section.
VOID CImportRipper::Export(PVOID pvOutput, DWORD dwBaseRva)
{
    PBYTE                    pbHeaders,
                             pbStrings;
    PIMPORTED_DLL            pCurrentDll;
    PIMAGE_IMPORT_DESCRIPTOR pDescriptor;

    if(pvOutput)
    {
        pbHeaders = (PBYTE)pvOutput;
        pbStrings = pbHeaders + m_dwHeaderSize;

        // write the kernel descriptor and iat
        WriteKernelData(&pbHeaders, &pbStrings, dwBaseRva);

        // write the other dll descriptors
        pCurrentDll = m_pImportedDlls;
        while(pCurrentDll)
        {
            pDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)pbHeaders;
            pbHeaders += sizeof(IMAGE_IMPORT_DESCRIPTOR);

            // all iats have only one entry, so we use the two unused members of
            // the descriptor to house the 8 byte iat (TimeDateStamp and
            // ForwarderChain)
            pDescriptor->OriginalFirstThunk = DWORD((PBYTE)&pDescriptor->TimeDateStamp - (PBYTE)pvOutput) + dwBaseRva;
            pDescriptor->FirstThunk = pDescriptor->OriginalFirstThunk;

            // copy dll name
            pDescriptor->Name = DWORD(pbStrings - (PBYTE)pvOutput) + dwBaseRva;
            lstrcpyA((PSTR)pbStrings, pCurrentDll->pDllName);
            pbStrings += (lstrlenA(pCurrentDll->pDllName) + 1);

            // handle the single iat entry
            // TimeDateStamp is used as the iat entry; calculate string rva
            if(pCurrentDll->bImportIsString)
            {
                pDescriptor->TimeDateStamp = DWORD(pbStrings - (PBYTE)pvOutput) + dwBaseRva - 2;
                lstrcpyA((PSTR)pbStrings, pCurrentDll->pFunctionName);
                pbStrings += (lstrlenA(pCurrentDll->pFunctionName) + 1);
            }
            else
                pDescriptor->TimeDateStamp = IMAGE_ORDINAL_FLAG | pCurrentDll->wOrdinal;

            // ForwarderChain is used as the null terminating iat entry
            pDescriptor->ForwarderChain = NULL;
            pCurrentDll = pCurrentDll->pLink;
        }
        ZeroMemory(pbHeaders, sizeof(IMAGE_IMPORT_DESCRIPTOR));
    }
}

// Gathers import information from a pe file and saves the collected data to a
// linked list. The dll name and the import with the shortest name is recorded.
VOID CImportRipper::ExtractImports()
{
    DWORD                    dwDllNameLength,
                             dwFunctionNameLength,
                             dwINTSize,
                             dwShortestIndex;
    PIMAGE_IMPORT_DESCRIPTOR pCurrentDesc;
    PSTR                     pDllName;
    PDWORD                   pdwIAT,
                             pdwINT;
    PIMAGE_IMPORT_BY_NAME    pFunctionName;
    PIMPORTED_DLL            pNewDll;
    PVOID                    pvINTBackup;

    pCurrentDesc = (PIMAGE_IMPORT_DESCRIPTOR)m_pbImports;
    while(pCurrentDesc->FirstThunk)
    {
        pdwINT = (PDWORD)RvaToPointer(m_pbFile, pCurrentDesc->OriginalFirstThunk);
        pvINTBackup = NULL;

        // if an OriginalFirstThunk chain exists we copy it to the
        // FirstThunk chain and null out the OriginalFirstThunk chain
        if(pdwINT)
        {
            // calculate size of the chain
            for(dwINTSize = 0; pdwINT[dwINTSize]; dwINTSize++);
            dwINTSize *= sizeof(DWORD);

            pvINTBackup = HeapAlloc(m_hHeap, 0, dwINTSize);
            CopyMemory(pvINTBackup, pdwINT, dwINTSize);
            ZeroMemory(pdwINT, dwINTSize);
            pCurrentDesc->OriginalFirstThunk = NULL;
        }

        pdwIAT = (PDWORD)RvaToPointer(m_pbFile, pCurrentDesc->FirstThunk);

        // generally we want to null these two unused fields in the input
        // file, but not if they are being used as the iat
        if(pdwIAT != &pCurrentDesc->TimeDateStamp)
        {
            pCurrentDesc->TimeDateStamp = NULL;
            pCurrentDesc->ForwarderChain = NULL;
        }

        // copy the OriginalFirstThunk chain to the FirstThunkChain
        if(pvINTBackup)
        {
            CopyMemory(pdwIAT, pvINTBackup, dwINTSize);
            HeapFree(m_hHeap, 0, pvINTBackup);
        }

        // now we copy the dll info to the class
        pDllName = (PSTR)RvaToPointer(m_pbFile, pCurrentDesc->Name);
        if(IsDllUnique(pDllName))
        {
            dwShortestIndex = FindShortestFunctionName(pdwIAT);
            if(dwShortestIndex != -1)
            {
                pNewDll = CreateImportedDll();
                dwDllNameLength = lstrlenA(pDllName) + 1;
                pNewDll->pDllName = (PSTR)HeapAlloc(m_hHeap, 0, dwDllNameLength);
                lstrcpyA(pNewDll->pDllName, pDllName);
                dwFunctionNameLength = 0;

                if(pdwIAT[dwShortestIndex] & IMAGE_ORDINAL_FLAG)
                    pNewDll->wOrdinal = (WORD)IMAGE_ORDINAL(pdwIAT[dwShortestIndex]);
                else
                {
                    pNewDll->bImportIsString = TRUE;
                    pFunctionName = (PIMAGE_IMPORT_BY_NAME)RvaToPointer(m_pbFile, pdwIAT[dwShortestIndex]);
                    dwFunctionNameLength = lstrlenA((PSTR)pFunctionName->Name) + 1;
                    pNewDll->pFunctionName = (PSTR)HeapAlloc(m_hHeap, 0, dwFunctionNameLength);
                    lstrcpyA(pNewDll->pFunctionName, (PSTR)pFunctionName->Name);
                }
                m_dwStringSize += (dwDllNameLength + dwFunctionNameLength);
                m_dwHeaderSize += sizeof(IMAGE_IMPORT_DESCRIPTOR);
            }
        }
        pCurrentDesc++;
    }
}

// Finds the index in an import table that has the shortest function name.
// Ordinals are considered to have a name length of zero.
DWORD CImportRipper::FindShortestFunctionName(PDWORD pdwINT)
{
    DWORD                 x,
                          dwShortestIndex,
                          dwShortestLength,
                          dwNameLength;
    PIMAGE_IMPORT_BY_NAME pFunctionName;

    dwShortestLength = INFINITE;
    dwShortestIndex = -1;
    for(x = 0; pdwINT[x]; x++)
    {
        if(pdwINT[x] & IMAGE_ORDINAL_FLAG)
        {
            dwShortestIndex = x;
            break;
        }
        else
        {
            pFunctionName = (PIMAGE_IMPORT_BY_NAME)RvaToPointer(m_pbFile, pdwINT[x]);
            if(pFunctionName)
            {
                dwNameLength = lstrlenA((PSTR)pFunctionName->Name);
                if(dwNameLength < dwShortestLength)
                {
                    dwShortestLength = dwNameLength;
                    dwShortestIndex = x;
                }
            }
        }
    }
    return dwShortestIndex;
}

// Returns size of the import section.
DWORD CImportRipper::GetSize()
{
    return m_dwHeaderSize + m_dwStringSize;
}

// Ensures that the given dll name is not currently recorded in the dll info
// list.
BOOL CImportRipper::IsDllUnique(PSTR pDllName)
{
    BOOL          bRet;
    PIMPORTED_DLL pCurrentDll;

    bRet = TRUE;
    if(pDllName)
    {
        // kernel32.dll is always used, so no need to reimport it
        if(lstrcmpiA(pDllName, "KERNEL32.DLL") == 0)
            bRet = FALSE;

        pCurrentDll = m_pImportedDlls;
        while(bRet && pCurrentDll)
        {
            if(lstrcmpiA(pDllName, pCurrentDll->pDllName) == 0)
                bRet = FALSE;
            pCurrentDll = pCurrentDll->pLink;
        }
    }
    else bRet = FALSE; // if the given name pointer is invalid then return false
    return bRet;
}

// Loads the input file. Returns FALSE if no import section exists.
BOOL CImportRipper::LoadFile(PBYTE pbFile)
{
    BOOL              bRet;
    DWORD             dwImportsRva;
    PIMAGE_NT_HEADERS pNt;

    bRet = FALSE;
    m_pbFile = pbFile;
    pNt = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew);
    dwImportsRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    m_pbImports = RvaToPointer(pbFile, dwImportsRva);
    if(m_pbImports) bRet = TRUE;
    return bRet;
}

// Rips the import section from the input file.
VOID CImportRipper::Rip(PVOID pvFile)
{
    DeleteImportedDlls();
    if(LoadFile((PBYTE)pvFile))
    {
        ExtractImports();
    }

    // strip any bound import table
    StripBoundImportsFromFile();
}

// Strips any bound import table.
VOID CImportRipper::StripBoundImportsFromFile()
{
    DWORD                          dwRefCount,
                                   x;
    PBYTE                          pbBoundImports,
                                   pbString;
    PIMAGE_BOUND_IMPORT_DESCRIPTOR pDesc;
    PIMAGE_BOUND_FORWARDER_REF     pRef;
    PIMAGE_NT_HEADERS              pNt;

    pNt = PIMAGE_NT_HEADERS(m_pbFile + PIMAGE_DOS_HEADER(m_pbFile)->e_lfanew);
    pbBoundImports = RvaToPointer(m_pbFile, pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress);
    if(pbBoundImports)
    {
        pDesc = PIMAGE_BOUND_IMPORT_DESCRIPTOR(pbBoundImports);
        while(pDesc->TimeDateStamp)
        {
            dwRefCount = pDesc->NumberOfModuleForwarderRefs;

            // null out module name
            if(pDesc->OffsetModuleName)
            {
                pbString = pbBoundImports + pDesc->OffsetModuleName;
                for(; *pbString; pbString++)
                    *pbString = NULL;
            }

            // null out forwarder refs
            pRef = PIMAGE_BOUND_FORWARDER_REF(pDesc + 1);
            for(x = 0; x < dwRefCount; x++)
            {
                // null out module name
                if(pRef[x].OffsetModuleName)
                {
                    pbString = pbBoundImports + pRef[x].OffsetModuleName;
                    for(; *pbString; pbString++)
                        *pbString = NULL;
                }
                ZeroMemory(&pRef[x], sizeof(IMAGE_BOUND_FORWARDER_REF));
            }
            ZeroMemory(pDesc, sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR));

            // skip past import descriptor and any forwarder refs
            pDesc++;
            pDesc = PIMAGE_BOUND_IMPORT_DESCRIPTOR(PIMAGE_BOUND_FORWARDER_REF(pDesc) + dwRefCount);
        }
    }
}

// Writes the kernel import information that is used by the loader.
VOID CImportRipper::WriteKernelData(PBYTE * ppbHeaders, PBYTE * ppbStrings, DWORD dwBaseRva)
{

    PIMAGE_IMPORT_DESCRIPTOR pKernelDesc;
    union
    {
        PKERNEL_IAT          pKernelIAT;
        PBYTE                pbBase;
    };

    pKernelIAT = (PKERNEL_IAT)*ppbHeaders;
    pKernelDesc = PIMAGE_IMPORT_DESCRIPTOR(*ppbHeaders + sizeof(KERNEL_IAT));
    *ppbHeaders += (sizeof(KERNEL_IAT) + sizeof(IMAGE_IMPORT_DESCRIPTOR));
    ZeroMemory(pKernelDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
    pKernelDesc->OriginalFirstThunk = dwBaseRva;
    pKernelDesc->FirstThunk = pKernelDesc->OriginalFirstThunk;

    // copy the dll name and store it's rva
    pKernelDesc->Name = DWORD(*ppbStrings - pbBase) + dwBaseRva;
    lstrcpyA((PSTR)*ppbStrings, "KERNEL32.DLL");
    *ppbStrings += sizeof("KERNEL32.DLL");

    // copy GetModuleHandleA and store it's rva in the iat
    pKernelIAT->pGetModuleHandleA = DWORD(*ppbStrings - pbBase) + dwBaseRva - 2;
    lstrcpyA((PSTR)*ppbStrings, "GetModuleHandleA");
    *ppbStrings += sizeof("GetModuleHandleA");

    // copy GetProcAddress and store it's rva in the iat
    pKernelIAT->pGetProcAddress = DWORD(*ppbStrings - pbBase) + dwBaseRva - 2;
    lstrcpyA((PSTR)*ppbStrings, "GetProcAddress");
    *ppbStrings += sizeof("GetProcAddress");

    // copy VirtualAlloc and store it's rva in the iat
    pKernelIAT->pVirtualAlloc = DWORD(*ppbStrings - pbBase) + dwBaseRva - 2;
    lstrcpyA((PSTR)*ppbStrings, "VirtualAlloc");
    *ppbStrings += sizeof("VirtualAlloc");

    // copy VirtualFree and store it's rva in the iat
    pKernelIAT->pVirtualFree = DWORD(*ppbStrings - pbBase) + dwBaseRva - 2;
    lstrcpyA((PSTR)*ppbStrings, "VirtualFree");
    *ppbStrings += sizeof("VirtualFree");

    // copy VirtualProtect and store it's rva in the iat
    pKernelIAT->pVirtualProtect = DWORD(*ppbStrings - pbBase) + dwBaseRva - 2;
    lstrcpyA((PSTR)*ppbStrings, "VirtualProtect");
    *ppbStrings += sizeof("VirtualProtect");

    // ensure terminating iat entry is null
    pKernelIAT->dwNullEntry = NULL;
}

⌨️ 快捷键说明

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