Announcement

Collapse
No announcement yet.

Feststellen, ob ein Programm von Delphi aufgerufen wurde

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Feststellen, ob ein Programm von Delphi aufgerufen wurde

    Hallo!<p>
    Wie finde ich in meinen Programm heraus, ob es von Delphi aus der Entwicklungsumgebung heraus gestartet oder direkt die EXE-Datei aufgerufen wurde?!?<p>
    Ich hoffe, jemand kann mir helfen...<p>
    Gruß,<br>
    Bernhard

  • #2
    Hallo,

    auf dem folgenden Weg kann erkannt werden, ob der Prozess unter der Kontrolle eines Debuggers gestartet wird. Die Messagebox ist nur dann sichbar, wenn das Programm aus Delphi (oder einem anderen Debugger heraus) aufgerufen wird:
    <pre>
    { Funktionen prüfen, ob der aktuelle Prozess unter der Kontrolle eines
    Debuggers ausgeführt wird. Dabei werden nur die gebräuchlichen
    Ring3-Debugger erkannt. Der SoftICE als Kernel-Debugger bleibt
    außen vor, d.h. er ist für ein Anwendungsprogramm "unsichtbar".

    a) Windows NT : API-Funktion »IsDebuggerRunning«
    b) Windows 9x : Undokumentierter Zugriff auf die PDB (Process Database)
    }

    {-------------------------------------------------------}
    { Prüfung unter Windows NT }
    {-------------------------------------------------------}

    type
    TIsDebuggerPresent = function: BOOL; stdcall;

    function IsDebuggerPresentForNT: Boolean;
    var
    Kernel32: LongInt;
    FIsDebuggerPresent: TIsDebuggerPresent;
    begin
    Result := False;
    Kernel32 := LoadLibrary('KERNEL32.DLL');
    if Kernel32 <> 0 then
    begin
    // Adresse von IsDebuggerPresent ermitteln
    FIsDebuggerPresent := GetProcAddress(Kernel32, 'IsDebuggerPresent');
    // Funktion aufrufen
    if Assigned(FIsDebuggerPresent) then
    Result := FIsDebuggerPresent;
    FreeLibrary(Kernel32);
    end;
    end;

    {-------------------------------------------------------}
    { Prüfung unter Windows 9x }
    {-------------------------------------------------------}

    const
    fDebugSingle = $00000001; // interessierendes Flag

    type
    PProcessDatabase = ^TProcessDatabase;
    TProcessDatabase = packed record
    DontCare1: array[0..7] of Integer;
    Flags: Integer;
    DontCare2: array[0..11] of Integer;
    DebugeeCB: Integer;
    DontCare3: array[0..22] of Integer;
    DontCare4: Word;
    end;

    function IsDebuggerPresentForWindows: Boolean;
    var
    PDB: PProcessDatabase;
    TID: Integer;
    Obsfucator: Integer;
    begin
    Result := False;
    Obsfucator := 0;
    TID := GetCurrentThreadID;
    // »Obsfucator« (Microsoft-Begriff) berechnen
    asm
    MOV EAX, FS:[18h]
    SUB EAX, 10h
    XOR EAX, [TID]
    MOV [Obsfucator], EAX
    end;
    if Obsfucator <> 0 then
    begin
    PDB := Pointer(GetCurrentProcessID xor Obsfucator);
    // Return True wenn der Prozess debuggt wird
    Result := (PDB^.Flags and fDebugSingle) <> 0;
    end;
    end;

    {-------------------------------------------------------}
    { Funktion »IsDebuggerPresent« }
    {-------------------------------------------------------}

    function IsDebuggerPresent: Boolean;
    var
    OSVersionInfo: TOSVersionInfo;
    begin
    OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
    GetVersionEx(OSVersionInfo);
    // Windows 9x oder Windows NT ?
    if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
    Result := IsDebuggerPresentForNT
    else
    Result := IsDebuggerPresentForWindows;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    if IsDebuggerPresent then
    ShowMessage('Start aus Delphi');
    end;
    </pre&gt

    Comment


    • #3
      Hallo Bernhard,

      Herr Kosch hat natürlich perfekt geantwortet. Es geht aber auch ein bischen schneller: "if FindWindow('TAppBuilder', Nil) > 0 then {-Delphi läuft..==>}

      Gruß

      Ott

      Comment


      • #4
        Hallo,

        nein - diese "schnelle" Lösung erfüllt nicht die Anforderungen. Die Frage war doch, wie ein Programm die beiden Fälle <br>
        a) Start aus der Delphi-IDE heraus, und <br>
        b) Direkter Start als EXE <br>
        unterscheiden kann. Der Weg für FindWindow kann diese beiden Fällen jedoch <b>nicht</b> unterscheiden, wenn Delphi als Programm aktiv ist. In diesem Fall wird das Delphi-Fenster auch im Fall b) gefunden

        Comment


        • #5
          Hallo Herr Kosch,

          mea culpa, mea maxima culpa, Sie haben natürlich recht, in diesem Fall muß der Debugger-Test ran. Ich hab die Frage wohl etwas zu schnell (und noch dazu um 3:00 morgens) gelesen, und dabei an die eigene Anforderung gedacht, für welche ich diesen "Quickie" verwende

          Comment


          • #6
            Hallo!<p>
            Erstmal vielen Dank an alle, die mir da geholfen haben. Leider funktioniert die Funktion IsDebuggerPresent bei all meinen Testprojekten bei mir (Delphi 5; Wintendo 98) genau umgekehrt: Sie liefert False zurück, bei einem Start aus der Delphi-IDE, und True, bei einem direkten Start der EXE.Betrifft dies nur die Funktion <i>IsDebuggerPresentForWindows</i>, oder gilt dass auch für die Funktion <i>IsDebuggerPresentForNT</i>, die ich mangels Testmöglichkeiten/Zeit/Geld/Nerven nicht testen konnte?<p>
            Wäre für Hinweise sehr dankbar,<br>
            Gruß,<br>
            Bernhar

            Comment


            • #7
              Hallo,

              ich habe mein Beispiel gerade noch einmal unter NT 4 SP5 getestet, und es verhält sich so wie erwartet. Beim Start aus der Delphi-IDE heraus erscheint die Messagebox, beim direkten Aufruf (und laufenden Delphi) als EXE jedoch nicht. Wenn sich das entgegengesetzte Verhalten unter Windows 9x jederzeit reproduzieren lässt, würde ich die Auswertung in IsDebuggerPresentForWindows umpolen. Wie man an den ASM-Anweisungen erkennen kann, ist IsDebuggerPresentForWindows sowieso mit Vorsicht zu geniessen (interner Aufbau der Process-Database kann sich mit jeder neuen Windows-Version ändern). Nur unter Windows NT/Windows 2000 steht mit der speziellen API-Funktion <b>IsDebuggerPresent</b> eine saubere Lösung zur Verfügung.
              &#10

              Comment


              • #8
                Leider habe ich beim Nachbilden des Beispiels das Problem das TProcessdatabase nicht bekannt ist. Was muß ich tun ?
                Der NT/W2K Teil läuft hervorragend

                Comment


                • #9
                  Hi

                  Der Weg von Andreas funktioniert nur falls aus der IDE herraus auch debuggt wird. Sollte das Debugging in der IDE aber abgeschaltet sein und das Program wurde dennoch vom delphi gestartet so gibt Andreas's Funktion FALSE zurück. Der einzigse mir bekannte Weg ist den Parent des Prozesses zu ermitteln. Dafür steht unter allen Win9x Systemen entweder der inoffizielle Weg über die internen ProcessDB's oder das ToolHelp API und für WinNT das PSAPI zur Verfügung. Ein anderes Problem entsteht wenn die Anwendung durch ein anderes Debugging Tool gestartet wurde. In diesem Moment gibt obige Funktion ebenfalls TRUE zurück wurde aber NICHT durch Delphi gestartet.
                  Wird unter D5/6 eine externe und schon laufende Anwendung debuggt, würde die Funktion VOR dem Debugger FALSE und nach dem Starten des Debuggens TRUE zurückgeben, OBWOHL die Anwendung NICHT vom delphi gestartet wurde.

                  Gruß Hage

                  Comment


                  • #10
                    Hallo,

                    im UDDF habe ich folgendes dazu gefunden:
                    <pre>

                    How to detect if running in IDE?

                    Solution 1
                    From: "Robert KORITNIK" <[email protected]>

                    ---------------------------------------------------------------------

                    if csDesigning in ComponentState then

                    ----------------------------------------------------------------------
                    .....
                    That's how you do it...

                    Solution 2
                    Mike O'Hanlon <[email protected]>

                    Here's a routine that works for Delphi 1. If you're using Delphi 2 and it also seems to work in that environment, please let me know.
                    ----------------------------------------------------------------------
                    function LaunchedFromDelphiIDE: Boolean;
                    {----------------------------------------------------------------}
                    { Checks whether calling application was launched from the IDE. }
                    { From a posting to Delphi-Talk by Ed Salgado <[email protected]>}
                    { of Eminent Domain Software. }
                    {----------------------------------------------------------------}
                    begin
                    LaunchedFromDelphiIDE := Bool(PrefixSeg) {ie. not a DLL} and
                    Bool(PWordArray(MemL[DSeg:36])^[8]);
                    end; {LaunchedFromDelphiIDE}
                    </pre>

                    Tschüss Ti

                    Comment


                    • #11
                      Hm, auch nicht das Ultimative.
                      Der erste Fall kann auch durchaus in der eigenen Anwendung eintreten, und im Falle von Delphi nur wenn debuggt wird. Wird die EXE ohne Debugging aus der IDE gestartet funktioniert auch dieser Trick nicht mehr. Der zweite Fall gilt nur für 16 Bit Anwendungen.

                      Am einfachsten ist es wirklich mal bei JEDI vorbeizuschauen. Ich glaube die haben einen Source der eine ProcessListe aller laufenden Processe erzeugt (egal welches OS). Nun, sucht man einfach seinen eigenen Process raus und hat damit auch schon das Parent Processhandle. Dann die Infos zu diesem process rausgesucht, pfad auf "Delphi" untersucht. Falls Ja, den Process geöffnet, die Resource "DVCAL" und "PackageInfo" und VerInfo geladen und bestimmte Werte verglichen. Noch besser ist von jeder Delphi Version gleich eine eigene "geheime" Prüfsumme zu berechnen und dann mit dem Parent Process vergleichen.

                      Gruß Hage

                      Comment


                      • #12
                        Hi

                        Ich vermute Bernhard will eine Trialversion coden die NUR aus der Delphi IDE heraus funktioniert. Nun, bisjetzt kenne ich keine einzigste Software die das je effektiv geschaft hat, auch nicht z.B. der Selbst-Schutz von APD II Protection oder AntiDebug/AntiHack Unit von Ali Sadat. Beide <b>sinnlose</b> Tools, versuchen zu ermitteln ob sie unter der Delphi IDE laufen, falls ja versuchen sie zu ermitteln ob sie unter dem Delphi Debugger analysiert werden und versuchen natürlich das zu verhindern. Ein erfahrener Entwickler knackt deren "Schutz" in 5-15 Minuten, und was lustig dabei ist ist der Fakt das es MEHR Möglichkeiten gibt solchen Schutzt zu umgehen/deaktivieren als ihn zu etablieren )

                        Nun, Bernhard, ich empfehle Dir einen ganz anderen Weg.
                        Anstatt sofort zu ermitteln ob die Anwendung unter Delphi läuft, ermitteln das nur sehr sporadisch und nicht jeden Tag. Desweiteren schaust Du NICHT nach ob der richtige ParentProcess, sprich Delphi32.exe sondern NUR ob Delphi auf dem Computer korrekt installiert wurde. Die Software selber wird als Trial Version angeboten, PUNKT, nicht mehr veraten.

                        Was passiert nun. Ein Anwender der die "kriminelle" Energie hat Deine Software/Shareware Trialversion denoch ohne Registrierung zu verwenden wird dies tun. Auf seinem System, da delphi installiert ist, meldet sich Dein Schutzmechanismus NIE, auch nicht auf den Systemen seiner Hackerfreunde. Er denkt sich, jo dann bau ma mal die Komponente mit ein. Er verkauft/vertreibt seine Software und erst auf den vielen NICHT Delphi rechnern meldet sich die Software mit dem Hinweis das diese Software mit eine UNLIZENSIERTEN Komponente von Dir entwickelt wurde, und das sich der User schnellstmöglich beim Entwickler dieser Software melden soll. Der User macht dann Druck und dem "Trialversions-Klauer" bleiben nur drei Wege offen, 1. entweder kauft er Deine Software nach, oder stellt den Verkauf Seiner Software ein, oder 3. er findet den Schutzmechansimus. Sein RUF ist aber auf alle Fälle ruiniert.

                        Gruß Hage

                        Comment


                        • #13
                          Also ich habe inzwischen 4 oder 5 Versionen gesehen, wie der 'Obsfucator' berechnet wird. Im obigen Beispiel wird aber eh' nur die TIB.PDB benötigt, die meines Wissens direkt in FS:[$30] steht (und mit der Prozeß-ID xor'ed ergibt es gleich den 'Obsfucator, wenn man ihn denn braucht).

                          Wüßte trotzdem gerne, welche Methode denn nun am 'sichersten' ist, und ob Microsoft in irgendeiner versteckten Doku was zum Thema erwähnt hat.

                          Gruß Nic

                          Comment


                          • #14
                            Unter Win9x nutze ich die FS:[] werte, ODER den import per Ordinal #18 aus kernel32.dll "GetProcessDWord(ID: ProcessID; Offset: Integer)". Mit dem dem Offset -40 "GDP_THDB" oder -36 "GDP_PDB" oder -8 für "GDP_PARENT" oder -4 "GDP_FLAGS".

                            Die FS:[] methode hat viel Vorteile, schnell viel Redundance die uns auf einfache Weise ein Überprüfung gestattet und mit der importierten Funktion GetProcessDWord() eben verifiziert werden kann. Bei meinen Tests ergab sich immer das es unter allen Win9x Versionen funktionierte. Es ist sogar so das es fürs FS:[] Segment starke Bezüge zu NT/2000 gibt. Die ersten 4 DWord haben in allen Windows Versionen die gleiche Bedeutung, auch die Exception Frame Felder sind identisch. Nun, mit der FS:[] Methode gibts also einen komfortablen Weg die Windows Version + eventl. alle process/thread relevanten Informatonen zu erlangen OHNE überhaupt irgendeine hookbare API Funktion zu nutzen.

                            Allerdings, als Schutzmethode muß immer eine Kombination her und mein obiger Vorschlag wird wohl noch der effektivste, legalste und druckvollste sein.

                            gruß hage

                            Comment


                            • #15
                              Das Problem ist, das die Funktion oben mir einen 'falschen' Obsfucator liefert und damit das Ergebnis nicht stimmt (alle anderen Funktionen ~5-6 sind sich bei ihren Werten einig, und die Referenz auf _PDB stimmt auch...)<p>
                              Kurze Aufzählung... Obsfucator über
                              * ToolHelp32 API (ParentProcessId von Process32First ist der Obsfucator)
                              * Stack (lokalen Variablen des Aufgerufen (esp-8)) nach GetCurrentProcessId oder GetCurrentThreadId mit der jeweiligen Id re-xor
                              * fs:[30] (TIB.PDB) xor PID
                              * [fs:[18h] + 30h] xor PID
                              * sogar der kernel-walk [[[@GetCurrentProcessId + 1]]] (geht auch mit @GetCurrentThreadId)

                              Nur das oben nicht.

                              Gruß Nico

                              PS: ich habe den Test mal unter http://www.bendlins.de/nico/cpp/ abgelegt ( ich glaube nicht, das ich mich bei der Übersetzung vertan habe... ist nervig, ich warte schon schon seit 2 Wochen auf die neue Delphi CD -- alte läßt sich dank Kratzer beim Umzug nicht mehr lesen, also muß erstmal C herhalten =/

                              Comment

                              Working...
                              X