2

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

Acctualy 我已经实现了我的目标,但是为了向导入表中添加一个新条目,我使用了 Stud_PE,它是一个 GUI 应用程序,我想自动化这部分过程。

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

4

3 回答 3

5

找到了正在寻找的东西。

c++的 m-PEFile :http: //forum.exetools.com/showpost.php? s=17e7516356489bb9dd17e294e147ef96&p=60183&postcount=3

还可以查看 python 的pefilehttp ://code.google.com/p/pefile/

以及用于 Java 的PE/COFF 4J :http: //pecoff4j.sourceforge.net/

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

代码: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();

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

代码: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");
}
于 2012-12-05T19:47:42.540 回答
4

您可以使用PeNet库添加新的导入,只需一行代码。有关示例,请参见此处:添加导入

var peFile = new PeFile("myapp.exe");
peFile.AddImport("gdi32.dll", "StartPage");
于 2020-06-05T13:32:59.807 回答
1

我自己也在寻找这样的程序。我也失败了。但这很容易手工完成。如果您需要自动化它,那么您可以制作自己的程序。访问http://www.unknowncheats.me/forum/http://www.rohitab.com 那里的人将能够帮助您编写自己的程序。

于 2012-12-03T17:26:36.060 回答