![]() |
OutputDebugString überwachen
|
Re: OutputDebugString überwachen
Indem du ganz gepflegt die gleiche Methode verwendest. Und die wäre diese:
1. Du lernst C/C++ und NT-Treiberprogrammierung (für Windoes 9x natürlich VXD-Programmierung) 2. Du schreibst einen Treiber und einen Service welcher mit dem Treiber kommuniziert 3. Der Treiber muß diverse APIs im Kernelmode hooken 4. Dein Tool zeigt die Ausgabe dessen an, was der Hook abfängt. Voila. Das war's schon. Viel Erfolg. Wenn irgendjemand meine "wilden Hypothesen" verifizieren möchte, mag er sich seinen Lieblingsressourceneditor/-betrachter zur Hand nehmen und in ebendiesem alle Ressourceneinträge unter "BINRES" betrachten. Für eine weitere Analyse empfiehlt sich dann ein Disassembler, wie z.B. ![]() |
Re: OutputDebugString überwachen
Zitat:
PS: Für mich bist du aber der "Schlaumeier des Tages". |
Re: OutputDebugString überwachen
Zitat:
|
Re: OutputDebugString überwachen
|
Re: OutputDebugString überwachen
Zitat:
OutputDebugString kann man abfangen indem man den prozess debuggt, mit hilfe der funktion ![]() ![]() |
Re: OutputDebugString überwachen
ok, Sprint war schneller ;)
|
Re: OutputDebugString überwachen
@w3seek: Du hast insofern recht, als diese natürlich ebenfalls abgefangen werden können. Da du im ROS-Projekt dabei bist, kennst du ja quasi die Windows-Interna. Allerdings debuggt eben der DbgView von Sysinternals keinesfalls den Target, sondern setzt auf einer tieferen Ebene an.
__________________________________________________ ________ @Sprint: Zitat:
Zitat:
Zitat:
Komisch, dann war ich wohl der einzige dumme Schlaumeier des Tages, der in der Fragestellung komischerweise genau das verstanden hat, was in ihr stand. Wie dumm von mir ... Delphi Star schrieb (Hervorhebung Mephisto): Ich bitte also untertänigst um Vergebung und werde mich sogleich aus diesem Thread entfernen. |
Re: OutputDebugString überwachen
Delphi-Quellcode:
Was ist daran falsch :?:
if WaitForDebugEvent(OUTPUT_DEBUG_STRING_EVENT,INFINITE)=true then
showmessage('test'); |
Re: OutputDebugString überwachen
Zitat:
Im Platform SDK steht: The WaitForDebugEvent function waits for a debugging event to occur in a process being debugged. (Speziell an w3seek:) Ich habe mir soeben mal die Implementation von Windows 2000's kernel32!OutputDebugString() angeschaut. Dabei ist mir aufgefallen, daß theoretisch auch wenn der Prozess nicht debuggt wird dieser String in eine MMF geschrieben wird. Zusätzlich werden 2 Ereignisse geöffnet und mglw. signalisiert. Und mit einem Mutex wird der Zugriff auf die MMF gesperrt (dieser scheint intern der Kernel32 zu gehören - zumindest kennt die Kernel32 sein Handle und öffnet ihn nicht explizit innerhalb der Funktion). Die MMF heißt: "DBWIN_BUFFER" Die Ereignisse heißen: "DBWIN_DATA_READY" und "DBWIN_BUFFER_READY" Wie kompatibel (mit Windows 9x) und vorigen/späteren NT-Versionen ein solches Vorgehen ist, bleibt dahingestellt. Wenn eine tiefere Analyse erwünscht ist, kann ich die u.U. noch nachliefern. Aber auch kernel32!OutputDebugString() ruft ntdll!DbgPrint() auf, welches wiederum ntdll!DebugPrint() aufruft, welches wiederum ntdll!DebugService() aufruft, welches den Aufruf über SYSENTER bzw. INT 2Eh über die SSDT in den Kernelmode weiterleitet. Da ich keine Zeit habe, kann ich die auch nicht sagen, wie der Service-Index auf eine Kernelmodefunktion mappt. Zumindest gleicht sich der Code o.g. Funktionsaufrufe im Kernel- und im Usermode wie ein Ei dem anderen (NTOSKRNL.EXE vs. NTDLL.DLL). PS: Das alles war ein sehr oberflächliches Anschauen des Codes. Könnte also Fehler in der Beschreibung enthalten. |
Re: OutputDebugString überwachen
Zitat:
|
Re: OutputDebugString überwachen
Ich sehe gerade, daß du eine DEBUG_EVENT-Struktur übergeben mußt, deren Member dann von der Funktion scheinbar gefüllt werden. Danach vergleichst du dwDebugEventCode, dwProcessId und dwThreadId mit den von dir gewünschten Werten und bist fein raus. Ob das ohne eigentliches Debuggen funktioniert, kannst du ja selber testen.
Zitat:
Zitat:
![]() Okay, ich gestehe "des Codes" ist zweideutig - mein Fehler. Beim Quelltext wäre aber sicherlich keine "peu-a-peu"-Beschreibung rauskommen. Aber wozu rechtfertige ich mich eigentlich dir gegenüber?! :gruebel: Mit Worten läßt sich trefflich streiten, Mit Worten ein System bereiten, An Worte läßt sich trefflich glauben, Von einem Wort läßt sich kein Iota rauben. |
Re: OutputDebugString überwachen
Ich bin davon ausgegangen dass er nur die OutputDebugString ausgaben eines bestimmten prozesses moechte. Mir ist DebugView selbstverstaendlich bekannt und es setzt in der Tat einen Level tiefer an.
Um OutputDebugString zu verstehen, ist ein wenig SEH (Structured Exception Handling) notwendig. Zuerst sollte man wissen, dass sobald ein prozess debugged wird, jede Exception erst einmal an den debugger weitergeleitet wird der ueber die weitere Vorgehensweise entscheided (im prinzip wie jeder "normale" exception handler), dies funktioniert ueber die sog. debug ports. OutputDebugString macht im prinzip nichts anderes, als dass es eine spezielle exception ausloest (DBG_PRINTEXCEPTION_C). Ist nun ein debugger praesent fuer diesen prozess, wird dieser aktiv (d.h. der debug port sendet eine nachricht an den debugger prozess der den Thread, der gerade in WaitForDebugEvent waert, aufwachen laesst und die exception informationen uebermittelt. Waehrend der debugger diese exception dann behandelt, ist der thread der sie ausgeloest hat, im Schlummerzustand so dass es dem Debugger ermoeglicht saemtliche zusaetzliche Informationen wie image dumps, register dumps, stack traces, ... auszulesen. Der Debugger kann dabei (wie jeder exception handler) auch die Ausfuehrung des threads uneingeschraenkt beeinflussen, beispielsweise die Register veraendern um Instruktionen zu ueberspringen oder den stack unwind (RtlUnwind) durchfuehren, oder die exception unbehandelt lassen so dass sich der thread spaeter selbst um die behandlung kuemmern muss. Schliesslich um die Ausfuehrung des Threads fortzusetzen, muss der debugger noch ContinueDebugEvent aufrufen, das den eingeschlaeferten Thread wieder aufwachen laesst. Im Prinzip durchlaeuft jeder Debugger diese Schleife um breakpoints, debug ausgaben, ... zu behandeln. DebugView ist aber in diesem Sinne kein richtiger debugger, d.h. er wird nicht automatisch aktiv sobald eine exception ausgeloest wird. Er macht sich dagegen einer anderen Eigenschaft (die weniger dokumentiert ist) zunutze die OutputDebugStringA hat. Wenn naemlich kein debugger aktiv ist, der diese spezielle exception behandelt, schreibt es diese informationen in eine named (DBWIN_BUFFER) section (aka Memory Mapped File, wie bereits angemerkt wurde). Named, deswegen, dass es im object namespace von jedem Prozess in der selben session (entsprechende Rechte vorausgesetzt) auffindbar ist. Diese section ist fuer alle Prozesse lesbar und schreibbar, weshalb man jeglichen zugriff darauf sichern sollte da die Informationen beim Lesen der Daten jederzeit veraendert oder corrupted werden koennen. Damit DebugView also nicht staendig von diesem puffer lesen (pollen) muss, um herauszufinden ob daten hineingeschrieben wurden, gibt es noch named events(DBWIN_BUFFER_READY und DBWIN_DATA_READY), die OutputDebugString ausloest. DBWIN_BUFFER_READY zeigt an, ob jemand gerade mit dieser section arbeitet und verhindert OutputDebugString Daten in der section zu veraendern. Sobald man also den string aus dem puffer gelesen hatte, sollte man diesen event wieder signalisieren so dass weitere OutputDebugString aufrufe erfolgen koennen. Dies deckt die Synchronisierung zum lesen/schreiben der Daten in diese section ab, um jetzt beispielsweise DebugView nicht staendig pollen lassen zu muessen, gibt es noch den DBWIN_DATA_READY event, welchen OutputDebugString signalisiert sobald es die nachricht in die section geschrieben hat. Kurz gefasst sieht die Vorgehensweise zum globalen Auslesen der OutputDebugString messages so aus: 1. Die DBWIN_BUFFER section mappen 2. Handles zu den DBWIN_BUFFER_READY und DBWIN_DATA_READY events erstellen 3. Den DBWIN_BUFFER_READY event setzen so dass OutputDebugString wieder Zugriff auf den puffer hat 4. Auf den DBWIN_DATA_READY event warten welcher signalisiert, dass neue nachrichten vorhanden sind 5. Die geoeffneten Handles schliessen Die Schritte 2-4 in einer Endlosschleife durchfuehren wenn man mehr als nur eine Nachricht abfangen moechte. Zu bemerken ist, dass man damit nur jene Debug ausgaben abfangen kann, die von Prozessen gesendet werden, die nicht mit einem Debugger verbunden sind, da sonst diese spezielle exception an den Debugger uebermittelt wuerde. Ich hoffe ich konnte das halbwegs erklaeren (sorry fuer die vielen Rechtschreib- und Grammatikfehler), so sollte das in der Realitaet funktionieren. Einen Treiber braucht man jedenfalls fuer das Abfangen von OutputDebugString nicht, anders sieht es mit DbgPrint aus, denn dafuer gibt es eine kernel mode implementierung (ntoskrnl.exe) und eine user mode implementierung (ntdll) - welche letztendlich aber auf den gleichen port schreiben... |
Re: OutputDebugString überwachen
Ich habe absichtlich die Win32-Termini benutzt um niemanden zu verwirren. Nicht jeder hier ist mit K-Mode und/oder Native API vertraut, denke ich.
Die Frage haben wir also offenbar unterschiedlich aufgefaßt. Ansonsten eine sehr gute Erklärung. Daß DebugView die Section ausliest, wußte ich garnicht - ich ging wegen des gleichen Schemas, welches sich durch viele der Sysinternals-Tools zieht, davon aus, daß einzig auf der tiefsten Ebene (eben K-Mode) gehookt wird. Wie gesagt, auch OutputDebugString() ruft ja schließlich DbgPrint() auf, welches in den K-Mode geroutet wird (s.o.). Genaueres muß man wohl oder übel in einem KD anschauen. Da hat wohl einer in die Windows-Sourcen geguckt - oder war es vielleicht doch nur ROS, ein guter Disassembler und ein Debugger :zwinker: ? Gelle, w3seek? :mrgreen: ... naja, Dax kennt eben noch nicht die besten und interessantesten OpenSource-Projekte, wie mir scheint. @Thomas: Hier eine Funktion, die in ROS 0.2.5 noch nicht deklariert war. Die wurde allerdings auch erst mit Windows XP eingeführt. Viel Spaß ;)
Delphi-Quellcode:
// Resembles the RtlValidateUnicodeString() function available from Windows XP
// on exactly as it is on this OS version, except for the calling convention. function RtlValidateUnicodeString(dwMustBeNull: DWORD; UnicodeString: PUNICODE_STRING): NTSTATUS; begin result := STATUS_INVALID_PARAMETER; if(dwMustBeNull = 0) then begin result := STATUS_SUCCESS; if(Assigned(UnicodeString)) then begin result := STATUS_INVALID_PARAMETER; if((UnicodeString^.Length mod 2 = 0) and (UnicodeString^.MaximumLength mod 2 = 0) and (UnicodeString^.Length <= UnicodeString^.MaximumLength)) then if((UnicodeString^.Length > 0) and (UnicodeString^.MaximumLength > 0)) then if(Assigned(UnicodeString^.Buffer)) then result := STATUS_SUCCESS; end; end; end; |
Re: OutputDebugString überwachen
Zitat:
Zitat:
Zitat:
|
Re: OutputDebugString überwachen
Zitat:
Zitat:
Der Kommentar war auch mehr auf Dax gemünzt, welcher offenbar meint, daß die mystischen Windows-Quelltexte, die ja wohl durch's Internet geistern, die einzige Möglichkeit zur Informationsbeschaffung sind. Achso, die Implementation der Funktion sollte dem Orginal entsprechen, aber natürlich ist das Orginal als __stdcall deklariert - dies beweisen Aufrufe dieser Funktion von anderen Stellen der ntdll.dll! Ach ja ... und unter C kannst du natürlich einfach mal "return" sagen. Unter Delphi ist das nicht so schön, weshalb ich geschachtelte IFs verwende. |
Re: OutputDebugString überwachen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz