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

eweu schrieb:
Kannst du checken, ob dummy_export auch wirklich exportiert wird mit dumpbin /exports WrapperDll.dll (mit der Developer Powershell)?
Ist da, hat aber Ordinal 3:

Code:
Dump of file .\WrapperDll.dll

File Type: DLL

  Section contains the following exports for WrapperDll.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           3 number of functions
           3 number of names

    ordinal hint RVA      name

          1    0 000112FD zeichensalat = zeichensalat
          2    1 00011096 zeichensalat = zeichensalat
          3    2 00011109 dummy_export = @ILT+260(dummy_export)

  Summary

        1000 .00cfg
        1000 .data
        1000 .idata
        1000 .msvcjmc
        3000 .pdata
        3000 .rdata
        1000 .reloc
        1000 .rsrc
        9000 .text
       10000 .textbss

Aber immerhin weiß ich jetzt , weshalb die Dateigröße immer gleich war.

So spät jetzt , das Bett ruft.
 
Nolag schrieb:
Eine Java Anwendung bekommt man auf dem Wege ja nicht eine einzelne Datei.

Ich weiß leider auch nicht, was hier ganz konkret erreicht werden soll, die DLL(s) kann man mit Detours aber als Payload einbetten (1, 2). Manual mapping kann Detours allerdings nicht (so wie das Projekt aus dem ersten Post), zum laden müssen die DLLs physisch on-disk sein, muss man also vorher extrahieren.
 
  • Gefällt mir
Reaktionen: Anna R
Es hat geklappt! Zumindest fast...

1. "x64 Native Tools Command Prompt for VS " öffnen (einfach unten in der Leiste danach suchen)
2. Nach Detours wechseln und nmake.exe aufrufen
3. Command Prompt wieder schließen und "...\Detours\bin.X64" in den Systempfad eintragen

4. WrapperDll-Projekt öffnen (DLL mit Exports braucht man eigentlich nicht):

WrapperDll.h ändern:

C++:
// Der folgende ifdef-Block ist die Standardmethode zum Erstellen von Makros, die das Exportieren
// aus einer DLL vereinfachen. Alle Dateien in dieser DLL werden mit dem WRAPPERDLL_EXPORTS-Symbol
// (in der Befehlszeile definiert) kompiliert. Dieses Symbol darf für kein Projekt definiert werden,
// das diese DLL verwendet. Alle anderen Projekte, deren Quelldateien diese Datei beinhalten, sehen
// WRAPPERDLL_API-Funktionen als aus einer DLL importiert an, während diese DLL
// mit diesem Makro definierte Symbole als exportiert ansieht.
#ifdef WRAPPERDLL_EXPORTS
#define WRAPPERDLL_API __declspec(dllexport)
#else
#define WRAPPERDLL_API __declspec(dllimport)
#endif

// Dies ist eine Beispiel-Exportfunktion, die die Ordinalnummer 1 hat.
extern "C" __declspec(dllexport) void dummy_export() {}

// Diese Klasse wird aus der DLL exportiert.
//class WRAPPERDLL_API CWrapperDll {
//public:
//    CWrapperDll(void);
//    // TODO: Methoden hier hinzufügen.
//};

extern WRAPPERDLL_API int nWrapperDll;

WRAPPERDLL_API int fnWrapperDll(void);

dllmain.cpp:

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);
                return FALSE;
            }
        }
        break;
    }
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

WrapperDll.cpp braucht man eigentlich nicht, kann leer sein...

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

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

5. Wieder übersetzen mit Strg+b und "WrapperDll.dll" in das Zielverzeichnis kopieren
6. Im Zielverzeichnis PS öffnen und "setdll.exe /d:WrapperDll.dll PasswordStrength.exe" aufrufen:

