win32

#include <iostream>
#include <Windows.h>
#include <ShlObj.h>
#include <Shlwapi.h>

#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Shlwapi.lib")

DWORD align(DWORD size, DWORD align, DWORD addr) {
    if (!(size % align))
        return addr + size;
    return addr + (size / align + 1) * align;
}

int main(int argc, char* argv[])
{
    /*if (argc < 3)
    {
        std::cout << "Argomenti insufficienti.
";
        return 0;
    }*/

    HANDLE FirstFile = CreateFileA("Test_Hello World.exe", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);            // File to read data from
    if (FirstFile == INVALID_HANDLE_VALUE)
    {
        std::cout << "Impossibile aprire il file passato come primo argomento.
";
        return 0;
    }

    HANDLE SecFile = CreateFileA("Test_Hello World.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);               // File to write the read data in
    if (SecFile == INVALID_HANDLE_VALUE)
    {
        std::cout << "Impossibile aprire il file passato come secondo argomento.
";
        return 0;
    }

    DWORD FirstFS = GetFileSize(FirstFile, 0);              // First file dimension
    DWORD SecondFS = GetFileSize(SecFile, 0);               // Second file dimension

    BYTE* FirstFB = (BYTE*)VirtualAlloc(NULL, FirstFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);           // Allocates memory for the first file
    BYTE* SecondFB = (BYTE*)VirtualAlloc(NULL, SecondFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);         // Allocates memory for the second file

    DWORD BytesRead = 0;
    DWORD BytesWritten = 0;

    if (bool Read = ReadFile(FirstFile, FirstFB, FirstFS, &BytesRead, NULL) == FALSE)                   // Reads the first file
    {
        std::cout << "Impossibile leggere primo file.
";
        return 0;
    }
    else
    {
        std::cout << "Letti " << BytesRead << " dal primo file.
";
        BytesRead = 0;
    }

    if (bool Read = ReadFile(SecFile, SecondFB, SecondFS, &BytesRead, NULL) == FALSE)                       // Reads the second file
    {
        std::cout << "Impossibile leggere secondo file.
";
        return 0;
    }
    else
    {
        std::cout << "Letti " << BytesRead << " bytes dal secondo file.
";
        BytesRead = 0;
    }

    /*
    *
    * The code is problematic beyond this point!
    *
    * SecondFB = Pointer to the second file's data buffer that needs to be modified by adding the new section.
    * FirstFB = Pointer to the first file's data buffer that will be written inside the ".sdata" section.
    * Both of them have been loaded in memory using VirtualAlloc.
    *
    * Ask me anything for further info and many, many thanks :D

    */

    // Here I add a new section to the second file.

    PIMAGE_DOS_HEADER sIDH = (IMAGE_DOS_HEADER*)SecondFB;
    PIMAGE_NT_HEADERS sINH = (IMAGE_NT_HEADERS*)(SecondFB + sIDH->e_lfanew);
    PIMAGE_FILE_HEADER sIFH = (PIMAGE_FILE_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD));
    PIMAGE_OPTIONAL_HEADER sIOH = (PIMAGE_OPTIONAL_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
    PIMAGE_SECTION_HEADER sISH = (PIMAGE_SECTION_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS));

    // Here I name the new section inside the file
    ZeroMemory(&sISH[sIFH->NumberOfSections], sizeof(IMAGE_SECTION_HEADER));
    CopyMemory(sISH[sIFH->NumberOfSections].Name, ".scode", 8);

    /*
        0xE00000E0 = IMAGE_SCN_MEM_WRITE |
                     IMAGE_SCN_CNT_CODE  |
                     IMAGE_SCN_CNT_UNINITIALIZED_DATA  |
                     IMAGE_SCN_MEM_EXECUTE |
                     IMAGE_SCN_CNT_INITIALIZED_DATA |
                     IMAGE_SCN_MEM_READ


    */

    // Here all the required information gets filled in
    sISH[sIFH->NumberOfSections].VirtualAddress = align(sISH[sIFH->NumberOfSections - 1].Misc.VirtualSize, sIOH->SectionAlignment, sISH[sIFH->NumberOfSections - 1].VirtualAddress);
    sISH[sIFH->NumberOfSections].SizeOfRawData = align(FirstFS, sIOH->SectionAlignment, 0);
    sISH[sIFH->NumberOfSections].Misc.VirtualSize = align(FirstFS, sIOH->SectionAlignment, 0);
    sISH[sIFH->NumberOfSections].PointerToRawData = align(sISH[sIFH->NumberOfSections - 1].SizeOfRawData, sIOH->FileAlignment, sISH[sIFH->NumberOfSections - 1].PointerToRawData);
    sISH[sIFH->NumberOfSections].Characteristics = 0xE00000E0;

    // Here the changes are written to the second file
    SetFilePointer(SecFile, sISH[sIFH->NumberOfSections].PointerToRawData + sISH[sIFH->NumberOfSections].SizeOfRawData, NULL, FILE_BEGIN);
    SetEndOfFile(SecFile);

    sIOH->SizeOfImage = sISH[sIFH->NumberOfSections].VirtualAddress + sISH[sIFH->NumberOfSections].Misc.VirtualSize;
    sIFH->NumberOfSections += 1;
    SetFilePointer(SecFile, 0, NULL, FILE_BEGIN);

    BytesWritten = 0;

    bool W = WriteFile(SecFile, SecondFB, SecondFS, &BytesWritten, NULL);

    if (W == FALSE)
    {
        std::cout << "Impossibile aggiungere sezione alla stub.
";
        return 0;
    }
    else
    {
        std::cout << "Scritti " << BytesWritten << " bytes nella stub. (Aggiunta nuova sezione.)
";
        BytesWritten = 0;
    }

    // Here I write the data inside the new section
    SetFilePointer(SecFile, sISH[sIFH->NumberOfSections - 1].PointerToRawData, 0, FILE_BEGIN);
    if (bool Write = WriteFile(SecFile, FirstFB, FirstFS, &BytesWritten, NULL) == FALSE)
    {
        std::cout << "Impossibile aggiungere sezione alla stub.
";
    }
    else
    {
        std::cout << "Scritti " << BytesWritten << " bytes nella stub.
";
        BytesWritten = 0;
    }

    // Here I close all the handles

    VirtualFree(FirstFB, FirstFS, MEM_RELEASE);
    CloseHandle(FirstFile);

    VirtualFree(SecondFB, SecondFS, MEM_RELEASE);
    CloseHandle(SecFile);

    std::cout << "Binding completato.
";

    return 0;
}
原文地址:https://www.cnblogs.com/strive-sun/p/13825731.html