Self-Extracting Executable C++

2019-06-24 12:07发布

问题:

I am trying to understand how self-extracting PE files work. Can somebody explain why my code isn't working, or fix the main() part.

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

using namespace std;

void ExtractResource(const HINSTANCE hInstance, WORD resourceID, const char* outputFilename);

int main()
{
    HINSTANCE hInst = GetModuleHandle (0);
    ExtractResource(hInst, 101, "101.dll");
    ExtractResource(hInst, 102, "102.dll");
    ExtractResource(hInst, 103, "103.dll");
    ExtractResource(hInst, 104, "104.dll");
    cout << "Files are now extracted!";
    Sleep(INFINITE);
}


void ExtractResource(const HINSTANCE hInstance, WORD resourceID, const char* outputFilename){

        // First find and load the required resource          

        HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), "BINARY");

        if(hResource==NULL)

                return;

        HGLOBAL hFileResource = LoadResource(hInstance, hResource);



        // Now open and map this to a disk file          

        LPVOID lpFile = LockResource(hFileResource);          

        DWORD dwSize = SizeofResource(hInstance, hResource);            



        // Open the file and filemap          

        HANDLE hFile = CreateFileA(outputFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,

                FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY, NULL);          

        HANDLE hFilemap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL);            

        LPVOID lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, 0, 0, 0);            



        // Write the file

        CopyMemory(lpBaseAddress, lpFile, dwSize);            



        // Unmap the file and close the handles

        UnmapViewOfFile(lpBaseAddress);

        CloseHandle(hFilemap);

        CloseHandle(hFile);

}

I have 4 dll-files in resources, but I can't extract them using this. The resource ID´s should be correct, I checked it from resource header.

Is the problem in hInst or what else there could be wrong? I hope somebody could help me :) I have just a ~month ago started learning C & C++ so forgive me.

回答1:

I do not see anything wrong with your code other than you not checking the return values of functions and printing appropriate messages when something goes wrong. Also note that you can replace the hInstance with nullptr and it still works.

Also note that if you are extracting to a location that requires extra permissions, you might have to run your program as administrator or add a manifest that forces it to ask for administrator privileges.

Personally, I use these in any of my resource applications:

    bool ExtractResource(std::uint16_t ResourceID, std::string OutputFileName, const char* ResType)
    {
        try
        {
            HRSRC hResource = FindResource(nullptr, MAKEINTRESOURCE(ResourceID), ResType);
            if (hResource == nullptr)
            {
                return false;
            }

            HGLOBAL hFileResource = LoadResource(nullptr, hResource);
            if (hFileResource == nullptr)
            {
                return false;
            }

            void* lpFile = LockResource(hFileResource);
            if (lpFile == nullptr)
            {
                return false;
            }

            std::uint32_t dwSize = SizeofResource(nullptr, hResource);
            if (dwSize == 0)
            {
                return false;
            }

            HANDLE hFile = CreateFile(OutputFileName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
            HANDLE hFilemap = CreateFileMapping(hFile, nullptr, PAGE_READWRITE, 0, dwSize, nullptr);
            if (hFilemap == nullptr)
            {
                return false;
            }

            void* lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, 0, 0, 0);
            CopyMemory(lpBaseAddress, lpFile, dwSize);
            UnmapViewOfFile(lpBaseAddress);
            CloseHandle(hFilemap);
            CloseHandle(hFile);

            return true;
        }
        catch (...) {}
        return false;
    }

Main.cpp:

#include "Resource.h"

bool Extract(HWND WindowHandle) //WindowHandle for MessageBox parent.
{
    return ExtractResource(101,"101.dll", "BINARY");
}

int main()
{
    std::cout<<"Extracted Successfully: "<<std::boolalpha<<Extract(GetModuleHandle(0));
}

Again, be very wary that you are using a CONSOLE application which may or may not have a resource embedded in it.