在PE的导入表中添加一个条目

2024-03-30

我正在寻找一个命令行程序来向 PE 文件的导入表添加条目。 我的目标是将一个新的导入函数从外部 DLL 添加到我的 EXE,然后使用 ollydbg 使用代码洞穴插入新代码。新代码将使用新导入的函数。

实际上我已经实现了我的目标,但是要向我使用的导入表添加一个新条目Stud_PE http://www.cgsoftlabs.ro/studpe.html,这是一个 GUI 应用程序,我想自动化这部分过程。

我会考虑以编程方式解决方案,但我担心 PE 结构太复杂,无法在我的时间范围内学习和探索。此外,如果已经存在一个实现,那么不使用它将是一种耻辱。 :-)


找到了正在寻找的东西。

m-PEFile对于 c++:

还请查看pefile对于蟒蛇:http://code.google.com/p/pefile/ http://code.google.com/p/pefile/

And PE/COFF 4J对于java:http://pecoff4j.sourceforge.net/ http://pecoff4j.sourceforge.net/

在我看来,PE/COFF 4J 的功能有限,但也许您会发现它很有帮助。

Code: PEFile.h

/*******************************************************************************
********************************   Team AT4RE   ********************************
********************************************************************************
*******************  PLEASE DON'T CHANGE/REMOVE THIS HEADER  *******************
********************************************************************************
**                                                                            **
**  Title:      PEFile class.                                                 **
**  Desc:       A handy class to manipulate pe files.                         **
**  Author:     MohammadHi [ in4matics at hotmail dot com ]                   **
**  WwW:        AT4RE      [ http://www.at4re.com ]                           **
**  Date:       2008-01-28                                                    **
**                                                                            **
********************************************************************************
*******************************************************************************/

/*
[  PE File Format   ]
---------------------
|    DOS Header     |
---------------------
|     DOS Stub      |
---------------------
|     PE Header     |
---------------------
|   Section Table   |
---------------------
|      Padding      |
---------------------
|     Section 1     |
---------------------
|     Section 2     |
---------------------
|        ...        |
---------------------
|     Section n     |
---------------------*/

//==============================================================================
#pragma once
#pragma pack(1)
//==============================================================================
#include <windows.h>
//==============================================================================
#define MAX_SECTION_COUNT       64
#define SECTION_IMPORT          "@.import"
#define SECTION_RESERV          "@.reserv"
//==============================================================================
struct PE_DOS_HEADER {
    WORD   Signature;
    WORD   LastPageBytes;
    WORD   NumberOfPages;
    WORD   Relocations;
    WORD   HeaderSize;
    WORD   MinMemory;
    WORD   MaxMemory;
    WORD   InitialSS;
    WORD   InitialSP;
    WORD   Checksum;
    WORD   InitialIP;
    WORD   InitialCS;
    WORD   RelocTableOffset;
    WORD   Overlay;
    WORD   Reserved1[4];
    WORD   OemId;
    WORD   OemInfo;
    WORD   Reserved2[10];
    LONG   PEHeaderOffset;
};
struct PE_DOS_STUB {
    char*   RawData;
    DWORD   Size;
};
struct PE_SECTION_DATA {
    DWORD   Offset;
    char*   RawData;
    DWORD   Size;
};
struct PE_IMPORT_FUNCTION {
    char*               FunctionName;
    int                 FunctionId;
    PE_IMPORT_FUNCTION* Next;
};
struct PE_IMPORT_DLL {
    char*               DllName;
    PE_IMPORT_FUNCTION* Functions;
    PE_IMPORT_DLL*  Next;
};
//==============================================================================
typedef IMAGE_NT_HEADERS PE_NT_HEADERS;
typedef IMAGE_SECTION_HEADER PE_SECTION_HEADER;
//==============================================================================
class PEFile {
public:
    PE_DOS_HEADER       dosHeader;
    PE_DOS_STUB         dosStub;
    PE_NT_HEADERS       peHeaders;
    PE_SECTION_HEADER   sectionTable[MAX_SECTION_COUNT];
    PE_SECTION_DATA     reservedData;
    PE_SECTION_DATA     sections[MAX_SECTION_COUNT];
    PE_IMPORT_DLL       importTable;
    PE_IMPORT_DLL       newImports;