Code:
Adding WrapperDll.dll to binary files.
  PasswordStrength.exe:
    WrapperDll.dll
    VERSION.dll -> VERSION.dll
    ADVAPI32.dll -> ADVAPI32.dll
    WS2_32.dll -> WS2_32.dll
    USERENV.dll -> USERENV.dll
    KERNEL32.dll -> KERNEL32.dll
    VCRUNTIME140.dll -> VCRUNTIME140.dll
    VCRUNTIME140_1.dll -> VCRUNTIME140_1.dll
    api-ms-win-crt-runtime-l1-1-0.dll -> api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-string-l1-1-0.dll -> api-ms-win-crt-string-l1-1-0.dll
    api-ms-win-crt-environment-l1-1-0.dll -> api-ms-win-crt-environment-l1-1-0.dll
    api-ms-win-crt-heap-l1-1-0.dll -> api-ms-win-crt-heap-l1-1-0.dll
    api-ms-win-crt-convert-l1-1-0.dll -> api-ms-win-crt-convert-l1-1-0.dll
    api-ms-win-crt-stdio-l1-1-0.dll -> api-ms-win-crt-stdio-l1-1-0.dll
    api-ms-win-crt-filesystem-l1-1-0.dll -> api-ms-win-crt-filesystem-l1-1-0.dll
    api-ms-win-crt-math-l1-1-0.dll -> api-ms-win-crt-math-l1-1-0.dll
    api-ms-win-crt-locale-l1-1-0.dll -> api-ms-win-crt-locale-l1-1-0.dll
    ncrypt.dll -> ncrypt.dll
    IPHLPAPI.DLL -> IPHLPAPI.DLL

Man sieht, es passiert etwas. Ich kann die neue .exe aber noch nicht ausführen. Ich vermute, meine LoadLibrary...-Logik ist falsch, bzw. wird gar nicht aufgerufen.

Wie exportiert man denn statische Funktionen, die mit LoadLibrary... geladen werden sollen - also so, dass diese quasi schon in der "WrapperDll.dll" sind, bevor man setdll aufruft?

Ich vermute, setdll ruft main... gar nicht auf.

Bin für jeden Tipp dankbar !
 
Anna R schrieb:
Ich vermute, setdll ruft main... gar nicht auf.

Import table resolves rufen DllMain Funktionen mit DLL_PROCESS_ATTACH auf, nicht mit DLL_THREAD_ATTACH.

Anna R schrieb:
Wie exportiert man denn statische Funktionen, die mit LoadLibrary... geladen werden sollen - also so, dass diese quasi schon in der "WrapperDll.dll" sind, bevor man setdll aufruft?

Das geht nur, wenn du diese Funktionen in einer statischen library (.lib) vorliegen hast und du statisch linkst (der Linker kopiert die Funktion von der .lib in das target executable).

Wenn diese Funktionen in einer .dll vorliegen, kannst du entweder "implizit linken" (das was du hier quasi mit PasswordStrength.exe und WrapperDll.dll machst, die DLL ist in der import table und wird beim Start automatisch geladen, normalerweise läuft das über eine "import library" die gemeinsam mit der DLL erstellt wird), oder "explizit linken", wobei du die DLL zur Laufzeit mit LoadLibrary lädst und Funktionen darin über GetProcAddress holst.

So wie du die DLLs in der Schleife lädst werden diese zwar korrekt in den Adressraum des Prozesses geladen wenn du PasswordStrength.exe startest, aber du willst ja wahrscheinlich Funktionen daraus aufrufen, also müsstest du die handles von LoadLibrary irgendwo zwischenspeichern, außerdem hast du so einen potentiellen resource leak wenn du nicht für jedes handle FreeLibrary aufrufst schlussendlich.
 
eweu schrieb:
Import table resolves rufen DllMain Funktionen mit DLL_PROCESS_ATTACH auf, nicht mit DLL_THREAD_ATTACH.
Bin eingerostet in C++, aber ist case DLL_PROCESS_ATTACH und case DLL_THREAD_ATTACH nicht eine Gruppierung? Habe ich einfach einen Syntaxfehler? Oder gilt Process Attach > Thread Attach?

eweu schrieb:
Wenn diese Funktionen in einer .dll vorliegen, kannst du entweder "implizit linken" (das was du hier quasi mit PasswordStrength.exe und WrapperDll.dll machst, die DLL ist in der import table und wird beim Start automatisch geladen, normalerweise läuft das über eine "import library" die gemeinsam mit der DLL erstellt wird)
Ok , das möchte ich auch beibehalten.

