C++ 64-bit DLLs und .exe Datei mergen

Anna R

Banned
Registriert
Sep. 2025
Beiträge
26
Hallo, weiß jemand, ob man 64-bit DLLs einer .exe Datei nachträglich hinzufügen kann, die vorher beim Kompilierungsschritt nicht statisch gelinkt wurden? Ich hab bis jetzt nur ein Programm auf Github gefunden, das es können soll, jedoch merged es nur 32-bit PE executables, aber nicht 64-bit: https://github.com/ytk2128/dll-merger

Da ich den Kompilierungsprozess nicht beeinflussen kann, muss ich die DLLs leider nachträglich hinzufügen.
 
Du musst schon die exe Datei modifizieren das die auch dort nach den dll sucht. Dann nennt man das aber nicht hinzufügen.

Du hast ein XY-Problem.
 
  • Gefällt mir
Reaktionen: User38, BeBur, madmax2010 und 2 andere
Lass es sein, die dafür notwendigen PE Tools erzeugen dann binaries, die von vielen Virenscannern etc geflagged werden.
 
Ja, das geht sogar extrem leicht mit Microsoft Detours. Verwende ich unter anderem für genau diesen use-case für ein paar Modprojekte.

Du hast folgende Optionen:

1. Wenn du eine DLL statisch zur import table einer .exe hinzufügen möchtest, kannst du DetourBinaryEditImports verwenden. Das Repository hat Beispielcode dafür, siehe SampleSetdll. Für deinen use-case kannst du einfach den example code unverändert übernehmen und setdll.exe verwenden um das executable zu patchen. Dann legst du einfach die gewünschte DLL in dasselbe Verzeichnis und das Programm lädt diese DLL ganz normal beim Start.

2. Wenn du aus welchem Grund auch immer das originale executable nicht on-disk modifizieren möchtest, kannst du einen kleinen Loader schreiben, der DetourCreateProcessWithDllEx verwendet (oder einfach SampleWithdll verwenden). Das ist im Grunde ein CreateProcess mit CREATE_SUSPENDED flag, welches die import table erst im RAM modifiziert.

Die andere Möglichkeit, ohne Detours, wäre die DLL search order auszunutzen. Wenn dein executable eine DLL aus dem lokalen Verzeichnis lädt, kannst du eine Proxy DLL schreiben mit demselben Namen, welche alle exportierten Funktionen der originalen DLL implementiert (einfach über LoadLibrary stub) plus die gewünschte Zusatzfunktionalität.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Yogi666, Micke und Anna R
@Anna R Und wie? Was hast du gemacht? Der nächste, der den Thread hier findet freut sich, wenn er lesen kann, wie du das Problem gelöst hast, genauso wie du dich über Antworten auf deine Frage gefreut hast.
 
  • Gefällt mir
Reaktionen: konkretor, Asghan, kuddlmuddl und 3 andere
An für sich, kein Zauberwerk:

Voraussetzungen:

  • git
  • Visual Studio
  • Desktopentwicklung mit C++ und Windows 11 SDK installiert

Jedes Sample enthält ein Makefile:

  • git clone https://github.com/microsoft/Detours.git
  • cd Detours und Mit Visual Studio öffnen
  • Developer-PowerShell öffnen (Strg+ö)
  • nmake.exe aufrufen, alle Samples werden daraufhin erstellt
  • (dass sn.exe nicht gefunden werden kann, kann an dieser Stelle ignoriert werden)
  • anschließend ...\Detours\bin.X86 im Pfad eintragen, oder setdll.exe kopieren
  • dann setdll.exe /d:toadd.dll binary.exe aufrufen:

Code:
Usage:
    setdll [options] binary_files
Options:
    /d:file.dll  : Add file.dll binary files
    /r           : Remove extra DLLs from binary files
    /?           : This help screen.

Leider bei mir aber noch die folgende Fehlermeldung: ...dll does not export function with ordinal #1. Aber theoretisch hätte das funktionieren sollen.
 
  • Gefällt mir
Reaktionen: BeBur
Deine toadd.dll muss eine Funktion mit Ordinal #1 exportieren, steht auch hier ganz unten:

Note: Each DLL inserted as a byway must export a function with ordinal #1. If the export table for the DLL does not export a function with ordinal #1, the target binary will fail to load correct.

Einfach per Linkerflag setzen /EXPORT:dummy_export,@1 oder über ein .def file. dummy_export kann eine leere void Funktion sein.

dumpbin /exports toadd.dll in der Developer Powershell sollte dann in etwa sowas ausgeben:

Code:
ordinal hint RVA      name

      1    0 000287D0 dummy_export
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Anna R
@eweu Ich habe doch auf den Erstellungsprozess bzw das Linken der DLLs keinen Einfluss...

Ich kann zwar Zeile 319 auskommentieren:

C++:
    else {
        if (!DoesDllExportOrdinal1(s_szDllPath)) {
            printf("Error: %hs does not export function with ordinal #1.\n",
                   s_szDllPath);
            //return 2;
        }
        printf("Adding %hs to binary files.\n", s_szDllPath);
    }

aber dann laufe ich doch gleich in das nächste Problem, da der Rest der Magie auf diesem Export #1 aufbaut:

Code:
  ...exe:
DetourBinaryOpen failed: 192
 
In diesem Fall würde ich eine kleine wrapper DLL schreiben, die diesen Export hat. Dann fügst du diese wrapper DLL mit setdll zur import table hinzu. In der wrapper DLL lädst du deine toadd.dll mit LoadLibrary.
 
Könnten Sie sagen, was hier falsch ist?

Vorgehensweise:

1. Visual Studio, Neues Projekt, DLL mit Exporten
2. Zwei Klassen:

C++:
// WrapperDll.cpp : Hiermit werden die exportierten Funktionen für die DLL definiert.
//

#include "pch.h"
#include "framework.h"
#include "WrapperDll.h"

// Dies ist ein Beispiel für eine exportierte Funktion.
WRAPPERDLL_API void dummy_export() {
}

C++:
// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
#include "pch.h"
#include <stdio.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    const wchar_t* toLoadArr[9] = {
        L"awt.dll", L"fontmanager.dll", L"freetype.dll", L"java.dll", L"javaaccessbridge.dll", L"javajpeg.dll", L"jawt.dll", L"jvm.dll", L"lcms.dll"
    };
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH: {
        for (const wchar_t* toLoad : toLoadArr) {
            HMODULE hm = LoadLibraryW(toLoad);
            if (!hm)
            {
                const DWORD errorCode = GetLastError();
                printf("LoadLibrary failed with error code 0x%X\n", errorCode);
            }
        }
        break;
    }
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

3. WrapperDll erstellen (Strg+B)
4. WrapperDll.dll in das Zielverzeichnis kopieren

Wenn ich jetzt setdll.exe /d:WrapperDll.dll program.exe aufrufen möchte, entsteht obskurerweise dieselbe Fehlermeldung:

Code:
setdll.exe: LoadLibraryEx(WrapperDll.dll) failed with error 193.
Error: WrapperDll.dll does not export function with ordinal #1.
 
Eine Java Anwendung bekommt man auf dem Wege ja nicht eine einzelne Datei. Dann könnte man doch auch einfach einen Launcher wie z.B. Launch4j verwenden.
 
Nolag schrieb:
Eine Java Anwendung bekommt man auf dem Wege ja nicht eine einzelne Datei.
Sorry, aber außer das es zeigt, das Sie nicht die geringste Ahnung haben, war das nicht hilfreich.
Ergänzung ()

Nolag schrieb:
Launch4j verwenden
Das sind aber alles nur JRE-Wrapper... und kein nativer Code.
 
Kannst du checken, ob dummy_export auch wirklich exportiert wird mit dumpbin /exports WrapperDll.dll (mit der Developer Powershell)?

Wenn die Funktion korrekt exportiert wird dann verwendest du wahrscheinlich die falsche Version von setdll.exe (x86/x64). Die Fehlermeldung ist da etwas irreführend, die bekommst du wenn du mit setdll.exe (x86) eine 64 bit DLL hinzufügen möchtest, und umgekehrt.

Btw, LoadLibrary direkt in DllMain aufrufen kann potentiell Probleme machen, siehe hier. Besser wäre wenn du in DllMain einen neuen Thread startest.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Anna R
eweu schrieb:
Wenn die Funktion korrekt exportiert wird dann verwendest du wahrscheinlich die falsche Version von setdll.exe (x86/x64).
Könnte sein. Wie bekomme ich eine x64 Version von setdll.exe?
 
nmake in x64 Native Tools Command Prompt for VS 2022 verwenden, einfach im Startmenü suchen
 
  • Gefällt mir
Reaktionen: Anna R
Zurück
Oben