    PEFile();
    PEFile(char* filePath);
    ~PEFile();
    bool                loadFromFile(char* filePath);
    bool                loadFromMemory(char* memoryAddress);
    bool                saveToFile(char* filePath);
    int                 addSection(char* name, DWORD size, bool isExecutable);
    void                addImport(char* dllName, char** functions, int functionCount);
    void                commit();

private:
    char*               peMemory;

    void                init();
    bool                readFileData(char* filePath);
    bool                checkValidity();
    bool                readHeaders();
    bool                readBody();
    bool                readImportTable();
    bool                writePadding(HANDLE fileHandle, long paddingSize);
    void                unloadFile();

    void                buildImportTable();
    char*               buildNewImports(DWORD baseRVA);
    DWORD               calcNewImportsSize(DWORD &sizeDlls, DWORD &sizeFunctions, DWORD &sizeStrings);

    DWORD               alignNumber(DWORD number, DWORD alignment);
    DWORD               rvaToOffset(DWORD rva);
    DWORD               offsetToRVA(DWORD offset);

    void                fixReservedData();
    void                fixHeaders();
    void                fixSectionTable();

};
//==============================================================================

Code: PEFile.cpp

/*******************************************************************************
********************************   Team AT4RE   ********************************
********************************************************************************
*******************  PLEASE DON'T CHANGE/REMOVE THIS HEADER  *******************
********************************************************************************
**                                                                            **
**  Title:      PEFile class.                                                 **
**  Desc:       A handy class to manipulate pe files.                         **
**  Author:     MohammadHi [ in4matics at hotmail dot com ]                   **
**  WwW:        AT4RE      [ http://www.at4re.com ]                           **
**  Date:       2008-01-28                                                    **
**                                                                            **
********************************************************************************
*******************************************************************************/

#include "PEFile.h"
#include <math.h>
//==============================================================================
#define DEBUG_ENABLED true;
#ifdef DEBUG_ENABLED
    #define echo(x)         MessageBox(0, x, "DEBUG", MB_ICONERROR);
    #define echo2(x, y)     { char v[256]; strcpy_s(v, 256, x); strcat_s(v, 256, y); echo(v); }
    #define echo3(x, y, z)  { char w[256]; strcpy_s(w, 256, x); strcat_s(w, 256, y); echo2(w, z); }
#else
    #define echo(x) ;
    #define echo2(x, y) ;
    #define echo3(x, y, z) ;