dms schrieb:
ist eher ein "Unstile"
Eine "Unsitte" ist auch , wenn schreibt , das etwas nicht geht , obwohl doch. Aber sorry. ✌️
 
Anna R schrieb:
Eine "Unsitte" ist auch , wenn schreibt , das etwas nicht geht , obwohl doch. Aber sorry.
Bedenke einfach - jeder kann nur auf den Kontext anworten welchen du hier ausbreitest (oder nicht).
Nur du weist was dein Ziel ist und was dein Wissensstand ist - hast das ganze Projekt auf dem Tisch.

Ich habe seit > 15 jahren keine DLLs mehr selber gebaut oder Wrappen müssen - habe aber da durchaus veraltete Vorstellungen und lese bissel mit und bin ob der Knappheit eben etwas traurig.

D.
 
  • Gefällt mir
Reaktionen: Anna R
Es hat geklappt , aber ich hatte vergessen , das Resultat auch aufzurufen ... :

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

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" };

static BOOL loadAll()
{
    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);
            return FALSE;
        }
        printf("Loaded %ls\n", toLoad);
    }
    return TRUE;
}

static void unloadAll()
{
    for (const wchar_t* toLoad : toLoadArr)
    {
        HMODULE hm = GetModuleHandleW(toLoad);
        if (hm)
        {
            if (FreeLibrary(hm))
            {
                printf("Unloaded %ls\n", toLoad);
            }
            else
            {
                const DWORD errorCode = GetLastError();
                printf("FreeLibrary failed with error code 0x%X\n", errorCode);
            }
        }
    }
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
        return loadAll();
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        unloadAll();
        break;
    }
    return TRUE;
}

Code:
> setdll.exe /d:WrapperDll.dll PasswordStrength.exe
Adding WrapperDll.dll to binary files.
  PasswordStrength.exe:
    WrapperDll.dll
    VERSION.dll -> VERSION.dll
    ADVAPI32.dll -> ADVAPI32.dll
    WS2_32.dll -> WS2_32.dll
    USERENV.dll -> USERENV.dll
    KERNEL32.dll -> KERNEL32.dll
    VCRUNTIME140.dll -> VCRUNTIME140.dll
    VCRUNTIME140_1.dll -> VCRUNTIME140_1.dll
    api-ms-win-crt-runtime-l1-1-0.dll -> api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-string-l1-1-0.dll -> api-ms-win-crt-string-l1-1-0.dll
    api-ms-win-crt-environment-l1-1-0.dll -> api-ms-win-crt-environment-l1-1-0.dll
    api-ms-win-crt-heap-l1-1-0.dll -> api-ms-win-crt-heap-l1-1-0.dll
    api-ms-win-crt-convert-l1-1-0.dll -> api-ms-win-crt-convert-l1-1-0.dll
    api-ms-win-crt-stdio-l1-1-0.dll -> api-ms-win-crt-stdio-l1-1-0.dll
    api-ms-win-crt-filesystem-l1-1-0.dll -> api-ms-win-crt-filesystem-l1-1-0.dll
    api-ms-win-crt-math-l1-1-0.dll -> api-ms-win-crt-math-l1-1-0.dll
    api-ms-win-crt-locale-l1-1-0.dll -> api-ms-win-crt-locale-l1-1-0.dll
    ncrypt.dll -> ncrypt.dll
    IPHLPAPI.DLL -> IPHLPAPI.DLL

