debugger
-
Das lässt sich nicht verhindern. Höchstens ein bisschen erschweren.
-
Debuggen kannst du nicht verhindern. Was du machen kannst, ist ohne jegliche Debug Infos zu kompilieren und zu linken. Dann muss man sich schon durch Assembler Code schlagen. Wenn du irgendwelche Inhalte schützen willst, dann solltest du dich vielleicht eher mal mit geeigneten Verfahren beschäftigen. Verschlüsselung ist zB eines.
-
hmm.. also um mal einen auf Klugkack zu machen:
Habt ihr das Wort "debuggen" mal auseinander genommen?
debuggen = Fehler suchen
Warum sollte ich verhindern, daß man Fehler in meinem Programm kann?
Also, was willst du genau verhindern?
-
DocJunioR schrieb:
hmm.. also um mal einen auf Klugkack zu machen:
Habt ihr das Wort "debuggen" mal auseinander genommen?
debuggen = Fehler suchen
Warum sollte ich verhindern, daß man Fehler in meinem Programm kann?
Also, was willst du genau verhindern?Weil das auch zum *bösesWort*->"Keksen" ganz nützlich ist...
-
DocJunioR schrieb:
hmm.. also um mal einen auf Klugkack zu machen:
Habt ihr das Wort "debuggen" mal auseinander genommen?
debuggen = Fehler suchen
Warum sollte ich verhindern, daß man Fehler in meinem Programm kann?
Also, was willst du genau verhindern?Ist doch klar, dass damit nicht gemeint ist, dass niemand sein Programm "debuggen" soll sondern dass er verhindern will, dass ein Debugger an seinen Prozess angefügt wird. Und ein Debugger entfernt auch nicht von allein die Fehler aus Programmen, obwohl er diesen Namen hat.
-
Unter Windows gibt es mehrere "boese" Tricks, die man verwenden kann, um das Debuggen zu verhindern.
Du kannst z.B. in einer WM_PAINT-Message-Behandlung "_asm int 3;" einfuegen, um einen Breakpoint einzufuegen. Der Debugger bleibt meistens dann einfach haengen, da ja dauernd neue WM_PAINT-Nachrichten erzeugt werden. Laeuft das Programm ohne Debugger, passiert bei "_asm int 3;" nichts. (Falls doch, biegt man einfach den SEH-Handler um, siehe "Structured Exception Handling" in der Windows Platform SDK Doku http://msdn.microsoft.com/library/ ).
Eine andere "gemeine" Moeglichkeit ist es, Strings ins Code-Segment zu legen (per Compiler-Option). Dadurch wird das disassemblieren etwas erschwert.
Mehrstufig selbstentpackender Code kann auch ein Hindernis sein, genauso wie virtuelle Maschinen oder Interpreter, die den eigentlichen Code ausfuehren.
Man kann in einer Multithread-Anwendung auch das Zeitverhalten des Programms messen. Merkt ein Thread, dass er fuer laengere Zeit unterbrochen war, wird das Programm ainfach beendet (und zwar am besten direkt mit ExitProcess(0), das kann der Debugger nicht mehr abfangen).
In C++ Programmen, die viel mit Exceptions arbeiten, kann man oefters Testexceptions werfen und in der Exception-Behandlung viel weiter "oben" irgendwelche Pruefungen machen. Die meisten Cracker scheitern an solchen Sachen.
Vehement PC-relativer Code (also ohne absolute Addressierung) kann einen auch zum Wahnsinn treiben!
Es gibt viele Moeglichkeiten ...
-
Power Off schrieb:
Du kannst z.B. in einer WM_PAINT-Message-Behandlung "_asm int 3;" einfuegen
Jo, und mit nop macht man's wieder raus.
Power Off schrieb:
Eine andere "gemeine" Moeglichkeit ist es, Strings ins Code-Segment zu legen (per Compiler-Option). Dadurch wird das disassemblieren etwas erschwert.
Versteh nicht ganz, was dadurch schwerer werden soll.
Power Off schrieb:
Mehrstufig selbstentpackender Code kann auch ein Hindernis sein
Yep, kenn ich. Das kann schon schwierig werden. Soweit zu gehen, dass Debuggen damit unmöglich wird, würde ich aber nicht gehen.
Power Off schrieb:
genauso wie virtuelle Maschinen oder Interpreter, die den eigentlichen Code ausfuehren.
Da ich davon ausgehe, dass der Threadersteller ein C/C++ Programm meint, lass ich das einfach mal ohne Kommentar so stehen.
Power Off schrieb:
gMan kann in einer Multithread-Anwendung auch das Zeitverhalten des Programms messen. Merkt ein Thread, dass er fuer laengere Zeit unterbrochen war, wird das Programm ainfach beendet
Auch hier helfen wiederum nop's.
Power Off schrieb:
In C++ Programmen, die viel mit Exceptions arbeiten, kann man oefters Testexceptions werfen und in der Exception-Behandlung viel weiter "oben" irgendwelche Pruefungen machen. Die meisten Cracker scheitern an solchen Sachen.
Jo, seh ich auch so. Möglichst viel unsinnigen Code in sein Programm reinbringen, damit jeder Hacker verzweifelt. Am besten man verliert selbst den Überblick, so kann man wenigstens nichts verraten.
Power Off schrieb:
Vehement PC-relativer Code (also ohne absolute Addressierung) kann einen auch zum Wahnsinn treiben!
Kannst du mal ein Beispiel nennen. Wüsste nämlich nicht, dass unter Windows absolut adressiert wird.
Power Off schrieb:
Es gibt viele Moeglichkeiten ...
die Debugging erschweren, aber nicht verhindern.
-
groovemaster schrieb:
Kannst du mal ein Beispiel nennen. Wüsste nämlich nicht, dass unter Windows absolut adressiert wird.
Guck Dir mal ein PE EXE File von innen an. Wenn Du die Relozierungstabellen siehst, weisst Du, das absolute Adressierung verwendet wird. Dann muss naemlich der Scatter-Loader des Betriebssystems (LoadModule() bei Windows) die ganzen Adressen wieder aufloesen. Ein Cracker kann so leicht Einsprungadressen und Datenadressen herausbekommen.
Bei relativer Adressierung, wo die Adresse nur als Offset im Code angegeben ist, wird es deutlich schwerer, also wenn der Scatter-Loader dort nix zu relozieren hatte (bzw. der Linker nix aufzuloesen hatte).
Hier ein paar Beispiele:
; absolute Adressierung: call _forkmeharder mov _bleifuss,eax ; relative Adressierung: call 128[eax] mov 80[eax],eax
-
Power Off schrieb:
Guck Dir mal ein PE EXE File von innen an. Wenn Du die Relozierungstabellen siehst, weisst Du, das absolute Adressierung verwendet wird.
Ja, meine Bemerkung war ja auch etwas ironisch gemeint, denn absolute Adressen sind das im Grunde auch nicht, eher virtuelle. Die absoluten Adressen kannst du nur anhand der GDT bestimmen.
Trotzdem bleibt dieses Vorhaben für C/C++ Programmierer unrealistisch, weil man das Verhalten eines Compilers dahingehend nicht beeinflussen kann. Dann musst du schon Assembler programmieren.
Dass Offsets (relativ) schwieriger nachzuverfolgen sind als Adressen (absolut) ist schon klar.
-
groovemaster schrieb:
Ja, meine Bemerkung war ja auch etwas ironisch gemeint, denn absolute Adressen sind das im Grunde auch nicht, eher virtuelle. Die absoluten Adressen kannst du nur anhand der GDT bestimmen.
Der Adressierungsmode heisst "absolute addressing mode". Vielleicht solltest Du mal einen Blick in die Intel-Dokumentation werfen.
Dass die CPU ueber die MMU und Selektoren die Adresse ummappen kann, ist ein Feature der CPU, das man nicht unbedingt verwenden muss. Natuerlichen machen Betriebssysteme das, um die Speicherverwaltung zu vereinfachen.
Aber das aendert nix daran, dass die Adressierungsart "absolut" heisst. :p
groovemaster schrieb:
Trotzdem bleibt dieses Vorhaben für C/C++ Programmierer unrealistisch, weil man das Verhalten eines Compilers dahingehend nicht beeinflussen kann. Dann musst du schon Assembler programmieren.
Das heangt vom verwendeten Compiler ab. Es gibt durchaus Compiler, die ausschliesslich relativ adressierten Code erzeugen koennen.
Abgesehen davon, kann jemand mit ernsthaften Absichten in der Richtung durchaus seine eigenen Compiler schreiben. Ich hab auch mal einen fuer so was geschrieben (fuer einen FORTH Dialekt).
groovemaster schrieb:
Dass Offsets (relativ) schwieriger nachzuverfolgen sind als Adressen (absolut) ist schon klar.
Eben, und wenn man viel solchen Code hat, ist so gut wie unmoeglich, dessen Bedeutung noch herauszubekommen. Man ja auch System-Calls ueber Sprungtabellen und relative Adressierung kaschieren.
-
Power Off schrieb:
Der Adressierungsmode heisst "absolute addressing mode". Vielleicht solltest Du mal einen Blick in die Intel-Dokumentation werfen.
Wie ich schon sagte, war das ironisch gemeint. Wenn du's nicht kapierst, tut's mir leid. Punkt.
Power Off schrieb:
Das heangt vom verwendeten Compiler ab. Es gibt durchaus Compiler, die ausschliesslich relativ adressierten Code erzeugen koennen.
Dann kannst du sicherlich auch mal einen C++ Compiler als Beispiel nennen?
Power Off schrieb:
Abgesehen davon, kann jemand mit ernsthaften Absichten in der Richtung durchaus seine eigenen Compiler schreiben.
Sicher, hat ja auch jeder schon mal einen C++ Compiler geschrieben. Natürlich, wer eigentlich nicht?
-
groovemaster schrieb:
Dann kannst du sicherlich auch mal einen C++ Compiler als Beispiel nennen?
Ich persoenlich kenne keinen C++ Compiler, der das kann. Aber es gibt bestimmt einen, vielleicht geht's sogar mit dem GCC.
groovemaster schrieb:
Sicher, hat ja auch jeder schon mal einen C++ Compiler geschrieben. Natürlich, wer eigentlich nicht?
Wo ist das Problem? Standard angucken, Compiler proggen, fertig!
C++ ist schon ein Happen, das geb ich zu. C Compiler sollten aber kein Problem sein, da steckt ja nicht viel dahinter. Ich hab selber auch noch keinen C Compiler gemacht (keinen vollstaendigen, nur ein paar ohne Code Generator, also nur Syntax Analyzer).
-
Um einen C++ Compiler alleine zu schreiben brauchst du mindestens 10 Jahre.
-
Kenner der Compiler-Szene schrieb:
Um einen C++ Compiler alleine zu schreiben brauchst du mindestens 10 Jahre.
Interessante Theorie. Vielleicht sollte man die mal auf die Probe stellen. Ich glaube es geht am einfachsten, wenn man zuerst einen Assembler, dann einen C Compiler schreibt, und dann einen C++ Transcompiler, der C Code erzeugt (so wie CFront). Compilerbau ist viel einfacher als man gemeinhin denkt, aber es ist halt viel Fleissarbeit.
-
@Power Off, ich dachte Windows ändert diese Absoluten Adressen auf die passenden Adressen beim laden der Anwendung in den Speicher, so stand das zumindest mal in nem Buch drin. Verwendet der EXE-Starter dann dieses CPU-Feature oder ist das Mist, was ich gelesen habe?
-
User--- schrieb:
@Power Off, ich dachte Windows ändert diese Absoluten Adressen auf die passenden Adressen beim laden der Anwendung in den Speicher, so stand das zumindest mal in nem Buch drin. Verwendet der EXE-Starter dann dieses CPU-Feature oder ist das Mist, was ich gelesen habe?
Wie oben schonmal erwaehnt, erzeugen unter Windows die meisten Linker eine Relozierungstabelle, die dann vom Scatter-Loader des Betriebssystems aufgeloest wird.
Solche absoluten Adressen (die ja nach der Relozierung immer noch absolut sind) lassen sich leicht dazu benutzen, herauszubekommen, was das Programm macht.
Beim 32-Bit Windows werden alle Programme an eine feste Adresse reloziert (meist 0X00400000 oder sowas). Diese 32-Bit Adresse wird dann ueber einen Selektor zu einer 48-Bit-Adresse erweitert. Diese Selektoren stehen in den Selektor-Registern CS, DS, ES, FS, und GS und werden vom Betriebssystem (also Windows) ausgewaehlt. Das begrenzt natuerlich die Anzahl gleichzeitig ausfuehrbarer Programme, was aber Windows eh kein Problem ist, da es ja bei mehreren hundert Programmen schon praktisch stillsteht.