#endif
//==============================================================================
PEFile::PEFile() {
    init();
}
//==============================================================================
PEFile::PEFile(char* filePath) {
    init();
    loadFromFile(filePath);
}
//==============================================================================
PEFile::~PEFile() {
    unloadFile();
}
//==============================================================================
void PEFile::init() {
    peMemory = NULL;
    ZeroMemory(&newImports, sizeof(PE_IMPORT_DLL));
}
//==============================================================================
bool PEFile::readFileData(char* filePath) {
    // open the file for read
    HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (fileHandle == INVALID_HANDLE_VALUE) {
        echo3("Couldn't open file : [", filePath, "]");
        return false;
    }

    // get the file size
    DWORD fileSize = GetFileSize(fileHandle, 0);
    if (fileSize == 0) {
        CloseHandle(fileHandle);
        echo3("File size is ZeR0! : [", filePath, "]");
        return false;
    }

    // allocate memory to read the pe file (note that we used VirtualAlloc not GlobalAlloc!)
    peMemory = (char*)VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (peMemory == NULL) {
        CloseHandle(fileHandle);
        echo("Couldn't allocate memory!");
        return false;
    }

    DWORD bytesRead;
    // read whole file data
    if (!ReadFile(fileHandle, peMemory, fileSize, &bytesRead, NULL) || bytesRead != fileSize) {
        CloseHandle(fileHandle);
        echo3("Couldn't read file! : [", filePath, "]");
        return false;
    }

    // close the file
    CloseHandle(fileHandle);

    return true;
}
//==============================================================================
bool PEFile::checkValidity() {
    // 'dosHeader.Signature' must be "MZ" && 'peHeaders.Signature' must be "PE\0\0"
    if (dosHeader.Signature != IMAGE_DOS_SIGNATURE || peHeaders.Signature != IMAGE_NT_SIGNATURE) {
        unloadFile();
        echo("Invalid PE file!");
        return false;
    }

    if (peHeaders.FileHeader.NumberOfSections > MAX_SECTION_COUNT) {
        unloadFile();
        echo("Number of sections > MAX_SECTION_COUNT !");
        return false;
    }

    return true;
}
//==============================================================================
bool PEFile::readHeaders() {
    // read dos/pe headers
    CopyMemory(&dosHeader, peMemory, sizeof(PE_DOS_HEADER));
    dosStub.RawData = peMemory + sizeof(PE_DOS_HEADER);
    dosStub.Size = dosHeader.PEHeaderOffset - sizeof(PE_DOS_HEADER);
    CopyMemory(&peHeaders, peMemory + dosHeader.PEHeaderOffset, sizeof(PE_NT_HEADERS));

    // check validity of the file to ensure that we loaded a "PE File" not another thing!
    if (!checkValidity()) {
        return false;
    }

    // read section table
    ZeroMemory(sectionTable, sizeof(sectionTable));
    CopyMemory(sectionTable, peMemory + dosHeader.PEHeaderOffset + sizeof(PE_NT_HEADERS), 
        peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER));

    return true;
}
//==============================================================================
bool PEFile::readBody() {
    // read reserved data
    DWORD reservedDataOffset = dosHeader.PEHeaderOffset + sizeof(PE_NT_HEADERS) + 
        peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER);

    reservedData.Offset = reservedDataOffset;
    reservedData.RawData = peMemory + reservedDataOffset;
    /*reservedData.Size = peHeaders.OptionalHeader.SizeOfHeaders - reservedDataOffset;*/
    if (sectionTable[0].PointerToRawData > 0) {
        reservedData.Size = sectionTable[0].PointerToRawData - reservedDataOffset;
    } else {
        reservedData.Size = sectionTable[0].VirtualAddress - reservedDataOffset;
    }

    // read sections
    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        sections[i].Offset = sectionTable[i].PointerToRawData;
        sections[i].RawData = peMemory + sectionTable[i].PointerToRawData;
        sections[i].Size = sectionTable[i].SizeOfRawData;
    }

    return true;
}
//==============================================================================
bool PEFile::readImportTable() {
    DWORD tableRVA = peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    DWORD tableOffset = rvaToOffset(tableRVA);
    if (tableOffset == 0) {
        return false;
    }

    ZeroMemory(&importTable, sizeof(PE_IMPORT_DLL));

    IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(peMemory + tableOffset);
    IMAGE_THUNK_DATA* importThunk;
    PE_IMPORT_DLL* importDll = &this->importTable;
    PE_IMPORT_FUNCTION* importFunction;

    while (true) {
        importDll->DllName = (char*)(peMemory + rvaToOffset(importDesc->Name));
        if (importDesc->OriginalFirstThunk > 0) {
            importThunk = (IMAGE_THUNK_DATA*)(peMemory + rvaToOffset(importDesc->OriginalFirstThunk));
        } else {
            importThunk = (IMAGE_THUNK_DATA*)(peMemory + rvaToOffset(importDesc->FirstThunk));
        }

        importDll->Functions = new PE_IMPORT_FUNCTION();
        ZeroMemory(importDll->Functions, sizeof(PE_IMPORT_FUNCTION));
        importFunction = importDll->Functions;
        while (true) {
            if ((importThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32) == IMAGE_ORDINAL_FLAG32) {
                importFunction->FunctionId = IMAGE_ORDINAL32(importThunk->u1.Ordinal);
            } else {
                DWORD nameOffset = rvaToOffset(importThunk->u1.AddressOfData);
                importFunction->FunctionName = (char*)(peMemory + nameOffset + 2);
            }

            importThunk = (IMAGE_THUNK_DATA*)((char*)importThunk + sizeof(IMAGE_THUNK_DATA));
            if (importThunk->u1.AddressOfData == 0) {
                break;
            }
            importFunction->Next = new PE_IMPORT_FUNCTION();
            ZeroMemory(importFunction->Next, sizeof(PE_IMPORT_FUNCTION));
            importFunction = importFunction->Next;
        }

        importDesc = (IMAGE_IMPORT_DESCRIPTOR*)((char*)importDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR));
        if (importDesc->Name == 0) {
            break;
        }
        importDll->Next = new PE_IMPORT_DLL();
        ZeroMemory(importDll->Next, sizeof(PE_IMPORT_DLL));
        importDll = importDll->Next;
    }

    return true;
}
//==============================================================================
bool PEFile::loadFromFile(char* filePath) {
    unloadFile();

    return readFileData(filePath) &&
           readHeaders() &&
           readBody() &&
           readImportTable();
}
//==============================================================================
bool PEFile::loadFromMemory(char* memoryAddress) {
    unloadFile();

    peMemory = memoryAddress;

    return readHeaders()/* &&
           readBody() &&
           readImportTable()*/;
}
//==============================================================================
bool PEFile::saveToFile(char* filePath) {
    commit();
    buildImportTable();

    // create the output file
    HANDLE fileHandle = CreateFile(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (fileHandle == INVALID_HANDLE_VALUE) {
        echo("Couldn't create file");
        return false;
    }

    DWORD bytesWritten;

    WriteFile(fileHandle, &dosHeader, sizeof(PE_DOS_HEADER), &bytesWritten, NULL);
    WriteFile(fileHandle, dosStub.RawData, dosStub.Size, &bytesWritten, NULL);
    writePadding(fileHandle, dosHeader.PEHeaderOffset - sizeof(PE_DOS_HEADER) - dosStub.Size);
    WriteFile(fileHandle, &peHeaders, sizeof(PE_NT_HEADERS), &bytesWritten, NULL);
    WriteFile(fileHandle, &sectionTable, peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER), &bytesWritten, NULL);
    WriteFile(fileHandle, reservedData.RawData, reservedData.Size, &bytesWritten, NULL);

    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        writePadding(fileHandle, sectionTable[i].PointerToRawData - GetFileSize(fileHandle, NULL));
        WriteFile(fileHandle, sections[i].RawData, sections[i].Size, &bytesWritten, NULL);
    }

    CloseHandle(fileHandle);

    return true;
}
//==============================================================================
bool PEFile::writePadding(HANDLE fileHandle, long paddingSize) {
    if (paddingSize <= 0)
        return false;

    DWORD bytesWritten;
    char* padding = new char[paddingSize];
    memset(padding, 0, paddingSize);
    WriteFile(fileHandle, padding, paddingSize, &bytesWritten, NULL);
    delete padding;

    return (bytesWritten == paddingSize);
}
//==============================================================================
void PEFile::unloadFile() {
    if (peMemory != NULL) {
        VirtualFree(peMemory, 0, MEM_RELEASE);
        peMemory = NULL;
    }
}
//==============================================================================
void PEFile::buildImportTable() {
    DWORD sizeDlls = 0;
    DWORD sizeFunctions = 0;
    DWORD sizeStrings = 0;
    DWORD newImportsSize = calcNewImportsSize(sizeDlls, sizeFunctions, sizeStrings);

    // we'll move the old dll list to the new import table, so we'll calc its size
    DWORD oldImportDllsSize = 0;
    PE_IMPORT_DLL* importDll = &this->importTable;
    while (importDll != NULL) {
        oldImportDllsSize += sizeof(IMAGE_IMPORT_DESCRIPTOR);
        importDll = importDll->Next;
    }

    // add a new section to handle the new import table
    int index = addSection(SECTION_IMPORT, oldImportDllsSize + newImportsSize, false);

    // copy old import dll list
    DWORD oldImportTableRVA = peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    DWORD oldImportTableOffset = rvaToOffset(oldImportTableRVA);
    CopyMemory(sections[index].RawData, peMemory + oldImportTableOffset, oldImportDllsSize);

    // copy new imports
    char* newImportsData = buildNewImports(sectionTable[index].VirtualAddress + oldImportDllsSize);
    CopyMemory(sections[index].RawData + oldImportDllsSize, newImportsData, newImportsSize);

    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = sectionTable[index].VirtualAddress;
    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sectionTable[index].SizeOfRawData;
    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
}
//==============================================================================
char* PEFile::buildNewImports(DWORD baseRVA) {
    commit();

    IMAGE_IMPORT_DESCRIPTOR importDesc;
    IMAGE_THUNK_DATA importThunk;
    PE_IMPORT_DLL* importDll;
    PE_IMPORT_FUNCTION* importFunction;

    DWORD sizeDlls = 0;
    DWORD sizeFunctions = 0;
    DWORD sizeStrings = 0;
    DWORD newImportsSize = calcNewImportsSize(sizeDlls, sizeFunctions, sizeStrings);
    DWORD offsetDlls = 0;
    DWORD offsetFunctions = sizeDlls;
    DWORD offsetStrings = sizeDlls + 2 * sizeFunctions;

    char* buffer = new char[newImportsSize];
    ZeroMemory(buffer, newImportsSize);

    importDll = &newImports;
    while (importDll != NULL) {
        ZeroMemory(&importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
        importDesc.OriginalFirstThunk = baseRVA + offsetFunctions;
        importDesc.FirstThunk = baseRVA + offsetFunctions + sizeFunctions;
        importDesc.Name = baseRVA + offsetStrings;
        CopyMemory(buffer + offsetStrings, importDll->DllName, strlen(importDll->DllName));     
        offsetStrings += alignNumber((DWORD)strlen(importDll->DllName) + 1, 2);

        CopyMemory(buffer + offsetDlls, &importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
        offsetDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR);

        importFunction = importDll->Functions;
        while (importFunction != NULL) {
            ZeroMemory(&importThunk, sizeof(IMAGE_THUNK_DATA));
            if (importFunction->FunctionId != 0) {
                importThunk.u1.Ordinal = importFunction->FunctionId | IMAGE_ORDINAL_FLAG32;
            } else {
                importThunk.u1.AddressOfData = baseRVA + offsetStrings;
                CopyMemory(buffer + offsetStrings + 2, importFunction->FunctionName, strlen(importFunction->FunctionName));     
                offsetStrings += 2 + alignNumber((DWORD)strlen(importFunction->FunctionName) + 1, 2);
            }

            CopyMemory(buffer + offsetFunctions, &importThunk, sizeof(IMAGE_THUNK_DATA));
            CopyMemory(buffer + offsetFunctions + sizeFunctions, &importThunk, sizeof(IMAGE_THUNK_DATA));
            offsetFunctions += sizeof(IMAGE_THUNK_DATA);

            importFunction = importFunction->Next;
        }
        offsetFunctions += sizeof(IMAGE_THUNK_DATA);

        importDll = importDll->Next;
    }

    return buffer;
}
//==============================================================================
DWORD PEFile::calcNewImportsSize(DWORD &sizeDlls, DWORD &sizeFunctions, DWORD &sizeStrings) {
    PE_IMPORT_DLL* importDll = &this->newImports;
    PE_IMPORT_FUNCTION* importFunction;

    // calc added imports size
    while (importDll != NULL) {
        sizeDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR);
        sizeStrings += alignNumber((DWORD)strlen(importDll->DllName) + 1, 2);
        importFunction = importDll->Functions;
        while (importFunction != NULL) {
            sizeFunctions += sizeof(IMAGE_THUNK_DATA);
            if (importFunction->FunctionId == 0) {
                sizeStrings += 2 + alignNumber((DWORD)strlen(importFunction->FunctionName) + 1, 2);
            }
            importFunction = importFunction->Next;
        }
        sizeFunctions += sizeof(IMAGE_THUNK_DATA); // for the terminator thunk data
        importDll = importDll->Next;
    }
    sizeDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR); // for the terminator import descriptor

    return sizeDlls + 2 * sizeFunctions + sizeStrings;
}
//==============================================================================
int PEFile::addSection(char* name, DWORD size, bool isExecutable) {
    if (peHeaders.FileHeader.NumberOfSections == MAX_SECTION_COUNT) {
        return -1;
    }

    PE_SECTION_DATA &newSection = sections[peHeaders.FileHeader.NumberOfSections];
    PE_SECTION_HEADER &newSectionHeader = sectionTable[peHeaders.FileHeader.NumberOfSections];
    PE_SECTION_HEADER &lastSectionHeader = sectionTable[peHeaders.FileHeader.NumberOfSections - 1];

    DWORD sectionSize = alignNumber(size, peHeaders.OptionalHeader.FileAlignment);
    DWORD virtualSize = alignNumber(sectionSize, peHeaders.OptionalHeader.SectionAlignment);

    DWORD sectionOffset = alignNumber(lastSectionHeader.PointerToRawData + lastSectionHeader.SizeOfRawData, peHeaders.OptionalHeader.FileAlignment);
    DWORD virtualOffset = alignNumber(lastSectionHeader.VirtualAddress + lastSectionHeader.Misc.VirtualSize, peHeaders.OptionalHeader.SectionAlignment);

    ZeroMemory(&newSectionHeader, sizeof(IMAGE_SECTION_HEADER));
    CopyMemory(newSectionHeader.Name, name, (strlen(name) > 8 ? 8 : strlen(name)));

    newSectionHeader.PointerToRawData = sectionOffset;
    newSectionHeader.VirtualAddress = virtualOffset;
    newSectionHeader.SizeOfRawData = sectionSize;
    newSectionHeader.Misc.VirtualSize = virtualSize;
    newSectionHeader.Characteristics = //0xC0000040; 
        IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;

    if (isExecutable) {
        newSectionHeader.Characteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
    }

    newSection.RawData = (char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sectionSize);
    newSection.Size = sectionSize;

    peHeaders.FileHeader.NumberOfSections++;
    if (reservedData.Size > 0) {
        reservedData.Size -= sizeof(IMAGE_SECTION_HEADER);
    }

    // return new section index
    return peHeaders.FileHeader.NumberOfSections - 1;
}
//==============================================================================
void PEFile::addImport(char* dllName, char** functions, int functionCount) {
    PE_IMPORT_DLL* importDll = &this->newImports;
    PE_IMPORT_FUNCTION* importFunction;

    if (newImports.DllName != NULL) {
        while (importDll->Next != NULL) {
            importDll = importDll->Next;
        }
        importDll->Next = new PE_IMPORT_DLL();
        importDll = importDll->Next;
    }
    importDll->DllName = dllName;
    importDll->Functions = new PE_IMPORT_FUNCTION();
    importDll->Next = NULL;

    importFunction = importDll->Functions;
    importFunction->FunctionName = functions[0];
    for (int i = 1; i < functionCount; i++) {
        importFunction->Next = new PE_IMPORT_FUNCTION();
        importFunction = importFunction->Next;
        importFunction->FunctionName = functions[i];
    }
    importFunction->Next = NULL;
}
//==============================================================================
DWORD PEFile::alignNumber(DWORD number, DWORD alignment) {
    return (DWORD)(ceil(number / (alignment + 0.0)) * alignment);
}
//==============================================================================
DWORD PEFile::rvaToOffset(DWORD rva) {
    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        if (rva >= sectionTable[i].VirtualAddress &&
            rva < sectionTable[i].VirtualAddress + sectionTable[i].Misc.VirtualSize) {
            return sectionTable[i].PointerToRawData + (rva - sectionTable[i].VirtualAddress);
        }
    }
    return 0;
}
//==============================================================================
DWORD PEFile::offsetToRVA(DWORD offset) {
    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        if (offset >= sectionTable[i].PointerToRawData &&
            offset < sectionTable[i].PointerToRawData + sectionTable[i].SizeOfRawData) {
            return sectionTable[i].VirtualAddress + (offset - sectionTable[i].PointerToRawData);
        }
    }
    return 0;
}
//==============================================================================
void PEFile::commit() {
    fixReservedData();
    fixHeaders();
    fixSectionTable();
}
//==============================================================================
void PEFile::fixReservedData() {
    DWORD dirIndex = 0;
    for (dirIndex = 0; dirIndex < peHeaders.OptionalHeader.NumberOfRvaAndSizes; dirIndex++) {
        if (peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress > 0 && 
            peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress >= reservedData.Offset &&
            peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress < reservedData.Size) {
            break;
        }
    }

    if (dirIndex == peHeaders.OptionalHeader.NumberOfRvaAndSizes) {
        return;
    }

    int sectionIndex = addSection(SECTION_RESERV, reservedData.Size, false);
    CopyMemory(sections[sectionIndex].RawData, reservedData.RawData, reservedData.Size);

    for (dirIndex = 0; dirIndex < peHeaders.OptionalHeader.NumberOfRvaAndSizes; dirIndex++) {
        if (peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress > 0 &&
            peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress >= reservedData.Offset &&
            peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress < reservedData.Size) {
            peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress += 
                sectionTable[sectionIndex].VirtualAddress - reservedData.Offset;
        }
    }

    reservedData.Size = 0;
}
//==============================================================================
void PEFile::fixHeaders() {
    peHeaders.OptionalHeader.SizeOfHeaders = alignNumber(dosHeader.PEHeaderOffset + peHeaders.FileHeader.SizeOfOptionalHeader +
        peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER), peHeaders.OptionalHeader.FileAlignment);

    DWORD imageSize = peHeaders.OptionalHeader.SizeOfHeaders;
    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        imageSize += alignNumber(sectionTable[i].Misc.VirtualSize, peHeaders.OptionalHeader.SectionAlignment);
    }
    peHeaders.OptionalHeader.SizeOfImage = alignNumber(imageSize, peHeaders.OptionalHeader.SectionAlignment);

    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
    peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
}
//==============================================================================
void PEFile::fixSectionTable() {
    DWORD offset = peHeaders.OptionalHeader.SizeOfHeaders;
    for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
        sectionTable[i].Characteristics |= IMAGE_SCN_MEM_WRITE;
        offset = alignNumber(offset, peHeaders.OptionalHeader.FileAlignment);
        sectionTable[i].PointerToRawData = offset;
        //sectionTable[i].SizeOfRawData = alignNumber(offset + sectionTable[i].Misc.VirtualSize, peHeaders.OptionalHeader.FileAlignment);
        offset += sectionTable[i].SizeOfRawData;
    }
}
//==============================================================================
#include "PEFile.h"