Code:
> .\PasswordStrength.exe
Loaded awt.dll
Loaded fontmanager.dll
Loaded freetype.dll
Loaded java.dll
Loaded javaaccessbridge.dll
Loaded javajpeg.dll
Loaded jawt.dll
Loaded jvm.dll
Loaded lcms.dll
Loaded awt.dll
Loaded fontmanager.dll
Loaded freetype.dll
Loaded java.dll
Loaded javaaccessbridge.dll
Loaded javajpeg.dll
Loaded jawt.dll
Loaded jvm.dll
Loaded lcms.dll
Exception in thread "main" java.lang.NoSuchMethodError: java.awt.Toolkit.getDefaultToolkit()Ljava/awt/Toolkit;
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.functions.JNIFunctions$Support.getMethodID(JNIFunctions.java:1853)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.functions.JNIFunctions$Support.getMethodID(JNIFunctions.java:1838)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.functions.JNIFunctions.GetStaticMethodID(JNIFunctions.java:449)
        at java.desktop@24.0.2/java.awt.Toolkit.initIDs(Native Method)
        at java.desktop@24.0.2/java.awt.Toolkit.initStatic(Toolkit.java:1320)
        at java.desktop@24.0.2/java.awt.Toolkit.<clinit>(Toolkit.java:1299)
        at java.desktop@24.0.2/java.awt.Component.<clinit>(Component.java:614)
        at java.base@24.0.2/java.lang.Class.ensureInitialized(DynamicHub.java:658)
        at java.base@24.0.2/java.lang.Class.ensureInitialized(DynamicHub.java:658)
        at java.base@24.0.2/java.lang.Class.ensureInitialized(DynamicHub.java:658)
        at Main.main(Main.java:12)
        at java.base@24.0.2/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Unloaded awt.dll
Unloaded fontmanager.dll
Unloaded freetype.dll
Unloaded java.dll
Unloaded javaaccessbridge.dll
Unloaded javajpeg.dll
Unloaded jawt.dll
Unloaded jvm.dll
Unloaded lcms.dll

Der Awt-Toolkit Fehler (Exception) liegt an Anderem - und fällt nicht mehr in meinen Zuständigkeitsbereich.

Aber wenn dazu jemand auch eine Idee hat, gerne melden.
 
Doch schon. Das zweite Laden kommt wahrscheinlich vom EDT Thread.
 
  • Gefällt mir
Reaktionen: eweu
Anna R schrieb:
Bin eingerostet in C++, aber ist case DLL_PROCESS_ATTACH und case DLL_THREAD_ATTACH nicht eine Gruppierung? Habe ich einfach einen Syntaxfehler? Oder gilt Process Attach > Thread Attach?

Ja, du hast Recht. Würde aber zumindest im Hinterkopf behalten, dass für jeden Thread der irgendwo erstellt wird, z.B. von einer deiner geladenen DLLs, worüber du keine Kontrolle hast, dein DllMain neu aufgerufen wird mit DLL_THREAD_ATTACH, siehe hier. Laut deinem Log passiert das anscheinend schon. Falls du mal die Logik in deiner DllMain ändern/erweitern solltest ist das ein potentieller Bug, aktuell ists nur eine unnötige Logausgabe, weil LoadLibrary die DLL nicht lädt, wenn sie schon geladen wurde (reference count erhöht sich aber).
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Anna R
Deine Erklärung macht Sinn. Habe das geändert:

C++:
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        return loadAll();
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        unloadAll();
        break;
    }
    return TRUE;
}

Es funktioniert inzwischen auch , aber das Ganze war doch eher eine unausgegorene , verfrühte Idee ...

Denn alle DLLs (auch die Wrapper-DLL...) und die exe-Datei müssen sich im selben Verzeichnis befinden, damit der Doppelklick auf die exe-Datei funktioniert - und ... ganzheitlich gesehen, ist dadurch nichts gewonnen, weil das Ziel ja war, nur eine (!!!) exe-Datei zu haben, in der alles (!1!1) gebündelt wäre.

Ich gebe vorerst auf. :)
 
Darf man hier zip-Files mit einer Größe von ca. 75 MB hochladen? Dann würde ich euch das Executable inkls Dlls mal zur Verfügung stellen , ob es bei bei euch auch ausgeführt werden kann . Das setzt natürlich Vertrauen voraus (oder ein isoliertes System ...), dass das Executable harmlos ist.

Es ist ein kleines Programm , das prüfen kann , ob ein gewähltes Passwort sicher bzw stark ist.
 
Als interessierter Mitleser interessiert mich das auch :D
75 Megabyte fuer ein Programm das Passwortkomplexizitaet prueft kommt mir ein bisschen viel vor. Oder ist da dann die ganze JRE mit eingepackt?
 
  • Gefällt mir
Reaktionen: Fabii02 und dms
Zurück
Oben