int main(int argc, char* argv[]) {
    // Open the input file
    PEFile pe("1.exe");

    // Add "MessageBoxA" & "ShowWindow" functions to the import table
    char* functions[] = { "MessageBoxA", "ShowWindow" };
    pe.addImport("user32.dll", functions, 2);

    // Add a new section named ".at4re" with size "0x1000" byte
    pe.addSection(".at4re", 0x1000, false);

    // Save the modified file
    pe.saveToFile("1+.exe");
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在PE的导入表中添加一个条目 的相关文章

  • 嵌入清单文件以要求具有 mingw32 的管理员执行级别

    我正在 ubuntu 下使用 i586 mingw32msvc 交叉编译应用程序 我很难理解如何嵌入清单文件以要求 mingw32 具有管理员执行级别 对于我的例子 我使用了这个hello c int main return 0 这个资源文
  • 如何让VLOOKUP在VBA中选择到最低行?

    希望自动在单元格中插入 VLOOKUP 公式 录制宏时 我指示它使用相同的公式填充下面的列 效果很好 但是 当 VLOOKUP 搜索的表发生变化 更多或更少的行 时 就会出现问题 在记录时 VLOOKUP 下降到表中的最后一行 273 但是
  • Word 2010 自动化:“转到书签”

    我有一个用 Delphi 7 编写的程序 它打开一个基于模板的新 Word 文档 文档打开后 系统会自动跳转到书签 在模板中预定义 并在其中添加一些文本 以下代码在 Word 2003 中工作正常 但会导致invalid variant o
  • 检测计算机何时解锁 Windows

    我用过这个优秀的方法 https stackoverflow com questions 20733441 lock windows workstation using python 20733443锁定 Windows 计算机 那部分工作
  • Qt(在 Windows 上)将权限级别设置为“requireAdministrator”

    我正在使用 Qt Creator 并努力制作 exe文件默认以管理员身份运行 在线阅读所有解决方案我试图将这一行放入我的 pro file QMAKE LFLAGS MANIFESTUAC level requireAdministrato
  • 如何在Windows上分离“Git bash”中启动的“git gui”?

    例如 我开始 git bash 我导航到某个目录 I start git gui 我关闭控制台窗口或按 Ctrl C Git gui 的窗口消失了 即使我用过git gui disown 即使当我按 Ctrl C 时它不在前台 如何正确分离
  • Git 扩展 - 无法在 Windows 上推送到网络驱动器中的 git bare 存储库

    我正在 Windows 上学习 git 我已经安装了 Git 扩展 版本 2 47 3 并使用了它 我在我的 C 单元中创建了一个裸存储库 作为中央存储库 并在硬盘中的其他任何位置创建了个人存储库 我对硬盘中的这两个存储库进行提交 推送和拉
  • C# - 方法必须有返回类型

    我在调用 C 中的方法时遇到问题 不断收到消息 方法 计算 必须有返回类型 using System Diagnostics namespace WindowsFormsApplication1 public partial class F
  • 自定义波特率,redux

    我遇到的问题详述如下自定义波特率 https stackoverflow com questions 7714060 custom baud rate SetCommState 波特率 921600 失败 但波特率 115200 成功 尽管
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • Windows 窗口对接

    我想知道如何在 Windows 中将窗口停靠 捕捉到屏幕的一侧 最好使用直接的 Win32 API 我正在寻找的效果就像任务栏 一个在屏幕上有保留空间的窗口 因此最大化另一个窗口会使该窗口占据屏幕的其余部分 但使我的窗口保持在适当的位置并可
  • 对于多重继承,使用隐式转换而不是 QueryInterface() 是否合法?

    假设我有一个类实现两个或多个 COM 接口 正如here https stackoverflow com questions 1742848 why exactly do i need an explicit upcast when imp
  • SetCurrentDirectoryW 中的错误 206

    在我之后之前不清楚的问题 https stackoverflow com questions 44389617 long path name in setcurrentdirectoryw 我以某种方式能够创建一个具有长路径名的目录 但是
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 在哪里可以找到 Windows 7 UX 指南中推荐的图标/动画?

    Windows 7 UX 指南有很好的插图和图标示例 但我在 SDK 中确实找不到它们 他们藏在某个地方 还是找不到 如果您谈论的是常见的 UI 图标 那么您应该以编程方式获取它们 例如 您可以使用 var errIcon HICON be
  • 常见的 Windows 编译器上有哪些 std::locale 名称可用?

    该标准对于什么构成有效的语言环境名称几乎没有提及 只有传递无效的区域设置名称才会导致std runtime error 哪些语言环境名称可用于常见的 Windows 编译器 例如 MSVC MinGW 和 ICC 好吧 C 和 C 语言环境
  • 编写一个加载 msvcr80.dll 并公开 free() 函数的 DLL

    我有一个依赖于 MSVCR80 的第三方 DLL 并分配我需要清理的资源 图书馆有not暴露一个free 执行此操作的函数 相反 我需要加载相同的运行时库并手动调用free功能 作为一种解决方法 我尝试编写一个 包装器 DLL 它加载正确的
  • 将所有文件与指定目录(和子目录)中的所有文件进行二进制比较

    我需要将目录及其子目录中包含的所有文件与同一目录及其子目录中包含的所有其他文件进行比较 并将匹配文件的路径记录到文本文件或 CSV 我意识到有一些软件工具可以做到这一点 但除非它可以在 Windows 中开箱即用 否则我将不被允许在我的网络
  • GUI 测试工具 PyUseCase 与 Dogtail 相比如何?

    GUI测试工具如何Py用例 http pypi python org pypi PyUseCase重命名为故事文本 http pypi python org pypi StoryText 相比于Dogtail http en wikiped
  • 将 OpenBLAS 链接到 MinGW

    我正在尝试链接OpenBLAS https www openblas net 图书馆与明GW w64 https mingw w64 org Windows 上的编译器 这是我的代码 include

随机推荐